We use now boehm as default, so the old gc files are not needed anymore.
[cacao.git] / mm / heap2.c
diff --git a/mm/heap2.c b/mm/heap2.c
deleted file mode 100644 (file)
index cb407a0..0000000
+++ /dev/null
@@ -1,993 +0,0 @@
-#include <stddef.h>
-#include <unistd.h>            /* getpagesize, mmap, ... */
-#include <sys/mman.h>
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <assert.h>
-
-#include "asmpart.h"
-#include "callargs.h"
-#include "threads/thread.h"
-#include "threads/locks.h"
-#include "threads.h"
-
-#include "lifespan.h"
-#include "mm.h"
-
-#if !defined(HAVE_MAP_FAILED)
-#define MAP_FAILED ((void*) -1)
-#endif
-
-
-#define PAGESIZE_MINUS_ONE     (getpagesize() - 1)
-
-#undef ALIGN
-#undef OFFSET
-
-#define HEURISTIC_SEL    0
-#define HEURISTIC_PARAM  2UL
-
-
-#define next_collection_heuristic_init()   \
-             (void*)((long)heap_top + (((long)heap_limit - (long)heap_top) >> 4))
-
-#if HEURISTIC_SEL == 0
-#define next_collection_heuristic()   \
-             (void*)((long)heap_top + (((long)heap_limit - (long)heap_top) >> HEURISTIC_PARAM))
-#elif HEURISTIC_SEL == 1
-#define next_collection_heuristic()   \
-             (void*)((long)heap_top + (((long)heap_top - (long)heap_base) << HEURISTIC_PARAM))
-#elif HEURISTIC_SEL == 2
-#define next_collection_heuristic()   \
-             (void*)((long)heap_top + HEURISTIC_PARAM)  
-#endif
-
-        /*
-//#define PSEUDO_GENERATIONAL
-//#define COLLECT_LIFESPAN
-//#define NEW_COLLECT_LIFESPAN
-//#define COLLECT_FRAGMENTATION
-//#define COLLECT_SIZES
-
-//#define GC_COLLECT_STATISTICS
-//#define FINALIZER_COUNTING
-*/
-
-#undef STRUCTURES_ON_HEAP
-        /*
-//#define STRUCTURES_ON_HEAP
-*/
-
-#define false 0
-#define true 1
-
-#include "allocator.h" /* rev. 1 allocator */
-#include "bitmap2.h"   /* rev. 2 bitmap management */
-
-bool collectverbose;
-
-void gc_call (void);
-
-/* --- macros */
-
-#define align_size(size)       ((size) & ~((1 << ALIGN) - 1))
-#define MAP_ADDRESS                    (void*) 0x10000000
-
-/* --- file-wide variables */
-
-static void*   heap_base = NULL;
-static SIZE            heap_size = 0;
-static void*   heap_top = NULL;
-static void*   heap_limit = NULL;
-static void*   heap_next_collection = NULL;
-
-static bitmap_t* start_bitmap = NULL;
-static BITBLOCK* start_bits = NULL;
-static bitmap_t* reference_bitmap = NULL;
-static BITBLOCK* reference_bits = NULL;
-static bitmap_t* mark_bitmap = NULL;
-static BITBLOCK* mark_bits = NULL;
-
-static void**  stackbottom = NULL;
-
-typedef struct address_list_node {
-       void* address;
-       struct address_list_node* prev;
-       struct address_list_node* next;
-} address_list_node;
-
-static address_list_node* references = NULL;
-static address_list_node* finalizers = NULL;
-
-#ifdef GC_COLLECT_STATISTICS
-
-static unsigned long gc_collections_count = 0;
-
-static unsigned long gc_alloc_total = 0;
-static unsigned long gc_alloc_count = 0;
-
-static unsigned long gc_mark_heapblocks_visited = 0;
-static unsigned long gc_mark_not_aligned = 0;
-static unsigned long gc_mark_not_inheap = 0;
-static unsigned long gc_mark_not_object = 0;
-static unsigned long gc_mark_objects_marked = 0;
-static unsigned long gc_mark_already_marked = 0;
-
-static unsigned long gc_mark_null_pointer = 0;
-
-#endif
-
-#ifdef FINALIZER_COUNTING
-
-static unsigned long gc_finalizers_executed = 0;
-static unsigned long gc_finalizers_detected = 0;
-
-#endif
-
-#ifdef USE_THREADS
-static iMux  alloc_mutex;
-#endif
-
-#ifdef COLLECT_LIFESPAN
-static FILE* tracefile;
-#endif
-
-#ifdef COLLECT_FRAGMENTATION
-static FILE* fragfile;
-static FILE* fragsizefile;
-#endif
-
-/* --- implementation */
-
-void 
-heap_init (SIZE size, 
-                  SIZE startsize, /* when should we collect for the first time ? */
-                  void **in_stackbottom)
-{
-       /* 1. Initialise the freelists & reset the allocator's state */
-       allocator_init(); 
-
-       /* 2. Allocate at least (alignment!) size bytes of memory for the heap */
-       heap_size = align_size(size + ((1 << ALIGN) - 1));
-
-#if !(defined(HAVE_MAP_ANONYMOUS))
-       heap_base = (void*)(((u8)malloc(heap_size+1023)+1023) & ~1023);
-#else
-       heap_base = (void*) mmap ((void*) 0x10000000, 
-                                                         ((size_t)heap_size + PAGESIZE_MINUS_ONE) & ~PAGESIZE_MINUS_ONE,
-                                                         PROT_READ | PROT_WRITE, 
-                                                         MAP_PRIVATE | MAP_ANONYMOUS, 
-                                                         -1, 
-                                                         (off_t) 0);
-#endif
-
-       if (heap_base == (void*)MAP_FAILED) {
-               /* unable to allocate the requested amount of memory */
-               fprintf(stderr, "heap2.c: The queen, mylord, is dead! (mmap failed)\n");
-               exit(-1);
-       }
-
-       /* 3. Allocate the bitmaps */
-       start_bitmap = bitmap_allocate(heap_base, heap_size);
-       reference_bitmap = bitmap_allocate(heap_base, heap_size);
-       mark_bitmap = bitmap_allocate(heap_base, heap_size);
-
-       start_bits = start_bitmap->bitmap;
-    reference_bits = reference_bitmap->bitmap;
-    mark_bits = mark_bitmap->bitmap;
-
-       /* 4. Mark the first free-area as an object-start */
-       bitmap_setbit(start_bits, heap_base);
-
-       /* 5. Initialise the heap's state (heap_top, etc.) */
-       stackbottom = in_stackbottom; /* copy the stackbottom */
-
-       heap_top = heap_base; /* the current end of the heap (just behind the last allocated object) */
-       heap_limit = (void*)((long)heap_base + heap_size); /* points just behind the last accessible block of the heap */
-
-       /* 6. calculate a useful first collection limit */
-       /* This is extremly primitive at this point... 
-          we should replace it with something more useful -- phil. */
-       heap_next_collection = next_collection_heuristic_init();
-
-       /* 7. Init the global reference lists & finalizer addresses */
-       references = NULL;
-       finalizers = NULL;
-
-#ifdef STRUCTURES_ON_HEAP
-       heap_addreference(&references);
-       heap_addreference(&finalizers);
-#endif
-
-#ifdef USE_THREADS
-       /* 8. Init the mutexes for synchronization */
-       alloc_mutex.holder = 0;
-#endif
-
-       /* 9. Set up collection of lifespan data */
-#ifdef COLLECT_LIFESPAN
-#if 0
-       tracefile = fopen("heap.trace", "w");
-#else
-       tracefile = popen("gzip -9 >heap.trace.gz", "w");
-#endif
-       if (!tracefile) {
-               fprintf(stderr, "heap2.c: Radio Ga Ga! (fopen failed)\n");
-               exit(-2);
-       }
-
-       fprintf(tracefile, "heap_base\t0x%lx\n", heap_base);    
-       fprintf(tracefile, "heap_limit\t0x%lx\n", heap_limit);
-       fprintf(tracefile, "heap_top\t0x%lx\n", heap_top);
-#endif
-
-#if defined(NEW_COLLECT_LIFESPAN) || defined(COLLECT_SIZES)
-       lifespan_init(heap_base, heap_size);
-#endif
-
-       /* 10. Set up collection of fragmentation data */
-#ifdef COLLECT_FRAGMENTATION
-       fragfile = popen("gzip -9 >fragmentation.gz", "w");
-       fragsizefile = popen("gzip -9 >freeblocks.gz", "w");
-#endif
-}
-
-inline
-static
-void
-heap_call_finalizer_for_object_at(java_objectheader* object_addr)
-{
-       asm_calljavamethod(object_addr->vftbl->class->finalizer, object_addr, NULL, NULL, NULL);
-#ifdef FINALIZER_COUNTING
-       ++gc_finalizers_executed;
-#endif
-}
-
-void 
-heap_close (void)
-{
-       address_list_node* curr = finalizers;
-
-       /* 0. clean up lifespan module */
-#ifdef COLLECT_LIFESPAN
-#if 0
-       fclose(tracefile);
-#else
-       pclose(tracefile);
-#endif
-#endif
-
-#if defined(NEW_COLLECT_LIFESPAN)
-       lifespan_close();
-#endif
-
-#ifdef COLLECT_FRAGMENTATION
-       pclose(fragfile);
-       pclose(fragsizefile);
-#endif
-
-       /* 1. Clean up on the heap... finalize all remaining objects */
-#if 1
-       while (curr) {
-               address_list_node* prev = curr;
-               java_objectheader* addr = (java_objectheader*)(curr->address);
-               
-               if (addr && bitmap_testbit(start_bits, addr))
-                       heap_call_finalizer_for_object_at(addr);
-               
-               curr = curr->next;
-               free(prev);
-       }
-#endif
-
-       /* 2. Release the bitmaps */
-       bitmap_release(start_bitmap);
-       bitmap_release(reference_bitmap);
-       bitmap_release(mark_bitmap);
-
-       /* 3. Release the memory allocated to the heap */
-       if (heap_base)
-               munmap(heap_base, heap_size);
-
-       /* 4. emit statistical data */
-#ifdef GC_COLLECT_STATISTICS
-       sprintf(logtext, "%ld bytes for %ld objects allocated.", 
-                       gc_alloc_total, gc_alloc_count); 
-       dolog();
-       sprintf(logtext, "%ld garbage collections performed.", gc_collections_count);
-       dolog();
-       sprintf(logtext, "%ld heapblocks visited, %ld objects marked", 
-                       gc_mark_heapblocks_visited, gc_mark_objects_marked);
-       dolog();
-       sprintf(logtext, "    %ld null pointers.", gc_mark_null_pointer);
-       dolog();
-       sprintf(logtext, "    %ld out of heap.", gc_mark_not_inheap);
-       dolog();
-       sprintf(logtext, "    %ld visits to objects already marked.", gc_mark_already_marked);
-       dolog();
-       sprintf(logtext, "    %ld not an object.", gc_mark_not_object);
-       dolog();
-       sprintf(logtext, "    %ld potential references not aligned.", gc_mark_not_aligned);
-       dolog();
-#endif
-
-#ifdef FINALIZER_COUNTING
-       sprintf(logtext, "%ld objects with a finalizer", gc_finalizers_detected);
-       dolog();
-
-       if (gc_finalizers_detected == gc_finalizers_executed)
-               sprintf(logtext, "    all finalizers executed.");
-       else
-               sprintf(logtext, "    only %ld finalizers executed.", gc_finalizers_executed);
-       dolog();
-#endif
-
-#if defined(NEW_COLLECT_LIFESPAN) || defined(COLLECT_SIZES)
-       lifespan_emit();
-#endif
-}
-
-inline
-static
-void 
-heap_add_address_to_address_list(address_list_node** list, void* address)
-{
-       /* Note: address lists are kept sorted to simplify finalization */
-
-       address_list_node* new_node = malloc(sizeof(address_list_node));
-       new_node->address = address;
-       new_node->next = NULL;
-
-       while (*list && (*list)->next) {
-               if ((*list)->next->address < address)
-                       list = &(*list)->next;
-               else {
-                       new_node->next = *list;
-                       *list = new_node;
-                       return;
-               }                       
-       }
-
-       new_node->next = *list;
-       *list = new_node;
-}
-
-
-inline
-static
-void 
-heap_add_address_to_address_list_unsorted(address_list_node** list, 
-                                                                                 void* address)
-{
-       address_list_node* new_node = malloc(sizeof(address_list_node));
-       new_node->address = address;
-       new_node->next = *list;
-       *list = new_node;
-}
-
-
-inline
-static
-void
-heap_add_finalizer_for_object_at(void* addr)
-{
-       /* Finalizers seem to be very rare... for this reason, I keep a linked
-          list of object addresses, which have a finalizer attached. This list
-          is kept in ascending order according to the order garbage is freed.
-          This list is currently kept separate from the heap, but should be 
-          moved onto it, but some JIT-marker code to handle these special
-          objects will need to be added first. -- phil. */
-
-       heap_add_address_to_address_list(&finalizers, addr);
-
-#ifdef COLLECT_LIFESPAN
-       fprintf(tracefile, "finalizer\t0x%lx\n", addr);
-#endif
-}
-
-void* 
-heap_allocate (SIZE              in_length, 
-                          bool           references, 
-                          methodinfo *finalizer)
-{
-       SIZE    length = align_size(in_length + ((1 << ALIGN) - 1)); 
-       void*   free_chunk = NULL;
-
-#if 0
-       /* check for misaligned in_length parameter */
-       if (length != in_length)
-               fprintf(stderr,
-                               "heap2.c: heap_allocate was passed unaligned in_length parameter: %ld, \n         aligned to %ld. (mistrust)\n",
-                               in_length, length);
-#endif
-
-#ifdef FINALIZER_COUNTING
-       if (finalizer)
-               ++gc_finalizers_detected;
-#endif
-
-#if defined(COLLECT_LIFESPAN) || defined(NEW_COLLECT_LIFESPAN)
-       /* perform garbage collection to collect data for lifespan analysis */
-       if (heap_top > heap_base)
-               gc_call();
-#endif
-
-#ifdef USE_THREADS
-       lock_mutex(&alloc_mutex);
-#endif 
- retry:
-       /* 1. attempt to get a free block with size >= length from the freelists */
-       free_chunk = allocator_alloc(length);
-
-       /* 2. if unsuccessful, try alternative allocation strategies */
-       if (!free_chunk) {
-               /* 2.a if the collection threshold would be exceeded, collect the heap */
-               if ((long)heap_top + length > (long)heap_next_collection) {
-                       /* 2.a.1. collect if the next_collection threshold would be exceeded */
-                       gc_call();
-
-                       /* 2.a.2. we just ran a collection, recheck the freelists */
-                       free_chunk = allocator_alloc(length);
-                       if (free_chunk)
-                               goto success;
-
-                       /* 2.a.3. we can't satisfy the request from the freelists, check
-                                 against the heap_limit whether growing the heap is possible */
-                       if ((long)heap_top + length > (long)heap_limit)
-                               goto failure;
-               }
-
-               /* 2.b. grow the heap */
-               free_chunk = heap_top;
-               heap_top = (void*)((long)heap_top + length);
-       }
-
- success:
-       /* 3.a. mark all necessary bits, store the finalizer & return the newly allocated block */
-
-       /* I don't mark the object-start anymore, as it always is at the beginning of a free-block,
-          which already is marked (Note: The first free-block gets marked in heap_init). -- phil. */
-       bitmap_setbit(start_bits, free_chunk); /* mark the new object */
-
-#ifndef SIZE_FROM_CLASSINFO
-       bitmap_setbit(start_bits, (void*)((long)free_chunk + (long)length)); /* mark the freespace behind the new object */
-#endif
-
-       if (references)
-               bitmap_setbit(reference_bits, free_chunk);
-       else 
-               bitmap_clearbit(reference_bits, free_chunk);
-
-       /* store a hint, that there's a finalizer for this address */
-       if (finalizer)
-               heap_add_finalizer_for_object_at(free_chunk);
-
-#ifdef GC_COLLECT_STATISTICS
-       gc_alloc_total += length;
-       ++gc_alloc_count;
-#endif
-
-#ifdef COLLECT_LIFESPAN
-       fprintf(tracefile, "alloc\t0x%lx\t0x%lx\n", 
-                       free_chunk, (long)free_chunk + length);
-#endif
-
-#if defined(NEW_COLLECT_LIFESPAN) || defined(COLLECT_SIZES)
-       lifespan_alloc(free_chunk, length);
-#endif
-
- failure:
-#ifdef USE_THREADS
-       unlock_mutex(&alloc_mutex);
-#endif 
-       return free_chunk;
-}
-
-void 
-heap_addreference (void **reflocation)
-{
-       /* I currently use a separate linked list (as in the original code) to hold
-          the global reference locations, but I'll change this to allocate these
-          in blocks on the heap; we'll have to add JIT-Marker code for those Java
-          objects then. -- phil. */
-
-       heap_add_address_to_address_list_unsorted(&references, reflocation);
-}
-
-static
-inline
-void gc_finalize (void)
-{
-       /* This will have to be slightly rewritten as soon the JIT-marked heap-based lists are used. -- phil. */
-
-       address_list_node*  curr = finalizers;
-       address_list_node*  prev;
-
-#if 0
-       /* FIXME: new code, please! */
-#else
-       while (curr) {
-               if (curr->address) {
-                       if (!bitmap_testbit(mark_bits, curr->address)) {
-                               int b;
-
-#ifdef FINALIZER_COUNTING
-                               ++gc_finalizers_executed;
-#endif
-#ifdef USE_THREADS
-                               b = blockInts;
-                               blockInts = 0;
-#endif
-                               asm_calljavamethod(((java_objectheader*)curr->address)->vftbl->class->finalizer, 
-                                                                  curr->address, NULL, NULL, NULL);
-#ifdef USE_THREADS
-                               blockInts = b;
-#endif
-                               curr->address = 0;
-                       }
-               }
-
-               curr = curr->next;
-       }
-#endif
-}
-
-
-inline
-static 
-void gc_reclaim (void)
-{
-#ifdef PSEUDO_GENERATIONAL
-       static void*  generation_start = 0;
-       static int    generation_num = 0;
-       void* addr = heap_base;
-#endif
-       void* free_start;
-       void* free_end = heap_base;
-       BITBLOCK* temp_bits;
-       bitmap_t* temp_bitmap;
-
-#ifdef COLLECT_FRAGMENTATION
-       unsigned long  free_size = 0;
-       unsigned long  free_fragments = 0;
-#endif
-
-#ifdef PSEUDO_GENERATIONAL
-       if (!generation_start || !(generation_num % 5))
-               generation_start = heap_base;
-
-       ++generation_num;
-#endif
-
-       /* 1. reset the freelists */
-
-#if 0
-       allocator_mark_free_kludge(start_bits); /* this line will be kicked out, when
-                                                                                          the SIZE_FROM_CLASSINFO reclaim
-                                                                                          is implemented (very soon!!) */
-#endif
-
-#ifdef PSEUDO_GENERATIONAL
-       for (addr = heap_base; addr <= generation_start; ++addr) {
-               if (bitmap_testbit(start_bits, addr))
-                       bitmap_setbit(mark_bits, addr);
-       }
-
-       allocator_mark_free_kludge(start_bits); /* this line will be kicked out, when
-                                                                                          the SIZE_FROM_CLASSINFO reclaim
-                                                                                          is implemented (very soon!!) */
-#endif
-
-       allocator_reset();
-
-       /* 2. reclaim unmarked objects */
-#if 0
-       if (!testbit(start_bits, heap_base))
-               free_start = heap_base;
-       else
-               free_start = bitmap_find_next_combination_set_unset(start_bitmap,
-                                                                                                                       mark_bitmap,
-                                                                                                                       free_start);
-
-#else
-       while (free_end < heap_top) {
-               free_start = bitmap_find_next_combination_set_unset(start_bitmap,
-                                                                                                                       mark_bitmap,
-                                                                                                                       free_end);
-
-               if (free_start < heap_top) {
-                       free_end = bitmap_find_next_setbit(mark_bitmap, (void*)((long)free_start + 8)); /* FIXME: constant used */
-
-                       if (free_end < heap_top) {
-                               allocator_free(free_start, (long)free_end - (long)free_start);
-
-#ifdef COLLECT_FRAGMENTATION
-                               free_size += (long)free_end - (long)free_start;
-                               free_fragments++;
-#endif
-
-#ifdef COLLECT_LIFESPAN
-                               fprintf(tracefile, 
-                                               "free\t0x%lx\t0x%lx\n", 
-                                               free_start,
-                                               (long)free_end);
-#endif
-
-#ifdef NEW_COLLECT_LIFESPAN
-                               lifespan_free(free_start, free_end);
-#endif
-
-#ifndef SIZE_FROM_CLASSINFO
-                               /* would make trouble with JIT-Marker support. The Marker for unused blocks 
-                                  might be called, leading to a bad dereference. -- phil. */
-                               bitmap_setbit(mark_bits, free_start); /* necessary to calculate obj-size bitmap based. */
-#endif
-                       }
-               } else {
-                       free_end = heap_top;    
-               }
-       }
-#endif
-
-       /* 3.1. swap mark & start bitmaps */
-       temp_bits = mark_bits;
-       mark_bits = start_bits;
-       start_bits = temp_bits;
-
-       temp_bitmap = mark_bitmap;
-       mark_bitmap = start_bitmap;
-       start_bitmap = temp_bitmap;
-
-#if 0 /* operation already handled in allocate */
-       /* 3.2. mask reference bitmap */
-       bitmap_mask_with_bitmap(reference_bitmap, start_bitmap);
-#endif
-
-       /* 3.3. update heap_top */
-       if (free_start < heap_top) {
-               heap_top = free_start;
-#ifdef NEW_COLLECT_LIFESPAN
-                       lifespan_free(free_start, free_end);
-#endif
-       }
-
-#if 0
-       if (heap_top < heap_limit)
-               bitmap_setbit(start_bits, heap_top);
-#endif
-
-       /* 3.4. emit fragmentation info */
-#ifdef COLLECT_FRAGMENTATION
-       {
-               unsigned long heap_full = (unsigned long)heap_top - (unsigned long)heap_base;
-               unsigned long heap_life = (unsigned long)heap_top - (unsigned long)heap_base - free_size;
-
-               fprintf(fragfile, 
-                               "%ld\t%ld\t%ld\t%ld\t%f\t%f\t%f\n", 
-                               heap_full,
-                               heap_life,
-                               free_size, 
-                               free_fragments,
-                               100*(float)free_size/(free_fragments ? free_fragments : 1),
-                               100*(float)heap_life/(heap_full ? heap_full : 1),
-                               100*(float)free_size/(heap_full ? heap_full : 1)
-                               );
-       }
-       fflush(fragfile);
-
-       allocator_dump_to_file(fragsizefile);
-#endif
-
-       /* 4. adjust the collection threshold */
-       heap_next_collection = next_collection_heuristic();
-       if (heap_next_collection > heap_limit)
-               heap_next_collection = heap_limit;
-
-#ifdef COLLECT_LIFESPAN
-       fprintf(tracefile, "heap_top\t0x%lx\n", heap_top);
-#endif
-
-#ifdef PSEUDO_GENERATIONAL
-       generation_start = heap_top;
-#endif
-}
-
-inline
-static
-void 
-gc_mark_object_at (void** addr)
-{
-       /*
-        * A note concerning the order of the tests:
-        *
-        * Statistics collected during a test run, where alignment
-        * was tested before checking whether the addr points into 
-        * the heap:
-        * >> LOG: 9301464 bytes for 196724 objects allocated.
-        * >> LOG: 15 garbage collections performed.
-        * >> LOG: 6568440 heapblocks visited, 469249 objects marked
-        * >> LOG:     1064447 visits to objects already marked.
-        * >> LOG:     988270 potential references not aligned.
-        * >> LOG:     4049446 out of heap.
-        * >> LOG:     5236 not an object.
-        *
-        * These results show, that only about 1/4 of all heapblocks 
-        * point to objects; The single most important reason why a 
-        * heapblock can not point at an object is, that it's value 
-        * doesn't fall within the heap area (this test was performed
-        * with a 3MB heap).
-        *
-        * From the results, the various tests have to be conducted 
-        * in the following order for maximum efficiency:
-        *    1. addr in heap?
-        *    2. already marked ?
-        *    3. aligned ?
-        *    4. object ?
-        *
-        * The results after reordering:
-        * >> LOG: 9301464 bytes for 196724 objects allocated.
-        * >> LOG: 15 garbage collections performed.
-        * >> LOG: 6568440 heapblocks visited, 469249 objects marked
-        * >> LOG:     1064447 visits to objects already marked.
-        * >> LOG:     350 potential references not aligned.
-        * >> LOG:     5037366 out of heap.
-        * >> LOG:     5236 not an object.
-        *
-        * And using:
-        *    1. addr in heap?
-        *    2. already marked ?
-        *    3. object ?
-        *    4. aligned ?
-        * 
-        * >> LOG: 9301464 bytes for 196724 objects allocated.
-        * >> LOG: 15 garbage collections performed.
-        * >> LOG: 6568440 heapblocks visited, 469249 objects marked
-        * >> LOG:     5037366 out of heap.
-        * >> LOG:     1064456 visits to objects already marked.
-        * >> LOG:     5539 not an object.
-        * >> LOG:     38 potential references not aligned.
-        *
-        * Apparently, most unaligned values will already be eliminated
-        * when checking against the bounds of the heap. Checking this
-        * property first, should thus improve collection times.
-        */
-
-       /* 1.a. if addr doesn't point into the heap, return. */
-       if ((unsigned long)addr - (unsigned long)heap_base >= 
-               ((unsigned long)heap_top - (unsigned long)heap_base)) {
-#ifdef GC_COLLECT_STATISTICS
-               if (addr == NULL)
-                       ++gc_mark_null_pointer;
-               else
-                       ++gc_mark_not_inheap;
-#endif
-               return;
-       }
-
-       /* 1.b. if align(addr) has already been marked during this collection, return. */
-       if (bitmap_testbit(mark_bits, (void*)addr)) {
-#ifdef GC_COLLECT_STATISTICS
-               ++gc_mark_already_marked;
-#endif
-               return;
-       }
-
-       /* 1.c. if align(addr) doesn't point to the start of an object, return. */
-       if (!bitmap_testbit(start_bits, (void*)addr)) {
-#ifdef GC_COLLECT_STATISTICS
-               ++gc_mark_not_object;
-#endif
-               return;
-       }
-
-       /* 1.d. if addr is not properly aligned, return. */
-       if ((long)addr & ((1 << ALIGN) - 1)) {
-#ifdef GC_COLLECT_STATISTICS
-               ++gc_mark_not_aligned;
-#endif
-               return;
-       }
-
-       /* 2. Mark the object at addr */
-       bitmap_setbit(mark_bits, (void*)addr); 
-#ifdef GC_COLLECT_STATISTICS
-       ++gc_mark_objects_marked;
-#endif
-
-#ifdef JIT_MARKER_SUPPORT
-       asm_calljavamethod(addr->vftbl->class->marker, addr, NULL, NULL, NULL);
-#else
-
-       /* 3. mark the references contained within the extents of the object at addr */
-       if (bitmap_testbit(reference_bits, addr)) {
-               /* 3.1. find the end of the object */
-               void** end;
-
-#ifdef SIZE_FROM_CLASSINFO
-               if (((java_objectheader*)addr)->vftbl == class_array->vftbl)
-                       end = (void**)((long)addr + (long)((java_arrayheader*)addr)->alignedsize);
-               else
-                       end = (void**)((long)addr + (long)((java_objectheader*)addr)->vftbl->class->alignedsize);
-#else
-               end = (void**)bitmap_find_next_setbit(start_bitmap, addr + 1); /* points just behind the object */
-#endif
-
-               /* 3.2. mark the references within the object at addr */
-#ifdef GC_COLLECT_STATISTICS
-               gc_mark_heapblocks_visited += ((long)end - (long)addr) >> ALIGN;
-#endif
-               while (addr < end)
-                       gc_mark_object_at(*(addr++));
-#endif 
-       }
-       
-       return;
-}
-
-
-inline
-static
-void gc_mark_references (void)
-{
-       address_list_node* curr = references;
-
-       while (curr) {
-#ifdef GC_COLLECT_STATISTICS
-               ++gc_mark_heapblocks_visited;
-#endif         
-               gc_mark_object_at(*((void**)(curr->address)));
-               curr = curr->next;
-       }
-}
-
-inline
-static
-void 
-markreferences(void** start, void** end)
-{
-       while (start < end) {
-#ifdef GC_COLLECT_STATISTICS
-               ++gc_mark_heapblocks_visited;
-#endif         
-               gc_mark_object_at(*(start++));
-       }
-}
-
-inline
-static
-void gc_mark_stack (void)
-{
-       void *dummy;
-
-#ifdef USE_THREADS 
-    thread *aThread;
-       
-       if (1) {
-               void **top_of_stack = &dummy;
-
-               for (aThread = liveThreads; aThread != 0;
-                        aThread = CONTEXT(aThread).nextlive) {
-                       gc_mark_object_at((void*)aThread);
-                       if (aThread == mainThread)
-                               continue;
-                       if (CONTEXT(aThread).usedStackTop > CONTEXT(aThread).stackEnd)
-                               markreferences((void**)CONTEXT(aThread).stackEnd,
-                                                          (void**)CONTEXT(aThread).usedStackTop);
-                       else    
-                               markreferences((void**)CONTEXT(aThread).usedStackTop,
-                                                          (void**)CONTEXT(aThread).stackEnd);
-               }
-               
-               /* Mark main thread now [stefan] */
-               /* (we are running on it) */
-               if (top_of_stack > stackbottom)
-                       markreferences(stackbottom, top_of_stack);
-               else
-                       markreferences(top_of_stack, stackbottom);
-
-               markreferences((void**)&threadQhead[0],
-                                          (void**)&threadQhead[MAX_THREAD_PRIO]);
-       }
-#else
-    void **top_of_stack = &dummy;
-
-    if (top_of_stack > stackbottom)
-        markreferences(stackbottom, top_of_stack);
-       else
-        markreferences(top_of_stack, stackbottom);
-#endif
-}
-
-
-static 
-void gc_run (void)
-{
-       static int armageddon_is_near = 0;
-
-       if (armageddon_is_near) {
-               /* armageddon_is_here! */
-               fprintf(stderr, "Oops, seems like there's a slight problem here: gc_run() called while still running?!\n");
-               return;
-       }
-
-       armageddon_is_near = true;
-       heap_next_collection = heap_limit;  /* try to avoid finalizer-induced collections */
-
-       bitmap_clear(mark_bitmap);
-
-       asm_dumpregistersandcall(gc_mark_stack);
-       gc_mark_references();
-       gc_finalize();
-       gc_reclaim();
-
-       armageddon_is_near = false;
-
-#ifdef GC_COLLECT_STATISTICS
-       ++gc_collections_count;
-#endif
-}
-
-
-/************************* Function: gc_init **********************************
-
-  Initializes anything that must be initialized to call the gc on the right
-  stack.
-
-******************************************************************************/
-
-void
-gc_init (void)
-{
-}
-
-/************************** Function: gc_call ********************************
-
-  Calls the garbage collector. The garbage collector should always be called
-  using this function since it ensures that enough stack space is available.
-
-******************************************************************************/
-
-void
-gc_call (void)
-{
-#ifdef USE_THREADS
-       u1 dummy;
-
-       assert(blockInts == 0);
-
-       intsDisable();
-       if (currentThread == NULL || currentThread == mainThread) {
-               gc_run();
-               }
-       else
-               asm_switchstackandcall(CONTEXT(mainThread).usedStackTop, gc_run,
-                                                          (void**)&(CONTEXT(currentThread).usedStackTop),NULL);
-       intsRestore();
-#else
-       gc_run();
-#endif
-
-       if (collectverbose) {
-               sprintf(logtext, "Garbage Collection:  previous/now = %d / %d ",
-                       (int) ((u1*) heap_top - (u1*) heap_base), 
-                       (int) ((u1*) heap_top - (u1*) heap_base));
-               dolog ();
-               }
-}
-
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
-