[kaffe] Weak references/Class destruction

Guilhem Lavaux guilhem at kaffe.org
Wed Dec 22 09:05:31 PST 2004


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.

There are some drawbacks:
* creating a weak reference is slow and consumes memory.
* walking a class takes more time as you have to decide whether to mark 
or not some memory.

Advantages:
* boehm-gc should work now (even if some bugs might still lurk around 
the structure is in place).
* Relieve the VM from caring about some pointers shared between several 
classes (like interface implementors).
* The patch does not touch the class structure.

It seems that I've still a failure from time to time in ClassGC when 
using the boehm-gc. We will have check this.

Here is the patch. If nobody rejects it I'll check it in tomorrow.

Regards,

Guilhem Lavaux.
-------------- next part --------------
? build_boehm
? build_intrp
? build_pth
? mem_patch
? pat
? weak-ref-patch
? config/powerpc/darwin/md.h.new
? kaffe/kaffe/main.ch
? libraries/javalib/Klasses.jar.bootstrap.save
? libraries/javalib/l
? po/fr.gmo
? po/zh_TW.gmo
Index: ChangeLog
===================================================================
RCS file: /cvs/kaffe/kaffe/ChangeLog,v
retrieving revision 1.3252
diff -u -r1.3252 ChangeLog
--- ChangeLog	22 Dec 2004 01:09:35 -0000	1.3252
+++ ChangeLog	22 Dec 2004 17:03:38 -0000
@@ -1,3 +1,53 @@
+2004-12-22  Guilhem Lavaux  <guilhem at kaffe.org>
+
+	* configure.ac: Fixed CPPFLAGS generation to be compatible with
+	boehm's configure.
+
+	* config/mips/irix5/md.h: Removed extra macros.
+
+	* include/Makefile.am: Moved ObjectInputStream and
+	VMObjectStreamClass to JNI headers.
+
+	* kaffe/kaffevm/baseClasses.c: Reset dummyClassClass before using
+	it.
+
+	* kaffe/kaffevm/classMethod.c
+	(processClass, resolveInterfaces): Use weak references to track
+	vanishing classes.
+	(processClass): Do not free explicitly the generated code anymore.
+	(buildInterfaceDispatchTable): Remember the total length of the
+	table.
+
+	* kaffe/kaffevm/gc.h: New type for interface table. Two new
+	functions to handle weak references.
+
+	* kaffe/kaffevm/gcFuncs.c
+	(destroyClass): Do not explicitly free memory for the
+	native/bytecode code. Use weak references to track classes which
+	has already been freed.
+	(walkMethods): Mark the bytecode _and_ the native code.
+	(walkClass): Mark the dtable, the interfaces, the vtable.
+	(initCollector): KGC_ALLOC_TRAMPOLINE, KGC_ALLOC_JITCODE,
+	KGC_ALLOC_BYTECODE, KGC_ALLOC_INTERFACE, KGC_ALLOC_INTERFACE_TABLE
+	are now dynamic.
+
+	* kaffe/kaffevm/kaffe-gc/gc-incremental.c
+	(finishGC): Invoke KaffeGC_clearWeakRef.
+	
+	* kaffe/kaffevm/kaffe-gc/gc-refs.c
+	(refObject): Renamed to strongRefObject.
+	(refTable): Likewise.
+	(weakRefObject, weakRefTable): New table.
+	(KaffeGC_addWeakRef, KaffeGC_rmWeakRef): New functions.
+	(KaffeGC_clearWeakRef): New function.
+
+	* kaffe/kaffevm/boehm-gc/gc-refs.c: Like kaffe-gc/gc-refs.c
+
+	* kaffe/kaffevm/boehm-gc/gc2.c
+	(finalizeObject): Invoke KaffeGC_clearWeakRef.
+	
+	* include/Makefile.in, configure: Regenerated.
+	
 2004-12-22  Dalibor Topic  <robilad at kaffe.org>
 
 	* m4/ac_prog_antlr.m4,
Index: configure
===================================================================
RCS file: /cvs/kaffe/kaffe/configure,v
retrieving revision 1.403
diff -u -r1.403 configure
--- configure	22 Dec 2004 01:09:37 -0000	1.403
+++ configure	22 Dec 2004 17:03:56 -0000
@@ -28530,6 +28530,7 @@
 	esac
 
 	VMLIBS="$VM_LIBS $PTHREAD_LIBS"
+	CPPFLAGS="$CPPFLAGS -D_REENTRANT"
  else
         CPPFLAGS="$CPPFLAGS -DBR_PTHREADS=0"
 fi
@@ -42735,13 +42736,8 @@
 			BOEHMGC_SPECIFIC_FLAGS="$BOEHMGC_SPECIFIC_FLAGS -DGC_HPUX_THREADS"
 			;;
 		linux*)
-			if test x"$ac_cv_c_compile_value_glibc" -le x"2"; then
-			   if test "$ac_c_compile_value_glibc_minor" -le "2"; then
-				BOEHMGC_SPECIFIC_FLAGS="$BOEHMGC_SPECIFIC_FLAGS -DGC_LINUX_THREADS"
-			   fi
-			   if test "$ac_cv_c_compile_value_glibc_minor" -ge "3"; then
-			        BOEHMGC_SPECIFIC_FLAGS="$BOEHMGC_SPECIFIC_FLAGS -DGC_PTHREADS"
-			   fi
+			if test "$ac_cv_c_compile_value_glibc" -le "2"; then
+			   BOEHMGC_SPECIFIC_FLAGS="$BOEHMGC_SPECIFIC_FLAGS -DGC_LINUX_THREADS -DTHREAD_LOCAL_ALLOC"
 			fi
 			;;
 		*)
Index: configure.ac
===================================================================
RCS file: /cvs/kaffe/kaffe/configure.ac,v
retrieving revision 1.96
diff -u -r1.96 configure.ac
--- configure.ac	22 Dec 2004 01:09:45 -0000	1.96
+++ configure.ac	22 Dec 2004 17:03:56 -0000
@@ -679,6 +679,7 @@
 
 	KAFFE_LIB_SOLARIS_PTHREAD
 	VMLIBS="$VM_LIBS $PTHREAD_LIBS"
+	CPPFLAGS="$CPPFLAGS -D_REENTRANT"
  else
         CPPFLAGS="$CPPFLAGS -DBR_PTHREADS=0"
 fi
@@ -1096,12 +1097,10 @@
 			BOEHMGC_SPECIFIC_FLAGS="$BOEHMGC_SPECIFIC_FLAGS -DGC_HPUX_THREADS"
 			;;
 		linux*)
-			if test x"$ac_cv_c_compile_value_glibc" -le x"2"; then
-			   if test "$ac_c_compile_value_glibc_minor" -le "2"; then
-				BOEHMGC_SPECIFIC_FLAGS="$BOEHMGC_SPECIFIC_FLAGS -DGC_LINUX_THREADS"
-			   fi
-			   if test "$ac_cv_c_compile_value_glibc_minor" -ge "3"; then
-			        BOEHMGC_SPECIFIC_FLAGS="$BOEHMGC_SPECIFIC_FLAGS -DGC_PTHREADS"
+			if test "$ac_cv_c_compile_value_glibc" -le "2"; then
+			   BOEHMGC_SPECIFIC_FLAGS="$BOEHMGC_SPECIFIC_FLAGS -DGC_LINUX_THREADS"
+			   if test "$Khost_cpu" = "i386"; then
+			     BOEHMGC_SPECIFIC_FLAGS="$BOEHMGC_SPECIFIC_FLAGS -DTHREAD_LOCAL_ALLOC"
 			   fi
 			fi
 			;;
Index: config/mips/irix5/md.h
===================================================================
RCS file: /cvs/kaffe/kaffe/config/mips/irix5/md.h,v
retrieving revision 1.6
diff -u -r1.6 md.h
--- config/mips/irix5/md.h	13 Jul 2004 13:52:00 -0000	1.6
+++ config/mips/irix5/md.h	22 Dec 2004 17:03:56 -0000
@@ -29,12 +29,6 @@
 #define SIGNAL_PC(scp) ((scp)->sc_pc)             /* pc at time of signal */
 #define STACK_POINTER(scp) ((scp)->sc_badvaddr)   /* cp0 bad virtual address */
 
-#define SIGNAL_ARGS(sig, sc) int sig, int code UNUSED, struct sigcontext *sc
-#define SIGNAL_CONTEXT_POINTER(scp) struct sigcontext *scp
-#define GET_SIGNAL_CONTEXT_POINTER(sc) (sc)
-#define SIGNAL_PC(scp) 
-#define STACK_POINTER(scp) ((scp)->sc_badvaddr)
-
 #include "kaffe-unix-stack.h"
 
 #endif
Index: include/Makefile.am
===================================================================
RCS file: /cvs/kaffe/kaffe/include/Makefile.am,v
retrieving revision 1.80
diff -u -r1.80 Makefile.am
--- include/Makefile.am	21 Dec 2004 16:51:11 -0000	1.80
+++ include/Makefile.am	22 Dec 2004 17:03:56 -0000
@@ -51,11 +51,9 @@
 	java_io_FileOutputStream.h \
 	java_io_InputStream.h \
 	java_io_InterruptedIOException.h \
-	java_io_ObjectInputStream.h \
 	java_io_PrintStream.h \
 	java_io_RandomAccessFile.h \
 	java_io_VMFile.h \
-	java_io_VMObjectStreamClass.h \
 	java_lang_Boolean.h \
 	java_lang_Byte.h \
 	java_lang_Character.h \
@@ -110,6 +108,8 @@
 	gnu_classpath_VMSystemProperties.h \
 	gnu_java_nio_channels_FileChannelImpl.h \
 	gnu_java_nio_SelectorImpl.h \
+	java_io_ObjectInputStream.h \
+	java_io_VMObjectStreamClass.h \
 	java_nio_channels_Channels.h \
 	java_nio_VMDirectByteBuffer.h \
 	java_nio_MappedByteBufferImpl.h \
Index: include/Makefile.in
===================================================================
RCS file: /cvs/kaffe/kaffe/include/Makefile.in,v
retrieving revision 1.199
diff -u -r1.199 Makefile.in
--- include/Makefile.in	22 Dec 2004 01:09:46 -0000	1.199
+++ include/Makefile.in	22 Dec 2004 17:03:56 -0000
@@ -407,11 +407,9 @@
 	java_io_FileOutputStream.h \
 	java_io_InputStream.h \
 	java_io_InterruptedIOException.h \
-	java_io_ObjectInputStream.h \
 	java_io_PrintStream.h \
 	java_io_RandomAccessFile.h \
 	java_io_VMFile.h \
-	java_io_VMObjectStreamClass.h \
 	java_lang_Boolean.h \
 	java_lang_Byte.h \
 	java_lang_Character.h \
@@ -464,6 +462,8 @@
 	gnu_classpath_VMSystemProperties.h \
 	gnu_java_nio_channels_FileChannelImpl.h \
 	gnu_java_nio_SelectorImpl.h \
+	java_io_ObjectInputStream.h \
+	java_io_VMObjectStreamClass.h \
 	java_nio_channels_Channels.h \
 	java_nio_VMDirectByteBuffer.h \
 	java_nio_MappedByteBufferImpl.h \
Index: kaffe/kaffevm/baseClasses.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/baseClasses.c,v
retrieving revision 1.56
diff -u -r1.56 baseClasses.c
--- kaffe/kaffevm/baseClasses.c	19 Dec 2004 06:25:07 -0000	1.56
+++ kaffe/kaffevm/baseClasses.c	22 Dec 2004 17:03:56 -0000
@@ -261,6 +261,8 @@
 {
         errorInfo einfo;
 
+	memset(&dummyClassClass, 0, sizeof(dummyClassClass));
+
         /* Primitive types */
         initTypes();
 	initVerifierPrimTypes();
Index: kaffe/kaffevm/classMethod.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/classMethod.c,v
retrieving revision 1.130
diff -u -r1.130 classMethod.c
--- kaffe/kaffevm/classMethod.c	21 Dec 2004 08:06:36 -0000	1.130
+++ kaffe/kaffevm/classMethod.c	22 Dec 2004 17:03:57 -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;
@@ -841,24 +842,27 @@
 		}
 		for (i = 0; i < class->interface_len; i++) {
 			newifaces[i] = class->interfaces[i];
+			KGC_addWeakRef(main_collector, newifaces[i], &newifaces[i]);
 		}
 		nclass = class->superclass;
 		if (nclass != 0 && nclass != ObjectClass) {
 			for (j = 0; j < nclass->total_interface_len; j++, i++) {
 				newifaces[i] = nclass->interfaces[j];
+				KGC_addWeakRef(main_collector, newifaces[i], &newifaces[i]);
 			}
 		}
 		for (k = 0; k < class->interface_len; k++) {
 			nclass = class->interfaces[k];
 			for (j = 0; j < nclass->total_interface_len; j++, i++) {
 				newifaces[i] = nclass->interfaces[j];
+				KGC_addWeakRef(main_collector, newifaces[i], &newifaces[i]);
 			}
 		}
-		/* free old list of interfaces */
-		if (class->interfaces != 0) {
-			KFREE(class->interfaces);
-		}
 		class->interfaces = newifaces;
+	} else {
+	  /* Add weak references now. */
+	  for (i = 0; i < class->interface_len; i++)
+	    KGC_addWeakRef(main_collector, class->interfaces[i], &class->interfaces[i]);
 	}
 
 	/* don't set total_interface_len before interfaces to avoid
@@ -2091,7 +2095,7 @@
 		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);
@@ -2105,7 +2109,9 @@
 		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);
Index: kaffe/kaffevm/gc.h
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/gc.h,v
retrieving revision 1.30
diff -u -r1.30 gc.h
--- kaffe/kaffevm/gc.h	21 Dec 2004 08:06:36 -0000	1.30
+++ kaffe/kaffevm/gc.h	22 Dec 2004 17:03:57 -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: kaffe/kaffevm/gcFuncs.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/gcFuncs.c,v
retrieving revision 1.62
diff -u -r1.62 gcFuncs.c
--- kaffe/kaffevm/gcFuncs.c	21 Dec 2004 16:51:05 -0000	1.62
+++ kaffe/kaffevm/gcFuncs.c	22 Dec 2004 17:04:00 -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,45 @@
 		}
 	}
 	/* free constant pool */
-	if (pool->data != 0) {
-		KFREE(pool->data);
-	}
+	if (pool->data != 0)
+	  {
+	    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 )
+	  {
+	    /* 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
-		 */
-		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) )
+        KFREE(clazz->if2itable);
+	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] = -1;
+	      }
+	  }
+	  /* 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).
+	   */
 	}
 	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 +212,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 +263,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);
+          }
+
+	KGC_markObject(collector, gc_info, class->gc_layout);
+	if (class->itable2dtable != NULL)
+	  {
+	    KGC_markObject(collector, gc_info, class->itable2dtable);
+
+	    for (idx = 0; idx < class->if2itable[class->total_interface_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 +307,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 +391,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 = 0, 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 +653,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 +673,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 +684,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: kaffe/kaffevm/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
--- kaffe/kaffevm/boehm-gc/gc-refs.c	9 Aug 2004 08:18:21 -0000	1.3
+++ kaffe/kaffevm/boehm-gc/gc-refs.c	22 Dec 2004 17:04:00 -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: kaffe/kaffevm/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
--- kaffe/kaffevm/boehm-gc/gc-refs.h	2 Aug 2004 10:44:56 -0000	1.1
+++ kaffe/kaffevm/boehm-gc/gc-refs.h	22 Dec 2004 17:04:00 -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: kaffe/kaffevm/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
--- kaffe/kaffevm/boehm-gc/gc2.c	16 Dec 2004 06:13:52 -0000	1.7
+++ kaffe/kaffevm/boehm-gc/gc2.c	22 Dec 2004 17:04:00 -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,6 +548,17 @@
     }
 }
 
+static
+bool
+KaffeGC_addWeakRef(Collector *collector UNUSED, void* mem UNUSED, void **ref UNUSED)
+{
+}
+
+static
+bool
+KaffeGC_rmWeakRef(Collector *collector UNUSED, void* mem UNUSED, void **ref UNUSED)
+{
+}
 
 /*
  * vtable for object implementing the collector interface.
@@ -574,7 +589,9 @@
   KaffeGC_HeapLimit,
   KaffeGC_HeapTotal,
   KaffeGC_addRef,
-  KaffeGC_rmRef
+  KaffeGC_rmRef,
+  KaffeGC_addWeakRef,
+  KaffeGC_rmWeakRef
 };
 
 /*
Index: kaffe/kaffevm/intrp/methodcalls.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/intrp/methodcalls.c,v
retrieving revision 1.3
diff -u -r1.3 methodcalls.c
--- kaffe/kaffevm/intrp/methodcalls.c	21 Oct 2004 14:20:34 -0000	1.3
+++ kaffe/kaffevm/intrp/methodcalls.c	22 Dec 2004 17:04:00 -0000
@@ -139,3 +139,4 @@
 	}
 
 }
+
Index: kaffe/kaffevm/jit/methodcalls.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/jit/methodcalls.c,v
retrieving revision 1.5
diff -u -r1.5 methodcalls.c
--- kaffe/kaffevm/jit/methodcalls.c	21 Dec 2004 05:50:00 -0000	1.5
+++ kaffe/kaffevm/jit/methodcalls.c	22 Dec 2004 17:04:00 -0000
@@ -63,7 +63,8 @@
 	 */
 #if defined(COMPARE_AND_EXCHANGE)
 	if (COMPARE_AND_EXCHANGE(where, tramp, METHOD_NATIVECODE(meth))) {
-		gc_free(tramp);
+	  //	  gc_rm_ref(tramp);
+	  //		gc_free(tramp);
 	}
 #elif defined(ATOMIC_EXCHANGE)
 	{
@@ -72,7 +73,8 @@
 		ATOMIC_EXCHANGE(where, tmp);
 
 		if (tmp == tramp) {
-			gc_free(tramp);
+		  //		  gc_rm_ref(tramp);
+		  //	gc_free(tramp);
 		}
 	}
 #else
@@ -182,6 +184,7 @@
 				!!!"Cannot override trampoline anchor");
 		}
 		ret = tramp;
+		//		gc_add_ref(tramp);
 	} else {
 		if (CLASS_GCJ((meth)->class)) {
 			_SET_METHOD_NATIVECODE(meth, meth->ncode);
Index: kaffe/kaffevm/jit/methodcalls.h
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/jit/methodcalls.h,v
retrieving revision 1.2
diff -u -r1.2 methodcalls.h
--- kaffe/kaffevm/jit/methodcalls.h	21 Aug 2004 14:53:32 -0000	1.2
+++ kaffe/kaffevm/jit/methodcalls.h	22 Dec 2004 17:04:00 -0000
@@ -42,5 +42,4 @@
  */
 #define engine_reservedArgs(M) 0
 
-
 #endif /* __method_dispatch_h__ */
Index: kaffe/kaffevm/jit3/machine.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/jit3/machine.c,v
retrieving revision 1.67
diff -u -r1.67 machine.c
--- kaffe/kaffevm/jit3/machine.c	22 Dec 2004 00:22:05 -0000	1.67
+++ kaffe/kaffevm/jit3/machine.c	22 Dec 2004 17:04:00 -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: kaffe/kaffevm/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/kaffevm/kaffe-gc/gc-incremental.c	20 Dec 2004 01:39:21 -0000	1.16
+++ kaffe/kaffevm/kaffe-gc/gc-incremental.c	22 Dec 2004 17:04:01 -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/kaffevm/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/kaffevm/kaffe-gc/gc-refs.c	21 Dec 2004 11:46:54 -0000	1.8
+++ kaffe/kaffevm/kaffe-gc/gc-refs.c	22 Dec 2004 17:04:01 -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/kaffevm/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/kaffevm/kaffe-gc/gc-refs.h	20 Nov 2004 18:15:13 -0000	1.4
+++ kaffe/kaffevm/kaffe-gc/gc-refs.h	22 Dec 2004 17:04:01 -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