This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java 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]

[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:   


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