This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch: RFA: versioning gcj classes
- From: Tom Tromey <tromey at redhat dot com>
- To: Gcc Patch List <gcc-patches at gcc dot gnu dot org>
- Cc: Java Patch List <java-patches at gcc dot gnu dot org>
- Date: 19 Jan 2005 17:09:15 -0700
- Subject: Patch: RFA: versioning gcj classes
- Reply-to: tromey at redhat dot com
This is a slightly revised (function name change) version of a patch I
sent last week concerning versioning gcj-compiled classes. See the
original thread:
http://gcc.gnu.org/ml/java-patches/2005-q1/msg00082.html
I've now run this through the test suite, in addition to the tests
mentioned in my earlier post.
Ok?
Tom
Index: gcc/java/ChangeLog
from Tom Tromey <tromey@redhat.com>
* java-tree.h (gcj_abi_version): Declare.
* class.c (make_class_data): Push gcj_abi_version into "next"
field.
* decl.c (gcj_abi_version): New global.
(parse_version): New function.
(java_init_decl_processing): Call it.
Include version.h.
(GCJ_BINARYCOMPAT_ADDITION): New define.
Index: gcc/java/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/class.c,v
retrieving revision 1.219
diff -u -r1.219 class.c
--- gcc/java/class.c 13 Dec 2004 06:57:13 -0000 1.219
+++ gcc/java/class.c 20 Jan 2005 00:05:29 -0000
@@ -1,5 +1,5 @@
/* Functions related to building classes and their related objects.
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of GCC.
@@ -1741,7 +1741,7 @@
FINISH_RECORD_CONSTRUCTOR (temp);
START_RECORD_CONSTRUCTOR (cons, class_type_node);
PUSH_SUPER_VALUE (cons, temp);
- PUSH_FIELD_VALUE (cons, "next", null_pointer_node);
+ PUSH_FIELD_VALUE (cons, "next", gcj_abi_version);
PUSH_FIELD_VALUE (cons, "name", build_utf8_ref (DECL_NAME (type_decl)));
PUSH_FIELD_VALUE (cons, "accflags",
build_int_cst (NULL_TREE,
Index: gcc/java/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/decl.c,v
retrieving revision 1.206
diff -u -r1.206 decl.c
--- gcc/java/decl.c 27 Nov 2004 20:48:16 -0000 1.206
+++ gcc/java/decl.c 20 Jan 2005 00:05:30 -0000
@@ -1,6 +1,6 @@
/* Process declarations and variables for the GNU compiler for the
Java(TM) language.
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of GCC.
@@ -47,6 +47,7 @@
#include "cgraph.h"
#include "tree-inline.h"
#include "target.h"
+#include "version.h"
#if defined (DEBUG_JAVA_BINDING_LEVELS)
extern void indent (void);
@@ -58,6 +59,13 @@
static struct binding_level *make_binding_level (void);
static tree create_primitive_vtable (const char *);
static tree check_local_unnamed_variable (tree, tree, tree);
+static void parse_version (void);
+
+/* Used when computing the ABI version. */
+#define GCJ_BINARYCOMPAT_ADDITION 5
+
+/* The ABI version number. */
+tree gcj_abi_version;
/* Name of the Cloneable class. */
tree java_lang_cloneable_identifier_node;
@@ -559,6 +567,48 @@
return t;
}
+/* Parse the version string and compute the ABI version number. */
+static void
+parse_version (void)
+{
+ const char *p = version_string;
+ unsigned int major = 0, minor = 0;
+ unsigned int abi_version;
+
+ /* Skip leading junk. */
+ while (*p && !ISDIGIT (*p))
+ ++p;
+ gcc_assert (*p);
+
+ /* Extract major version. */
+ while (ISDIGIT (*p))
+ {
+ major = major * 10 + *p - '0';
+ ++p;
+ }
+
+ gcc_assert (*p == '.' || ISDIGIT (p[1]));
+ ++p;
+
+ /* Extract minor version. */
+ while (ISDIGIT (*p))
+ {
+ minor = minor * 10 + *p - '0';
+ ++p;
+ }
+
+ /* Implicit in this computation is the idea that we won't break the
+ old-style binary ABI in a minor release. */
+ abi_version = 10000 * major + 10 * minor;
+ /* It is helpful to distinguish BC ABI from ordinary ABI at this
+ level, since at some point we will recognize a variety of BC ABIs
+ (objects generated by different version of gcj), but will
+ probably always require strict matching for ordinary ABI. */
+ if (flag_indirect_dispatch)
+ abi_version += GCJ_BINARYCOMPAT_ADDITION;
+
+ gcj_abi_version = build_int_cstu (ptr_type_node, abi_version);
+}
void
java_init_decl_processing (void)
@@ -1100,6 +1150,8 @@
#if 0
soft_fmodf_node = built_in_decls[BUILT_IN_FMODF];
#endif
+
+ parse_version ();
}
Index: gcc/java/java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.224
diff -u -r1.224 java-tree.h
--- gcc/java/java-tree.h 6 Dec 2004 15:32:37 -0000 1.224
+++ gcc/java/java-tree.h 20 Jan 2005 00:05:31 -0000
@@ -1,6 +1,6 @@
/* Definitions for parsing and type checking for the GNU compiler for
the Java(TM) language.
- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of GCC.
@@ -274,6 +274,7 @@
extern GTY(()) tree java_lang_cloneable_identifier_node;
extern GTY(()) tree java_io_serializable_identifier_node;
+extern GTY(()) tree gcj_abi_version;
enum java_tree_index
{
Index: libjava/ChangeLog
from Tom Tromey <tromey@redhat.com>
* java/lang/Class.h (next): Updated documentation.
* java/lang/natClassLoader.cc (_Jv_RegisterClasses): Use
_Jv_CheckABIVersion.
(_Jv_RegisterClasses_Counted): Likewise.
(_Jv_RegisterClassHookDefault): Fix starting condition of
duplicate-checking loop.
* include/jvm.h (GCJ_VERSION): New define.
(GCJ_BINARYCOMPAT_ADDITION): Likewise.
(_Jv_CheckABIVersion): New function.
Index: libjava/include/jvm.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/jvm.h,v
retrieving revision 1.74
diff -u -r1.74 jvm.h
--- libjava/include/jvm.h 14 Jan 2005 07:36:27 -0000 1.74
+++ libjava/include/jvm.h 20 Jan 2005 00:05:42 -0000
@@ -566,4 +566,19 @@
extern void _Jv_RegisterBootstrapPackages ();
+
+// This is used to find ABI versions we recognize.
+#define GCJ_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 10)
+#define GCJ_BINARYCOMPAT_ADDITION 5
+
+inline bool
+_Jv_CheckABIVersion (unsigned long value)
+{
+ // For this release, recognize just our defined C++ ABI and our
+ // defined BC ABI. (In the future we may recognize past BC ABIs as
+ // well.)
+ return (value == GCJ_VERSION
+ || value == (GCJ_VERSION + GCJ_BINARYCOMPAT_ADDITION));
+}
+
#endif /* __JAVA_JVM_H__ */
Index: libjava/java/lang/Class.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/Class.h,v
retrieving revision 1.75
diff -u -r1.75 Class.h
--- libjava/java/lang/Class.h 10 Jan 2005 19:39:25 -0000 1.75
+++ libjava/java/lang/Class.h 20 Jan 2005 00:05:42 -0000
@@ -488,7 +488,9 @@
friend void ::_Jv_sharedlib_register_hook (jclass klass);
- // Chain for class pool.
+ // Chain for class pool. This also doubles as the ABI version
+ // number. It is only used for this purpose at class registration
+ // time, and only for precompiled classes.
jclass next;
// Name of class.
_Jv_Utf8Const *name;
Index: libjava/java/lang/natClassLoader.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natClassLoader.cc,v
retrieving revision 1.74
diff -u -r1.74 natClassLoader.cc
--- libjava/java/lang/natClassLoader.cc 10 Jan 2005 19:39:26 -0000 1.74
+++ libjava/java/lang/natClassLoader.cc 20 Jan 2005 00:05:43 -0000
@@ -122,7 +122,8 @@
{
jclass klass = *classes;
- (*_Jv_RegisterClassHook) (klass);
+ if (_Jv_CheckABIVersion ((unsigned long) klass->next))
+ (*_Jv_RegisterClassHook) (klass);
}
}
@@ -135,7 +136,8 @@
{
jclass klass = classes[i];
- (*_Jv_RegisterClassHook) (klass);
+ if (_Jv_CheckABIVersion ((unsigned long) klass->next))
+ (*_Jv_RegisterClassHook) (klass);
}
}
@@ -144,12 +146,10 @@
{
jint hash = HASH_UTF (klass->name);
- // The BC ABI makes this check unnecessary: we always resolve all
- // data references via the appropriate class loader, so the kludge
- // that required this check has gone.
// If the class is already registered, don't re-register it.
- jclass check_class = klass->next;
- while (check_class != NULL)
+ for (jclass check_class = loaded_classes[hash];
+ check_class != NULL;
+ check_class = check_class->next)
{
if (check_class == klass)
{
@@ -170,8 +170,6 @@
throw new java::lang::VirtualMachineError (str);
}
}
-
- check_class = check_class->next;
}
// FIXME: this is really bogus!