Commit 9dfc2ec2 by Andrew Haley Committed by Andrew Haley

jcf-parse.c (java_parse_file): Write otable and atable.

2003-10-01  Andrew Haley  <aph@redhat.com>

        * jcf-parse.c (java_parse_file): Write otable and atable.
        * java-tree.h (atable_methods): New.
        (atable_decl): New.
        (atable_syms_decl): New.
        (enum java_tree_index): Add JTI_ATABLE_METHODS, JTI_ATABLE_DECL,
        JTI_ATABLE_SYMS_DECL.  Rename JTI_METHOD_SYMBOL* to JTI_SYMBOL*.
        (symbol_*type): Rename method_symbol* to symbol*type.
        (emit_offset_symbol_table): Delete.
        (emit_symbol_table): New.
        (get_symbol_table_index): New.
        (atable_type): New.
        * expr.c (build_field_ref): Handle flag_indirect_dispatch.
        (build_known_method_ref): Likewise.
        (get_symbol_table_index): Rename from get_offset_table_index.
        Parameterize to allow re-use by differing types of symbol table.
        (build_invokevirtual): Pass table to get_offset_table_index.
        * decl.c (java_init_decl_processing): Push types and decls for
        atable and atable_syyms.
        * class.c (build_static_field_ref): Handle flag_indirect_dispatch.
        (make_class_data): Add new fields atable and atable_syms.
        (emit_symbol_table): Rename from emit_offset_symbol_table.
        Parameterize to allow re-use by different types of symbol table.
        (build_symbol_entry): Renamed from build_method_symbols_entry.

2003-10-01  Andrew Haley  <aph@redhat.com>

        * java/lang/natClass.cc (initializeClass): Check for otable and
        atable.
        (_Jv_LinkOffsetTable): Check for existence of atable.  Rewrite
        loops using for().  Search superinterfaces.  Check for fields as
        well as methods.  Initialize atable as well as otable: check for
        static methods as well as virtual methods.
        * java/lang/Class.h (struct _Jv_AddressTable): New.
        (atable): New.
        (atable_syms): New.
        * include/jvm.h (_Jv_equalUtf8Consts): constify.
        * prims.cc (_Jv_equalUtf8Consts): constify.

From-SVN: r71979
parent 530ce551
2003-10-01 Andrew Haley <aph@redhat.com>
* jcf-parse.c (java_parse_file): Write otable and atable.
* java-tree.h (atable_methods): New.
(atable_decl): New.
(atable_syms_decl): New.
(enum java_tree_index): Add JTI_ATABLE_METHODS, JTI_ATABLE_DECL,
JTI_ATABLE_SYMS_DECL. Rename JTI_METHOD_SYMBOL* to JTI_SYMBOL*.
(symbol_*type): Rename method_symbol* to symbol*type.
(emit_offset_symbol_table): Delete.
(emit_symbol_table): New.
(get_symbol_table_index): New.
(atable_type): New.
* expr.c (build_field_ref): Handle flag_indirect_dispatch.
(build_known_method_ref): Likewise.
(get_symbol_table_index): Rename from get_offset_table_index.
Parameterize to allow re-use by differing types of symbol table.
(build_invokevirtual): Pass table to get_offset_table_index.
* decl.c (java_init_decl_processing): Push types and decls for
atable and atable_syyms.
* class.c (build_static_field_ref): Handle flag_indirect_dispatch.
(make_class_data): Add new fields atable and atable_syms.
(emit_symbol_table): Rename from emit_offset_symbol_table.
Parameterize to allow re-use by different types of symbol table.
(build_symbol_entry): Renamed from build_method_symbols_entry.
2003-09-30 Roger Sayle <roger@eyesopen.com> 2003-09-30 Roger Sayle <roger@eyesopen.com>
* jcf-write.c (generate_bytecode_insns): Implement evaluate-once * jcf-write.c (generate_bytecode_insns): Implement evaluate-once
......
...@@ -59,7 +59,7 @@ static void add_interface_do (tree, tree, int); ...@@ -59,7 +59,7 @@ static void add_interface_do (tree, tree, int);
static tree maybe_layout_super_class (tree, tree); static tree maybe_layout_super_class (tree, tree);
static void add_miranda_methods (tree, tree); static void add_miranda_methods (tree, tree);
static int assume_compiled (const char *); static int assume_compiled (const char *);
static tree build_method_symbols_entry (tree); static tree build_symbol_entry (tree);
static GTY(()) rtx registerClass_libfunc; static GTY(()) rtx registerClass_libfunc;
...@@ -925,7 +925,8 @@ build_static_field_ref (tree fdecl) ...@@ -925,7 +925,8 @@ build_static_field_ref (tree fdecl)
However, currently sometimes gcj is too eager and will end up However, currently sometimes gcj is too eager and will end up
returning the field itself, leading to an incorrect external returning the field itself, leading to an incorrect external
reference being generated. */ reference being generated. */
if (is_compiled if ((is_compiled
&& (! flag_indirect_dispatch || current_class == fclass))
|| (FIELD_FINAL (fdecl) && DECL_INITIAL (fdecl) != NULL_TREE || (FIELD_FINAL (fdecl) && DECL_INITIAL (fdecl) != NULL_TREE
&& (JSTRING_TYPE_P (TREE_TYPE (fdecl)) && (JSTRING_TYPE_P (TREE_TYPE (fdecl))
|| JNUMERIC_TYPE_P (TREE_TYPE (fdecl))) || JNUMERIC_TYPE_P (TREE_TYPE (fdecl)))
...@@ -939,6 +940,17 @@ build_static_field_ref (tree fdecl) ...@@ -939,6 +940,17 @@ build_static_field_ref (tree fdecl)
} }
return fdecl; return fdecl;
} }
if (flag_indirect_dispatch)
{
tree table_index
= build_int_2 (get_symbol_table_index (fdecl, &atable_methods), 0);
tree field_address
= build (ARRAY_REF, build_pointer_type (TREE_TYPE (fdecl)),
atable_decl, table_index);
return fold (build1 (INDIRECT_REF, TREE_TYPE (fdecl),
field_address));
}
else else
{ {
/* Compile as: /* Compile as:
...@@ -1500,7 +1512,6 @@ make_class_data (tree type) ...@@ -1500,7 +1512,6 @@ make_class_data (tree type)
: build (PLUS_EXPR, dtable_ptr_type, : build (PLUS_EXPR, dtable_ptr_type,
build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl), build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl),
dtable_start_offset)); dtable_start_offset));
if (otable_methods == NULL_TREE) if (otable_methods == NULL_TREE)
{ {
PUSH_FIELD_VALUE (cons, "otable", null_pointer_node); PUSH_FIELD_VALUE (cons, "otable", null_pointer_node);
...@@ -1511,9 +1522,25 @@ make_class_data (tree type) ...@@ -1511,9 +1522,25 @@ make_class_data (tree type)
PUSH_FIELD_VALUE (cons, "otable", PUSH_FIELD_VALUE (cons, "otable",
build1 (ADDR_EXPR, otable_ptr_type, otable_decl)); build1 (ADDR_EXPR, otable_ptr_type, otable_decl));
PUSH_FIELD_VALUE (cons, "otable_syms", PUSH_FIELD_VALUE (cons, "otable_syms",
build1 (ADDR_EXPR, method_symbols_array_ptr_type, build1 (ADDR_EXPR, symbols_array_ptr_type,
otable_syms_decl)); otable_syms_decl));
TREE_CONSTANT (otable_decl) = 1;
}
if (atable_methods == NULL_TREE)
{
PUSH_FIELD_VALUE (cons, "atable", null_pointer_node);
PUSH_FIELD_VALUE (cons, "atable_syms", null_pointer_node);
} }
else
{
PUSH_FIELD_VALUE (cons, "atable",
build1 (ADDR_EXPR, atable_ptr_type, atable_decl));
PUSH_FIELD_VALUE (cons, "atable_syms",
build1 (ADDR_EXPR, symbols_array_ptr_type,
atable_syms_decl));
TREE_CONSTANT (atable_decl) = 1;
}
PUSH_FIELD_VALUE (cons, "interfaces", interfaces); PUSH_FIELD_VALUE (cons, "interfaces", interfaces);
PUSH_FIELD_VALUE (cons, "loader", null_pointer_node); PUSH_FIELD_VALUE (cons, "loader", null_pointer_node);
PUSH_FIELD_VALUE (cons, "interface_count", build_int_2 (interface_len, 0)); PUSH_FIELD_VALUE (cons, "interface_count", build_int_2 (interface_len, 0));
...@@ -2098,58 +2125,59 @@ emit_register_classes (void) ...@@ -2098,58 +2125,59 @@ emit_register_classes (void)
} }
} }
/* Make a method_symbol_type (_Jv_MethodSymbol) node for METHOD. */ /* Make a symbol_type (_Jv_MethodSymbol) node for DECL. */
static tree static tree
build_method_symbols_entry (tree method) build_symbol_entry (tree decl)
{ {
tree clname, name, signature, method_symbol; tree clname, name, signature, sym;
clname = build_utf8_ref (DECL_NAME (TYPE_NAME (DECL_CONTEXT (method)))); clname = build_utf8_ref (DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))));
name = build_utf8_ref (DECL_NAME (method)); name = build_utf8_ref (DECL_NAME (decl));
signature = build_java_signature (TREE_TYPE (method)); signature = build_java_signature (TREE_TYPE (decl));
signature = build_utf8_ref (unmangle_classname signature = build_utf8_ref (unmangle_classname
(IDENTIFIER_POINTER (signature), (IDENTIFIER_POINTER (signature),
IDENTIFIER_LENGTH (signature))); IDENTIFIER_LENGTH (signature)));
START_RECORD_CONSTRUCTOR (method_symbol, method_symbol_type); START_RECORD_CONSTRUCTOR (sym, symbol_type);
PUSH_FIELD_VALUE (method_symbol, "clname", clname); PUSH_FIELD_VALUE (sym, "clname", clname);
PUSH_FIELD_VALUE (method_symbol, "name", name); PUSH_FIELD_VALUE (sym, "name", name);
PUSH_FIELD_VALUE (method_symbol, "signature", signature); PUSH_FIELD_VALUE (sym, "signature", signature);
FINISH_RECORD_CONSTRUCTOR (method_symbol); FINISH_RECORD_CONSTRUCTOR (sym);
TREE_CONSTANT (method_symbol) = 1; TREE_CONSTANT (sym) = 1;
return method_symbol; return sym;
} }
/* Emit the offset symbols table for indirect virtual dispatch. */ /* Emit a symbol table: used by -findirect-dispatch. */
void tree
emit_offset_symbol_table (void) emit_symbol_table (tree name, tree the_table, tree decl_list, tree the_syms_decl,
tree the_array_element_type)
{ {
tree method_list, method, table, list, null_symbol; tree method_list, method, table, list, null_symbol;
tree otable_bound, otable_array_type; tree table_size, the_array_type;
int index; int index;
/* Only emit an offset table if this translation unit actually made virtual /* Only emit a table if this translation unit actually made any
calls. */ references via it. */
if (otable_methods == NULL_TREE) if (decl_list == NULL_TREE)
return; return the_table;
/* Build a list of _Jv_MethodSymbols for each entry in otable_methods. */ /* Build a list of _Jv_MethodSymbols for each entry in otable_methods. */
index = 0; index = 0;
method_list = otable_methods; method_list = decl_list;
list = NULL_TREE; list = NULL_TREE;
while (method_list != NULL_TREE) while (method_list != NULL_TREE)
{ {
method = TREE_VALUE (method_list); method = TREE_VALUE (method_list);
list = tree_cons (NULL_TREE, build_method_symbols_entry (method), list); list = tree_cons (NULL_TREE, build_symbol_entry (method), list);
method_list = TREE_CHAIN (method_list); method_list = TREE_CHAIN (method_list);
index++; index++;
} }
/* Terminate the list with a "null" entry. */ /* Terminate the list with a "null" entry. */
START_RECORD_CONSTRUCTOR (null_symbol, method_symbol_type); START_RECORD_CONSTRUCTOR (null_symbol, symbol_type);
PUSH_FIELD_VALUE (null_symbol, "clname", null_pointer_node); PUSH_FIELD_VALUE (null_symbol, "clname", null_pointer_node);
PUSH_FIELD_VALUE (null_symbol, "name", null_pointer_node); PUSH_FIELD_VALUE (null_symbol, "name", null_pointer_node);
PUSH_FIELD_VALUE (null_symbol, "signature", null_pointer_node); PUSH_FIELD_VALUE (null_symbol, "signature", null_pointer_node);
...@@ -2159,24 +2187,26 @@ emit_offset_symbol_table (void) ...@@ -2159,24 +2187,26 @@ emit_offset_symbol_table (void)
/* Put the list in the right order and make it a constructor. */ /* Put the list in the right order and make it a constructor. */
list = nreverse (list); list = nreverse (list);
table = build_constructor (method_symbols_array_type, list); table = build_constructor (symbols_array_type, list);
/* Make it the initial value for otable_syms and emit the decl. */ /* Make it the initial value for otable_syms and emit the decl. */
DECL_INITIAL (otable_syms_decl) = table; DECL_INITIAL (the_syms_decl) = table;
DECL_ARTIFICIAL (otable_syms_decl) = 1; DECL_ARTIFICIAL (the_syms_decl) = 1;
DECL_IGNORED_P (otable_syms_decl) = 1; DECL_IGNORED_P (the_syms_decl) = 1;
rest_of_decl_compilation (otable_syms_decl, NULL, 1, 0); rest_of_decl_compilation (the_syms_decl, NULL, 1, 0);
/* Now that its size is known, redefine otable as an uninitialized static /* Now that its size is known, redefine the table as an
array of INDEX + 1 integers. The extra entry is used by the runtime uninitialized static array of INDEX + 1 elements. The extra entry
to track whether the otable has been initialized. */ is used by the runtime to track whether the table has been
otable_bound = build_index_type (build_int_2 (index, 0)); initialized. */
otable_array_type = build_array_type (integer_type_node, otable_bound); table_size = build_index_type (build_int_2 (index, 0));
otable_decl = build_decl (VAR_DECL, get_identifier ("otable"), the_array_type = build_array_type (the_array_element_type, table_size);
otable_array_type); the_table = build_decl (VAR_DECL, name, the_array_type);
TREE_STATIC (otable_decl) = 1; TREE_STATIC (the_table) = 1;
TREE_READONLY (otable_decl) = 1; TREE_READONLY (the_table) = 1;
rest_of_decl_compilation (otable_decl, NULL, 1, 0); rest_of_decl_compilation (the_table, NULL, 1, 0);
return the_table;
} }
void void
......
...@@ -621,32 +621,46 @@ java_init_decl_processing (void) ...@@ -621,32 +621,46 @@ java_init_decl_processing (void)
one_elt_array_domain_type); one_elt_array_domain_type);
TYPE_NONALIASED_COMPONENT (otable_type) = 1; TYPE_NONALIASED_COMPONENT (otable_type) = 1;
otable_ptr_type = build_pointer_type (otable_type); otable_ptr_type = build_pointer_type (otable_type);
atable_type = build_array_type (ptr_type_node,
one_elt_array_domain_type);
TYPE_NONALIASED_COMPONENT (atable_type) = 1;
atable_ptr_type = build_pointer_type (atable_type);
method_symbol_type = make_node (RECORD_TYPE); symbol_type = make_node (RECORD_TYPE);
PUSH_FIELD (method_symbol_type, field, "clname", utf8const_ptr_type); PUSH_FIELD (symbol_type, field, "clname", utf8const_ptr_type);
PUSH_FIELD (method_symbol_type, field, "name", utf8const_ptr_type); PUSH_FIELD (symbol_type, field, "name", utf8const_ptr_type);
PUSH_FIELD (method_symbol_type, field, "signature", utf8const_ptr_type); PUSH_FIELD (symbol_type, field, "signature", utf8const_ptr_type);
FINISH_RECORD (method_symbol_type); FINISH_RECORD (symbol_type);
method_symbols_array_type = build_array_type (method_symbol_type, symbols_array_type = build_array_type (symbol_type,
one_elt_array_domain_type); one_elt_array_domain_type);
method_symbols_array_ptr_type = build_pointer_type symbols_array_ptr_type = build_pointer_type (symbols_array_type);
(method_symbols_array_type);
if (flag_indirect_dispatch) if (flag_indirect_dispatch)
{ {
otable_decl = build_decl (VAR_DECL, get_identifier ("otable"), otable_decl = build_decl (VAR_DECL, get_identifier ("otable"), otable_type);
otable_type);
DECL_EXTERNAL (otable_decl) = 1; DECL_EXTERNAL (otable_decl) = 1;
TREE_STATIC (otable_decl) = 1; TREE_STATIC (otable_decl) = 1;
TREE_READONLY (otable_decl) = 1; TREE_READONLY (otable_decl) = 1;
TREE_CONSTANT (otable_decl) = 1;
pushdecl (otable_decl); pushdecl (otable_decl);
otable_syms_decl = build_decl (VAR_DECL, get_identifier ("otable_syms"), otable_syms_decl = build_decl (VAR_DECL, get_identifier ("otable_syms"),
method_symbols_array_type); symbols_array_type);
TREE_STATIC (otable_syms_decl) = 1; TREE_STATIC (otable_syms_decl) = 1;
TREE_CONSTANT (otable_syms_decl) = 1; TREE_CONSTANT (otable_syms_decl) = 1;
pushdecl (otable_syms_decl); pushdecl (otable_syms_decl);
atable_decl = build_decl (VAR_DECL, get_identifier ("atable"), atable_type);
DECL_EXTERNAL (atable_decl) = 1;
TREE_STATIC (atable_decl) = 1;
TREE_READONLY (atable_decl) = 1;
TREE_CONSTANT (atable_decl) = 1;
pushdecl (atable_decl);
atable_syms_decl = build_decl (VAR_DECL, get_identifier ("atable_syms"),
symbols_array_type);
TREE_STATIC (atable_syms_decl) = 1;
TREE_CONSTANT (atable_syms_decl) = 1;
pushdecl (atable_syms_decl);
} }
PUSH_FIELD (object_type_node, field, "vtable", dtable_ptr_type); PUSH_FIELD (object_type_node, field, "vtable", dtable_ptr_type);
...@@ -684,7 +698,10 @@ java_init_decl_processing (void) ...@@ -684,7 +698,10 @@ java_init_decl_processing (void)
PUSH_FIELD (class_type_node, field, "vtable", dtable_ptr_type); 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", otable_ptr_type);
PUSH_FIELD (class_type_node, field, "otable_syms", PUSH_FIELD (class_type_node, field, "otable_syms",
method_symbols_array_ptr_type); symbols_array_ptr_type);
PUSH_FIELD (class_type_node, field, "atable", atable_ptr_type);
PUSH_FIELD (class_type_node, field, "atable_syms",
symbols_array_ptr_type);
PUSH_FIELD (class_type_node, field, "interfaces", PUSH_FIELD (class_type_node, field, "interfaces",
build_pointer_type (class_ptr_type)); build_pointer_type (class_ptr_type));
PUSH_FIELD (class_type_node, field, "loader", ptr_type_node); PUSH_FIELD (class_type_node, field, "loader", ptr_type_node);
......
...@@ -84,7 +84,6 @@ static tree build_java_check_indexed_type (tree, tree); ...@@ -84,7 +84,6 @@ static tree build_java_check_indexed_type (tree, tree);
static tree case_identity (tree, tree); static tree case_identity (tree, tree);
static unsigned char peek_opcode_at_pc (struct JCF *, int, int); static unsigned char peek_opcode_at_pc (struct JCF *, int, int);
static int emit_init_test_initialization (void **entry, void * ptr); static int emit_init_test_initialization (void **entry, void * ptr);
static int get_offset_table_index (tree);
static GTY(()) tree operand_type[59]; static GTY(()) tree operand_type[59];
...@@ -1510,6 +1509,25 @@ build_field_ref (tree self_value, tree self_class, tree name) ...@@ -1510,6 +1509,25 @@ build_field_ref (tree self_value, tree self_class, tree name)
tree base_type = promote_type (base_class); tree base_type = promote_type (base_class);
if (base_type != TREE_TYPE (self_value)) if (base_type != TREE_TYPE (self_value))
self_value = fold (build1 (NOP_EXPR, base_type, self_value)); self_value = fold (build1 (NOP_EXPR, base_type, self_value));
if (flag_indirect_dispatch
&& current_class != self_class)
/* FIXME: current_class != self_class is not exactly the right
test. What we really want to know is whether self_class is
in the same translation unit as current_class. If it is,
we can make a direct reference. */
{
tree otable_index
= build_int_2
(get_symbol_table_index (field_decl, &otable_methods), 0);
tree field_offset = build (ARRAY_REF, integer_type_node, otable_decl,
otable_index);
tree address
= fold (build (PLUS_EXPR,
build_pointer_type (TREE_TYPE (field_decl)),
self_value, field_offset));
return fold (build1 (INDIRECT_REF, TREE_TYPE (field_decl), address));
}
self_value = build_java_indirect_ref (TREE_TYPE (TREE_TYPE (self_value)), self_value = build_java_indirect_ref (TREE_TYPE (TREE_TYPE (self_value)),
self_value, check); self_value, check);
return fold (build (COMPONENT_REF, TREE_TYPE (field_decl), return fold (build (COMPONENT_REF, TREE_TYPE (field_decl),
...@@ -1744,11 +1762,22 @@ build_known_method_ref (tree method, tree method_type ATTRIBUTE_UNUSED, ...@@ -1744,11 +1762,22 @@ build_known_method_ref (tree method, tree method_type ATTRIBUTE_UNUSED,
tree func; tree func;
if (is_compiled_class (self_type)) if (is_compiled_class (self_type))
{ {
if (!flag_indirect_dispatch
|| (!TREE_PUBLIC (method) && DECL_CONTEXT (method)))
{
make_decl_rtl (method, NULL); make_decl_rtl (method, NULL);
func = build1 (ADDR_EXPR, method_ptr_type_node, method); func = build1 (ADDR_EXPR, method_ptr_type_node, method);
} }
else else
{ {
tree table_index = build_int_2 (get_symbol_table_index
(method, &atable_methods), 0);
func = build (ARRAY_REF, method_ptr_type_node, atable_decl,
table_index);
}
}
else
{
/* We don't know whether the method has been (statically) compiled. /* We don't know whether the method has been (statically) compiled.
Compile this code to get a reference to the method's code: Compile this code to get a reference to the method's code:
...@@ -1816,27 +1845,29 @@ invoke_build_dtable (int is_invoke_interface, tree arg_list) ...@@ -1816,27 +1845,29 @@ invoke_build_dtable (int is_invoke_interface, tree arg_list)
return dtable; return dtable;
} }
/* Determine the index in the virtual offset table (otable) for a call to /* Determine the index in SYMBOL_TABLE for a reference to the decl
METHOD. If this method has not been seen before, it will be added to the T. If this decl has not been seen before, it will be added to the
otable_methods. If it has, the existing otable slot will be reused. */ otable_methods. If it has, the existing table slot will be
reused. */
static int int
get_offset_table_index (tree method) get_symbol_table_index (tree t, tree *symbol_table)
{ {
int i = 1; int i = 1;
tree method_list; tree method_list;
if (otable_methods == NULL_TREE) if (*symbol_table == NULL_TREE)
{ {
otable_methods = build_tree_list (method, method); *symbol_table = build_tree_list (t, t);
return 1; return 1;
} }
method_list = otable_methods; method_list = *symbol_table;
while (1) while (1)
{ {
if (TREE_VALUE (method_list) == method) tree value = TREE_VALUE (method_list);
if (value == t)
return i; return i;
i++; i++;
if (TREE_CHAIN (method_list) == NULL_TREE) if (TREE_CHAIN (method_list) == NULL_TREE)
...@@ -1845,7 +1876,7 @@ get_offset_table_index (tree method) ...@@ -1845,7 +1876,7 @@ get_offset_table_index (tree method)
method_list = TREE_CHAIN (method_list); method_list = TREE_CHAIN (method_list);
} }
TREE_CHAIN (method_list) = build_tree_list (method, method); TREE_CHAIN (method_list) = build_tree_list (t, t);
return i; return i;
} }
...@@ -1860,7 +1891,8 @@ build_invokevirtual (tree dtable, tree method) ...@@ -1860,7 +1891,8 @@ build_invokevirtual (tree dtable, tree method)
if (flag_indirect_dispatch) if (flag_indirect_dispatch)
{ {
otable_index = build_int_2 (get_offset_table_index (method), 0); otable_index
= build_int_2 (get_symbol_table_index (method, &otable_methods), 0);
method_index = build (ARRAY_REF, integer_type_node, otable_decl, method_index = build (ARRAY_REF, integer_type_node, otable_decl,
otable_index); otable_index);
} }
...@@ -1924,7 +1956,8 @@ build_invokeinterface (tree dtable, tree method) ...@@ -1924,7 +1956,8 @@ build_invokeinterface (tree dtable, tree method)
if (flag_indirect_dispatch) if (flag_indirect_dispatch)
{ {
otable_index = build_int_2 (get_offset_table_index (method), 0); otable_index
= build_int_2 (get_symbol_table_index (method, &otable_methods), 0);
idx = build (ARRAY_REF, integer_type_node, otable_decl, otable_index); idx = build (ARRAY_REF, integer_type_node, otable_decl, otable_index);
} }
else else
......
...@@ -146,17 +146,26 @@ extern int compiling_from_source; ...@@ -146,17 +146,26 @@ extern int compiling_from_source;
/* List of all class filenames seen so far. */ /* List of all class filenames seen so far. */
#define all_class_filename java_global_trees [JTI_ALL_CLASS_FILENAME] #define all_class_filename java_global_trees [JTI_ALL_CLASS_FILENAME]
/* List of virtual method decls called in this translation unit, used to /* List of virtual decls referred to by this translation unit, used to
generate virtual method offset symbol table. */ generate virtual method offset symbol table. */
#define otable_methods java_global_trees [JTI_OTABLE_METHODS] #define otable_methods java_global_trees [JTI_OTABLE_METHODS]
/* List of static decls referred to by this translation unit, used to
generate virtual method offset symbol table. */
#define atable_methods java_global_trees [JTI_ATABLE_METHODS]
/* The virtual method offset table. This is emitted as uninitialized data of /* The virtual offset table. This is emitted as uninitialized data of
the required length, and filled out at run time during class linking. */ the required length, and filled out at run time during class
linking. */
#define otable_decl java_global_trees [JTI_OTABLE_DECL] #define otable_decl java_global_trees [JTI_OTABLE_DECL]
/* The static address table. */
#define atable_decl java_global_trees [JTI_ATABLE_DECL]
/* The virtual method offset symbol table. Used by the runtime to fill out the /* The virtual offset symbol table. Used by the runtime to fill out
otable. */ the otable. */
#define otable_syms_decl java_global_trees [JTI_OTABLE_SYMS_DECL] #define otable_syms_decl java_global_trees [JTI_OTABLE_SYMS_DECL]
/* The static symbol table. Used by the runtime to fill out the
otable. */
#define atable_syms_decl java_global_trees [JTI_ATABLE_SYMS_DECL]
extern int flag_emit_class_files; extern int flag_emit_class_files;
...@@ -364,9 +373,11 @@ enum java_tree_index ...@@ -364,9 +373,11 @@ enum java_tree_index
JTI_METHOD_PTR_TYPE_NODE, JTI_METHOD_PTR_TYPE_NODE,
JTI_OTABLE_TYPE, JTI_OTABLE_TYPE,
JTI_OTABLE_PTR_TYPE, JTI_OTABLE_PTR_TYPE,
JTI_METHOD_SYMBOL_TYPE, JTI_ATABLE_TYPE,
JTI_METHOD_SYMBOLS_ARRAY_TYPE, JTI_ATABLE_PTR_TYPE,
JTI_METHOD_SYMBOLS_ARRAY_PTR_TYPE, JTI_SYMBOL_TYPE,
JTI_SYMBOLS_ARRAY_TYPE,
JTI_SYMBOLS_ARRAY_PTR_TYPE,
JTI_END_PARAMS_NODE, JTI_END_PARAMS_NODE,
...@@ -409,6 +420,10 @@ enum java_tree_index ...@@ -409,6 +420,10 @@ enum java_tree_index
JTI_OTABLE_DECL, JTI_OTABLE_DECL,
JTI_OTABLE_SYMS_DECL, JTI_OTABLE_SYMS_DECL,
JTI_ATABLE_METHODS,
JTI_ATABLE_DECL,
JTI_ATABLE_SYMS_DECL,
JTI_PREDEF_FILENAMES, JTI_PREDEF_FILENAMES,
JTI_MAX JTI_MAX
...@@ -602,14 +617,18 @@ extern GTY(()) tree java_global_trees[JTI_MAX]; ...@@ -602,14 +617,18 @@ extern GTY(()) tree java_global_trees[JTI_MAX];
java_global_trees[JTI_METHOD_PTR_TYPE_NODE] java_global_trees[JTI_METHOD_PTR_TYPE_NODE]
#define otable_type \ #define otable_type \
java_global_trees[JTI_OTABLE_TYPE] java_global_trees[JTI_OTABLE_TYPE]
#define atable_type \
java_global_trees[JTI_ATABLE_TYPE]
#define otable_ptr_type \ #define otable_ptr_type \
java_global_trees[JTI_OTABLE_PTR_TYPE] java_global_trees[JTI_OTABLE_PTR_TYPE]
#define method_symbol_type \ #define atable_ptr_type \
java_global_trees[JTI_METHOD_SYMBOL_TYPE] java_global_trees[JTI_ATABLE_PTR_TYPE]
#define method_symbols_array_type \ #define symbol_type \
java_global_trees[JTI_METHOD_SYMBOLS_ARRAY_TYPE] java_global_trees[JTI_SYMBOL_TYPE]
#define method_symbols_array_ptr_type \ #define symbols_array_type \
java_global_trees[JTI_METHOD_SYMBOLS_ARRAY_PTR_TYPE] java_global_trees[JTI_SYMBOLS_ARRAY_TYPE]
#define symbols_array_ptr_type \
java_global_trees[JTI_SYMBOLS_ARRAY_PTR_TYPE]
#define end_params_node \ #define end_params_node \
java_global_trees[JTI_END_PARAMS_NODE] java_global_trees[JTI_END_PARAMS_NODE]
...@@ -1199,7 +1218,7 @@ extern void make_class_data (tree); ...@@ -1199,7 +1218,7 @@ extern void make_class_data (tree);
extern void register_class (void); extern void register_class (void);
extern int alloc_name_constant (int, tree); extern int alloc_name_constant (int, tree);
extern void emit_register_classes (void); extern void emit_register_classes (void);
extern void emit_offset_symbol_table (void); extern tree emit_symbol_table (tree, tree, tree, tree, tree);
extern void lang_init_source (int); extern void lang_init_source (int);
extern void write_classfile (tree); extern void write_classfile (tree);
extern char *print_int_node (tree); extern char *print_int_node (tree);
...@@ -1299,6 +1318,7 @@ extern void init_resource_processing (void); ...@@ -1299,6 +1318,7 @@ extern void init_resource_processing (void);
extern void start_complete_expand_method (tree); extern void start_complete_expand_method (tree);
extern void java_expand_body (tree); extern void java_expand_body (tree);
extern int get_symbol_table_index (tree, tree *);
#define DECL_FINAL(DECL) DECL_LANG_FLAG_3 (DECL) #define DECL_FINAL(DECL) DECL_LANG_FLAG_3 (DECL)
...@@ -1658,7 +1678,7 @@ extern tree *type_map; ...@@ -1658,7 +1678,7 @@ extern tree *type_map;
/* Append a field initializer to CONS for a field with the given VALUE. /* Append a field initializer to CONS for a field with the given VALUE.
NAME is a char* string used for error checking; NAME is a char* string used for error checking;
the initializer must be specified in order. */ the initializer must be specified in order. */
#define PUSH_FIELD_VALUE(CONS, NAME, VALUE) {\ #define PUSH_FIELD_VALUE(CONS, NAME, VALUE) {\
tree field = TREE_CHAIN(CONS);\ tree field = TREE_CHAIN(CONS);\
if (strcmp (IDENTIFIER_POINTER (DECL_NAME (field)), NAME) != 0) abort();\ if (strcmp (IDENTIFIER_POINTER (DECL_NAME (field)), NAME) != 0) abort();\
CONSTRUCTOR_ELTS(CONS) = tree_cons (field, VALUE, CONSTRUCTOR_ELTS(CONS));\ CONSTRUCTOR_ELTS(CONS) = tree_cons (field, VALUE, CONSTRUCTOR_ELTS(CONS));\
......
...@@ -1127,7 +1127,16 @@ java_parse_file (int set_yydebug ATTRIBUTE_UNUSED) ...@@ -1127,7 +1127,16 @@ java_parse_file (int set_yydebug ATTRIBUTE_UNUSED)
/* Emit the .jcf section. */ /* Emit the .jcf section. */
emit_register_classes (); emit_register_classes ();
if (flag_indirect_dispatch) if (flag_indirect_dispatch)
emit_offset_symbol_table (); {
otable_decl
= emit_symbol_table
(get_identifier ("otable"),
otable_decl, otable_methods, otable_syms_decl, integer_type_node);
atable_decl
= emit_symbol_table
(get_identifier ("atable"),
atable_decl, atable_methods, atable_syms_decl, ptr_type_node);
}
} }
write_resource_constructor (); write_resource_constructor ();
......
2003-10-01 Andrew Haley <aph@redhat.com>
* java/lang/natClass.cc (initializeClass): Check for otable and
atable.
(_Jv_LinkOffsetTable): Check for existence of atable. Rewrite
loops using for(). Search superinterfaces. Check for fields as
well as methods. Initialize atable as well as otable: check for
static methods as well as virtual methods.
* java/lang/Class.h (struct _Jv_AddressTable): New.
(atable): New.
(atable_syms): New.
* include/jvm.h (_Jv_equalUtf8Consts): constify.
* prims.cc (_Jv_equalUtf8Consts): constify.
2003-09-29 Tom Tromey <tromey@redhat.com> 2003-09-29 Tom Tromey <tromey@redhat.com>
PR libgcj/10596: PR libgcj/10596:
......
...@@ -145,7 +145,7 @@ extern int _Jv_strLengthUtf8(char* str, int len); ...@@ -145,7 +145,7 @@ extern int _Jv_strLengthUtf8(char* str, int len);
typedef struct _Jv_Utf8Const Utf8Const; typedef struct _Jv_Utf8Const Utf8Const;
_Jv_Utf8Const *_Jv_makeUtf8Const (char *s, int len); _Jv_Utf8Const *_Jv_makeUtf8Const (char *s, int len);
_Jv_Utf8Const *_Jv_makeUtf8Const (jstring string); _Jv_Utf8Const *_Jv_makeUtf8Const (jstring string);
extern jboolean _Jv_equalUtf8Consts (_Jv_Utf8Const *, _Jv_Utf8Const *); extern jboolean _Jv_equalUtf8Consts (const _Jv_Utf8Const *, const _Jv_Utf8Const *);
extern jboolean _Jv_equal (_Jv_Utf8Const *, jstring, jint); extern jboolean _Jv_equal (_Jv_Utf8Const *, jstring, jint);
extern jboolean _Jv_equaln (_Jv_Utf8Const *, jstring, jint); extern jboolean _Jv_equaln (_Jv_Utf8Const *, jstring, jint);
......
...@@ -125,6 +125,12 @@ struct _Jv_OffsetTable ...@@ -125,6 +125,12 @@ struct _Jv_OffsetTable
jint offsets[]; jint offsets[];
}; };
struct _Jv_AddressTable
{
jint state;
void *addresses[];
};
#define JV_PRIMITIVE_VTABLE ((_Jv_VTable *) -1) #define JV_PRIMITIVE_VTABLE ((_Jv_VTable *) -1)
#define JV_CLASS(Obj) ((jclass) (*(_Jv_VTable **) Obj)->clas) #define JV_CLASS(Obj) ((jclass) (*(_Jv_VTable **) Obj)->clas)
...@@ -324,7 +330,7 @@ private: ...@@ -324,7 +330,7 @@ private:
friend jstring _Jv_GetMethodString(jclass, _Jv_Utf8Const *); friend jstring _Jv_GetMethodString(jclass, _Jv_Utf8Const *);
friend jshort _Jv_AppendPartialITable (jclass, jclass, void **, jshort); friend jshort _Jv_AppendPartialITable (jclass, jclass, void **, jshort);
friend jshort _Jv_FindIIndex (jclass *, jshort *, jshort); friend jshort _Jv_FindIIndex (jclass *, jshort *, jshort);
friend void _Jv_LinkOffsetTable (jclass); friend void _Jv_LinkSymbolTable (jclass);
friend void _Jv_LayoutVTableMethods (jclass klass); friend void _Jv_LayoutVTableMethods (jclass klass);
friend void _Jv_SetVTableEntries (jclass, _Jv_VTable *, jboolean *); friend void _Jv_SetVTableEntries (jclass, _Jv_VTable *, jboolean *);
friend void _Jv_MakeVTable (jclass); friend void _Jv_MakeVTable (jclass);
...@@ -404,6 +410,8 @@ private: ...@@ -404,6 +410,8 @@ private:
_Jv_OffsetTable *otable; _Jv_OffsetTable *otable;
// Offset table symbols. // Offset table symbols.
_Jv_MethodSymbol *otable_syms; _Jv_MethodSymbol *otable_syms;
_Jv_AddressTable *atable;
_Jv_MethodSymbol *atable_syms;
// Interfaces implemented by this class. // Interfaces implemented by this class.
jclass *interfaces; jclass *interfaces;
// The class loader for this class. // The class loader for this class.
......
...@@ -36,6 +36,7 @@ details. */ ...@@ -36,6 +36,7 @@ details. */
#include <java/lang/IllegalAccessError.h> #include <java/lang/IllegalAccessError.h>
#include <java/lang/IllegalArgumentException.h> #include <java/lang/IllegalArgumentException.h>
#include <java/lang/IncompatibleClassChangeError.h> #include <java/lang/IncompatibleClassChangeError.h>
#include <java/lang/NoSuchFieldError.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h> #include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <java/lang/InstantiationException.h> #include <java/lang/InstantiationException.h>
#include <java/lang/NoClassDefFoundError.h> #include <java/lang/NoClassDefFoundError.h>
...@@ -790,7 +791,7 @@ java::lang::Class::initializeClass (void) ...@@ -790,7 +791,7 @@ java::lang::Class::initializeClass (void)
so ensure internal tables are built. */ so ensure internal tables are built. */
_Jv_PrepareConstantTimeTables (this); _Jv_PrepareConstantTimeTables (this);
_Jv_MakeVTable(this); _Jv_MakeVTable(this);
_Jv_LinkOffsetTable(this); _Jv_LinkSymbolTable(this);
return; return;
} }
...@@ -830,8 +831,8 @@ java::lang::Class::initializeClass (void) ...@@ -830,8 +831,8 @@ java::lang::Class::initializeClass (void)
if (vtable == NULL) if (vtable == NULL)
_Jv_MakeVTable(this); _Jv_MakeVTable(this);
if (otable != NULL && otable->state == 0) if (otable || atable)
_Jv_LinkOffsetTable(this); _Jv_LinkSymbolTable(this);
// Steps 8, 9, 10, 11. // Steps 8, 9, 10, 11.
try try
...@@ -1533,50 +1534,77 @@ java::lang::Class::getProtectionDomain0 () ...@@ -1533,50 +1534,77 @@ java::lang::Class::getProtectionDomain0 ()
return protectionDomain; return protectionDomain;
} }
// Functions for indirect dispatch (symbolic virtual method binding) support. // Functions for indirect dispatch (symbolic virtual binding) support.
// There are two tables, atable and otable. atable is an array of
// addresses, and otable is an array of offsets, and these are used
// for static and virtual members respectively.
// {a,o}table_syms is an array of _Jv_MethodSymbols. Each such symbol
// is a tuple of {classname, member name, signature}.
// _Jv_LinkSymbolTable() scans these two arrays and fills in the
// corresponding atable and otable with the addresses of static
// members and the offsets of virtual members.
// The offset (in bytes) for each resolved method or field is placed
// at the corresponding position in the virtual method offset table
// (klass->otable).
// The same otable and atable may be shared by many classes.
// Resolve entries in the virtual method offset symbol table
// (klass->otable_syms). The vtable offset (in bytes) for each resolved method
// is placed at the corresponding position in the virtual method offset table
// (klass->otable). A single otable and otable_syms pair may be shared by many
// classes.
void void
_Jv_LinkOffsetTable(jclass klass) _Jv_LinkSymbolTable(jclass klass)
{ {
//// FIXME: Need to lock the otable //// //// FIXME: Need to lock the tables ////
int index = 0;
_Jv_MethodSymbol sym;
if (klass->otable == NULL if (klass->otable == NULL
|| klass->otable->state != 0) || klass->otable->state != 0)
return; goto atable;
klass->otable->state = 1; klass->otable->state = 1;
int index = 0; for (index = 0; sym = klass->otable_syms[index], sym.name != NULL; index++)
_Jv_MethodSymbol sym = klass->otable_syms[0];
while (sym.name != NULL)
{ {
jclass target_class = _Jv_FindClass (sym.class_name, NULL); jclass target_class = _Jv_FindClass (sym.class_name, NULL);
_Jv_Method *meth = NULL; _Jv_Method *meth = NULL;
if (target_class != NULL) const _Jv_Utf8Const *signature = sym.signature;
// FIXME: This should be special index for ThrowNoSuchMethod().
klass->otable->offsets[index] = -1;
if (target_class == NULL)
continue;
if (target_class->isInterface()) if (target_class->isInterface())
{ {
// FIXME: This does not yet fully conform to binary compatibility // FIXME: This does not yet fully conform to binary compatibility
// rules. It will break if a declaration is moved into a // rules. It will break if a declaration is moved into a
// superinterface. // superinterface.
for (int i=0; i < target_class->method_count; i++) for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
{
for (int i=0; i < cls->method_count; i++)
{ {
meth = &target_class->methods[i]; meth = &cls->methods[i];
if (_Jv_equalUtf8Consts (sym.name, meth->name) if (_Jv_equalUtf8Consts (sym.name, meth->name)
&& _Jv_equalUtf8Consts (sym.signature, meth->signature)) && _Jv_equalUtf8Consts (signature, meth->signature))
{ {
klass->otable->offsets[index] = i + 1; klass->otable->offsets[index] = i + 1;
break; goto found;
} }
} }
} }
else found:
continue;
}
// We're looking for a field or a method, and we can tell
// which is needed by looking at the signature.
if (signature->length >= 2
&& signature->data[0] == '(')
{ {
// If the target class does not have a vtable_method_count yet, // If the target class does not have a vtable_method_count yet,
// then we can't tell the offsets for its methods, so we must lay // then we can't tell the offsets for its methods, so we must lay
...@@ -1595,13 +1623,149 @@ _Jv_LinkOffsetTable(jclass klass) ...@@ -1595,13 +1623,149 @@ _Jv_LinkOffsetTable(jclass klass)
klass->otable->offsets[index] = klass->otable->offsets[index] =
_Jv_VTable::idx_to_offset (meth->index); _Jv_VTable::idx_to_offset (meth->index);
} }
continue;
} }
if (meth == NULL) // try fields
// FIXME: This should be special index for ThrowNoSuchMethod(). {
klass->otable->offsets[index] = -1; _Jv_Field *the_field = NULL;
for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
{
for (int i = 0; i < cls->field_count; i++)
{
_Jv_Field *field = &cls->fields[i];
if (! _Jv_equalUtf8Consts (field->name, sym.name))
continue;
// FIXME: What access checks should we perform here?
// if (_Jv_CheckAccess (klass, cls, field->flags))
// {
if (!field->isResolved ())
_Jv_ResolveField (field, cls->loader);
// if (field_type != 0 && field->type != field_type)
// throw new java::lang::LinkageError
// (JvNewStringLatin1
// ("field type mismatch with different loaders"));
the_field = field;
goto end_of_field_search;
}
}
end_of_field_search:
if (the_field != NULL)
{
if (the_field->flags & 0x0008 /* Modifier::STATIC */)
{
throw new java::lang::IncompatibleClassChangeError;
}
else
{
klass->otable->offsets[index] = the_field->u.boffset;
}
}
else
{
throw new java::lang::NoSuchFieldError
(_Jv_NewStringUtf8Const (sym.name));
}
}
}
sym = klass->otable_syms[++index]; atable:
if (klass->atable == NULL
|| klass->atable->state != 0)
return;
klass->atable->state = 1;
for (index = 0; sym = klass->atable_syms[index], sym.name != NULL; index++)
{
jclass target_class = _Jv_FindClass (sym.class_name, NULL);
_Jv_Method *meth = NULL;
const _Jv_Utf8Const *signature = sym.signature;
// ??? Setting this pointer to null will at least get us a
// NullPointerException
klass->atable->addresses[index] = NULL;
if (target_class == NULL)
continue;
// We're looking for a static field or a static method, and we
// can tell which is needed by looking at the signature.
if (signature->length >= 2
&& signature->data[0] == '(')
{
// If the target class does not have a vtable_method_count yet,
// then we can't tell the offsets for its methods, so we must lay
// it out now.
if (target_class->vtable_method_count == -1)
{
JvSynchronize sync (target_class);
_Jv_LayoutVTableMethods (target_class);
}
meth = _Jv_LookupDeclaredMethod(target_class, sym.name,
sym.signature);
if (meth != NULL)
klass->atable->addresses[index] = meth->ncode;
else
klass->atable->addresses[index] = (void *)_Jv_ThrowNoSuchMethodError;
continue;
}
// try fields
{
_Jv_Field *the_field = NULL;
for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
{
for (int i = 0; i < cls->field_count; i++)
{
_Jv_Field *field = &cls->fields[i];
if (! _Jv_equalUtf8Consts (field->name, sym.name))
continue;
// FIXME: What access checks should we perform here?
// if (_Jv_CheckAccess (klass, cls, field->flags))
// {
if (!field->isResolved ())
_Jv_ResolveField (field, cls->loader);
// if (field_type != 0 && field->type != field_type)
// throw new java::lang::LinkageError
// (JvNewStringLatin1
// ("field type mismatch with different loaders"));
the_field = field;
goto end_of_static_field_search;
}
}
end_of_static_field_search:
if (the_field != NULL)
{
if (the_field->flags & 0x0008 /* Modifier::STATIC */)
{
klass->atable->addresses[index] = the_field->u.addr;
}
else
{
throw new java::lang::IncompatibleClassChangeError;
}
}
else
{
throw new java::lang::NoSuchFieldError
(_Jv_NewStringUtf8Const (sym.name));
}
}
} }
} }
......
/* LinkedList.java -- Linked list implementation of the List interface /* LinkedList.java -- Linked list implementation of the List interface
Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath. This file is part of GNU Classpath.
......
...@@ -165,10 +165,10 @@ SIGNAL_HANDLER (catch_fpe) ...@@ -165,10 +165,10 @@ SIGNAL_HANDLER (catch_fpe)
jboolean jboolean
_Jv_equalUtf8Consts (Utf8Const* a, Utf8Const *b) _Jv_equalUtf8Consts (const Utf8Const* a, const Utf8Const *b)
{ {
int len; int len;
_Jv_ushort *aptr, *bptr; const _Jv_ushort *aptr, *bptr;
if (a == b) if (a == b)
return true; return true;
if (a->hash != b->hash) if (a->hash != b->hash)
...@@ -176,8 +176,8 @@ _Jv_equalUtf8Consts (Utf8Const* a, Utf8Const *b) ...@@ -176,8 +176,8 @@ _Jv_equalUtf8Consts (Utf8Const* a, Utf8Const *b)
len = a->length; len = a->length;
if (b->length != len) if (b->length != len)
return false; return false;
aptr = (_Jv_ushort *)a->data; aptr = (const _Jv_ushort *)a->data;
bptr = (_Jv_ushort *)b->data; bptr = (const _Jv_ushort *)b->data;
len = (len + 1) >> 1; len = (len + 1) >> 1;
while (--len >= 0) while (--len >= 0)
if (*aptr++ != *bptr++) if (*aptr++ != *bptr++)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment