[kaffe] Weak references/Class destruction
Guilhem Lavaux
guilhem at kaffe.org
Sat Dec 25 08:47:57 PST 2004
Hi,
Here is the final implementation (before commit). I have 0 regressions
on my laptop. BTW, I've removed
one or two mutex protections which looks like causing a deadlock in
glibc when the world is suspended.
I do not yet understand how this can be caused but removing them
suppresses the deadlocks and
GCTest passes everytime I've run it here (for the time being). We'll
need to clear this up to check whether
it is really a glibc bug.
Adam, could you try it on your real SMP ?
Cheers,
Guilhem Lavaux.
-------------- next part --------------
? build_boehm
? build_intrp
? build_pth
? pat
? config/powerpc/darwin/md.h.new
? kaffe/kaffe/main.ch
? libraries/javalib/Klasses.jar.bootstrap.save
? libraries/javalib/core.29414
? libraries/javalib/l
? po/fr.gmo
? po/zh_TW.gmo
Index: ChangeLog
===================================================================
RCS file: /cvs/kaffe/kaffe/ChangeLog,v
retrieving revision 1.3268
diff -u -b -B -r1.3268 ChangeLog
--- ChangeLog 24 Dec 2004 21:04:28 -0000 1.3268
+++ ChangeLog 25 Dec 2004 16:43:39 -0000
@@ -1,3 +1,67 @@
+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. Store the parent class of the table in the first entry.
+ (computeInterfaceImplementationIndex): Store a pointer to the
+ itable2dtable instead of an index.
+
+ * kaffe/kaffevm/soft.c
+ (soft_lookupinterfacemethod): Use directly the pointer in
+ implementors.
+ (instanceof_interface): Use implementors to directly check the
+ inheritancy.
+
+ * 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.
+
+ * kaffe/kaffevm/systems/unix-pthreads/thread-impl.c
+ (jthread_unsuspend_all): Removed mutex protection.
+ (jthread_walkLiveThreads_r, jthread_walkLiveThreads): Splitted in
+ a reentrant function and a non-reentrant one. (See
+ jthread_unsuspend_all)
+
+ * include/Makefile.in, configure: Regenerated.
+
2004-12-24 Adam Heath <doogie at brainfood.com>
* libraries/javalib/java/util/zip/ZipFile.java:
Index: configure
===================================================================
RCS file: /cvs/kaffe/kaffe/configure,v
retrieving revision 1.406
diff -u -b -B -r1.406 configure
--- configure 22 Dec 2004 20:01:58 -0000 1.406
+++ configure 25 Dec 2004 16:44:12 -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.97
diff -u -b -B -r1.97 configure.ac
--- configure.ac 22 Dec 2004 20:02:03 -0000 1.97
+++ configure.ac 25 Dec 2004 16:44:16 -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
+ if test "$ac_cv_c_compile_value_glibc" -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 "$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 -b -B -r1.6 md.h
--- config/mips/irix5/md.h 13 Jul 2004 13:52:00 -0000 1.6
+++ config/mips/irix5/md.h 25 Dec 2004 16:44:16 -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 -b -B -r1.80 Makefile.am
--- include/Makefile.am 21 Dec 2004 16:51:11 -0000 1.80
+++ include/Makefile.am 25 Dec 2004 16:44:16 -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.200
diff -u -b -B -r1.200 Makefile.in
--- include/Makefile.in 22 Dec 2004 19:04:48 -0000 1.200
+++ include/Makefile.in 25 Dec 2004 16:44:16 -0000
@@ -410,11 +410,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 \
@@ -467,6 +465,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 -b -B -r1.56 baseClasses.c
--- kaffe/kaffevm/baseClasses.c 19 Dec 2004 06:25:07 -0000 1.56
+++ kaffe/kaffevm/baseClasses.c 25 Dec 2004 16:44:16 -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 -b -B -r1.130 classMethod.c
--- kaffe/kaffevm/classMethod.c 21 Dec 2004 08:06:36 -0000 1.130
+++ kaffe/kaffevm/classMethod.c 25 Dec 2004 16:44:19 -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;
}
@@ -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] + 1) * 2;
if (len <= i) {
- len = i + 4;
+ len = (i + 1) + 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: kaffe/kaffevm/classMethod.h
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/classMethod.h,v
retrieving revision 1.73
diff -u -b -B -r1.73 classMethod.h
--- kaffe/kaffevm/classMethod.h 21 Dec 2004 16:51:05 -0000 1.73
+++ kaffe/kaffevm/classMethod.h 25 Dec 2004 16:44:19 -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: kaffe/kaffevm/gc.h
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/gc.h,v
retrieving revision 1.30
diff -u -b -B -r1.30 gc.h
--- kaffe/kaffevm/gc.h 21 Dec 2004 08:06:36 -0000 1.30
+++ kaffe/kaffevm/gc.h 25 Dec 2004 16:44:23 -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 -b -B -r1.62 gcFuncs.c
--- kaffe/kaffevm/gcFuncs.c 21 Dec 2004 16:51:05 -0000 1.62
+++ kaffe/kaffevm/gcFuncs.c 25 Dec 2004 16:44:23 -0000
@@ -44,6 +44,7 @@
#include "thread.h"
#include "methodCache.h"
#include "jvmpi_kaffe.h"
+#include "methodcalls.h"
/*****************************************************************************
* Class-related functions
@@ -143,14 +144,8 @@
if( m->ndeclared_exceptions != -1 )
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) {
+ if (pool->data != NULL)
+ {
KFREE(pool->data);
}
/* free various other fixed things */
KFREE(CLASS_STATICDATA(clazz));
- if( clazz->vtable )
+
+ if(clazz->vtable != NULL)
+ {
+ /* The native methods in the vtable are swept by the GC. */
+ KFREE(clazz->vtable);
+ }
+
+ KFREE(clazz->if2itable);
+
+ if (clazz->implementors != NULL)
{
- for( i = 0; i < clazz->msize; i++ )
+ uintp len, uidx;
+
+ len = (uintp)clazz->implementors[0] + 1;
+ for (uidx = 1; uidx < len; uidx++)
{
- if( clazz->vtable->method[i] == 0 )
+ void *impl = clazz->implementors[uidx];
+ Hjava_lang_Class **impl_clazz;
+
+ if (impl == NULL)
continue;
- /* Free ncode if necessary: this concerns
- * any uninvoked trampolines
+
+ 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.
*/
- if (KGC_getObjectIndex(collector,
- clazz->vtable->method[i])
- == KGC_ALLOC_DISPATCHTABLE) {
- KFREE(clazz->vtable->method[i]);
+ for (i = 0; i < (*impl_clazz)->total_interface_len; i++)
+ if ((*impl_clazz)->interfaces[i] == clazz)
+ {
+ (*impl_clazz)->interfaces[i] = NULL;
+ break;
}
}
- KFREE(clazz->vtable);
+
+ KFREE(clazz->implementors);
}
- 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;
- }
- }
-
- /* NB: we can't just sum up the msizes of the interfaces
- * here because they might be destroyed simultaneously
+ /* only if interface has not been freed already. We
+ * update the implementors section of the interface
+ * accordingly.
*/
- 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]);
+ 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).
+ */
}
- KGC_free(collector, clazz->itable2dtable);
- }
- if( clazz->gc_layout &&
- (clazz->superclass->gc_layout != clazz->gc_layout) )
- {
+ 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,8 +245,20 @@
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 */
if (m->exception_table != 0) {
@@ -284,6 +298,34 @@
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);
for (idx = 0; idx < pool->size; idx++) {
@@ -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: kaffe/kaffevm/soft.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/soft.c,v
retrieving revision 1.73
diff -u -b -B -r1.73 soft.c
--- kaffe/kaffevm/soft.c 21 Dec 2004 05:49:59 -0000 1.73
+++ kaffe/kaffevm/soft.c 25 Dec 2004 16:44:23 -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) {
+ if (ncode == (void *)-1)
return NULL;
- }
assert(ncode != NULL);
- return (ncode);
+
+ return ncode;
}
inline
@@ -299,14 +299,39 @@
instanceof_interface(Hjava_lang_Class* c, Hjava_lang_Class* oc)
{
int i;
+ Hjava_lang_Class **impl_clazz;
- /* Check 'total' interface list */
+ if (oc->state < CSTATE_USABLE || c->state < CSTATE_USABLE || 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 1;
}
}
- return (0);
+ 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 || c->implementors == NULL ||
+ 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: kaffe/kaffevm/thread.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/thread.c,v
retrieving revision 1.88
diff -u -b -B -r1.88 thread.c
--- kaffe/kaffevm/thread.c 21 Dec 2004 16:51:05 -0000 1.88
+++ kaffe/kaffevm/thread.c 25 Dec 2004 16:44:23 -0000
@@ -610,7 +610,7 @@
dumpThreads(void)
{
dprintf("Dumping live threads:\n");
- KTHREAD(walkLiveThreads)(dumpJavaThread, NULL);
+ KTHREAD(walkLiveThreads_r)(dumpJavaThread, NULL);
}
/*
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 -b -B -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 25 Dec 2004 16:44:23 -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;
-static refTable refObjects;
+typedef struct _weakRefObject {
+ const void * mem;
+ unsigned int ref;
+ void *** allRefs;
+ struct _weakRefObject *next;
+} weakRefObject;
+
+typedef struct _weakRefTable {
+ weakRefObject* hash[REFOBJHASHSZ];
+} weakRefTable;
+
+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 -b -B -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 25 Dec 2004 16:44:23 -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 -b -B -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 25 Dec 2004 16:44:23 -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
@@ -574,7 +577,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 -b -B -r1.3 methodcalls.c
Index: kaffe/kaffevm/jit/methodcalls.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/jit/methodcalls.c,v
retrieving revision 1.5
diff -u -b -B -r1.5 methodcalls.c
--- kaffe/kaffevm/jit/methodcalls.c 21 Dec 2004 05:50:00 -0000 1.5
+++ kaffe/kaffevm/jit/methodcalls.c 25 Dec 2004 16:44:23 -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: kaffe/kaffevm/jit/methodcalls.h
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/jit/methodcalls.h,v
retrieving revision 1.2
diff -u -b -B -r1.2 methodcalls.h
Index: kaffe/kaffevm/jit3/machine.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/jit3/machine.c,v
retrieving revision 1.67
diff -u -b -B -r1.67 machine.c
--- kaffe/kaffevm/jit3/machine.c 22 Dec 2004 00:22:05 -0000 1.67
+++ kaffe/kaffevm/jit3/machine.c 25 Dec 2004 16:44:28 -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/jni/jni-callmethod.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/jni/jni-callmethod.c,v
retrieving revision 1.4
diff -u -b -B -r1.4 jni-callmethod.c
--- kaffe/kaffevm/jni/jni-callmethod.c 20 Dec 2004 00:13:16 -0000 1.4
+++ kaffe/kaffevm/jni/jni-callmethod.c 25 Dec 2004 16:44:28 -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/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 -b -B -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 25 Dec 2004 16:44:28 -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 -b -B -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 25 Dec 2004 16:44:28 -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;
-static refTable refObjects;
+typedef struct _weakRefObject {
+ const void * mem;
+ unsigned int ref;
+ void *** allRefs;
+ struct _weakRefObject *next;
+} weakRefObject;
+
+typedef struct _weakRefTable {
+ weakRefObject* hash[REFOBJHASHSZ];
+} weakRefTable;
+
+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,6 +114,86 @@
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
@@ -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 -b -B -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 25 Dec 2004 16:44:28 -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 */
Index: kaffe/kaffevm/systems/unix-jthreads/jthread.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/systems/unix-jthreads/jthread.c,v
retrieving revision 1.127
diff -u -b -B -r1.127 jthread.c
--- kaffe/kaffevm/systems/unix-jthreads/jthread.c 21 Dec 2004 05:50:02 -0000 1.127
+++ kaffe/kaffevm/systems/unix-jthreads/jthread.c 25 Dec 2004 16:44:31 -0000
@@ -1096,6 +1096,12 @@
}
}
+void
+jthread_walkLiveThreads_r(void (*func)(jthread_t,void*), void *priv)
+{
+ jthread_walkLiveThreads(func, priv);
+}
+
/*
* determine the interesting stack range for a conservative gc
*/
Index: kaffe/kaffevm/systems/unix-jthreads/jthread.h
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/systems/unix-jthreads/jthread.h,v
retrieving revision 1.65
diff -u -b -B -r1.65 jthread.h
--- kaffe/kaffevm/systems/unix-jthreads/jthread.h 21 Dec 2004 05:50:03 -0000 1.65
+++ kaffe/kaffevm/systems/unix-jthreads/jthread.h 25 Dec 2004 16:44:31 -0000
@@ -178,11 +178,18 @@
*/
void jthread_atexit(void (*f)(void));
-/*
+/**
* walk all live threads, and invoke `func', passing in their cookie
* this is used with `func' set to walkMemory
*/
void jthread_walkLiveThreads(void (*func)(jthread_t, void*), void*);
+
+/**
+ * walk all live threads, and invoke `func', passing in their cookie
+ * this is used with `func' set to walkMemory.
+ * This function is reentrant.
+ */
+void jthread_walkLiveThreads_r(void (*func)(jthread_t, void*), void*);
/*
* destroy this jthread structure
Index: kaffe/kaffevm/systems/unix-pthreads/thread-impl.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-impl.c,v
retrieving revision 1.62
diff -u -b -B -r1.62 thread-impl.c
--- kaffe/kaffevm/systems/unix-pthreads/thread-impl.c 21 Dec 2004 05:50:03 -0000 1.62
+++ kaffe/kaffevm/systems/unix-pthreads/thread-impl.c 25 Dec 2004 16:44:35 -0000
@@ -1335,10 +1335,10 @@
return;
if ( --critSection == 0 ){
- /* No need to sync, there's nobody else running. It's just a matter of
- * defensive programming (and we use our fast locks)
+ /* No need to sync, there's nobody else running. However it seems
+ * we cannot use mutexes as they cause a deadlock when the world
+ * is suspended.
*/
- protectThreadList(cur);
#if !defined(KAFFE_BOEHM_GC)
for ( t=activeThreads; t; t = t->next ){
@@ -1381,7 +1381,6 @@
#endif
- unprotectThreadList(cur);
}
DBG( JTHREAD, dprintf("exit crit section (%d)\n", critSection));
@@ -1410,17 +1409,24 @@
jthread_walkLiveThreads (void(*func)(jthread_t,void*), void *private)
{
jthread_t t;
- jthread_t cur = jthread_current();
DBG( JTHREAD, dprintf("start walking threads\n"));
- protectThreadList(cur);
for ( t = activeThreads; t != NULL; t = t->next) {
func(t, private);
}
- unprotectThreadList(cur);
DBG( JTHREAD, dprintf("end walking threads\n"));
+}
+
+void
+jthread_walkLiveThreads_r (void(*func)(jthread_t, void *), void *private)
+{
+ jthread_t cur = jthread_current();
+
+ protectThreadList(cur);
+ jthread_walkLiveThreads (func, private);
+ unprotectThreadList(cur);
}
void
Index: kaffe/kaffevm/systems/unix-pthreads/thread-internal.h
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-internal.h,v
retrieving revision 1.27
diff -u -b -B -r1.27 thread-internal.h
--- kaffe/kaffevm/systems/unix-pthreads/thread-internal.h 21 Dec 2004 05:50:03 -0000 1.27
+++ kaffe/kaffevm/systems/unix-pthreads/thread-internal.h 25 Dec 2004 16:44:35 -0000
@@ -363,9 +363,16 @@
/**
* Call a function once for each active thread.
- *
+ * Caution. This should only be used when all threads
+ * are suspended using jthread_suspendall.
*/
void jthread_walkLiveThreads (void(*)(jthread_t,void*), void *);
+
+/**
+ * Call a function once for each active thread.
+ * This is a reentrant version.
+ */
+void jthread_walkLiveThreads_r (void(*)(jthread_t,void*), void *);
/**
* Return thread status
More information about the kaffe
mailing list