mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
530ce5517c
commit
9dfc2ec225
|
@ -1,3 +1,29 @@
|
||||||
|
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
|
||||||
|
|
116
gcc/java/class.c
116
gcc/java/class.c
|
@ -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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
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)
|
||||||
: 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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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)
|
||||||
|
|
||||||
/* 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)
|
||||||
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)
|
||||||
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);
|
||||||
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)
|
||||||
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,8 +1762,19 @@ 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))
|
||||||
{
|
{
|
||||||
make_decl_rtl (method, NULL);
|
if (!flag_indirect_dispatch
|
||||||
func = build1 (ADDR_EXPR, method_ptr_type_node, method);
|
|| (!TREE_PUBLIC (method) && DECL_CONTEXT (method)))
|
||||||
|
{
|
||||||
|
make_decl_rtl (method, NULL);
|
||||||
|
func = build1 (ADDR_EXPR, method_ptr_type_node, method);
|
||||||
|
}
|
||||||
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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;
|
||||||
/* 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
|
||||||
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
|
||||||
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];
|
||||||
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);
|
||||||
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);
|
||||||
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,11 +1678,11 @@ 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));\
|
||||||
TREE_CHAIN(CONS) = TREE_CHAIN (field); }
|
TREE_CHAIN(CONS) = TREE_CHAIN (field); }
|
||||||
|
|
||||||
/* Finish creating a record CONSTRUCTOR CONS. */
|
/* Finish creating a record CONSTRUCTOR CONS. */
|
||||||
#define FINISH_RECORD_CONSTRUCTOR(CONS) \
|
#define FINISH_RECORD_CONSTRUCTOR(CONS) \
|
||||||
|
|
|
@ -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 ();
|
||||||
|
|
|
@ -1,3 +1,17 @@
|
||||||
|
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);
|
||||||
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
|
||||||
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:
|
||||||
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:
|
||||||
_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. */
|
||||||
#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)
|
||||||
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)
|
||||||
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,75 +1534,238 @@ 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;
|
||||||
if (target_class->isInterface())
|
|
||||||
|
// FIXME: This should be special index for ThrowNoSuchMethod().
|
||||||
|
klass->otable->offsets[index] = -1;
|
||||||
|
|
||||||
|
if (target_class == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (target_class->isInterface())
|
||||||
|
{
|
||||||
|
// FIXME: This does not yet fully conform to binary compatibility
|
||||||
|
// rules. It will break if a declaration is moved into a
|
||||||
|
// superinterface.
|
||||||
|
for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
|
||||||
|
{
|
||||||
|
for (int i=0; i < cls->method_count; i++)
|
||||||
|
{
|
||||||
|
meth = &cls->methods[i];
|
||||||
|
if (_Jv_equalUtf8Consts (sym.name, meth->name)
|
||||||
|
&& _Jv_equalUtf8Consts (signature, meth->signature))
|
||||||
|
{
|
||||||
|
klass->otable->offsets[index] = i + 1;
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
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,
|
||||||
|
// 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->otable->offsets[index] =
|
||||||
|
_Jv_VTable::idx_to_offset (meth->index);
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// try fields
|
||||||
|
{
|
||||||
|
_Jv_Field *the_field = NULL;
|
||||||
|
|
||||||
|
for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
|
||||||
{
|
{
|
||||||
// FIXME: This does not yet fully conform to binary compatibility
|
for (int i = 0; i < cls->field_count; i++)
|
||||||
// rules. It will break if a declaration is moved into a
|
|
||||||
// superinterface.
|
|
||||||
for (int i=0; i < target_class->method_count; i++)
|
|
||||||
{
|
{
|
||||||
meth = &target_class->methods[i];
|
_Jv_Field *field = &cls->fields[i];
|
||||||
if (_Jv_equalUtf8Consts (sym.name, meth->name)
|
if (! _Jv_equalUtf8Consts (field->name, sym.name))
|
||||||
&& _Jv_equalUtf8Consts (sym.signature, meth->signature))
|
continue;
|
||||||
{
|
|
||||||
klass->otable->offsets[index] = i + 1;
|
// FIXME: What access checks should we perform here?
|
||||||
break;
|
// 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
|
else
|
||||||
{
|
{
|
||||||
// If the target class does not have a vtable_method_count yet,
|
throw new java::lang::NoSuchFieldError
|
||||||
// then we can't tell the offsets for its methods, so we must lay
|
(_Jv_NewStringUtf8Const (sym.name));
|
||||||
// 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,
|
atable:
|
||||||
sym.signature);
|
if (klass->atable == NULL
|
||||||
|
|| klass->atable->state != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
if (meth != NULL)
|
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++)
|
||||||
{
|
{
|
||||||
klass->otable->offsets[index] =
|
_Jv_Field *field = &cls->fields[i];
|
||||||
_Jv_VTable::idx_to_offset (meth->index);
|
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 (meth == NULL)
|
if (the_field != NULL)
|
||||||
// FIXME: This should be special index for ThrowNoSuchMethod().
|
{
|
||||||
klass->otable->offsets[index] = -1;
|
if (the_field->flags & 0x0008 /* Modifier::STATIC */)
|
||||||
|
{
|
||||||
sym = klass->otable_syms[++index];
|
klass->atable->addresses[index] = the_field->u.addr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new java::lang::IncompatibleClassChangeError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new java::lang::NoSuchFieldError
|
||||||
|
(_Jv_NewStringUtf8Const (sym.name));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* 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)
|
||||||
|
|
||||||
|
|
||||||
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)
|
||||||
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++)
|
||||||
|
|
Loading…
Reference in New Issue