? 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 + + * 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 * 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