aboutsummaryrefslogtreecommitdiff
path: root/gcc/java
diff options
context:
space:
mode:
authorBryce McKinlay <bryce@waitaki.otago.ac.nz>2001-12-15 08:31:49 +0000
committerBryce McKinlay <bryce@waitaki.otago.ac.nz>2001-12-15 08:31:49 +0000
commit090564a63d08fbcc0358c321b21602ec4c7fd2b2 (patch)
treea15d17366ad109cb78a0bc4f4aaf8e142550387d /gcc/java
parent8c2bf0e36b51fe679915dfc0c248e539778e7be1 (diff)
gcc/java:
* java-tree.h (otable_methods, otable_decl, otable_syms_decl, otable_type, otable_ptr_type, method_symbol_type, method_symbols_array_type, method_symbols_array_ptr_type): New field/global tree definitions. (flag_indirect_dispatch): New flag. * decl.c (java_init_decl_processing): Initialize new otable and otable_syms type nodes and decls. Add new field "index" to method_type_node. * class.c (build_method_symbols_entry): New function. (make_method_value): Set "index" to to method's vtable index for virtual methods when indirect-dispatch is not used. (make_class_data): For indirect-dispatch, dont emit the dtable_decl, and set vtable_method_count to -1. Set otable and otable_syms field if indirect-dispatch is used and there was something to put in them. (build_method_symbols_entry): New function. (emit_offset_symbol_table): New function. * expr.c (get_offset_table_index): New function. (build_invokevirtual): Build array reference to otable at the index returned by get_offset_table_index, and use the result as the vtable offset. (build_invokeinterface): Similar. * jcf-parse.c (yyparse): If indirect-dispatch, call emit_offset_symbol_table at the end of compilation, after all classes have been generated. * jvspec.c: Don't pass findirect-dispatch to jvgenmain. * lang.c (flag_indirect_dispatch): Define. (lang_f_options): Add indirect-dispatch flag. libjava: * include/jvm.h (_Jv_VTable::idx_to_offset): New method. * java/lang/natClassLoader.cc (_Jv_PrepareCompiledClass): Call _Jv_MakeVTable and _Jv_LinkOffsetTable if needed. * java/lang/Class.h (_Jv_Method): Add "index" field. (_Jv_MethodSymbol): New struct type. (_Jv_LinkOffsetTable, _Jv_LayoutVTableMethods, _Jv_SetVTableEntries, _Jv_MakeVTable): Friends. (otable, otable_syms): New Class fields. * java/lang/natClass.cc (_Jv_LinkOffsetTable): New function. (isVirtualMethod): New static function. (_Jv_LayoutVTableMethods): New function. (_Jv_SetVTableEntries): New function. (_Jv_MakeVTable): New function. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@48038 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/java')
-rw-r--r--gcc/java/ChangeLog30
-rw-r--r--gcc/java/class.c124
-rw-r--r--gcc/java/decl.c35
-rw-r--r--gcc/java/expr.c95
-rw-r--r--gcc/java/java-tree.h36
-rw-r--r--gcc/java/jcf-parse.c6
-rw-r--r--gcc/java/jvspec.c1
-rw-r--r--gcc/java/lang.c7
8 files changed, 307 insertions, 27 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 192b6bc104d..46e3e57db6c 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,33 @@
+2001-12-15 Bryce McKinlay <bryce@waitaki.otago.ac.nz>
+
+ * java-tree.h (otable_methods, otable_decl, otable_syms_decl,
+ otable_type, otable_ptr_type, method_symbol_type,
+ method_symbols_array_type, method_symbols_array_ptr_type): New
+ field/global tree definitions.
+ (flag_indirect_dispatch): New flag.
+ * decl.c (java_init_decl_processing): Initialize new otable and
+ otable_syms type nodes and decls. Add new field "index" to
+ method_type_node.
+ * class.c (build_method_symbols_entry): New function.
+ (make_method_value): Set "index" to to method's vtable index for
+ virtual methods when indirect-dispatch is not used.
+ (make_class_data): For indirect-dispatch, dont emit the dtable_decl,
+ and set vtable_method_count to -1. Set otable and otable_syms field
+ if indirect-dispatch is used and there was something to put in them.
+ (build_method_symbols_entry): New function.
+ (emit_offset_symbol_table): New function.
+ * expr.c (get_offset_table_index): New function.
+ (build_invokevirtual): Build array reference to otable at the index
+ returned by get_offset_table_index, and use the result as the vtable
+ offset.
+ (build_invokeinterface): Similar.
+ * jcf-parse.c (yyparse): If indirect-dispatch, call
+ emit_offset_symbol_table at the end of compilation, after all classes
+ have been generated.
+ * jvspec.c: Don't pass findirect-dispatch to jvgenmain.
+ * lang.c (flag_indirect_dispatch): Define.
+ (lang_f_options): Add indirect-dispatch flag.
+
2001-12-14 Matthias Klose <doko@debian.org>
* gcj.texi: Markup for man page generation. Document missing
diff --git a/gcc/java/class.c b/gcc/java/class.c
index 5695aba3e40..6b05435c11e 100644
--- a/gcc/java/class.c
+++ b/gcc/java/class.c
@@ -58,6 +58,8 @@ static int assume_compiled PARAMS ((const char *));
static struct hash_entry *init_test_hash_newfunc PARAMS ((struct hash_entry *,
struct hash_table *,
hash_table_key));
+static tree build_method_symbols_entry PARAMS ((tree));
+
static rtx registerClass_libfunc;
static rtx registerResource_libfunc;
@@ -1276,9 +1278,16 @@ make_method_value (mdecl)
{
static int method_name_count = 0;
tree minit;
+ tree index;
tree code;
#define ACC_TRANSLATED 0x4000
int accflags = get_access_flags_from_decl (mdecl) | ACC_TRANSLATED;
+
+ if (!flag_indirect_dispatch && DECL_VINDEX (mdecl) != NULL_TREE)
+ index = DECL_VINDEX (mdecl);
+ else
+ index = integer_minus_one_node;
+
code = null_pointer_node;
if (DECL_RTL_SET_P (mdecl))
code = build1 (ADDR_EXPR, nativecode_ptr_type_node, mdecl);
@@ -1296,6 +1305,7 @@ make_method_value (mdecl)
IDENTIFIER_LENGTH(signature)))));
}
PUSH_FIELD_VALUE (minit, "accflags", build_int_2 (accflags, 0));
+ PUSH_FIELD_VALUE (minit, "index", index);
PUSH_FIELD_VALUE (minit, "ncode", code);
{
@@ -1541,7 +1551,7 @@ make_class_data (type)
rest_of_decl_compilation (methods_decl, (char*) 0, 1, 0);
if (assume_compiled (IDENTIFIER_POINTER (DECL_NAME (type_decl)))
- && ! CLASS_INTERFACE (type_decl))
+ && ! CLASS_INTERFACE (type_decl) && !flag_indirect_dispatch)
{
tree dtable = get_dispatch_table (type, this_class_addr);
dtable_decl = build_dtable_decl (type);
@@ -1635,7 +1645,12 @@ make_class_data (type)
PUSH_FIELD_VALUE (cons, "methods",
build1 (ADDR_EXPR, method_ptr_type_node, methods_decl));
PUSH_FIELD_VALUE (cons, "method_count", build_int_2 (method_count, 0));
- PUSH_FIELD_VALUE (cons, "vtable_method_count", TYPE_NVIRTUALS (type));
+
+ if (flag_indirect_dispatch)
+ PUSH_FIELD_VALUE (cons, "vtable_method_count", integer_minus_one_node)
+ else
+ PUSH_FIELD_VALUE (cons, "vtable_method_count", TYPE_NVIRTUALS (type));
+
PUSH_FIELD_VALUE (cons, "fields",
fields_decl == NULL_TREE ? null_pointer_node
: build1 (ADDR_EXPR, field_ptr_type_node, fields_decl));
@@ -1643,9 +1658,27 @@ make_class_data (type)
PUSH_FIELD_VALUE (cons, "field_count", build_int_2 (field_count, 0));
PUSH_FIELD_VALUE (cons, "static_field_count",
build_int_2 (static_field_count, 0));
- PUSH_FIELD_VALUE (cons, "vtable",
- dtable_decl == NULL_TREE ? null_pointer_node
- : build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl));
+
+ if (flag_indirect_dispatch)
+ PUSH_FIELD_VALUE (cons, "vtable", null_pointer_node)
+ else
+ PUSH_FIELD_VALUE (cons, "vtable",
+ dtable_decl == NULL_TREE ? null_pointer_node
+ : build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl));
+
+ if (otable_methods == NULL_TREE)
+ {
+ PUSH_FIELD_VALUE (cons, "otable", null_pointer_node);
+ PUSH_FIELD_VALUE (cons, "otable_syms", null_pointer_node);
+ }
+ else
+ {
+ PUSH_FIELD_VALUE (cons, "otable",
+ build1 (ADDR_EXPR, otable_ptr_type, otable_decl));
+ PUSH_FIELD_VALUE (cons, "otable_syms",
+ build1 (ADDR_EXPR, method_symbols_array_ptr_type,
+ otable_syms_decl));
+ }
PUSH_FIELD_VALUE (cons, "interfaces", interfaces);
PUSH_FIELD_VALUE (cons, "loader", null_pointer_node);
PUSH_FIELD_VALUE (cons, "interface_count", build_int_2 (interface_len, 0));
@@ -2160,6 +2193,87 @@ emit_register_classes ()
}
}
+/* Make a method_symbol_type (_Jv_MethodSymbol) node for METHOD. */
+
+tree
+build_method_symbols_entry (tree method)
+{
+ tree clname, name, signature, method_symbol;
+
+ clname = build_utf8_ref (DECL_NAME (TYPE_NAME (DECL_CONTEXT (method))));
+ name = build_utf8_ref (DECL_NAME (method));
+ signature = build_java_signature (TREE_TYPE (method));
+ signature = build_utf8_ref (unmangle_classname
+ (IDENTIFIER_POINTER (signature),
+ IDENTIFIER_LENGTH (signature)));
+
+ START_RECORD_CONSTRUCTOR (method_symbol, method_symbol_type);
+ PUSH_FIELD_VALUE (method_symbol, "clname", clname);
+ PUSH_FIELD_VALUE (method_symbol, "name", name);
+ PUSH_FIELD_VALUE (method_symbol, "signature", signature);
+ FINISH_RECORD_CONSTRUCTOR (method_symbol);
+ TREE_CONSTANT (method_symbol) = 1;
+
+ return method_symbol;
+}
+
+/* Emit the offset symbols table for indirect virtual dispatch. */
+
+void
+emit_offset_symbol_table ()
+{
+ tree method_list, method, table, list, null_symbol;
+ tree otable_bound, otable_array_type;
+ int index;
+
+ /* Only emit an offset table if this translation unit actually made virtual
+ calls. */
+ if (otable_methods == NULL_TREE)
+ return;
+
+ /* Build a list of _Jv_MethodSymbols for each entry in otable_methods. */
+ index = 0;
+ method_list = otable_methods;
+ list = NULL_TREE;
+ while (method_list != NULL_TREE)
+ {
+ method = TREE_VALUE (method_list);
+ list = tree_cons (NULL_TREE, build_method_symbols_entry (method), list);
+ method_list = TREE_CHAIN (method_list);
+ index++;
+ }
+
+ /* Terminate the list with a "null" entry. */
+ START_RECORD_CONSTRUCTOR (null_symbol, method_symbol_type);
+ PUSH_FIELD_VALUE (null_symbol, "clname", null_pointer_node);
+ PUSH_FIELD_VALUE (null_symbol, "name", null_pointer_node);
+ PUSH_FIELD_VALUE (null_symbol, "signature", null_pointer_node);
+ FINISH_RECORD_CONSTRUCTOR (null_symbol);
+ TREE_CONSTANT (null_symbol) = 1;
+ list = tree_cons (NULL_TREE, null_symbol, list);
+
+ /* Put the list in the right order and make it a constructor. */
+ list = nreverse (list);
+ table = build (CONSTRUCTOR, method_symbols_array_type, NULL_TREE, list);
+
+ /* Make it the initial value for otable_syms and emit the decl. */
+ DECL_INITIAL (otable_syms_decl) = table;
+ DECL_ARTIFICIAL (otable_syms_decl) = 1;
+ DECL_IGNORED_P (otable_syms_decl) = 1;
+ rest_of_decl_compilation (otable_syms_decl, NULL, 1, 0);
+
+ /* Now that its size is known, redefine otable as an uninitialized static
+ array of INDEX + 1 integers. The extra entry is used by the runtime
+ to track whether the otable has been initialized. */
+ otable_bound = build_index_type (build_int_2 (index, 0));
+ otable_array_type = build_array_type (integer_type_node, otable_bound);
+ otable_decl = build_decl (VAR_DECL, get_identifier ("otable"),
+ otable_array_type);
+ TREE_STATIC (otable_decl) = 1;
+ TREE_READONLY (otable_decl) = 1;
+ rest_of_decl_compilation (otable_decl, NULL, 1, 0);
+}
+
void
init_class_processing ()
{
diff --git a/gcc/java/decl.c b/gcc/java/decl.c
index 17b3607a871..4cfa9ba7ee0 100644
--- a/gcc/java/decl.c
+++ b/gcc/java/decl.c
@@ -614,6 +614,35 @@ java_init_decl_processing ()
dtable_type = make_node (RECORD_TYPE);
dtable_ptr_type = build_pointer_type (dtable_type);
+ otable_type = make_node (RECORD_TYPE);
+ otable_ptr_type = build_pointer_type (otable_type);
+
+ method_symbol_type = make_node (RECORD_TYPE);
+ PUSH_FIELD (method_symbol_type, field, "clname", utf8const_ptr_type);
+ PUSH_FIELD (method_symbol_type, field, "name", utf8const_ptr_type);
+ PUSH_FIELD (method_symbol_type, field, "signature", utf8const_ptr_type);
+ FINISH_RECORD (method_symbol_type);
+
+ one_elt_array_domain_type = build_index_type (integer_one_node);
+ method_symbols_array_type = build_array_type (method_symbol_type,
+ one_elt_array_domain_type);
+ method_symbols_array_ptr_type = build_pointer_type
+ (method_symbols_array_type);
+
+ otable_decl = build_decl (VAR_DECL, get_identifier ("otable"),
+ build_array_type (integer_type_node,
+ one_elt_array_domain_type));
+ DECL_EXTERNAL (otable_decl) = 1;
+ TREE_STATIC (otable_decl) = 1;
+ TREE_READONLY (otable_decl) = 1;
+ pushdecl (otable_decl);
+
+ otable_syms_decl = build_decl (VAR_DECL, get_identifier ("otable_syms"),
+ method_symbols_array_type);
+ TREE_STATIC (otable_syms_decl) = 1;
+ TREE_CONSTANT (otable_syms_decl) = 1;
+ pushdecl (otable_syms_decl);
+
PUSH_FIELD (object_type_node, field, "vtable", dtable_ptr_type);
/* This isn't exactly true, but it is what we have in the source.
There is an unresolved issue here, which is whether the vtable
@@ -647,6 +676,9 @@ java_init_decl_processing ()
PUSH_FIELD (class_type_node, field, "field_count", short_type_node);
PUSH_FIELD (class_type_node, field, "static_field_count", short_type_node);
PUSH_FIELD (class_type_node, field, "vtable", dtable_ptr_type);
+ PUSH_FIELD (class_type_node, field, "otable", otable_ptr_type);
+ PUSH_FIELD (class_type_node, field, "otable_syms",
+ method_symbols_array_ptr_type);
PUSH_FIELD (class_type_node, field, "interfaces",
build_pointer_type (class_ptr_type));
PUSH_FIELD (class_type_node, field, "loader", ptr_type_node);
@@ -661,6 +693,7 @@ java_init_decl_processing ()
for (t = TYPE_FIELDS (class_type_node); t != NULL_TREE; t = TREE_CHAIN (t))
FIELD_PRIVATE (t) = 1;
push_super_field (class_type_node, object_type_node);
+
FINISH_RECORD (class_type_node);
build_decl (TYPE_DECL, get_identifier ("Class"), class_type_node);
@@ -680,7 +713,6 @@ java_init_decl_processing ()
FINISH_RECORD (field_type_node);
build_decl (TYPE_DECL, get_identifier ("Field"), field_type_node);
- one_elt_array_domain_type = build_index_type (integer_one_node);
nativecode_ptr_array_type_node
= build_array_type (nativecode_ptr_type_node, one_elt_array_domain_type);
@@ -717,6 +749,7 @@ java_init_decl_processing ()
PUSH_FIELD (method_type_node, field, "name", utf8const_ptr_type);
PUSH_FIELD (method_type_node, field, "signature", utf8const_ptr_type);
PUSH_FIELD (method_type_node, field, "accflags", access_flags_type_node);
+ PUSH_FIELD (method_type_node, field, "index", unsigned_short_type_node);
PUSH_FIELD (method_type_node, field, "ncode", nativecode_ptr_type_node);
PUSH_FIELD (method_type_node, field, "throws", ptr_type_node);
FINISH_RECORD (method_type_node);
diff --git a/gcc/java/expr.c b/gcc/java/expr.c
index ef1a13959e1..e5d141ea5e4 100644
--- a/gcc/java/expr.c
+++ b/gcc/java/expr.c
@@ -84,6 +84,7 @@ static tree case_identity PARAMS ((tree, tree));
static unsigned char peek_opcode_at_pc PARAMS ((struct JCF *, int, int));
static bool emit_init_test_initialization PARAMS ((struct hash_entry *,
PTR ptr));
+static int get_offset_table_index PARAMS ((tree));
static tree operand_type[59];
extern struct obstack permanent_obstack;
@@ -1856,6 +1857,40 @@ invoke_build_dtable (is_invoke_interface, arg_list)
return dtable;
}
+/* Determine the index in the virtual offset table (otable) for a call to
+ METHOD. If this method has not been seen before, it will be added to the
+ otable_methods. If it has, the existing otable slot will be reused. */
+
+int
+get_offset_table_index (method)
+ tree method;
+{
+ int i = 1;
+ tree method_list;
+
+ if (otable_methods == NULL_TREE)
+ {
+ otable_methods = build_tree_list (method, method);
+ return 1;
+ }
+
+ method_list = otable_methods;
+
+ while (1)
+ {
+ if (TREE_VALUE (method_list) == method)
+ return i;
+ i++;
+ if (TREE_CHAIN (method_list) == NULL_TREE)
+ break;
+ else
+ method_list = TREE_CHAIN (method_list);
+ }
+
+ TREE_CHAIN (method_list) = build_tree_list (method, method);
+ return i;
+}
+
tree
build_invokevirtual (dtable, method)
tree dtable, method;
@@ -1863,20 +1898,33 @@ build_invokevirtual (dtable, method)
tree func;
tree nativecode_ptr_ptr_type_node
= build_pointer_type (nativecode_ptr_type_node);
- tree method_index = convert (sizetype, DECL_VINDEX (method));
+ tree method_index;
+ tree otable_index;
- if (TARGET_VTABLE_USES_DESCRIPTORS)
- /* Add one to skip bogus descriptor for class and GC descriptor. */
- method_index = size_binop (PLUS_EXPR, method_index, size_int (1));
+ if (flag_indirect_dispatch)
+ {
+ otable_index = build_int_2 (get_offset_table_index (method), 0);
+ method_index = build (ARRAY_REF, integer_type_node, otable_decl,
+ otable_index);
+ }
else
- /* Add 1 to skip "class" field of dtable, and 1 to skip GC descriptor. */
- method_index = size_binop (PLUS_EXPR, method_index, size_int (2));
- method_index = size_binop (MULT_EXPR, method_index,
- TYPE_SIZE_UNIT (nativecode_ptr_ptr_type_node));
+ {
+ method_index = convert (sizetype, DECL_VINDEX (method));
- if (TARGET_VTABLE_USES_DESCRIPTORS)
- method_index = size_binop (MULT_EXPR, method_index,
- size_int (TARGET_VTABLE_USES_DESCRIPTORS));
+ if (TARGET_VTABLE_USES_DESCRIPTORS)
+ /* Add one to skip bogus descriptor for class and GC descriptor. */
+ method_index = size_binop (PLUS_EXPR, method_index, size_int (1));
+ else
+ /* Add 1 to skip "class" field of dtable, and 1 to skip GC descriptor. */
+ method_index = size_binop (PLUS_EXPR, method_index, size_int (2));
+
+ method_index = size_binop (MULT_EXPR, method_index,
+ TYPE_SIZE_UNIT (nativecode_ptr_ptr_type_node));
+
+ if (TARGET_VTABLE_USES_DESCRIPTORS)
+ method_index = size_binop (MULT_EXPR, method_index,
+ size_int (TARGET_VTABLE_USES_DESCRIPTORS));
+ }
func = fold (build (PLUS_EXPR, nativecode_ptr_ptr_type_node, dtable,
convert (nativecode_ptr_ptr_type_node, method_index)));
@@ -1898,6 +1946,7 @@ build_invokeinterface (dtable, method)
tree interface;
tree idx;
tree meth;
+ tree otable_index;
int i;
/* We expand invokeinterface here. _Jv_LookupInterfaceMethod() will
@@ -1917,16 +1966,24 @@ build_invokeinterface (dtable, method)
interface = DECL_CONTEXT (method);
layout_class_methods (interface);
- i = 1;
- for (meth = TYPE_METHODS (interface); ; meth = TREE_CHAIN (meth), i++)
+ if (flag_indirect_dispatch)
{
- if (meth == method)
- {
- idx = build_int_2 (i, 0);
- break;
+ otable_index = build_int_2 (get_offset_table_index (method), 0);
+ idx = build (ARRAY_REF, integer_type_node, otable_decl, otable_index);
+ }
+ else
+ {
+ i = 1;
+ for (meth = TYPE_METHODS (interface); ; meth = TREE_CHAIN (meth), i++)
+ {
+ if (meth == method)
+ {
+ idx = build_int_2 (i, 0);
+ break;
+ }
+ if (meth == NULL_TREE)
+ abort ();
}
- if (meth == NULL_TREE)
- abort ();
}
lookup_arg = tree_cons (NULL_TREE, dtable,
diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
index 9d11bf6baf1..17a06382815 100644
--- a/gcc/java/java-tree.h
+++ b/gcc/java/java-tree.h
@@ -141,6 +141,18 @@ extern int compiling_from_source;
/* List of all class filenames seen so far. */
#define all_class_filename java_global_trees [JTI_ALL_CLASS_FILENAME]
+/* List of virtual method decls called in this translation unit, used to
+ generate virtual method offset symbol table. */
+#define otable_methods java_global_trees [JTI_OTABLE_METHODS]
+
+/* The virtual method offset table. This is emitted as uninitialized data of
+ the required length, and filled out at run time during class linking. */
+#define otable_decl java_global_trees [JTI_OTABLE_DECL]
+
+/* The virtual method offset symbol table. Used by the runtime to fill out the
+ otable. */
+#define otable_syms_decl java_global_trees [JTI_OTABLE_SYMS_DECL]
+
extern int flag_emit_class_files;
extern int flag_filelist_file;
@@ -196,6 +208,10 @@ extern int flag_check_references;
initialization optimization should be performed. */
extern int flag_optimize_sci;
+/* When non zero, use offset tables for virtual method calls
+ in order to improve binary compatibility. */
+extern int flag_indirect_dispatch;
+
/* Encoding used for source files. */
extern const char *current_encoding;
@@ -331,6 +347,11 @@ enum java_tree_index
JTI_LINENUMBERS_TYPE,
JTI_METHOD_TYPE_NODE,
JTI_METHOD_PTR_TYPE_NODE,
+ JTI_OTABLE_TYPE,
+ JTI_OTABLE_PTR_TYPE,
+ JTI_METHOD_SYMBOL_TYPE,
+ JTI_METHOD_SYMBOLS_ARRAY_TYPE,
+ JTI_METHOD_SYMBOLS_ARRAY_PTR_TYPE,
JTI_END_PARAMS_NODE,
@@ -370,6 +391,10 @@ enum java_tree_index
JTI_ALL_CLASS_LIST,
JTI_ALL_CLASS_FILENAME,
+ JTI_OTABLE_METHODS,
+ JTI_OTABLE_DECL,
+ JTI_OTABLE_SYMS_DECL,
+
JTI_MAX
};
@@ -565,6 +590,16 @@ extern tree java_global_trees[JTI_MAX];
java_global_trees[JTI_METHOD_TYPE_NODE]
#define method_ptr_type_node \
java_global_trees[JTI_METHOD_PTR_TYPE_NODE]
+#define otable_type \
+ java_global_trees[JTI_OTABLE_TYPE]
+#define otable_ptr_type \
+ java_global_trees[JTI_OTABLE_PTR_TYPE]
+#define method_symbol_type \
+ java_global_trees[JTI_METHOD_SYMBOL_TYPE]
+#define method_symbols_array_type \
+ java_global_trees[JTI_METHOD_SYMBOLS_ARRAY_TYPE]
+#define method_symbols_array_ptr_type \
+ java_global_trees[JTI_METHOD_SYMBOLS_ARRAY_PTR_TYPE]
#define end_params_node \
java_global_trees[JTI_END_PARAMS_NODE]
@@ -1098,6 +1133,7 @@ extern void make_class_data PARAMS ((tree));
extern void register_class PARAMS ((void));
extern int alloc_name_constant PARAMS ((int, tree));
extern void emit_register_classes PARAMS ((void));
+extern void emit_offset_symbol_table PARAMS ((void));
extern void lang_init_source PARAMS ((int));
extern void write_classfile PARAMS ((tree));
extern char *print_int_node PARAMS ((tree));
diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c
index 15dcd071e5f..61d09729727 100644
--- a/gcc/java/jcf-parse.c
+++ b/gcc/java/jcf-parse.c
@@ -1188,7 +1188,11 @@ yyparse ()
java_expand_classes ();
if (!java_report_errors () && !flag_syntax_only)
- emit_register_classes ();
+ {
+ emit_register_classes ();
+ if (flag_indirect_dispatch)
+ emit_offset_symbol_table ();
+ }
return 0;
}
diff --git a/gcc/java/jvspec.c b/gcc/java/jvspec.c
index 1b53bf5a7a0..1fd4f4cc87a 100644
--- a/gcc/java/jvspec.c
+++ b/gcc/java/jvspec.c
@@ -64,6 +64,7 @@ const char jvgenmain_spec[] =
%{<fcompile-resource*}\
%{<femit-class-file} %{<femit-class-files} %{<fencoding*}\
%{<fuse-boehm-gc} %{<fhash-synchronization} %{<fjni}\
+ %{<findirect-dispatch} \
%{<fclasspath*} %{<fCLASSPATH*} %{<foutput-class-dir}\
%{<fuse-divide-subroutine} %{<fno-use-divide-subroutine}\
%{<fcheck-references} %{<fno-check-references}\
diff --git a/gcc/java/lang.c b/gcc/java/lang.c
index c07c5868017..11e036ca38a 100644
--- a/gcc/java/lang.c
+++ b/gcc/java/lang.c
@@ -153,6 +153,10 @@ int flag_force_classes_archive_check;
be tested alone, use STATIC_CLASS_INITIALIZATION_OPTIMIZATION_P instead. */
int flag_optimize_sci = 1;
+/* When non zero, use offset tables for virtual method calls
+ in order to improve binary compatibility. */
+int flag_indirect_dispatch = 0;
+
/* When non zero, print extra version information. */
static int version_flag = 0;
@@ -174,7 +178,8 @@ lang_f_options[] =
{"jni", &flag_jni, 1},
{"check-references", &flag_check_references, 1},
{"force-classes-archive-check", &flag_force_classes_archive_check, 1},
- {"optimize-static-class-initialization", &flag_optimize_sci, 1 }
+ {"optimize-static-class-initialization", &flag_optimize_sci, 1 },
+ {"indirect-dispatch", &flag_indirect_dispatch, 1}
};
static struct string_option