[kaffe] Weak references/Class destruction

Guilhem Lavaux guilhem at kaffe.org
Thu Dec 23 10:01:33 PST 2004


Hi,

I've implemented the idea. It looks like working fine though instanceof does
not like some particular cases with the new implementation: CLASS_IS_ARRAY,
CLASS_IS_INTERFACE are normal special cases as they do not have any 
implementors
and so we cannot find their interface ancestors. But it looks like there 
are some others
when looking at the testcases results. I have still not found them as 
I'm trying to
fix a deadlock in GCTest.

Also, I think I can remove safely the atomic exchange in 
soft_fixup_trampoline now and only put a "*where = ret".

Anyway here is the new patch.

Regards,

Guilhem Lavaux.

Helmer Krämer wrote:

>Guilhem Lavaux <guilhem at kaffe.org> wrote:
>
>  
>
>>Helmer Krämer wrote:
>>
>>    
>>
>>>Guilhem Lavaux <guilhem at kaffe.org> wrote:
>>>
>>>Hi,
>>>
>>> 
>>>
>>>      
>>>
>>>>Here is a patch which changes the way the classes are destroyed and 
>>>>implements
>>>>weak references for boehm-gc and kaffe-gc. This fixes class concurrent
>>>>destruction issues which was bugging boehm-gc (and maybe also kaffe-gc) and
>>>>should insure that we do not access already freed memory.
>>>>   
>>>>
>>>>        
>>>>
>>>If I remember it correctly, the problems with boehm-gc and
>>>garbage collecting classes are:
>>>
>>>a) Suppose class A  is the only class implementing interface I. If
>>>  A becomes unreachable, so does I. In this case however, there's
>>>  no guarantee that C is destroyed before I. This means that destroyClass
>>>  has to deal with the fact that I might already have been destroyed
>>>  when C is destroyed. This gets complicated for the implementors
>>>  table and the interface dispatch tables because destroyClass has
>>>  to remove C from some of the structures stored inside I.
>>>
>>>b) Same thing when a class A and its super class A' become unreachable
>>>  at the same time. In this case, some of the pointers stored in the
>>>  vtable (and interface dispatch table) may no longer be valid because
>>>  A' was already destroyed.
>>>
>>>The solution for a) is to use weak references.
>>>
>>>The solution for b) is to use allocation types that are automatically
>>>freed by the gc for everything that might be stored in a vtable (or
>>>interface dispatch table).
>>>
>>>Is this correct so far?
>>>
>>> 
>>>
>>>      
>>>
>>Completely right ! :)
>>    
>>
>
>Cool :)
>
>The solution for Problem b looks fine to me too, although I'm missing
>freeing the gc_layout bitmap (I might have overlooked that, though).
>
>For Problem a, I'm going to describe an alternative  solution that
>doesn't need weak references, mainly to get some arguments for the
>different implementations into the mail archives (the implementation
>of weak references itself seems ok to me and should go in so we can
>have support for java.lang.ref later on).
>
>The itable2dtable of a class is just one large chunk of memory
>containing all dispatch tables of all interfaces. If we stored
>the Hjava_lang_Class* of the class owning the itable2dtable at
>the beginning of the table, we could use KGC_getObjectBase to get
>the class implementing the interfaces (sort of like its done in
>stackTrace.c to retrieve the java method of a given pc). All we
>need is a pointer somewhere into the itable2dtable chunk.
>
>If we further modified the implementors table to store a pointer into
>the itable2dtable instead of an index (soft_lookupinterfacemethod
>would look like ncode = ifclass->implementors[cls->impl_idx][idx+1]),
>we should get all the information we need to implement destroyClass
>without relaying on the gc to keep track of destroyed objects:
>
>A class can still remove itself from the implemented interfaces.
>An interface can remove itself from the implementing classes by
>traversing the implementors table and using KGC_getObjectBase to
>get the implementing class. Since a class is removed from the
>implementors table when it is destroyed, we can assume that the
>pointers stored in the implementors table are valid when an
>interface is destroyed.
>
>Having this sort of table would probably also allow us to easily
>implement instanceof_interface in constant time.
>
>Regards,
>Helmer
>
>_______________________________________________
>kaffe mailing list
>kaffe at kaffe.org
>http://kaffe.org/cgi-bin/mailman/listinfo/kaffe
>
>  
>

-------------- next part --------------
? systems/unix-pthreads/.thread-impl.c.swp
Index: baseClasses.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/baseClasses.c,v
retrieving revision 1.56
diff -u -r1.56 baseClasses.c
--- baseClasses.c	19 Dec 2004 06:25:07 -0000	1.56
+++ baseClasses.c	23 Dec 2004 18:02:50 -0000
@@ -261,6 +261,8 @@
 {
         errorInfo einfo;
 
+	memset(&dummyClassClass, 0, sizeof(dummyClassClass));
+
         /* Primitive types */
         initTypes();
 	initVerifierPrimTypes();
Index: classMethod.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/classMethod.c,v
retrieving revision 1.130
diff -u -r1.130 classMethod.c
--- classMethod.c	21 Dec 2004 08:06:36 -0000	1.130
+++ classMethod.c	23 Dec 2004 18:02:51 -0000
@@ -196,7 +196,7 @@
 #endif
 			{
 				class->superclass =
-					getClass((uintp)class->superclass,
+					getClass((constIndex)(uintp)class->superclass,
 						 class,
 						 einfo);
 			}
@@ -207,6 +207,7 @@
 				success = false;
 				goto done;
 			}
+			KGC_addWeakRef(main_collector, class->superclass, &(class->superclass));
 			if( !(class->accflags & ACC_INTERFACE) &&
 			    (class->superclass->accflags & ACC_INTERFACE)) {
 				postExceptionMessage(
@@ -622,7 +623,6 @@
 #endif
 		    1) {
 			_SET_METHOD_NATIVECODE(meth, NULL);
-			KFREE(meth->c.ncode.ncode_start);
 			meth->c.ncode.ncode_start = NULL;
 			meth->c.ncode.ncode_end = NULL;
 		}
@@ -803,6 +803,7 @@
 #endif /* HAVE_GCJ_SUPPORT */
 
 		class->interfaces[i] = nclass;
+
 		lockClass(class);
 		if (class->interfaces[i] == 0) {
 			success = false;
@@ -854,10 +855,6 @@
 				newifaces[i] = nclass->interfaces[j];
 			}
 		}
-		/* free old list of interfaces */
-		if (class->interfaces != 0) {
-			KFREE(class->interfaces);
-		}
 		class->interfaces = newifaces;
 	}
 
@@ -2091,26 +2088,31 @@
 		return (true);
 	}
 
-	class->if2itable = gc_malloc(class->total_interface_len * sizeof(short), KGC_ALLOC_CLASSMISC);
+	class->if2itable = gc_malloc((class->total_interface_len + 1) * sizeof(short), KGC_ALLOC_CLASSMISC);
 
 	if (class->if2itable == 0) {
 		postOutOfMemory(einfo);
 		return (false);
 	}
 
-	/* first count how many indices we need */
-	j = 0;
+	/* first count how many indices we need. We need at least one entry to put
+	 * the pointer to the class.
+	 */
+	j = 1;
 	for (i = 0; i < class->total_interface_len; i++) {
 		class->if2itable[i] = j;
 		j += 1;		/* add one word to store interface class */
 		j += class->interfaces[i]->msize;
 	}
-	class->itable2dtable = gc_malloc(j * sizeof(void *), KGC_ALLOC_CLASSMISC);
+	/* This last entry is to specify the total length of the table. */
+	class->if2itable[class->total_interface_len] = j;
+	class->itable2dtable = gc_malloc(j * sizeof(void *), KGC_ALLOC_INTERFACE_TABLE);
 	if (class->itable2dtable == 0) {
 		postOutOfMemory(einfo);
 		return (false);
 	}
-	j = 0;
+	class->itable2dtable[0] = class;
+	j = 1;
 	for (i = 0; i < class->total_interface_len; i++) {
 		int inm = CLASS_NMETHODS(class->interfaces[i]);
 		Method *imeth = CLASS_METHODS(class->interfaces[i]);
@@ -2249,15 +2251,17 @@
 		found_i = 1;
 		for (j = 0; j < clazz->total_interface_len; j++) {
 			Hjava_lang_Class* iface = clazz->interfaces[j];
-	    		int len = 0;
+	    		uintp len = 0;
 
-			if (iface->implementors != 0) {
+			if (iface->implementors != NULL) {
 				/* This is how many entries follow, so the
-				 * array has a[0] + 1 elements
+				 * array has a[0] + 1 elements. We have to convert
+				 * the value from pointer type (which is at least 16 bits
+				 * as previously).
 				 */
-				len = iface->implementors[0];
+			        len = (uintp)iface->implementors[0];
 			}
-			if (i >= len || iface->implementors[i+1] == -1) {
+			if (i >= len || iface->implementors[i+1] == NULL) {
 				continue;	/* this one would work */
 			} else {
 				found_i = 0;
@@ -2277,41 +2281,38 @@
 	 */
 	for (j = 0; j < clazz->total_interface_len; j++) {
 		Hjava_lang_Class* iface = clazz->interfaces[j];
-		short len;
+		uintp len;
 
 		/* make sure the implementor table is big enough */
-		if (iface->implementors == NULL || i > iface->implementors[0]) {
-			short firstnewentry;
+		if (iface->implementors == NULL || i > (uintp)iface->implementors[0]) {
 			if (iface->implementors == NULL) {
 				len = (i + 1) + 4; /* 4 is slack only */
-				iface->implementors = gc_malloc(len * sizeof(short), KGC_ALLOC_CLASSMISC);
+				iface->implementors = (void ***)gc_malloc(len * sizeof(void **), KGC_ALLOC_CLASSMISC);
 			} else {
 				/* double in size */
-				len = iface->implementors[0] * 2;
+				len = (uintp)iface->implementors[0] * 2;
 				if (len <= i) {
 					len = i + 4;
 				}
-				iface->implementors = gc_realloc(
+				iface->implementors = (void ***)gc_realloc(
 					iface->implementors,
-					len * sizeof(short), KGC_ALLOC_CLASSMISC);
+					len * sizeof(void **), KGC_ALLOC_CLASSMISC);
 			}
 
-			if (iface->implementors == 0) {
+			if (iface->implementors == NULL) {
 				postOutOfMemory(einfo);
 				goto done;
 			}
 			/* NB: we assume KMALLOC/KREALLOC zero memory out */
-			firstnewentry = iface->implementors[0] + 1;
-			iface->implementors[0] = len - 1;
+			iface->implementors[0] = (void *)(len - 1);
 
-			/* mark new entries as unused */
-			for (k = firstnewentry; k < len; k++) {
-				iface->implementors[k] = -1;
-			}
+			/* New entries are magically marked as unused by the GC
+			 * as it fills the memory with 0.
+			 */
 		}
 
-		assert(i < iface->implementors[0] + 1);
-		iface->implementors[i] = clazz->if2itable[j];
+		assert(i < (uintp)iface->implementors[0] + 1);
+		iface->implementors[i] = &(clazz->itable2dtable[clazz->if2itable[j]]);
 	}
 	rc = true;
 
Index: classMethod.h
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/classMethod.h,v
retrieving revision 1.73
diff -u -r1.73 classMethod.h
--- classMethod.h	21 Dec 2004 16:51:05 -0000	1.73
+++ classMethod.h	23 Dec 2004 18:02:54 -0000
@@ -131,9 +131,9 @@
 	void**			itable2dtable;
 	short			interface_len;
 	short			total_interface_len;
-	/* indices for all classes implementing this interface */
-	short*			implementors;	/* interfaces only */
-	int			impl_index;
+	/* pointers to all itable2dtable entries of classes implementing this interface */
+	void***			implementors;	/* interfaces only */
+        int			impl_index;    /* index of the class in the implementors array. */
 
 	Hjava_lang_ClassLoader*	loader;
 
Index: gc.h
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/gc.h,v
retrieving revision 1.30
diff -u -r1.30 gc.h
--- gc.h	21 Dec 2004 08:06:36 -0000	1.30
+++ gc.h	23 Dec 2004 18:02:54 -0000
@@ -72,6 +72,7 @@
 	KGC_ALLOC_LINENRTABLE,
 	KGC_ALLOC_LOCALVARTABLE,
 	KGC_ALLOC_DECLAREDEXC,
+	KGC_ALLOC_INTERFACE_TABLE,
 	KGC_ALLOC_CLASSMISC,
 
 	/* miscelanious allocation types */
@@ -138,6 +139,8 @@
 
         bool    (*addRef)(Collector *, const void *mem);
         bool    (*rmRef)(Collector *, void *ref);
+        bool    (*addWeakRef)(Collector *, void *mem, void **ref);
+        bool    (*rmWeakRef)(Collector *, void *mem, void **ref);
 };
 
 Collector* createGC(void);
@@ -167,6 +170,10 @@
     ((G)->ops->addRef)((Collector*)(G), (addr))
 #define KGC_rmRef(G, addr) \
     ((G)->ops->rmRef)((Collector*)(G), (addr))
+#define KGC_addWeakRef(G, addr, ref) \
+    ((G)->ops->addWeakRef((Collector *)(G), (addr), (ref)))
+#define KGC_rmWeakRef(G, addr, ref) \
+    ((G)->ops->rmWeakRef((Collector *)(G), (addr), (ref)))
 
 #if !defined(KAFFEH)
 static inline void KGC_markObject(void *g, void *gc_info, const void *addr)
Index: gcFuncs.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/gcFuncs.c,v
retrieving revision 1.62
diff -u -r1.62 gcFuncs.c
--- gcFuncs.c	21 Dec 2004 16:51:05 -0000	1.62
+++ gcFuncs.c	23 Dec 2004 18:02:54 -0000
@@ -44,6 +44,7 @@
 #include "thread.h"
 #include "methodCache.h"
 #include "jvmpi_kaffe.h"
+#include "methodcalls.h"
 
 /*****************************************************************************
  * Class-related functions
@@ -135,22 +136,16 @@
 				}
 #endif
 			}
-                        utf8ConstRelease(m->name);
+			utf8ConstRelease(m->name);
                         utf8ConstRelease(METHOD_SIG(m));
                         KFREE(METHOD_PSIG(m));
                         KFREE(m->lines);
 			KFREE(m->lvars);
 			if( m->ndeclared_exceptions != -1 )
-				KFREE(m->declared_exceptions);
+			  KFREE(m->declared_exceptions);
                         KFREE(m->exception_table);
-                        KFREE(m->c.bcode.code);	 /* aka c.ncode.ncode_start */
 
-			/* Free ncode if necessary: this concerns
-			 * any uninvoked trampolines
-			 */
-			if (KGC_getObjectIndex(collector, ncode) != -1) {
-				KFREE(ncode);
-			}
+			/* ncode is swept by the GC. */
 			m++;
                 }
                 KFREE(CLASS_METHODS(clazz));
@@ -167,71 +162,78 @@
 		}
 	}
 	/* free constant pool */
-	if (pool->data != 0) {
-		KFREE(pool->data);
-	}
+	if (pool->data != NULL)
+	  {
+	    KFREE(pool->data);
+	  }
 
         /* free various other fixed things */
         KFREE(CLASS_STATICDATA(clazz));
-	if( clazz->vtable )
-	{
-		for( i = 0; i < clazz->msize; i++ )
-		{
-			if( clazz->vtable->method[i] == 0 )
-				continue;
-			/* Free ncode if necessary: this concerns
-			 * any uninvoked trampolines
-			 */
-			if (KGC_getObjectIndex(collector,
-					      clazz->vtable->method[i])
-			    == KGC_ALLOC_DISPATCHTABLE) {
-				KFREE(clazz->vtable->method[i]);
-			}
-		}
-		KFREE(clazz->vtable);
-	}
-        KFREE(clazz->if2itable);
-	if( clazz->itable2dtable )
-	{
-		for (i = 0; i < clazz->total_interface_len; i++) {
-			Hjava_lang_Class* iface = clazz->interfaces[i];
 
-			/* only if interface has not been freed already */
-			if (KGC_getObjectIndex(collector, iface)
-			    == KGC_ALLOC_CLASSOBJECT)
-			{
-				iface->implementors[clazz->impl_index] = -1;
-			}
-		}
+       	if(clazz->vtable != NULL)
+	  {
+	    /* The native methods in the vtable are swept by the GC. */
+	    KFREE(clazz->vtable);
+	  }
 
-		/* NB: we can't just sum up the msizes of the interfaces
-		 * here because they might be destroyed simultaneously
+        KFREE(clazz->if2itable);
+
+	if (clazz->implementors != NULL)
+	  {
+	    uintp len, uidx;
+
+	    len = (uintp)clazz->implementors[0] + 1;
+	    for (uidx = 1; uidx < len; uidx++)
+	      {
+		void *impl = clazz->implementors[uidx];
+		Hjava_lang_Class **impl_clazz;
+
+		if (impl == NULL)
+		  continue;
+		
+		impl_clazz = (Hjava_lang_Class **)KGC_getObjectBase(collector, impl);
+		assert(impl_clazz != NULL);
+
+		/* We must walk the list of interfaces for this class and
+		 * unregister this interface. As the class should also be
+		 * freed (in the other case this interface would not have 
+		 * been destroyed), there is no problem with this.
 		 */
-		j = KGC_getObjectSize(collector, clazz->itable2dtable)
-			/ sizeof (void*);
-		for( i = 0; i < j; i++ )
-		{
-			if (KGC_getObjectIndex(collector,
-					      clazz->itable2dtable[i])
-			    == KGC_ALLOC_DISPATCHTABLE) {
-				KGC_free(collector, clazz->itable2dtable[i]);
-			}
-		}
-		KGC_free(collector, clazz->itable2dtable);
-	}
-	if( clazz->gc_layout &&
-	    (clazz->superclass->gc_layout != clazz->gc_layout) )
+		for (i = 0; i < (*impl_clazz)->total_interface_len; i++)
+		  if ((*impl_clazz)->interfaces[i] == clazz)
+		    {
+		      (*impl_clazz)->interfaces[i] = NULL;
+		      break;
+		    }
+	      }
+	    
+	    KFREE(clazz->implementors);
+	  }
+
+	if( clazz->itable2dtable )
 	{
-		KFREE(clazz->gc_layout);
+	  for (i = 0; i < clazz->total_interface_len; i++) {
+	    Hjava_lang_Class* iface = clazz->interfaces[i];
+	    
+	    /* only if interface has not been freed already. We
+	     * update the implementors section of the interface
+	     * accordingly.
+	     */
+	    if (iface != NULL)
+	      iface->implementors[clazz->impl_index] = NULL;
+	  }
+	  /* The itable2dtable table will be automatically swept by the
+	   * GC when the class becomes unused as it is only marked while
+	   * the class is being walked (see walkClass).
+	   */
 	}
+	if (clazz->gc_layout != NULL && clazz->superclass != NULL &&
+	    clazz->superclass->gc_layout != clazz->gc_layout)
+	  KFREE(clazz->gc_layout);
+
 	KFREE(clazz->sourcefile);
-	KFREE(clazz->implementors);
 	KFREE(clazz->inner_classes);
 
-        /* The interface table for array classes points to static memory */
-        if (!CLASS_IS_ARRAY(clazz)) {
-                KFREE(clazz->interfaces);
-        }
         utf8ConstRelease(clazz->name);
 }
 
@@ -243,7 +245,19 @@
 walkMethods(Collector* collector, void *gc_info, Method* m, int nm)
 {
         while (nm-- > 0) {
+	        int index;
+
                 KGC_markObject(collector, gc_info, m->class);
+		
+		index = KGC_getObjectIndex(collector, m->ncode);
+		if (index == KGC_ALLOC_JITCODE || index == KGC_ALLOC_TRAMPOLINE)
+		  KGC_markObject(collector, gc_info, m->ncode);
+		
+		index = KGC_getObjectIndex(collector, m->c.bcode.code);
+		if (index == KGC_ALLOC_JITCODE || index == KGC_ALLOC_TRAMPOLINE ||
+		    index == KGC_ALLOC_BYTECODE)
+		  KGC_markObject(collector, gc_info, m->c.bcode.code);
+		
 
                 /* walk exception table in order to keep resolved catch types
                    alive */
@@ -282,7 +296,35 @@
 
         if (class->state >= CSTATE_PREPARED) {
                 KGC_markObject(collector, gc_info, class->superclass);
-        }
+        } 
+
+        /* We only need the interface array to be allocated.
+	 * We do not want to mark array's interfaces as the pointer is
+	 * static (see lookupArray). */
+	if (class->interfaces != NULL && CLASS_CNAME(class)[0] != '[')
+          {
+            KGC_markObject(collector, gc_info, class->interfaces);
+          }
+
+	if (class->itable2dtable != NULL)
+	  {
+	    unsigned int len = class->if2itable[class->total_interface_len];
+	    KGC_markObject(collector, gc_info, class->itable2dtable);
+
+	    for (idx = 1; idx < len; idx++)
+	      {
+		void *method = class->itable2dtable[idx];
+		int index;
+		
+		if (method == (void*)-1)
+		  continue;
+		
+		index = KGC_getObjectIndex(collector, method);
+		
+		if (index == KGC_ALLOC_JITCODE || index == KGC_ALLOC_TRAMPOLINE)
+		  KGC_markObject(collector, gc_info, method);
+	      }
+	  }
 
         /* walk constant pool - only resolved classes and strings count */
         pool = CLASS_CONSTANTS(class);
@@ -298,6 +340,18 @@
                 }
         }
 
+	/* walk the local vtable */
+	if (class->vtable != NULL && !CLASS_IS_PRIMITIVE(class))
+	  for (idx = 0; idx < class->msize; idx++)
+	    {
+	      void *method = class->vtable->method[idx];
+	      int index = KGC_getObjectIndex(collector, method);
+
+	      if (index == KGC_ALLOC_JITCODE || index == KGC_ALLOC_TRAMPOLINE ||
+		  index == KGC_ALLOC_BYTECODE)
+		KGC_markObject(collector, gc_info, method);
+	    }
+
         /*
          * NB: We suspect that walking the class pool should suffice if
          * we ensured that all classes referenced from this would show up
@@ -370,6 +424,25 @@
 		}
         }
 
+	/* Now we walk the interface table pointer. */
+	if (class->itable2dtable != NULL)
+	  {
+	    unsigned int num_interfaces;
+
+	    KGC_markObject(collector, gc_info, class->itable2dtable);
+	    /* We want the number of interfaces registered in the table. As
+	     * this number is not recorded in the table we recompute it
+	     * quickly using if2itable. (See classMethod.c/buildInterfaceDispatchTable).
+	     */
+	    for (idx = 1, n = 0; n < class->total_interface_len; n++)
+	      {
+		void *iface = class->itable2dtable[idx];
+		
+		KGC_markObject(collector, gc_info, iface);
+		idx += class->interfaces[n]->msize+1;
+	      }
+	  }
+
         /* CLASS_METHODS only points to the method array for non-array and
          * non-primitive classes */
         if (!CLASS_IS_PRIMITIVE(class) && !CLASS_IS_ARRAY(class) && CLASS_METHODS(class) != 0) {
@@ -613,11 +686,19 @@
 	    "j.l.ClassLoader");
 	KGC_registerGcTypeByIndex(gc, KGC_ALLOC_THREADCTX, 
 	    NULL, KGC_OBJECT_NORMAL, NULL, "thread-ctxts");
+	KGC_registerGcTypeByIndex(gc, KGC_ALLOC_INTERFACE,
+  	    NULL, KGC_OBJECT_NORMAL, NULL, "interfaces");
+	KGC_registerGcTypeByIndex(gc, KGC_ALLOC_INTERFACE_TABLE,
+            NULL, KGC_OBJECT_NORMAL, NULL, "interface table");
+	KGC_registerGcTypeByIndex(gc, KGC_ALLOC_TRAMPOLINE,
+	    NULL, KGC_OBJECT_NORMAL, NULL, "trampoline");
+	KGC_registerGcTypeByIndex(gc, KGC_ALLOC_JITCODE,
+	    NULL, KGC_OBJECT_NORMAL, NULL, "jit-code");
+	KGC_registerGcTypeByIndex(gc, KGC_ALLOC_BYTECODE,
+	    NULL, KGC_OBJECT_NORMAL, NULL, "java-bytecode");
 
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_STATIC_THREADDATA, "thread-data");
-	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_BYTECODE, "java-bytecode");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_EXCEPTIONTABLE, "exc-table");
-	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_JITCODE, "jitcode");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_STATICDATA, "static-data");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_CONSTANT, "constants");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_FIXED, "other-fixed");
@@ -625,7 +706,6 @@
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_METHOD, "methods");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_FIELD, "fields");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_UTF8CONST, "utf8consts");
-	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_INTERFACE, "interfaces");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_LOCK, "locks");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_REF, "gc-refs");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_JITTEMP, "jit-temp-data");
@@ -637,7 +717,6 @@
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_DECLAREDEXC, "declared-exc");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_CLASSMISC, "class-misc");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_VERIFIER, "verifier");
-	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_TRAMPOLINE, "trampoline");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_NATIVELIB, "native-lib");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_JIT_SEQ, "jit-seq");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_JIT_CONST, "jit-const");
Index: soft.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/soft.c,v
retrieving revision 1.73
diff -u -r1.73 soft.c
--- soft.c	21 Dec 2004 05:49:59 -0000	1.73
+++ soft.c	23 Dec 2004 18:02:54 -0000
@@ -238,7 +238,7 @@
 	Hjava_lang_Class* cls;
 	void*	ncode;
 	register int i;
-	register short* implementors;
+	register void*** implementors;
 
 	if (obj == NULL) {
 		soft_nullpointer();
@@ -262,7 +262,7 @@
 	}
 #endif
 	/* skip word at the beginning of itable2dtable */
-	ncode = cls->itable2dtable[implementors[i] + idx + 1];
+	ncode = implementors[i][idx + 1];
 
 	/* This means this class does not implement this interface method
 	 * at all.  This is something we detect at the time the interface
@@ -272,11 +272,11 @@
 	 * is that's missing (or create multiple nosuch_method routines,
 	 * given that they should be rare---minus possible DoS.)
 	 */
-	if (ncode == (void *)-1) {
-		return NULL;
-	}
+	if (ncode == (void *)-1)
+	  return NULL;
 	assert(ncode != NULL);
-	return (ncode);
+
+	return ncode;
 }
 
 inline
@@ -299,14 +299,38 @@
 instanceof_interface(Hjava_lang_Class* c, Hjava_lang_Class* oc)
 {
 	int i;
+	Hjava_lang_Class **impl_clazz;
 
-	/* Check 'total' interface list */
-	for (i = oc->total_interface_len - 1; i >= 0; i--) {
-		if (c == oc->interfaces[i]) {
-			return (1);
-		}
-	}
-	return (0);
+	if (1 || c->state < CSTATE_PREPARED || CLASS_IS_ARRAY(oc) || CLASS_IS_INTERFACE(oc))
+	  {
+	    /* Check 'total' interface list. If the class is not
+	     * prepared the dumb way is the only way. Arrays and interface do not have
+	     * any implementors too so we have to go through the all list.
+	     */
+	    for (i = oc->total_interface_len - 1; i >= 0; i--) {
+	      if (c == oc->interfaces[i]) {
+		return 1;
+	      }
+	    }
+	    return 0;
+	  }
+	else
+	  {
+	    /* Fetch the implementation reference from the class. */
+	    i = oc->impl_index;
+	    /* No interface implemented or this class is not implementing this
+	     * interface. Bailing out. */
+	    if (i == 0 || i >= (uintp)c->implementors[0] ||
+		c->implementors[i] == NULL)
+	      return 0;
+	    
+	    /* We retrieve the first pointer in the itable2dtable array. */
+	    impl_clazz = (Hjava_lang_Class **)(KGC_getObjectBase(main_collector, c->implementors[i]));
+	    assert(impl_clazz != NULL);
+	    
+	    /* Now we may compare the raw pointers. */
+	    return (*impl_clazz == oc);
+	  }
 }
 
 inline
Index: boehm-gc/gc-refs.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/boehm-gc/gc-refs.c,v
retrieving revision 1.3
diff -u -r1.3 gc-refs.c
--- boehm-gc/gc-refs.c	9 Aug 2004 08:18:21 -0000	1.3
+++ boehm-gc/gc-refs.c	23 Dec 2004 18:02:54 -0000
@@ -29,17 +29,29 @@
 #include "gc2.h"
 
 #define	REFOBJHASHSZ	128
-typedef struct _refObject {
+typedef struct _strongRefObject {
   const void*		mem;
   unsigned int		ref;
-  struct _refObject*	next;
-} refObject;
+  struct _strongRefObject* next;
+} strongRefObject;
 
-typedef struct _refTable {
-  refObject*		hash[REFOBJHASHSZ];
-} refTable;
+typedef struct _strongRefTable {
+  strongRefObject*		hash[REFOBJHASHSZ];
+} strongRefTable;
+
+typedef struct _weakRefObject {
+  const void *          mem;
+  unsigned int          ref;
+  void ***              allRefs;
+  struct _weakRefObject *next;
+} weakRefObject;
+
+typedef struct _weakRefTable {
+  weakRefObject*               hash[REFOBJHASHSZ];
+} weakRefTable;
 
-static refTable			refObjects;
+static strongRefTable			strongRefObjects;
+static weakRefTable                     weakRefObjects;
 
 /* This is a bit homemade.  We need a 7-bit hash from the address here */
 #define	REFOBJHASH(V)	((((uintp)(V) >> 2) ^ ((uintp)(V) >> 9))%REFOBJHASHSZ)
@@ -51,10 +63,10 @@
 KaffeGC_addRef(Collector *collector, const void* mem)
 {
   uint32 idx;
-  refObject* obj;
+  strongRefObject* obj;
 
   idx = REFOBJHASH(mem);
-  for (obj = refObjects.hash[idx]; obj != 0; obj = obj->next) {
+  for (obj = strongRefObjects.hash[idx]; obj != 0; obj = obj->next) {
     /* Found it - just increase reference */
     if (obj->mem == mem) {
       obj->ref++;
@@ -63,14 +75,14 @@
   }
 
   /* Not found - create a new one */
-  obj = (refObject*)GC_malloc_uncollectable(sizeof(refObject));
+  obj = (strongRefObject*)GC_malloc_uncollectable(sizeof(strongRefObject));
   if (!obj)
     return false;
 	
   obj->mem = ALIGN_BACKWARD(mem);
   obj->ref = 1;
-  obj->next = refObjects.hash[idx];
-  refObjects.hash[idx] = obj;
+  obj->next = strongRefObjects.hash[idx];
+  strongRefObjects.hash[idx] = obj;
   return true;
 }
 
@@ -82,13 +94,13 @@
 KaffeGC_rmRef(Collector *collector, const void* mem)
 {
   uint32 idx;
-  refObject** objp;
-  refObject* obj;
+  strongRefObject** objp;
+  strongRefObject* obj;
 
   idx = REFOBJHASH(mem);
   mem = ALIGN_BACKWARD(mem);
 
-  for (objp = &refObjects.hash[idx]; *objp != 0; objp = &obj->next) {
+  for (objp = &strongRefObjects.hash[idx]; *objp != 0; objp = &obj->next) {
     obj = *objp;
     /* Found it - just decrease reference */
     if (obj->mem == mem) {
@@ -103,4 +115,117 @@
 
   /* Not found!! */
   return false;
+}
+
+bool
+KaffeGC_addWeakRef(Collector *collector, void* mem, void** refobj)
+{
+  int idx;
+  weakRefObject* obj;
+
+  idx = REFOBJHASH(mem);
+  for (obj = weakRefObjects.hash[idx]; obj != 0; obj = obj->next) {
+    /* Found it - just register a new weak reference */
+    if (obj->mem == mem) {
+      void ***newRefs;
+      obj->ref++;
+
+      newRefs = (void ***)GC_malloc_uncollectable(sizeof(void ***)*obj->ref);
+      memcpy(newRefs, obj->allRefs, sizeof(void ***)*(obj->ref-1));
+      GC_free(obj->allRefs);
+
+      obj->allRefs = newRefs;
+      obj->allRefs[obj->ref-1] = refobj;
+      return true;
+    }
+  }
+
+  /* Not found - create a new one */
+  obj = (weakRefObject*)GC_malloc_uncollectable(sizeof(weakRefObject));
+  if (!obj)
+    return false;
+
+  obj->mem = mem;
+  obj->ref = 1;
+  obj->allRefs = (void ***)GC_malloc_uncollectable(sizeof(void ***));
+  obj->allRefs[0] = refobj;
+  obj->next = weakRefObjects.hash[idx];
+  weakRefObjects.hash[idx] = obj;
+  return true;
+}
+
+bool
+KaffeGC_rmWeakRef(Collector *collector, void* mem, void** refobj)
+{
+  uint32 idx;
+  weakRefObject** objp;
+  weakRefObject* obj;
+  unsigned int i;
+
+  idx = REFOBJHASH(mem);
+  for (objp = &weakRefObjects.hash[idx]; *objp != 0; objp = &obj->next) {
+    obj = *objp;
+    /* Found it - just decrease reference */
+    if (obj->mem == mem)
+      {
+	for (i = 0; i < obj->ref; i++)
+	  {
+	    if (obj->allRefs[i] == refobj)
+	      {
+		void ***newRefs;
+		
+		obj->ref--;
+		newRefs = (void ***)GC_malloc_uncollectable(sizeof(void ***)*obj->ref);
+		memcpy(newRefs, obj->allRefs, i*sizeof(void ***));
+		memcpy(&newRefs[i], &obj->allRefs[i+1], obj->ref*sizeof(void ***));
+		GC_free(obj->allRefs);
+		obj->allRefs = newRefs;
+		break;
+	      }
+	  }
+	if (i == obj->ref)
+	  return false;
+	if (obj->ref == 0) {
+	  *objp = obj->next;
+	  GC_free(obj);
+	}
+	return true;
+      }
+  }
+
+  /* Not found!! */
+  return false;
+}
+
+/**
+ * This function clear all weak references to the specified object. 
+ * The references are then removed from the database.
+ *
+ * @param collector a garbage collector instance.
+ * @param mem a valid memory object.
+ */
+void
+KaffeGC_clearWeakRef(Collector *collector, void* mem)
+{ 
+  uint32 idx;
+  weakRefObject** objp;
+  weakRefObject* obj;
+  unsigned int i;
+
+  idx = REFOBJHASH(mem);
+  for (objp = &weakRefObjects.hash[idx]; *objp != 0; objp = &obj->next)
+    {
+      obj = *objp;
+      /* Found it - clear all references attached to it. */
+      if (obj->mem == mem)
+	{
+	  for (i = 0; i < obj->ref; i++)
+	    *(obj->allRefs[i]) = NULL;
+	  GC_free(obj->allRefs);
+
+	  *objp = obj->next;
+	  GC_free(obj);
+	  return;
+	}
+    }
 }
Index: boehm-gc/gc-refs.h
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/boehm-gc/gc-refs.h,v
retrieving revision 1.1
diff -u -r1.1 gc-refs.h
--- boehm-gc/gc-refs.h	2 Aug 2004 10:44:56 -0000	1.1
+++ boehm-gc/gc-refs.h	23 Dec 2004 18:02:54 -0000
@@ -18,5 +18,8 @@
 struct _Collector;
 bool KaffeGC_addRef(struct _Collector *collector, const void* mem);
 bool KaffeGC_rmRef(struct _Collector *collector, const void* mem);
+bool KaffeGC_addWeakRef(struct _Collector *collector, void *mem, void **obj);
+bool KaffeGC_rmWeakRef(struct _Collector *collector, void *mem, void **obj);
+void KaffeGC_clearWeakRef(struct _Collector *collector, void *mem);
 
 #endif /* __gcrefs_h */
Index: boehm-gc/gc2.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/boehm-gc/gc2.c,v
retrieving revision 1.7
diff -u -r1.7 gc2.c
--- boehm-gc/gc2.c	16 Dec 2004 06:13:52 -0000	1.7
+++ boehm-gc/gc2.c	23 Dec 2004 18:02:54 -0000
@@ -145,6 +145,8 @@
   if (f->final != KGC_OBJECT_NORMAL && f->final != NULL)
     f->final(&boehm_gc.collector, ALIGN_FORWARD(ob));
 
+  KaffeGC_clearWeakRef(&boehm_gc.collector, ALIGN_FORWARD(ob));
+
   if (f->destroy != NULL)
     f->destroy(&boehm_gc.collector, ALIGN_FORWARD(ob));
 }
@@ -498,7 +500,9 @@
 static void
 KaffeGC_warnproc(char *msg, GC_word arg)
 {
-DBG(GCDIAG, dprintf(msg, arg); )
+DBG(GCDIAG, 
+     dprintf(msg, arg);
+    );
 }
 
 static void
@@ -544,7 +548,6 @@
     }
 }
 
-
 /*
  * vtable for object implementing the collector interface.
  */
@@ -574,7 +577,9 @@
   KaffeGC_HeapLimit,
   KaffeGC_HeapTotal,
   KaffeGC_addRef,
-  KaffeGC_rmRef
+  KaffeGC_rmRef,
+  KaffeGC_addWeakRef,
+  KaffeGC_rmWeakRef
 };
 
 /*
Index: intrp/methodcalls.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/intrp/methodcalls.c,v
retrieving revision 1.3
diff -u -r1.3 methodcalls.c
--- intrp/methodcalls.c	21 Oct 2004 14:20:34 -0000	1.3
+++ intrp/methodcalls.c	23 Dec 2004 18:02:54 -0000
@@ -139,3 +139,4 @@
 	}
 
 }
+
Index: jit/methodcalls.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/jit/methodcalls.c,v
retrieving revision 1.5
diff -u -r1.5 methodcalls.c
--- jit/methodcalls.c	21 Dec 2004 05:50:00 -0000	1.5
+++ jit/methodcalls.c	23 Dec 2004 18:02:54 -0000
@@ -63,17 +63,13 @@
 	 */
 #if defined(COMPARE_AND_EXCHANGE)
 	if (COMPARE_AND_EXCHANGE(where, tramp, METHOD_NATIVECODE(meth))) {
-		gc_free(tramp);
+		;
 	}
 #elif defined(ATOMIC_EXCHANGE)
 	{
 		void *tmp = METHOD_NATIVECODE(meth);
 
 		ATOMIC_EXCHANGE(where, tmp);
-
-		if (tmp == tramp) {
-			gc_free(tramp);
-		}
 	}
 #else
 #error "You have to define either COMPARE_AND_EXCHANGE or ATOMIC_EXCHANGE"
@@ -182,6 +178,7 @@
 				!!!"Cannot override trampoline anchor");
 		}
 		ret = tramp;
+		//		gc_add_ref(tramp);
 	} else {
 		if (CLASS_GCJ((meth)->class)) {
 			_SET_METHOD_NATIVECODE(meth, meth->ncode);
Index: jit/methodcalls.h
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/jit/methodcalls.h,v
retrieving revision 1.2
diff -u -r1.2 methodcalls.h
--- jit/methodcalls.h	21 Aug 2004 14:53:32 -0000	1.2
+++ jit/methodcalls.h	23 Dec 2004 18:02:54 -0000
@@ -42,5 +42,4 @@
  */
 #define engine_reservedArgs(M) 0
 
-
 #endif /* __method_dispatch_h__ */
Index: jit3/machine.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/jit3/machine.c,v
retrieving revision 1.67
diff -u -r1.67 machine.c
--- jit3/machine.c	22 Dec 2004 00:22:05 -0000	1.67
+++ jit3/machine.c	23 Dec 2004 18:02:55 -0000
@@ -585,8 +585,6 @@
 
 	SET_METHOD_JITCODE(meth, code->code);
 
-	if( meth->c.bcode.code )
-		gc_free(meth->c.bcode.code);
 	meth->c.ncode.ncode_start = code->mem;
 	meth->c.ncode.ncode_end = (void*)((uintp)code->code + code->codelen);
 	
@@ -634,8 +632,6 @@
 #if defined(FLUSH_DCACHE)
 	FLUSH_DCACHE(code->code, (void*)((uintp)code->code + code->codelen));
 #endif
-
-	gc_free(tramp);
 
 	/* Translate exception table and make it available */
 	if (meth->exception_table != 0) {
Index: jni/jni-callmethod.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/jni/jni-callmethod.c,v
retrieving revision 1.4
diff -u -r1.4 jni-callmethod.c
--- jni/jni-callmethod.c	20 Dec 2004 00:13:16 -0000	1.4
+++ jni/jni-callmethod.c	23 Dec 2004 18:02:55 -0000
@@ -28,7 +28,7 @@
 getMethodFunc (Method* meth, Hjava_lang_Object *obj)
 {
   if (obj && CLASS_IS_INTERFACE (meth->class)) {
-    register short *implementors;
+    register void ***implementors;
     register Hjava_lang_Class *clazz;
 		
     assert (meth->idx >= 0);
@@ -36,9 +36,9 @@
     implementors = meth->class->implementors;
     clazz = OBJECT_CLASS(obj);
 
-    assert (implementors != NULL && clazz->impl_index <= implementors[0]);
+    assert (implementors != NULL && clazz->impl_index <= (uintp)implementors[0]);
 		
-    return clazz->itable2dtable[implementors[clazz->impl_index] + meth->idx + 1]; 	
+    return implementors[clazz->impl_index][meth->idx + 1]; 	
   } else {
     return meth->idx >= 0 ? obj->vtable->method[meth->idx] : METHOD_NATIVECODE (meth);
   }
Index: kaffe-gc/gc-incremental.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/kaffe-gc/gc-incremental.c,v
retrieving revision 1.16
diff -u -r1.16 gc-incremental.c
--- kaffe-gc/gc-incremental.c	20 Dec 2004 01:39:21 -0000	1.16
+++ kaffe-gc/gc-incremental.c	23 Dec 2004 18:02:55 -0000
@@ -799,6 +799,9 @@
 		}
 #endif
 
+		/* clear all weak references to the object */
+		KaffeGC_clearWeakRef(gcif, UTOMEM(unit));
+
 		/* invoke destroy function before freeing the object */
 		info = gc_mem2block(unit);
 		idx = GCMEM2IDX(info, unit);
@@ -1475,7 +1478,9 @@
 	gcGetHeapLimit,
 	gcGetHeapTotal,
 	KaffeGC_addRef,
-	KaffeGC_rmRef
+	KaffeGC_rmRef,
+	KaffeGC_addWeakRef,
+	KaffeGC_rmWeakRef
 };
 
 /*
Index: kaffe-gc/gc-refs.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/kaffe-gc/gc-refs.c,v
retrieving revision 1.8
diff -u -r1.8 gc-refs.c
--- kaffe-gc/gc-refs.c	21 Dec 2004 11:46:54 -0000	1.8
+++ kaffe-gc/gc-refs.c	23 Dec 2004 18:02:55 -0000
@@ -28,17 +28,29 @@
 #include "java_lang_Thread.h"
 
 #define	REFOBJHASHSZ	128
-typedef struct _refObject {
+typedef struct _strongRefObject {
   const void*		mem;
   unsigned int		ref;
-  struct _refObject*	next;
-} refObject;
+  struct _strongRefObject* next;
+} strongRefObject;
 
-typedef struct _refTable {
-  refObject*		hash[REFOBJHASHSZ];
-} refTable;
+typedef struct _strongRefTable {
+  strongRefObject*		hash[REFOBJHASHSZ];
+} strongRefTable;
+
+typedef struct _weakRefObject {
+  const void *          mem;
+  unsigned int          ref;
+  void ***              allRefs;
+  struct _weakRefObject *next;
+} weakRefObject;
+
+typedef struct _weakRefTable {
+  weakRefObject*               hash[REFOBJHASHSZ];
+} weakRefTable;
 
-static refTable			refObjects;
+static strongRefTable			strongRefObjects;
+static weakRefTable                     weakRefObjects;
 
 /* This is a bit homemade.  We need a 7-bit hash from the address here */
 #define	REFOBJHASH(V)	((((uintp)(V) >> 2) ^ ((uintp)(V) >> 9))%REFOBJHASHSZ)
@@ -50,10 +62,10 @@
 KaffeGC_addRef(Collector *collector, const void* mem)
 {
   uint32 idx;
-  refObject* obj;
+  strongRefObject* obj;
 
   idx = REFOBJHASH(mem);
-  for (obj = refObjects.hash[idx]; obj != 0; obj = obj->next) {
+  for (obj = strongRefObjects.hash[idx]; obj != 0; obj = obj->next) {
     /* Found it - just increase reference */
     if (obj->mem == mem) {
       obj->ref++;
@@ -62,14 +74,14 @@
   }
 
   /* Not found - create a new one */
-  obj = (refObject*)KGC_malloc(collector, sizeof(refObject), KGC_ALLOC_REF);
+  obj = (strongRefObject*)KGC_malloc(collector, sizeof(strongRefObject), KGC_ALLOC_REF);
   if (!obj)
     return false;
 	
   obj->mem = mem;
   obj->ref = 1;
-  obj->next = refObjects.hash[idx];
-  refObjects.hash[idx] = obj;
+  obj->next = strongRefObjects.hash[idx];
+  strongRefObjects.hash[idx] = obj;
   return true;
 }
 
@@ -81,11 +93,11 @@
 KaffeGC_rmRef(Collector *collector, void* mem)
 {
   uint32 idx;
-  refObject** objp;
-  refObject* obj;
+  strongRefObject** objp;
+  strongRefObject* obj;
 
   idx = REFOBJHASH(mem);
-  for (objp = &refObjects.hash[idx]; *objp != 0; objp = &obj->next) {
+  for (objp = &strongRefObjects.hash[idx]; *objp != 0; objp = &obj->next) {
     obj = *objp;
     /* Found it - just decrease reference */
     if (obj->mem == mem) {
@@ -102,7 +114,87 @@
   return false;
 }
 
-/*      
+bool
+KaffeGC_addWeakRef(Collector *collector, void* mem, void** refobj)
+{
+  int idx;
+  weakRefObject* obj;
+
+  idx = REFOBJHASH(mem);
+  for (obj = weakRefObjects.hash[idx]; obj != 0; obj = obj->next) {
+    /* Found it - just register a new weak reference */
+    if (obj->mem == mem) {
+      void ***newRefs;
+      obj->ref++;
+
+      newRefs = (void ***)KGC_malloc(collector, sizeof(void ***)*obj->ref, KGC_ALLOC_REF);
+      memcpy(newRefs, obj->allRefs, sizeof(void ***)*(obj->ref-1));
+      KGC_free(collector, obj->allRefs);
+
+      obj->allRefs = newRefs;
+      obj->allRefs[obj->ref-1] = refobj;
+      return true;
+    }
+  }
+
+  /* Not found - create a new one */
+  obj = (weakRefObject*)KGC_malloc(collector, sizeof(weakRefObject), KGC_ALLOC_REF);
+  if (!obj)
+    return false;
+
+  obj->mem = mem;
+  obj->ref = 1;
+  obj->allRefs = (void ***)KGC_malloc(collector, sizeof(void ***), KGC_ALLOC_REF);
+  obj->allRefs[0] = refobj;
+  obj->next = weakRefObjects.hash[idx];
+  weakRefObjects.hash[idx] = obj;
+  return true;
+}
+
+bool
+KaffeGC_rmWeakRef(Collector *collector, void* mem, void** refobj)
+{
+  uint32 idx;
+  weakRefObject** objp;
+  weakRefObject* obj;
+  unsigned int i;
+
+  idx = REFOBJHASH(mem);
+  for (objp = &weakRefObjects.hash[idx]; *objp != 0; objp = &obj->next) {
+    obj = *objp;
+    /* Found it - just decrease reference */
+    if (obj->mem == mem)
+      {
+	for (i = 0; i < obj->ref; i++)
+	  {
+	    if (obj->allRefs[i] == refobj)
+	      {
+		void ***newRefs;
+		
+		obj->ref--;
+		newRefs = (void ***)KGC_malloc(collector, sizeof(void ***)*obj->ref, KGC_ALLOC_REF);
+		memcpy(newRefs, obj->allRefs, i*sizeof(void ***));
+		memcpy(&newRefs[i], &obj->allRefs[i+1], obj->ref*sizeof(void ***));
+		KGC_free(collector, obj->allRefs);
+		obj->allRefs = newRefs;
+		break;
+	      }
+	  }
+	if (i == obj->ref)
+	  return false;
+	if (obj->ref == 0) {
+	  *objp = obj->next;
+	  KGC_free(collector, obj);
+	}
+	return true;
+      }
+  }
+
+  /* Not found!! */
+  return false;
+}
+
+/*
  * Walk the thread's internal context.
  * This is invoked by the garbage collector thread, which is not
  * stopped.
@@ -183,7 +275,7 @@
 KaffeGC_walkRefs(Collector* collector)
 {
   int i;
-  refObject* robj;
+  strongRefObject* robj;
   
 DBG(GCWALK,
     dprintf("Walking gc roots...\n");
@@ -191,7 +283,7 @@
 
   /* Walk the referenced objects */
   for (i = 0; i < REFOBJHASHSZ; i++) {
-    for (robj = refObjects.hash[i]; robj != 0; robj = robj->next) {
+    for (robj = strongRefObjects.hash[i]; robj != 0; robj = robj->next) {
       KGC_markObject(collector, NULL, robj->mem);
     }
   }
@@ -209,4 +301,38 @@
  DBG(GCWALK,
      dprintf("Following references now...\n");
      );
+}
+
+
+/**
+ * This function clear all weak references to the specified object. 
+ * The references are then removed from the database.
+ *
+ * @param collector a garbage collector instance.
+ * @param mem a valid memory object.
+ */
+void
+KaffeGC_clearWeakRef(Collector *collector, void* mem)
+{ 
+  uint32 idx;
+  weakRefObject** objp;
+  weakRefObject* obj;
+  unsigned int i;
+
+  idx = REFOBJHASH(mem);
+  for (objp = &weakRefObjects.hash[idx]; *objp != 0; objp = &obj->next)
+    {
+      obj = *objp;
+      /* Found it - clear all references attached to it. */
+      if (obj->mem == mem)
+	{
+	  for (i = 0; i < obj->ref; i++)
+	    *(obj->allRefs[i]) = NULL;
+	  KGC_free(collector, obj->allRefs);
+
+	  *objp = obj->next;
+	  KGC_free(collector, obj);
+	  return;
+	}
+    }
 }
Index: kaffe-gc/gc-refs.h
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/kaffe-gc/gc-refs.h,v
retrieving revision 1.4
diff -u -r1.4 gc-refs.h
--- kaffe-gc/gc-refs.h	20 Nov 2004 18:15:13 -0000	1.4
+++ kaffe-gc/gc-refs.h	23 Dec 2004 18:02:55 -0000
@@ -22,5 +22,8 @@
 bool KaffeGC_addRef(struct _Collector *collector, const void* mem);
 bool KaffeGC_rmRef(struct _Collector *collector, void* mem);
 void KaffeGC_walkRefs(struct _Collector* collector);
+bool KaffeGC_addWeakRef(struct _Collector *collector, void *mem, void **obj);
+bool KaffeGC_rmWeakRef(struct _Collector *collector, void *mem, void **obj);
+void KaffeGC_clearWeakRef(struct _Collector *collector, void *mem);
 
 #endif /* __gcrefs_h */


More information about the kaffe mailing list