X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fmm%2Fcacao-gc%2Fgc.c;h=f2739cbdbf6307cd498fe5ec8efe334dc81e8c20;hb=3c1e50c6cd0e56a1560543e9e9755e890c7ec0ab;hp=71e07c5a2a74f6d5d8c633c83184e5134b72604b;hpb=5087d532d7f6ebb6074025edde7a16c0b1270439;p=cacao.git diff --git a/src/mm/cacao-gc/gc.c b/src/mm/cacao-gc/gc.c index 71e07c5a2..f2739cbdb 100644 --- a/src/mm/cacao-gc/gc.c +++ b/src/mm/cacao-gc/gc.c @@ -1,9 +1,7 @@ /* src/mm/cacao-gc/gc.c - main garbage collector methods - Copyright (C) 2006 R. Grafl, A. Krall, C. Kruegel, - C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring, - E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, - J. Wenninger, Institut f. Computersprachen - TU Wien + Copyright (C) 2006, 2007, 2008 + CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO This file is part of CACAO. @@ -22,21 +20,18 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id$ - */ #include "config.h" + #include +#include + #include "vm/types.h" -#if defined(ENABLE_THREADS) -# include "threads/native/threads.h" -#else -# include "threads/none/lock.h" -/*# include "threads/none/threads.h"*/ -#endif +#include "threads/lock-common.h" +#include "threads/threads-common.h" #include "compact.h" #include "copy.h" @@ -59,9 +54,8 @@ bool gc_pending; bool gc_running; bool gc_notify_finalizer; -#if defined(ENABLE_THREADS) -java_objectheader *gc_global_lock; -#endif +list_t *gc_reflist_strong; +list_t *gc_reflist_weak; #if !defined(ENABLE_THREADS) executionstate_t *_no_threads_executionstate; @@ -83,6 +77,16 @@ void gc_init(u4 heapmaxsize, u4 heapstartsize) dolog("GC: Initialising with heap-size %d (max. %d)", heapstartsize, heapmaxsize); +#if defined(ENABLE_HANDLES) + /* check our indirection cells */ + if (OFFSET(java_handle_t, heap_object) != 0) + vm_abort("gc_init: indirection cell offset is displaced: %d", OFFSET(java_handle_t, heap_object)); + if (OFFSET(hashtable_classloader_entry, object) != 0) + vm_abort("gc_init: classloader entry cannot be used as indirection cell: %d", OFFSET(hashtable_classloader_entry, object)); + if (OFFSET(hashtable_global_ref_entry, o) != 0) + vm_abort("gc_init: global reference entry cannot be used as indirection cell: %d", OFFSET(hashtable_global_ref_entry, o)); +#endif + /* finalizer stuff */ final_init(); @@ -90,11 +94,9 @@ void gc_init(u4 heapmaxsize, u4 heapstartsize) gc_pending = false; gc_running = false; -#if defined(ENABLE_THREADS) - /* create global gc lock object */ - gc_global_lock = NEW(java_objectheader); - lock_init_object_lock(gc_global_lock); -#endif + /* create list for external references */ + gc_reflist_strong = list_create(OFFSET(list_gcref_entry_t, linkage)); + gc_reflist_weak = list_create(OFFSET(list_gcref_entry_t, linkage)); /* region for uncollectable objects */ heap_region_sys = NEW(regioninfo_t); @@ -111,6 +113,109 @@ void gc_init(u4 heapmaxsize, u4 heapstartsize) } +/* gc_reference_register ******************************************************* + + Register an external reference which points onto the Heap. The + reference needs to be cleared (set to NULL) when registering and + has to be set after it has been registered (to avoid a race condition). + + STRONG REFERENCE: gets updated and keeps objects alive + WEAK REFERENCE: only gets updated (or maybe cleared) + +*******************************************************************************/ + +static void gc_reference_register_intern(list_t *list, java_object_t **ref, int32_t reftype) +{ + list_gcref_entry_t *re; + + /* the global GC lock also guards the reference lists */ + GC_MUTEX_LOCK; + + GC_LOG2( printf("Registering Reference at %p\n", (void *) ref); ); + + /* the reference needs to be registered before it is set, so make sure the + reference is not yet set */ + GC_ASSERT(*ref == NULL); + +#if !defined(NDEBUG) + /* check if this reference is already registered */ + for (re = list_first_unsynced(list); re != NULL; re = list_next_unsynced(list, re)) { + if (re->ref == ref) + vm_abort("gc_reference_register_intern: reference already registered"); + } +#endif + + /* create a new reference entry */ + re = NEW(list_gcref_entry_t); + + re->ref = ref; +#if !defined(NDEBUG) + re->reftype = reftype; +#endif + + /* add the entry to the given list */ + list_add_last_unsynced(list, re); + + /* the global GC lock also guards the reference lists */ + GC_MUTEX_UNLOCK; +} + +void gc_reference_register(java_object_t **ref, int32_t reftype) +{ + gc_reference_register_intern(gc_reflist_strong, ref, reftype); +} + +void gc_weakreference_register(java_object_t **ref, int32_t reftype) +{ + gc_reference_register_intern(gc_reflist_weak, ref, reftype); +} + + +/* gc_reference_unregister ***************************************************** + + Unregister a previously registered external reference. + +*******************************************************************************/ + +static void gc_reference_unregister_intern(list_t *list, java_object_t **ref) +{ + list_gcref_entry_t *re; + + /* the global GC lock also guards the reference lists */ + GC_MUTEX_LOCK; + + GC_LOG2( printf("Un-Registering Reference at %p\n", (void *) ref); ); + + /* search for the appropriate reference entry */ + for (re = list_first_unsynced(list); re != NULL; re = list_next_unsynced(list, re)) { + if (re->ref == ref) { + /* remove the entry from the given list */ + list_remove_unsynced(list, re); + + /* free the reference entry */ + FREE(re, list_gcref_entry_t); + + break; + } + } + + vm_abort("gc_reference_unregister_intern: reference not found"); + + /* the global GC lock also guards the reference lists */ + GC_MUTEX_UNLOCK; +} + +void gc_reference_unregister(java_object_t **ref) +{ + gc_reference_unregister_intern(gc_reflist_strong, ref); +} + +void gc_weakreference_unregister(java_object_t **ref) +{ + gc_reference_unregister_intern(gc_reflist_weak, ref); +} + + /* gc_collect ****************************************************************** This is the main machinery which manages a collection. It should be run by @@ -127,20 +232,20 @@ void gc_init(u4 heapmaxsize, u4 heapstartsize) void gc_collect(s4 level) { rootset_t *rs; - s4 dumpsize; + int32_t dumpmarker; #if !defined(NDEBUG) - stackframeinfo *sfi; - stacktracebuffer *stb + stackframeinfo_t *sfi; + stacktracebuffer *stb; #endif #if defined(ENABLE_RT_TIMING) struct timespec time_start, time_suspend, time_rootset, time_mark, time_compact, time_end; #endif /* enter the global gc lock */ - LOCK_MONITOR_ENTER(gc_global_lock); + GC_MUTEX_LOCK; /* remember start of dump memory area */ - dumpsize = dump_size(); + DMARKER; GCSTAT_COUNT(gcstat_collections); @@ -158,7 +263,7 @@ void gc_collect(s4 level) GC_LOG( dolog("GC: Suspending threads ..."); ); GC_LOG( threads_dump(); ); threads_stopworld(); - GC_LOG( threads_dump(); ); + /*GC_LOG( threads_dump(); );*/ GC_LOG( dolog("GC: Suspension finished."); ); #endif @@ -191,7 +296,12 @@ void gc_collect(s4 level) /* find the global and local rootsets */ rs = rootset_readout(); - GC_LOG( rootset_print(rs); ); + +#if !defined(NDEBUG) + /* print the rootsets if debugging is enabled */ + if (opt_GCDebugRootSet) + rootset_print(rs); +#endif RT_TIMING_GET_TIME(time_rootset); @@ -199,14 +309,13 @@ void gc_collect(s4 level) /* mark the objects considering the given rootset */ mark_me(rs); - /*GC_LOG( heap_dump_region(heap_region_main, true); );*/ + /*GC_LOG( heap_dump_region(heap_region_main, false); );*/ RT_TIMING_GET_TIME(time_mark); /* compact the heap */ compact_me(rs, heap_region_main); - /*GC_LOG( heap_dump_region(heap_region_main, false); ); - GC_LOG( rootset_print(rs); );*/ + /*GC_LOG( heap_dump_region(heap_region_main, false); );*/ #if defined(ENABLE_MEMCHECK) /* invalidate the rest of the main region */ @@ -215,6 +324,10 @@ void gc_collect(s4 level) RT_TIMING_GET_TIME(time_compact); + /* check if we should increase the heap size */ + if (gc_get_free_bytes() < gc_get_heap_size() / 3) /* TODO: improve this heuristic */ + heap_increase_size(rs); + #else /* copy the heap to new region */ @@ -270,11 +383,13 @@ void gc_collect(s4 level) RT_TIMING_TIME_DIFF(time_start , time_end , RT_TIMING_GC_TOTAL); /* free dump memory area */ - dump_release(dumpsize); + DRELEASE; /* leave the global gc lock */ - LOCK_MONITOR_EXIT(gc_global_lock); + GC_MUTEX_UNLOCK; + /* XXX move this to an appropriate place */ + lock_hashtable_cleanup(); }