This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
[ecj] Bump ABI version
- From: Andrew Haley <aph at redhat dot com>
- To: Java Patch List <java-patches at gcc dot gnu dot org>, gcc at gcc dot gnu dot org
- Date: Tue, 19 Dec 2006 15:04:50 +0000
- Subject: [ecj] Bump ABI version
Java 5 has an extended class file format for annotations. We have to
support that in gcj-compiled code too, and it requires an ABI change.
Tom Tromey, I'd appreciate it if you'd have a quick check of this one.
We should probably port the code that throws a ClassFormatError if
we're not ABI-compatible to the active branches.
Andrew.
2006-12-19 Andrew Haley <aph@redhat.com>
* java/lang/natClassLoader.cc (_Jv_CheckABIVersion): Move here
from include/jvm.h.
Add BC ABI Version 1.
Throw a ClassFormatError if we're not ABI-compatible.
(_Jv_RegisterClasses): Throw a ClassFormatError if we're not
ABI-compatible.
(_Jv_RegisterClasses_Counted): Likewise.
(_Jv_NewClassFromInitializer): Likewise.
Call Class::initializerSize to get size of initializer struct.
* include/jvm.h (_Jv_CheckABIVersion): Move to natClassLoader.cc.
* java/lang/Class.h (Class::initializerSize): New function.
gIndex: gcc/java/decl.c
===================================================================
--- gcc/java/decl.c (revision 120004)
+++ gcc/java/decl.c (working copy)
@@ -75,9 +75,9 @@
loader. */
/* If an ABI change is made within a GCC release series, rendering current
- binaries incompatible with the old runtimes, this number can be set to
+ binaries incompatible with the old runtimes, this number must be set to
enforce the compatibility rules. */
-#define MINOR_BINARYCOMPAT_ABI_VERSION 0
+#define MINOR_BINARYCOMPAT_ABI_VERSION 1
/* The runtime may recognize a variety of BC ABIs (objects generated by
different version of gcj), but will probably always require strict
Index: libjava/include/jvm.h
===================================================================
--- libjava/include/jvm.h (revision 120004)
+++ libjava/include/jvm.h (working copy)
@@ -658,30 +658,8 @@
// New style version IDs used by GCJ 4.0.1 and later.
#define GCJ_40_BC_ABI_VERSION (4 * 100000 + 0 * 1000)
-inline bool
-_Jv_CheckABIVersion (unsigned long value)
-{
- // We are compatible with GCJ 4.0.0 BC-ABI classes. This release used a
- // different format for the version ID string.
- if (value == OLD_GCJ_40_BC_ABI_VERSION)
- return true;
-
- // The 20 low-end bits are used for the version number.
- unsigned long version = value & 0xfffff;
-
- if (value & FLAG_BINARYCOMPAT_ABI)
- {
- int abi_rev = version % 100;
- int abi_ver = version - abi_rev;
- if (abi_ver == GCJ_40_BC_ABI_VERSION && abi_rev <= 0)
- return true;
- }
- else
- // C++ ABI
- return version == GCJ_CXX_ABI_VERSION;
-
- return false;
-}
+void _Jv_CheckABIVersion (unsigned long value);
+
inline bool
_Jv_ClassForBootstrapLoader (unsigned long value)
Index: libjava/java/lang/natClassLoader.cc
===================================================================
--- libjava/java/lang/natClassLoader.cc (revision 120004)
+++ libjava/java/lang/natClassLoader.cc (working copy)
@@ -180,6 +180,41 @@
// _Jv_RegisterNewClasses() are of Type 2.
+// Check that the file we're trying to load has been compiled with a
+// compatible version of gcj. In previous versions of libgcj we
+// silently failed to register classes of an incompatible ABI version,
+// but this was totally bogus.
+void
+_Jv_CheckABIVersion (unsigned long value)
+{
+ // We are compatible with GCJ 4.0.0 BC-ABI classes. This release used a
+ // different format for the version ID string.
+ if (value == OLD_GCJ_40_BC_ABI_VERSION)
+ return;
+
+ // The 20 low-end bits are used for the version number.
+ unsigned long version = value & 0xfffff;
+
+ if (value & FLAG_BINARYCOMPAT_ABI)
+ {
+ int abi_rev = version % 100;
+ int abi_ver = version - abi_rev;
+ // We are compatible with abi_rev 0 and 1.
+ if (abi_ver == GCJ_40_BC_ABI_VERSION && abi_rev <= 1)
+ return;
+ }
+ else
+ {
+ // C++ ABI
+ if (version == GCJ_CXX_ABI_VERSION)
+ return;
+ }
+
+ throw new ::java::lang::ClassFormatError
+ (JvNewStringLatin1 ("Library compiled with later ABI version than"
+ " this version of libgcj supports"));
+}
+
// This function is called many times during startup, before main() is
// run. At that point in time we know for certain we are running
// single-threaded, so we don't need to lock when adding classes to the
@@ -194,14 +229,8 @@
{
jclass klass = *classes;
- if (_Jv_CheckABIVersion ((unsigned long) klass->next_or_version))
- (*_Jv_RegisterClassHook) (klass);
- else
- {
- fprintf (stderr, "ABI mismatch: library is compiled with "
- "the wrong version of gcj\n");
- abort ();
- }
+ _Jv_CheckABIVersion ((unsigned long) klass->next_or_version);
+ (*_Jv_RegisterClassHook) (klass);
}
}
@@ -217,32 +246,37 @@
{
jclass klass = classes[i];
- if (_Jv_CheckABIVersion ((unsigned long) klass->next_or_version))
- (*_Jv_RegisterClassHook) (klass);
+ _Jv_CheckABIVersion ((unsigned long) klass->next_or_version);
+ (*_Jv_RegisterClassHook) (klass);
}
}
// Create a class on the heap from an initializer struct.
-jclass
+inline jclass
_Jv_NewClassFromInitializer (const char *class_initializer)
{
+ const unsigned long version
+ = ((unsigned long)
+ ((::java::lang::Class *)class_initializer)->next_or_version);
+ _Jv_CheckABIVersion (version);
+
/* We create an instance of java::lang::Class and copy all of its
fields except the first word (the vtable pointer) from
CLASS_INITIALIZER. This first word is pre-initialized by
_Jv_AllocObj, and we don't want to overwrite it. */
-
+
jclass new_class
- = (jclass)_Jv_AllocObj (sizeof (java::lang::Class),
- &java::lang::Class::class$);
+ = (jclass)_Jv_AllocObj (sizeof (::java::lang::Class),
+ &::java::lang::Class::class$);
const char *src = class_initializer + sizeof (void*);
char *dst = (char*)new_class + sizeof (void*);
- size_t len = sizeof (*new_class) - sizeof (void*);
+ size_t len = (::java::lang::Class::initializerSize (version)
+ - sizeof (void*));
memcpy (dst, src, len);
-
+
new_class->engine = &_Jv_soleIndirectCompiledEngine;
-
- if (_Jv_CheckABIVersion ((unsigned long) new_class->next_or_version))
- (*_Jv_RegisterClassHook) (new_class);
+
+ (*_Jv_RegisterClassHook) (new_class);
return new_class;
}
Index: libjava/java/lang/Class.h
===================================================================
--- libjava/java/lang/Class.h (revision 120004)
+++ libjava/java/lang/Class.h (working copy)
@@ -479,6 +479,20 @@
// types. See prims.cc.
Class ();
+ // Given the BC ABI version, return the size of an Class initializer.
+ static jlong initializerSize (jlong ABI)
+ {
+ unsigned long version = ABI & 0xfffff;
+ int abi_rev = version % 100;
+
+ // The reflection_data field was added by abi_rev 1.
+ if (abi_rev == 0)
+ return ((char*)(&::java::lang::Class::class$.reflection_data)
+ - (char*)&::java::lang::Class::class$);
+
+ return sizeof (::java::lang::Class);
+ }
+
static java::lang::Class class$;
private: