[kaffe] Re: circular linking difficulties

Helmer Krämer hkraemer at freenet.de
Mon Jul 5 00:30:44 PDT 2004


On Tue, 29 Jun 2004 09:16:17 -0400 (EDT)
Rob Gonzalez <rgonzale at wso.williams.edu> wrote:

Hi Rob,

sorry for the delay.
 
> Are you sure that the problem we see there isn't that UnknownElement is in
> the midst of linking when that checkMethodCall() call is made?

More or less. The real problem seems to be that superclasses are brought
to LINKED when the subclass is LOADED. If verification of the superclass
requires the subclass to be LINKED, kaffe will incorrectly throw a
ClassCircularityError. 

With the attached path, I can run ant somewhat more successfully (It fails
because isArray(TNULL) doesn't work properly). However, it changes the
way classes are loaded so I might have broken something.

Regards,
Helmer
-------------- next part --------------
Index: kaffe/kaffevm/classMethod.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/classMethod.c,v
retrieving revision 1.119
diff -u -r1.119 classMethod.c
--- kaffe/kaffevm/classMethod.c	18 Apr 2004 13:57:26 -0000	1.119
+++ kaffe/kaffevm/classMethod.c	5 Jul 2004 07:22:46 -0000
@@ -193,10 +193,33 @@
 			else
 #endif
 			{
+				uintp idx = (uintp)class->superclass;
+				int tag = CLASS_CONSTANTS(class)->tags[idx];
+
+				if (tag != CONSTANT_Class) {
+					postExceptionMessage(einfo,
+							     JAVA_LANG(ClassFormatError),
+							     "%s (Invalid constant reference, %d, "
+							     "expecting class, likely an internal "
+							     "error)",
+							     class->name->data,
+							     tag);
+					success = false;
+					goto done;
+				}
+
 				class->superclass =
-					getClass((uintp)class->superclass,
-						 class,
-						 einfo);
+					loadClass (WORD2UTF(CLASS_CONSTANTS(class)->data[idx]),
+						   class->loader,
+						   einfo);
+
+				/* updating the const pool w/o holding a lock is ok, since no other
+				 * thread can use this class at this early stage
+				 */
+				if (class->superclass != NULL) {
+					CLASS_CONSTANTS(class)->tags[idx] = CONSTANT_ResolvedClass;
+					CLASS_CONSTANTS(class)->data[idx] = (ConstSlot)class->superclass;
+				}
 			}
 			
 			lockClass(class);
@@ -216,21 +239,26 @@
 				success = false;
 				goto done;
 			}
-			/* that's pretty much obsolete. */
-			assert(class->superclass->state >= CSTATE_DOING_LINK);
-			classMappingLoaded(ce, class);
 			/* Copy initial field size and gc layout.
 			 * Later, as this class's fields are resolved, they
 			 * are added to the superclass's layout.
 			 */
 			CLASS_FSIZE(class) = CLASS_FSIZE(class->superclass);
 			class->gc_layout = class->superclass->gc_layout;
+
+			/* Mark the class as loaded and set the state to CSTATE_LOADED_SUPER before
+			 * processing the superclass to LINKED. That way, we will process this class
+			 * to LINKED when it has to be loaded while verifying one of its superclasses.
+			 * Since the superclass is already PREPARED, possible ClassCircularityErrors
+			 * would've been detected earlier.
+			 */
+			classMappingLoaded(ce, class);
+			SET_CLASS_STATE(CSTATE_LOADED_SUPER);
+			if (processClass (class->superclass, CSTATE_LINKED, einfo) == false) {
+				success = false;
+				goto done;
+			}
 		}
-		if( class->superclass )
-		{
-			assert(class->superclass->state >= CSTATE_DOING_LINK);
-		}
-		
 	}
 	
 	DO_CLASS_STATE(CSTATE_VERIFIED) {
@@ -364,7 +392,8 @@
 		}
 		
 		SET_CLASS_STATE(CSTATE_DOING_LINK);
-		
+		class->processingThread = THREAD_NATIVE ();
+
 		/* Third stage verification - check the bytecode is okay */
 		success = verify3(class, einfo);
 		if (success == false) {
@@ -1477,8 +1506,7 @@
 				/* No joy, update state. */
 				setClassMappingState(ce, NMS_EMPTY);
 			}
-			else if( processClass(retval, CSTATE_LINKED, einfo)
-				 == false )
+			else if ( processClass(retval, CSTATE_PREPARED, einfo) == false )
 			{
 				retval = NULL;
 			}
Index: kaffe/kaffevm/itypes.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/itypes.c,v
retrieving revision 1.30
diff -u -r1.30 itypes.c
--- kaffe/kaffevm/itypes.c	7 Apr 2004 21:30:15 -0000	1.30
+++ kaffe/kaffevm/itypes.c	5 Jul 2004 07:22:46 -0000
@@ -186,6 +186,9 @@
 			return (0);
 		}
 		cl = loadClass(utf8, loader, einfo);
+		if (cl != NULL && !processClass (cl, CSTATE_LINKED, einfo)) {
+			cl = NULL;
+		}
 		utf8ConstRelease(utf8);
 		return(cl);
 
@@ -212,12 +215,13 @@
 	if (cls != 0 && *sig == 0) {
 		return (cls);
 	}
+
 	/* 
 	 * or rather VerifyError?  It could be a malformed sig in a malformed
 	 * .class file, or it could be a malformed user input from 
 	 * Class.forName()
 	 */
-	postExceptionMessage(einfo, JAVA_LANG(NoClassDefFoundError), "%s", sig0);
+	/* postExceptionMessage(einfo, JAVA_LANG(NoClassDefFoundError), "%s", sig0); */
 	return (0);
 }
 
Index: kaffe/kaffevm/lookup.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/lookup.c,v
retrieving revision 1.35
diff -u -r1.35 lookup.c
--- kaffe/kaffevm/lookup.c	29 Mar 2004 21:13:33 -0000	1.35
+++ kaffe/kaffevm/lookup.c	5 Jul 2004 07:22:46 -0000
@@ -221,6 +221,12 @@
 		return NULL;
 	}
 
+	/* process the class to LINKED if necessary */
+	if (processClass (class, CSTATE_LINKED, einfo) == false)
+	{
+		return NULL;
+	}
+
 	/* Lock the class while we update the constant pool.  Someone
 	 * may have done this already but we don't care.
 	 */
Index: libraries/clib/native/Class.c
===================================================================
RCS file: /cvs/kaffe/kaffe/libraries/clib/native/Class.c,v
retrieving revision 1.73
diff -u -r1.73 Class.c
--- libraries/clib/native/Class.c	21 May 2004 15:19:24 -0000	1.73
+++ libraries/clib/native/Class.c	5 Jul 2004 07:22:46 -0000
@@ -118,6 +118,9 @@
 	if (doinit && processClass(clazz, CSTATE_COMPLETE, &einfo) == false) {
 		throwError(&einfo);
 	}
+	else if (!doinit && processClass(clazz, CSTATE_LINKED, &einfo) == false) {
+		throwError(&einfo);
+	}
 	return (clazz);
 }
 
Index: libraries/clib/native/PrimordialClassLoader.c
===================================================================
RCS file: /cvs/kaffe/kaffe/libraries/clib/native/PrimordialClassLoader.c,v
retrieving revision 1.3
diff -u -r1.3 PrimordialClassLoader.c
--- libraries/clib/native/PrimordialClassLoader.c	21 May 2004 15:19:24 -0000	1.3
+++ libraries/clib/native/PrimordialClassLoader.c	5 Jul 2004 07:22:46 -0000
@@ -53,19 +53,7 @@
 		{
 			clazz = loadClass(c, 0, &info);
 		}
-		if( clazz )
-		{
-			/*
-			 * do not process to COMPLETE, it will run static
-			 * initializers prematurely!
-			 */
-			if( processClass(clazz, CSTATE_LINKED, &info) ==
-			    false )
-			{
-				error = 1;
-			}
-		}
-		else
+		if( clazz == NULL )
 		{
 			error = 1;
 		}


More information about the kaffe mailing list