This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]