Class initialization, take two

Jeff Sturm jsturm@one-point.com
Fri Jan 3 05:44:00 GMT 2003


My last classloader patch inadvertently broke Kawa builds.  This corrects
it and also improves support for -fno-assume-compiled.

The old sequence of class initialization was:

a) prepare class (resolve constant pool entries)
b) build tables (ancestors, vtable, etc.)
c) initialize superclass
d) invoke <clinit>

For -fno-assume-compiled, b) must come after linking, and linking is a
side effect of c).  So the order changed to a, c, b, d.  However that
means we can see a class with no ancestor table, if it is reinitialized
while superclass initialization takes place (as happens in gnu.bytecode).

This patch is one way to handle it.  An alternative is to add an explicit
link step to class initialization, as the bytecode interpreter does.

Also check that interfaces are linked when building constant time tables.

Tested on mainline with i686-pc-linux-gnu.


2003-01-03  Jeff Sturm  <jsturm@one-point.com>

	* java/lang/natClass.cc (initializeClass): Check tables when
	(state == JV_STATE_IN_PROGRESS).
	(_Jv_GetInterfaces): Use _Jv_WaitForState to link interface.
	* java/lang/natClassLoader.cc (_Jv_WaitForState): Handle
	interpreted classes.
	(linkClass0): Use _Jv_WaitForState.

Index: java/lang/natClass.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natClass.cc,v
retrieving revision 1.59
diff -u -p -r1.59 natClass.cc
--- java/lang/natClass.cc	23 Dec 2002 19:59:31 -0000	1.59
+++ java/lang/natClass.cc	3 Jan 2003 04:32:59 -0000
@@ -766,11 +766,23 @@ java::lang::Class::initializeClass (void
     wait ();

   // Steps 3 &  4.
-  if (state == JV_STATE_DONE || state == JV_STATE_IN_PROGRESS)
+  if (state == JV_STATE_DONE)
     {
       _Jv_MonitorExit (this);
       return;
     }
+  if (state == JV_STATE_IN_PROGRESS)
+    {
+      _Jv_MonitorExit (this);
+
+      /* Initialization in progress.  The class is linked now,
+         so ensure internal tables are built.  */
+      _Jv_PrepareConstantTimeTables (this);
+      _Jv_MakeVTable(this);
+      _Jv_LinkOffsetTable(this);
+
+      return;
+    }

   // Step 5.
   if (state == JV_STATE_ERROR)
@@ -1213,6 +1225,10 @@ _Jv_GetInterfaces (jclass klass, _Jv_ifa
   for (int i=0; i < klass->interface_count; i++)
     {
       jclass iface = klass->interfaces[i];
+
+      /* Make sure interface is linked.  */
+      _Jv_WaitForState(iface, JV_STATE_LINKED);
+
       if (_Jv_IndexOf (iface, (void **) ifaces->list, ifaces->count) == -1)
         {
 	  if (ifaces->count + 1 >= ifaces->len)
Index: java/lang/natClassLoader.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natClassLoader.cc,v
retrieving revision 1.57
diff -u -p -r1.57 natClassLoader.cc
--- java/lang/natClassLoader.cc	23 Dec 2002 19:59:31 -0000	1.57
+++ java/lang/natClassLoader.cc	3 Jan 2003 04:32:59 -0000
@@ -117,6 +117,10 @@ _Jv_WaitForState (jclass klass, int stat
     {
       // Must call _Jv_PrepareCompiledClass while holding the class
       // mutex.
+#ifdef INTERPRETER
+      if (_Jv_IsInterpretedClass (klass))
+	_Jv_PrepareClass (klass);
+#endif
       _Jv_PrepareCompiledClass (klass);
       _Jv_MonitorExit (klass);
       return;
@@ -141,15 +145,7 @@ _Jv_WaitForState (jclass klass, int stat
 void
 java::lang::ClassLoader::linkClass0 (java::lang::Class *klass)
 {
-  if (klass->state >= JV_STATE_LINKED)
-    return;
-
-#ifdef INTERPRETER
-  if (_Jv_IsInterpretedClass (klass))
-    _Jv_PrepareClass (klass);
-#endif
-
-  _Jv_PrepareCompiledClass (klass);
+  _Jv_WaitForState (klass, JV_STATE_LINKED);
 }

 void



More information about the Java-patches mailing list