* src/mm/cacao-gc/heap.c (heap_update_references, heap_increase_size): Added.
authormichi <none@none>
Sun, 10 Jun 2007 14:35:26 +0000 (14:35 +0000)
committermichi <none@none>
Sun, 10 Jun 2007 14:35:26 +0000 (14:35 +0000)
* src/mm/cacao-gc/region.c (region_resize): Added.
* src/mm/cacao-gc/gc.c (gc_collect): Heap gets resized if it's too small.

* src/mm/cacao-gc/gc.c (gc_reference_register): Can be called without gc_init.

--HG--
branch : exact-gc

src/mm/cacao-gc/gc.c
src/mm/cacao-gc/heap.c
src/mm/cacao-gc/region.c

index 52828ae6e109493ac2d4160a367ffd941590c6e4..b54cb155e7c2bdf675e5d2f37246b1c628817343 100644 (file)
@@ -127,6 +127,12 @@ void gc_reference_register(java_objectheader **ref)
           reference is not yet set */
        GC_ASSERT(*ref == NULL);
 
+       /* are we called from threads_preinit? */
+       if (gc_reflist == NULL) {
+               GC_LOG( dolog("GC: Unable to register Reference!"); );
+               return;
+       }
+
        GC_LOG2( printf("Registering Reference at %p\n", (void *) ref); );
 
        re = NEW(list_gcref_entry_t);
@@ -240,6 +246,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 */
index 8fdbc08bcf304737840bad5bc3d7279739548d51..546370c922750a5379c490e59b71c6a5799cd550 100644 (file)
@@ -84,12 +84,90 @@ void heap_init_objectheader(java_objectheader *o, u4 bytelength)
 }
 
 
-s4 heap_increase_size() {
-       void *p;
-       s4    increasesize;
-       s4    newsize;
+void heap_update_references(rootset_t *rs, regioninfo_t *region, u4 offset)
+{
+       java_objectheader  *o;
+       java_objectheader  *ref;
+       java_objectheader **refptr;
+       u1* start;
+       u1* end;
+       int i;
+
+       GC_LOG( dolog("GC: Updating all references (offset=%x) ...", offset); );
+
+       start = region->base - offset;
+       end = region->ptr - offset;
+       GC_LOG( printf("Region previously was [ %p ; %p]\n", start, end); );
+
+       GC_LOG2( printf("updating in root-sets ..."); );
+
+       /* walk through all rootsets */
+       while (rs) {
+
+               /* walk through the references of this rootset */
+               for (i = 0; i < rs->refcount; i++) {
+
+                       /* load the reference */
+                       refptr = rs->refs[i];
+                       ref = *( refptr );
+
+                       GC_LOG2( printf("\troot pointer to %p\n", (void *) ref); );
+
+                       /* update the references */
+                       if (POINTS_INTO(ref, start, end))
+                               *refptr = ((u1 *) ref) + offset;
+
+               }
+
+               /* skip to next rootset in chain */
+               rs = rs->next;
+
+       }
+
+
+       o = region->base;
+       while (o < region->ptr) {
+
+               GC_LOG2( printf("updating in %p ...\n", (void *) o); );
+
+               if (IS_ARRAY(o)) {
+
+                       /* walk through the references of an Array */
+                       FOREACH_ARRAY_REF(o,ref,refptr,
 
-       /* TODO: locking for threads!!! */
+                               GC_LOG2( printf("\tarray-entry %p -> %p\n", (void *) ref, ((u1 *) ref) + offset); );
+
+                               if (POINTS_INTO(ref, start, end))
+                                       *refptr = ((u1 *) ref) + offset;
+
+                       );
+
+               } else {
+
+                       /* walk through the references of an Object */
+                       FOREACH_OBJECT_REF(o,ref,refptr,
+
+                               GC_LOG2( printf("\tobject-field %p -> %p\n", (void *) ref, ((u1 *) ref) + offset); );
+
+                               if (POINTS_INTO(ref, start, end))
+                                       *refptr = ((u1 *) ref) + offset;
+
+                       );
+
+               }
+
+               /* skip to next object */
+               o = ((u1 *) o) + get_object_size(o);
+
+       }
+
+}
+
+
+void heap_increase_size(rootset_t *rs)
+{
+       s4 newsize;
+       s4 resize_offset;
 
        /* only a quick sanity check */
        GC_ASSERT(heap_current_size <= heap_maximal_size);
@@ -98,25 +176,21 @@ s4 heap_increase_size() {
        if (heap_current_size == heap_maximal_size)
                vm_abort("heap_increase_size: reached maximal heap size: out of memory");
 
-       /* TODO: find out how much to increase the heap??? */
-       increasesize = heap_maximal_size - heap_current_size;
-       GC_LOG( dolog("GC: Increasing Heap Size by %d", increasesize); );
+       /* find out how much to increase the heap??? */
+       newsize = 2 * heap_current_size; /* XXX TODO: better heuristic here */
+       dolog("GC: Increasing Heap Size to %d bytes", newsize); /* XXX remove me */
+       GC_LOG( dolog("GC: Increasing Heap Size to %d bytes", newsize); );
 
-       /* allocate new heap from the system */
-       newsize = heap_current_size + increasesize;
-       /*p = malloc(newsize);*/
-
-       /* check if the newly allocated heap exists */
-       if (p == NULL)
-               vm_abort("heap_increase_size: malloc failed: out of memory");
+       /* resize the main heap region */
+       resize_offset = region_resize(heap_region_main, newsize);
 
-       /* TODO: copy the old content to the new heap */
-       /* TODO: find a complete rootset and update it to the new position */
-       /* TODO: free the old heap */
+       /* update all references if necesarry */
+       if (resize_offset != 0)
+               heap_update_references(rs, heap_region_main, resize_offset);
+       else
+               dolog("GC WARNING: References are not updated after heap resizing!");
 
        /* set the new values */
-       /*heap_ptr = p + (heap_ptr - heap_base);
-       heap_base = p;*/
        heap_current_size = newsize;
 
        GC_LOG( dolog("GC: Increasing Heap Size was successful");
@@ -125,7 +199,6 @@ s4 heap_increase_size() {
        /* only a quick sanity check */
        GC_ASSERT(heap_current_size <= heap_maximal_size);
 
-       return increasesize;
 }
 
 
index 8172697fe99898e1aa5ecad0112753f887bcdadb..28a34c3b981ef28b39e5e08ca8ad671842519f88 100644 (file)
@@ -79,6 +79,40 @@ void *region_create(regioninfo_t *region, u4 size)
 }
 
 
+u4 region_resize(regioninfo_t *region, u4 size)
+{
+       u1 *ptr;
+       u4 offset;
+       u4 used;
+
+       /* reallocate memory for the region */
+       ptr = MREALLOC(region->base, u1, region->size, size);
+
+       if (ptr == NULL)
+               vm_abort("region_resize: realloc failed!");
+
+       /* was the region moved? */
+       offset = ptr - region->base;
+       used   = region->size - region->free;
+
+       /* update structure */
+       region->base = ptr;
+       region->end  = ptr + size;
+       region->ptr  = ptr + used;
+       region->size = size;
+       region->free = size - used;
+
+#if defined(ENABLE_MEMCHECK)
+       /* poison this region */
+       region_invalidate(region);
+#endif
+
+       GC_LOG( dolog("GC: Region resized to [ %p ; %p ]", region->base, region->end); );
+
+       return offset;
+}
+
+
 /* region_invalidate ***********************************************************
 
    Invalidates the free memory area inside a heap region by overwriting it with