This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch: FYI: fix PR java/26390
- From: Tom Tromey <tromey at redhat dot com>
- To: Java Patch List <java-patches at gcc dot gnu dot org>
- Cc: Gcc Patch List <gcc-patches at gcc dot gnu dot org>
- Date: 15 Mar 2006 11:22:48 -0700
- Subject: Patch: FYI: fix PR java/26390
- Reply-to: tromey at redhat dot com
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