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