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]

Patch: FYI: fix PR java/26390


I'm checking this in on the trunk.  Note that this patch requires a
clean rebuild of libgcj as it changes interface dispatch tables a bit.
(And consequently I don't think this patch can go on the 4.1 branch.)

The problem in PR 26390 is that gcj generates different methods for a
particular interface for the bytecode and object cases.  In particular
in one case it generates a <clinit> and in the other it does not.
This means that dispatching via this interface can be broken depending
on whether the source file or the class file is used when generating
the interface call.

This is broken but fixing it in the most direct way looked tricky.  In
particular, maybe_yank_clinit() explicitly checks to see whether it is
generating an object file, and intentionally does nothing in this
case.  I still don't understand this.

Meanwhile, it seems wrong to put <clinit> into the interface dispatch
table.  We can never actually call this method this way (and in fact
the runtime puts a NULL pointer into this slot at link time).  So,
this patch fixes the problem by removing <clinit> from these tables.

Tom

Index: gcc/java/ChangeLog
from  Tom Tromey  <tromey@redhat.com>
	PR java/26390:
	* class.c (get_interface_method_index): Don't put <clinit> into
	interface table.

Index: libjava/ChangeLog
from  Tom Tromey  <tromey@redhat.com>
	PR java/26390:
	* link.cc (get_interfaces): Skip <clinit>.
	(append_partial_itable): Likewise.

Index: gcc/java/class.c
===================================================================
--- gcc/java/class.c	(revision 111942)
+++ gcc/java/class.c	(working copy)
@@ -1,5 +1,5 @@
 /* Functions related to building classes and their related objects.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -2303,18 +2303,21 @@
   TYPE_NVIRTUALS (this_class) = dtable_count;
 }
 
-/* Return the index of METHOD in INTERFACE.  This index begins at 1 and is used as an
-   argument for _Jv_LookupInterfaceMethodIdx(). */
+/* Return the index of METHOD in INTERFACE.  This index begins at 1
+   and is used as an argument for _Jv_LookupInterfaceMethodIdx(). */
 int
 get_interface_method_index (tree method, tree interface)
 {
   tree meth;
   int i = 1;
 
-  for (meth = TYPE_METHODS (interface); ; meth = TREE_CHAIN (meth), i++)
+  for (meth = TYPE_METHODS (interface); ; meth = TREE_CHAIN (meth))
     {
       if (meth == method)
 	return i;
+      /* We don't want to put <clinit> into the interface table.  */
+      if (! ID_CLINIT_P (DECL_NAME (meth)))
+	++i;
       gcc_assert (meth != NULL_TREE);
     }
 }

Index: libjava/link.cc
===================================================================
--- libjava/link.cc	(revision 111948)
+++ libjava/link.cc	(working copy)
@@ -699,9 +699,18 @@
 	  result += get_interfaces (klass->interfaces[i], ifaces);
 	}
     }
-    
+
   if (klass->isInterface())
-    result += klass->method_count + 1;
+    {
+      // We want to add 1 plus the number of interface methods here.
+      // But, we take special care to skip <clinit>.
+      ++result;
+      for (int i = 0; i < klass->method_count; ++i)
+	{
+	  if (klass->methods[i].name->first() != '<')
+	    ++result;
+	}
+    }
   else if (klass->superclass)
     result += get_interfaces (klass->superclass, ifaces);
   return result;
@@ -817,7 +826,7 @@
 // Returns the offset at which the next partial ITable should be appended.
 jshort
 _Jv_Linker::append_partial_itable (jclass klass, jclass iface,
-				     void **itable, jshort pos)
+				   void **itable, jshort pos)
 {
   using namespace java::lang::reflect;
 
@@ -826,6 +835,10 @@
   
   for (int j=0; j < iface->method_count; j++)
     {
+      // Skip '<clinit>' here.
+      if (iface->methods[j].name->first() == '<')
+	continue;
+
       meth = NULL;
       for (jclass cl = klass; cl; cl = cl->getSuperclass())
         {
@@ -836,12 +849,7 @@
 	    break;
 	}
 
-      if (meth && (meth->name->first() == '<'))
-	{
-	  // leave a placeholder in the itable for hidden init methods.
-          itable[pos] = NULL;	
-	}
-      else if (meth)
+      if (meth)
         {
 	  if ((meth->accflags & Modifier::STATIC) != 0)
 	    throw new java::lang::IncompatibleClassChangeError


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