This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: PR java/12760 [BC ABI] Re-enable fast interface dispatch
Bryce McKinlay writes:
> Andrew Haley wrote:
>
> >This allows BC-compiled programs to use fast interface dispatch, with
> >full binary compatibility. It uses two atable slots for each call,
> >one for the interface and one for the index. Runtime patch to follow.
> >
> >
> Cool, thanks for fixing that.
>
> >It's a little space inefficient in that it wastes a dummy symbol table
> >entry for each interface referenced. The problem here is that our
> >current symbol table design doesn't seem to have any way to indicate
> >whether we're looking for an interface or a class.
> >
> >
> Perhaps we should make another table ("iotable" ?) for interface references?
Done. Works with full rebuild of JOnAS, passes basic tests.
Andrew.
2004-09-10 Andrew Haley <aph@redhat.com>
* expr.c (build_invokeinterface): Use fast method for interface
dispatch.
* java-tree.h (enum java_tree_index): Add JTI_ITABLE_TYPE,
JTI_ITABLE_PTR_TYPE.
(struct lang_type): Add itable_methods, itable_decl, itable_syms_decl.
(emit_symbol_table): Add new arg, element_size.
* decl.c (java_init_decl_processing): Initialize Class.itable.
* class.c (GEN_TABLE): New macro.
(gen_indirect_dispatch_tables): Use it. Add itable.
(make_class_data): Add new arg for emit_symbol_table().
Emit itable.
(add_miranda_methods): Make sure search_class has been parsed.
(emit_symbol_table): Add new arg, element_size.
2004-09-10 Andrew Haley <aph@redhat.com>
* java/lang/Class.h (_Jv_getInterfaceMethod(): new friend.
* java/lang/natClass.cc (initializeClass): Check itable.
(_Jv_getInterfaceMethod): New.
(_Jv_LinkSymbolTable): Rewrite code that handles inerface calls.
Check that an interface method isn't called with invokevirtual.
* java/lang/natClass.cc (_Jv_LayoutVTableMethods): Make sure
super_meth is virtual.
Index: libjava/java/lang/Class.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/Class.h,v
retrieving revision 1.63.12.7
diff -p -2 -c -r1.63.12.7 Class.h
*** libjava/java/lang/Class.h 27 Aug 2004 19:54:23 -0000 1.63.12.7
--- libjava/java/lang/Class.h 10 Sep 2004 16:18:32 -0000
*************** private:
*** 376,379 ****
--- 376,381 ----
friend bool _Jv_isBinaryCompatible (jclass);
+ friend bool _Jv_getInterfaceMethod(jclass, jclass&, int&,
+ const _Jv_Utf8Const*, const _Jv_Utf8Const*);
// Return array class corresponding to element type KLASS, creating it if
*************** private:
*** 451,456 ****
--- 453,462 ----
// Offset table symbols.
_Jv_MethodSymbol *otable_syms;
+ // Address table
_Jv_AddressTable *atable;
_Jv_MethodSymbol *atable_syms;
+ // Interface table
+ _Jv_AddressTable *itable;
+ _Jv_MethodSymbol *itable_syms;
_Jv_CatchClass *catch_classes;
// Interfaces implemented by this class.
Index: libjava/java/lang/natClass.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natClass.cc,v
retrieving revision 1.75.2.11
diff -p -2 -c -r1.75.2.11 natClass.cc
*** libjava/java/lang/natClass.cc 30 Aug 2004 15:45:25 -0000 1.75.2.11
--- libjava/java/lang/natClass.cc 10 Sep 2004 16:18:33 -0000
*************** java::lang::Class::initializeClass (void
*** 878,882 ****
_Jv_MakeVTable(this);
! if (otable || atable)
_Jv_LinkSymbolTable(this);
--- 878,882 ----
_Jv_MakeVTable(this);
! if (otable || atable || itable)
_Jv_LinkSymbolTable(this);
*************** java::lang::Class::setSigners(JArray<job
*** 1677,1691 ****
}
! // Set this to true to enable debugging of indirect dispatch tables/linking.
! static bool debug_link = false;
// 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
--- 1677,1755 ----
}
!
! // Lookup an interface method by name. This is very similar to
! // purpose to _getMethod, but the interfaces are quite different. It
! // might be a good idea for _getMethod to call this function.
! //
! // Return true of the method is found, with the class in FOUND_CLASS
! // and the index in INDEX.
!
! bool
! _Jv_getInterfaceMethod (jclass search_class, jclass &found_class, int &index,
! const _Jv_Utf8Const *utf_name,
! const _Jv_Utf8Const *utf_sig)
! {
! for (jclass klass = search_class; klass; klass = klass->getSuperclass())
! {
! // FIXME: Throw an exception?
! if (!klass->isInterface ())
! return false;
!
! int i = klass->method_count;
! while (--i >= 0)
! {
! if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
! && _Jv_equalUtf8Consts (klass->methods[i].signature, utf_sig))
! {
! // Found it.
! using namespace java::lang::reflect;
!
! // FIXME: Method must be public. Throw an exception?
! if (! Modifier::isPublic (klass->methods[i].accflags))
! break;
!
! found_class = klass;
! // Interface method indexes count from 1.
! index = i+1;
! return true;
! }
! }
! }
!
! // If we haven't found a match, and this class is an interface, then
! // check all the superinterfaces.
! if (search_class->isInterface())
! {
! for (int i = 0; i < search_class->interface_count; ++i)
! {
! using namespace java::lang::reflect;
! bool found = _Jv_getInterfaceMethod (search_class->interfaces[i],
! found_class, index,
! utf_name, utf_sig);
! if (found)
! return true;
! }
! }
!
! return false;
! }
!
// Functions for indirect dispatch (symbolic virtual binding) support.
! // There are three tables, atable otable and itable. atable is an
! // array of addresses, and otable is an array of offsets, and these
! // are used for static and virtual members respectively. itable is an
! // array of pairs {address, index} where each address is a pointer to
! // an interface.
!
! // {a,o,i}table_syms is an array of _Jv_MethodSymbols. Each such
! // symbol is a tuple of {classname, member name, signature}.
!
!
! // Set this to true to enable debugging of indirect dispatch tables/linking.
! static bool debug_link = false;
!
// _Jv_LinkSymbolTable() scans these two arrays and fills in the
// corresponding atable and otable with the addresses of static
*************** _Jv_LinkSymbolTable(jclass klass)
*** 1713,1717 ****
if (debug_link)
fprintf (stderr, "Fixing up otable in %s:\n", klass->name->data);
! for (index = 0; sym = klass->otable_syms[index], sym.name != NULL; index++)
{
jclass target_class = _Jv_FindClass (sym.class_name, klass->loader);
--- 1777,1782 ----
if (debug_link)
fprintf (stderr, "Fixing up otable in %s:\n", klass->name->data);
! for (index = 0; sym = klass->otable_syms[index], sym.class_name != NULL;
! index++)
{
jclass target_class = _Jv_FindClass (sym.class_name, klass->loader);
*************** _Jv_LinkSymbolTable(jclass klass)
*** 1730,1764 ****
(_Jv_NewStringUTF (sym.class_name->data));
- 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;
- if (debug_link)
- fprintf (stderr, " offsets[%d] = %d (interface %s@%p : %s(%s))\n",
- index,
- klass->otable->offsets[index],
- (const char*)cls->name->data,
- klass,
- (const char*)sym.name->data,
- (const char*)signature->data);
- 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.
--- 1795,1798 ----
*************** _Jv_LinkSymbolTable(jclass klass)
*** 1766,1769 ****
--- 1800,1814 ----
&& signature->data[0] == '(')
{
+ // Looks like someone is trying to invoke an interface method
+ if (target_class->isInterface())
+ {
+ using namespace java::lang;
+ StringBuffer *sb = new StringBuffer();
+ sb->append(JvNewStringLatin1("found interface "));
+ sb->append(target_class->getName());
+ sb->append(JvNewStringLatin1(" when searching for a class"));
+ throw new VerifyError(sb->toString());
+ }
+
// 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
*************** _Jv_LinkSymbolTable(jclass klass)
*** 1862,1870 ****
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, klass->loader);
--- 1907,1916 ----
if (klass->atable == NULL
|| klass->atable->state != 0)
! goto itable;
klass->atable->state = 1;
! for (index = 0; sym = klass->atable_syms[index], sym.class_name != NULL;
! index++)
{
jclass target_class = _Jv_FindClass (sym.class_name, klass->loader);
*************** _Jv_LinkSymbolTable(jclass klass)
*** 1894,1897 ****
--- 1940,1954 ----
}
+ // Interface methods cannot have bodies.
+ if (target_class->isInterface())
+ {
+ using namespace java::lang;
+ StringBuffer *sb = new StringBuffer();
+ sb->append(JvNewStringLatin1("class "));
+ sb->append(target_class->getName());
+ sb->append(JvNewStringLatin1(" is an interface: class expected"));
+ throw new VerifyError(sb->toString());
+ }
+
meth = _Jv_LookupDeclaredMethod(target_class, sym.name,
sym.signature);
*************** _Jv_LinkSymbolTable(jclass klass)
*** 1999,2002 ****
--- 2056,2102 ----
}
}
+
+ itable:
+ if (klass->itable == NULL
+ || klass->itable->state != 0)
+ return;
+
+ klass->itable->state = 1;
+
+ for (index = 0; sym = klass->itable_syms[index], sym.class_name != NULL;
+ index++)
+ {
+ jclass target_class = _Jv_FindClass (sym.class_name, klass->loader);
+ const _Jv_Utf8Const *signature = sym.signature;
+
+ jclass cls;
+ int i;
+
+ bool found
+ = _Jv_getInterfaceMethod (target_class, cls, i, sym.name, sym.signature);
+
+ if (found)
+ {
+ klass->itable->addresses[index*2] = cls;
+ klass->itable->addresses[index*2 + 1] = (void*)i;
+ if (debug_link)
+ {
+ fprintf (stderr, " interfaces[%d] = %p (interface %s@%p : %s(%s))\n",
+ index,
+ klass->itable->addresses[index*2],
+ (const char*)cls->name->data,
+ cls,
+ (const char*)sym.name->data,
+ (const char*)signature->data);
+ fprintf (stderr, " [%d] = offset %d\n",
+ index + 1,
+ (int)klass->itable->addresses[index*2 + 1]);
+ }
+
+ }
+ else
+ throw new java::lang::IncompatibleClassChangeError;
+ }
+
}
*************** _Jv_LayoutVTableMethods (jclass klass)
*** 2091,2095 ****
}
! if (super_meth)
meth->index = super_meth->index;
else
--- 2191,2195 ----
}
! if (super_meth && _Jv_isVirtualMethod (super_meth))
meth->index = super_meth->index;
else
Index: gcc/java/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/class.c,v
retrieving revision 1.180.2.11
diff -p -2 -c -r1.180.2.11 class.c
*** gcc/java/class.c 3 Sep 2004 14:36:48 -0000 1.180.2.11
--- gcc/java/class.c 10 Sep 2004 16:18:40 -0000
*************** unmangle_classname (const char *name, in
*** 350,355 ****
}
! /* Given a class, create the DECLs for all its associated indirect dispatch tables. */
void
gen_indirect_dispatch_tables (tree type)
--- 350,385 ----
}
+ #define GEN_TABLE(TABLE, NAME, TABLE_TYPE, TYPE) \
+ do \
+ { \
+ const char *typename = IDENTIFIER_POINTER (mangled_classname ("", TYPE)); \
+ char *buf = alloca (strlen (typename) + strlen (#NAME "_syms_") + 1); \
+ tree decl; \
+ \
+ sprintf (buf, #NAME "_%s", typename); \
+ TYPE_## TABLE ##_DECL (type) = decl = \
+ build_decl (VAR_DECL, get_identifier (buf), TABLE_TYPE); \
+ DECL_EXTERNAL (decl) = 1; \
+ TREE_STATIC (decl) = 1; \
+ TREE_READONLY (decl) = 1; \
+ TREE_CONSTANT (decl) = 1; \
+ DECL_IGNORED_P (decl) = 1; \
+ /* Mark the table as belonging to this class. */ \
+ pushdecl (decl); \
+ MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl); \
+ DECL_OWNER (decl) = TYPE; \
+ sprintf (buf, #NAME "_syms_%s", typename); \
+ TYPE_## TABLE ##_SYMS_DECL (TYPE) = \
+ build_decl (VAR_DECL, get_identifier (buf), symbols_array_type); \
+ TREE_STATIC (TYPE_## TABLE ##_SYMS_DECL (TYPE)) = 1; \
+ TREE_CONSTANT (TYPE_## TABLE ##_SYMS_DECL (TYPE)) = 1; \
+ DECL_IGNORED_P (TYPE_## TABLE ##_SYMS_DECL (TYPE)) = 1; \
+ pushdecl (TYPE_## TABLE ##_SYMS_DECL (TYPE)); \
+ } \
+ while (0)
!
! /* Given a class, create the DECLs for all its associated indirect
! dispatch tables. */
void
gen_indirect_dispatch_tables (tree type)
*************** gen_indirect_dispatch_tables (tree type)
*** 379,432 ****
if (flag_indirect_dispatch)
{
! {
! char *buf = alloca (strlen (typename) + strlen ("_otable_syms_") + 1);
!
! sprintf (buf, "_otable_%s", typename);
! TYPE_OTABLE_DECL (type) =
! build_decl (VAR_DECL, get_identifier (buf), otable_type);
! DECL_EXTERNAL (TYPE_OTABLE_DECL (type)) = 1;
! TREE_STATIC (TYPE_OTABLE_DECL (type)) = 1;
! TREE_READONLY (TYPE_OTABLE_DECL (type)) = 1;
! TREE_CONSTANT (TYPE_OTABLE_DECL (type)) = 1;
! DECL_IGNORED_P (TYPE_OTABLE_DECL (type)) = 1;
! pushdecl (TYPE_OTABLE_DECL (type));
! MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (TYPE_OTABLE_DECL (type));
! DECL_OWNER (TYPE_OTABLE_DECL (type)) = type;
! sprintf (buf, "_otable_syms_%s", typename);
! TYPE_OTABLE_SYMS_DECL (type) =
! build_decl (VAR_DECL, get_identifier (buf), symbols_array_type);
! TREE_STATIC (TYPE_OTABLE_SYMS_DECL (type)) = 1;
! TREE_CONSTANT (TYPE_OTABLE_SYMS_DECL (type)) = 1;
! DECL_IGNORED_P(TYPE_OTABLE_SYMS_DECL (type)) = 1;
! pushdecl (TYPE_OTABLE_SYMS_DECL (type));
! }
!
! {
! char *buf = alloca (strlen (typename) + strlen ("_atable_syms_") + 1);
! tree decl;
!
! sprintf (buf, "_atable_%s", typename);
! TYPE_ATABLE_DECL (type) = decl =
! build_decl (VAR_DECL, get_identifier (buf), atable_type);
! DECL_EXTERNAL (decl) = 1;
! TREE_STATIC (decl) = 1;
! TREE_READONLY (decl) = 1;
! TREE_CONSTANT (decl) = 1;
! DECL_IGNORED_P (decl) = 1;
! /* Mark the atable as belonging to this class. */
! pushdecl (decl);
! MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
! DECL_OWNER (decl) = type;
! sprintf (buf, "_atable_syms_%s", typename);
! TYPE_ATABLE_SYMS_DECL (type) =
! build_decl (VAR_DECL, get_identifier (buf), symbols_array_type);
! TREE_STATIC (TYPE_ATABLE_SYMS_DECL (type)) = 1;
! TREE_CONSTANT (TYPE_ATABLE_SYMS_DECL (type)) = 1;
! DECL_IGNORED_P (TYPE_ATABLE_SYMS_DECL (type)) = 1;
! pushdecl (TYPE_ATABLE_SYMS_DECL (type));
! }
}
}
tree
push_class (tree class_type, tree class_name)
--- 409,420 ----
if (flag_indirect_dispatch)
{
! GEN_TABLE (ATABLE, _atable, atable_type, type);
! GEN_TABLE (OTABLE, _otable, otable_type, type);
! GEN_TABLE (ITABLE, _itable, itable_type, type);
}
}
+ #undef GEN_TABLE
+
tree
push_class (tree class_type, tree class_name)
*************** make_class_data (tree type)
*** 1684,1688 ****
(DECL_NAME (TYPE_OTABLE_DECL (type)),
TYPE_OTABLE_DECL (type), TYPE_OTABLE_METHODS (type),
! TYPE_OTABLE_SYMS_DECL (type), integer_type_node);
TYPE_ATABLE_DECL (type)
--- 1672,1676 ----
(DECL_NAME (TYPE_OTABLE_DECL (type)),
TYPE_OTABLE_DECL (type), TYPE_OTABLE_METHODS (type),
! TYPE_OTABLE_SYMS_DECL (type), integer_type_node, 1);
TYPE_ATABLE_DECL (type)
*************** make_class_data (tree type)
*** 1690,1694 ****
(DECL_NAME (TYPE_ATABLE_DECL (type)),
TYPE_ATABLE_DECL (type), TYPE_ATABLE_METHODS (type),
! TYPE_ATABLE_SYMS_DECL (type), ptr_type_node);
}
--- 1678,1688 ----
(DECL_NAME (TYPE_ATABLE_DECL (type)),
TYPE_ATABLE_DECL (type), TYPE_ATABLE_METHODS (type),
! TYPE_ATABLE_SYMS_DECL (type), ptr_type_node, 1);
!
! TYPE_ITABLE_DECL (type)
! = emit_symbol_table
! (DECL_NAME (TYPE_ITABLE_DECL (type)),
! TYPE_ITABLE_DECL (type), TYPE_ITABLE_METHODS (type),
! TYPE_ITABLE_SYMS_DECL (type), ptr_type_node, 2);
}
*************** make_class_data (tree type)
*** 1774,1777 ****
--- 1768,1786 ----
TREE_INVARIANT (TYPE_ATABLE_DECL (type)) = 1;
}
+ if (TYPE_ITABLE_METHODS(type) == NULL_TREE)
+ {
+ PUSH_FIELD_VALUE (cons, "itable", null_pointer_node);
+ PUSH_FIELD_VALUE (cons, "itable_syms", null_pointer_node);
+ }
+ else
+ {
+ PUSH_FIELD_VALUE (cons, "itable",
+ build1 (ADDR_EXPR, itable_ptr_type, TYPE_ITABLE_DECL (type)));
+ PUSH_FIELD_VALUE (cons, "itable_syms",
+ build1 (ADDR_EXPR, symbols_array_ptr_type,
+ TYPE_ITABLE_SYMS_DECL (type)));
+ TREE_CONSTANT (TYPE_ITABLE_DECL (type)) = 1;
+ TREE_INVARIANT (TYPE_ITABLE_DECL (type)) = 1;
+ }
PUSH_FIELD_VALUE (cons, "catch_classes",
*************** static void
*** 2109,2114 ****
add_miranda_methods (tree base_class, tree search_class)
{
! tree basetype_vec = TYPE_BINFO_BASETYPES (search_class);
! int i, n = TREE_VEC_LENGTH (basetype_vec);
for (i = 1; i < n; ++i)
{
--- 2118,2127 ----
add_miranda_methods (tree base_class, tree search_class)
{
! tree basetype_vec;
! int i, n;
! if (!CLASS_PARSED_P (search_class))
! load_class (search_class, 1);
! basetype_vec = TYPE_BINFO_BASETYPES (search_class);
! n = TREE_VEC_LENGTH (basetype_vec);
for (i = 1; i < n; ++i)
{
*************** build_symbol_entry (tree decl)
*** 2408,2412 ****
(IDENTIFIER_POINTER (signature),
IDENTIFIER_LENGTH (signature)));
!
START_RECORD_CONSTRUCTOR (sym, symbol_type);
PUSH_FIELD_VALUE (sym, "clname", clname);
--- 2421,2425 ----
(IDENTIFIER_POINTER (signature),
IDENTIFIER_LENGTH (signature)));
!
START_RECORD_CONSTRUCTOR (sym, symbol_type);
PUSH_FIELD_VALUE (sym, "clname", clname);
*************** build_symbol_entry (tree decl)
*** 2420,2428 ****
}
! /* Emit a symbol table: used by -findirect-dispatch. */
tree
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;
--- 2433,2442 ----
}
! /* Emit a symbol table: used by -findirect-dispatch. ELEMENT_SIZE is
! the number of elements per symbol. */
tree
emit_symbol_table (tree name, tree the_table, tree decl_list, tree the_syms_decl,
! tree the_array_element_type, int element_size)
{
tree method_list, method, table, list, null_symbol;
*************** emit_symbol_table (tree name, tree the_t
*** 2471,2475 ****
is used by the runtime to track whether the table has been
initialized. */
! table_size = build_index_type (build_int_2 (index, 0));
the_array_type = build_array_type (the_array_element_type, table_size);
the_table = build_decl (VAR_DECL, name, the_array_type);
--- 2485,2489 ----
is used by the runtime to track whether the table has been
initialized. */
! table_size = build_index_type (build_int_2 (index * element_size + 1, 0));
the_array_type = build_array_type (the_array_element_type, table_size);
the_table = build_decl (VAR_DECL, name, the_array_type);
Index: gcc/java/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/decl.c,v
retrieving revision 1.178.4.7
diff -p -2 -c -r1.178.4.7 decl.c
*** gcc/java/decl.c 1 Sep 2004 13:10:47 -0000 1.178.4.7
--- gcc/java/decl.c 10 Sep 2004 16:18:40 -0000
*************** java_init_decl_processing (void)
*** 704,707 ****
--- 704,712 ----
atable_ptr_type = build_pointer_type (atable_type);
+ itable_type = build_array_type (ptr_type_node,
+ one_elt_array_domain_type);
+ TYPE_NONALIASED_COMPONENT (itable_type) = 1;
+ itable_ptr_type = build_pointer_type (itable_type);
+
symbol_type = make_node (RECORD_TYPE);
PUSH_FIELD (symbol_type, field, "clname", utf8const_ptr_type);
*************** java_init_decl_processing (void)
*** 830,833 ****
--- 835,841 ----
PUSH_FIELD (class_type_node, field, "atable_syms",
symbols_array_ptr_type);
+ PUSH_FIELD (class_type_node, field, "itable", itable_ptr_type);
+ PUSH_FIELD (class_type_node, field, "itable_syms",
+ symbols_array_ptr_type);
PUSH_FIELD (class_type_node, field, "catch_classes", ptr_type_node);
PUSH_FIELD (class_type_node, field, "interfaces",
Index: gcc/java/expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/expr.c,v
retrieving revision 1.185.2.12
diff -p -2 -c -r1.185.2.12 expr.c
*** gcc/java/expr.c 6 Sep 2004 14:05:04 -0000 1.185.2.12
--- gcc/java/expr.c 10 Sep 2004 16:18:41 -0000
*************** expand_iinc (unsigned int local_var_inde
*** 1477,1481 ****
}
!
tree
build_java_soft_divmod (enum tree_code op, tree type, tree op1, tree op2)
--- 1477,1481 ----
}
!
tree
build_java_soft_divmod (enum tree_code op, tree type, tree op1, tree op2)
*************** invoke_build_dtable (int is_invoke_inter
*** 2078,2083 ****
/* Determine the index in SYMBOL_TABLE for a reference to the decl
T. If this decl has not been seen before, it will be added to the
! otable_methods. If it has, the existing table slot will be
! reused. */
int
--- 2078,2083 ----
/* Determine the index in SYMBOL_TABLE for a reference to the decl
T. If this decl has not been seen before, it will be added to the
! [oa]table_methods. If it has, the existing table slot will be
! reused. */
int
*************** get_symbol_table_index (tree t, tree *sy
*** 2099,2103 ****
tree value = TREE_VALUE (method_list);
if (value == t)
! return i;
i++;
if (TREE_CHAIN (method_list) == NULL_TREE)
--- 2099,2103 ----
tree value = TREE_VALUE (method_list);
if (value == t)
! return i;
i++;
if (TREE_CHAIN (method_list) == NULL_TREE)
*************** build_invokeinterface (tree dtable, tree
*** 2165,2171 ****
tree idx;
! /* We expand invokeinterface here. _Jv_LookupInterfaceMethod() will
! ensure that the selected method exists, is public and not
! abstract nor static. */
if (class_ident == NULL_TREE)
--- 2165,2169 ----
tree idx;
! /* We expand invokeinterface here. */
if (class_ident == NULL_TREE)
*************** build_invokeinterface (tree dtable, tree
*** 2184,2223 ****
if (flag_indirect_dispatch)
{
! // FIXME: We look up the interface by name every time we make an
! // interface call. There is an interface cache in the runtime
! // library, but even so this sucks.
!
! // PR 12760 says: "... the best solution would be to make the
! // "otable" for interfaces have a pair of values - interface
! // where the target method is found in addition to offset. Both
! // of these would be passed to _Jv_LookupInterfaceMethodIdx."
! // However, other Java implementations seem to resolve
! // interfaces lazily, so there is some compatibility advantage
! // in doing things this way.
!
! tree method_signature = TYPE_SIGNATURE (TREE_TYPE (method));
! tree method_name = DECL_NAME (method);
!
! lookup_arg = build_tree_list (NULL_TREE,
! (build_utf8_ref
! (unmangle_classname
! (IDENTIFIER_POINTER(method_signature),
! IDENTIFIER_LENGTH(method_signature)))));
! lookup_arg = tree_cons (NULL_TREE, dtable,
! tree_cons (NULL_TREE, build_utf8_ref (method_name),
! lookup_arg));
! return build (CALL_EXPR, ptr_type_node,
! build_address_of (soft_lookupinterfacemethodbyname_node),
! lookup_arg, NULL_TREE);
}
else
{
idx = build_int_2 (get_interface_method_index (method, interface), 0);
}
-
- lookup_arg = tree_cons (NULL_TREE, dtable,
- tree_cons (NULL_TREE, build_class_ref (interface),
- build_tree_list (NULL_TREE, idx)));
return build (CALL_EXPR, ptr_type_node,
build_address_of (soft_lookupinterfacemethod_node),
--- 2182,2211 ----
if (flag_indirect_dispatch)
{
! int itable_index
! = 2 * (get_symbol_table_index
! (method, &TYPE_ITABLE_METHODS (output_class)));
! interface
! = build (ARRAY_REF,
! TREE_TYPE (TREE_TYPE (TYPE_ITABLE_DECL (output_class))),
! TYPE_ITABLE_DECL (output_class),
! build_int_2 (itable_index-1, 0));
! idx
! = build (ARRAY_REF,
! TREE_TYPE (TREE_TYPE (TYPE_ITABLE_DECL (output_class))),
! TYPE_ITABLE_DECL (output_class),
! build_int_2 (itable_index, 0));
! interface = convert (class_ptr_type, interface);
! idx = convert (integer_type_node, idx);
}
else
{
idx = build_int_2 (get_interface_method_index (method, interface), 0);
+ interface = build_class_ref (interface);
}
+ lookup_arg = tree_cons (NULL_TREE, dtable,
+ tree_cons (NULL_TREE, interface,
+ build_tree_list (NULL_TREE, idx)));
+
return build (CALL_EXPR, ptr_type_node,
build_address_of (soft_lookupinterfacemethod_node),
*************** build_invokeinterface (tree dtable, tree
*** 2226,2230 ****
/* Expand one of the invoke_* opcodes.
! OCPODE is the specific opcode.
METHOD_REF_INDEX is an index into the constant pool.
NARGS is the number of arguments, or -1 if not specified. */
--- 2214,2218 ----
/* Expand one of the invoke_* opcodes.
! OPCODE is the specific opcode.
METHOD_REF_INDEX is an index into the constant pool.
NARGS is the number of arguments, or -1 if not specified. */
Index: gcc/java/java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.197.2.7
diff -p -2 -c -r1.197.2.7 java-tree.h
*** gcc/java/java-tree.h 1 Sep 2004 13:10:48 -0000 1.197.2.7
--- gcc/java/java-tree.h 10 Sep 2004 16:18:42 -0000
*************** enum java_tree_index
*** 378,381 ****
--- 378,383 ----
JTI_ATABLE_TYPE,
JTI_ATABLE_PTR_TYPE,
+ JTI_ITABLE_TYPE,
+ JTI_ITABLE_PTR_TYPE,
JTI_SYMBOL_TYPE,
JTI_SYMBOLS_ARRAY_TYPE,
*************** extern GTY(()) tree java_global_trees[JT
*** 613,620 ****
--- 615,626 ----
#define atable_type \
java_global_trees[JTI_ATABLE_TYPE]
+ #define itable_type \
+ java_global_trees[JTI_ITABLE_TYPE]
#define otable_ptr_type \
java_global_trees[JTI_OTABLE_PTR_TYPE]
#define atable_ptr_type \
java_global_trees[JTI_ATABLE_PTR_TYPE]
+ #define itable_ptr_type \
+ java_global_trees[JTI_ITABLE_PTR_TYPE]
#define symbol_type \
java_global_trees[JTI_SYMBOL_TYPE]
*************** struct lang_decl GTY(())
*** 1086,1089 ****
--- 1092,1099 ----
#define TYPE_OTABLE_DECL(T) (TYPE_LANG_SPECIFIC (T)->otable_decl)
+ #define TYPE_ITABLE_METHODS(T) (TYPE_LANG_SPECIFIC (T)->itable_methods)
+ #define TYPE_ITABLE_SYMS_DECL(T) (TYPE_LANG_SPECIFIC (T)->itable_syms_decl)
+ #define TYPE_ITABLE_DECL(T) (TYPE_LANG_SPECIFIC (T)->itable_decl)
+
#define TYPE_CTABLE_DECL(T) (TYPE_LANG_SPECIFIC (T)->ctable_decl)
#define TYPE_CATCH_CLASSES(T) (TYPE_LANG_SPECIFIC (T)->catch_classes)
*************** struct lang_type GTY(())
*** 1120,1123 ****
--- 1130,1138 ----
tree atable_syms_decl;
+ tree itable_methods; /* List of interfaces methods referred
+ to by this class. */
+ tree itable_decl; /* The interfaces table. */
+ tree itable_syms_decl;
+
tree ctable_decl; /* The table of classes for the runtime
type matcher. */
*************** extern void register_class (void);
*** 1277,1281 ****
extern int alloc_name_constant (int, tree);
extern void emit_register_classes (void);
! extern tree emit_symbol_table (tree, tree, tree, tree, tree);
extern void lang_init_source (int);
extern void write_classfile (tree);
--- 1292,1296 ----
extern int alloc_name_constant (int, tree);
extern void emit_register_classes (void);
! extern tree emit_symbol_table (tree, tree, tree, tree, tree, int);
extern void lang_init_source (int);
extern void write_classfile (tree);