* src/mm/cacao-gc/mark.h, src/mm/cacao-gc/heap.h, src/mm/cacao-gc/heap.c,
authormichi <none@none>
Fri, 23 Feb 2007 23:20:45 +0000 (23:20 +0000)
committermichi <none@none>
Fri, 23 Feb 2007 23:20:45 +0000 (23:20 +0000)
src/mm/cacao-gc/region.h, src/mm/cacao-gc/region.c: Added.

* src/mm/cacao-gc/Makefile.am: See above.

* src/mm/cacao-gc/gc.h, src/mm/cacao-gc/gc.c: Moved development breaks.
(gc_collect): Added.

* src/mm/cacao-gc/compact.c: Classloaders are threaded in now.
(compact_move): Fixed a severe typo.

--HG--
branch : exact-gc

src/mm/cacao-gc/Makefile.am
src/mm/cacao-gc/compact.c
src/mm/cacao-gc/gc.c
src/mm/cacao-gc/gc.h
src/mm/cacao-gc/heap.c [new file with mode: 0644]
src/mm/cacao-gc/heap.h [new file with mode: 0644]
src/mm/cacao-gc/mark.c
src/mm/cacao-gc/mark.h [new file with mode: 0644]
src/mm/cacao-gc/region.c [new file with mode: 0644]
src/mm/cacao-gc/region.h [new file with mode: 0644]

index 5150edadc9aad088c394ddb78f67a0a8dd13131a..b4ba11f116c83164b444ceeef3f916e707931332 100644 (file)
@@ -39,10 +39,16 @@ LIBS =
 noinst_LTLIBRARIES = libgc.la
 
 libgc_la_SOURCES = \
+       compact.c \
+       compact.h \
        gc.c \
        gc.h \
        heap.c \
-       mark.c
+       heap.h \
+       mark.c \
+       mark.h \
+       region.c \
+       region.h
 
 
 ## Local variables:
index eba72c1a9d335e4985b51cf16491eaf5216b4a52..b8332217b58f8c0a51a6d35fd5b4529576176a71 100644 (file)
@@ -94,7 +94,8 @@ void compact_thread_rootset(rootset_t *rs, void *start, void *end)
 
 /* compact_thread_classes ******************************************************
 
-   Threads all the references from classinfo structures (static fields)
+   Threads all the references from classinfo structures (static fields and
+   classloaders)
 
    IN:
       start.....Region to be compacted start here
@@ -108,6 +109,7 @@ void compact_thread_classes(void *start, void *end)
        java_objectheader **refptr;
        classinfo          *c;
        fieldinfo          *f;
+       hashtable_classloader_entry *cle;
        void *sys_start, *sys_end;
        int i;
 
@@ -117,9 +119,31 @@ void compact_thread_classes(void *start, void *end)
        sys_start = heap_region_sys->base;
        sys_end = heap_region_sys->ptr;
 
+       /* walk through all classloaders */
+       for (i = 0; i < hashtable_classloader->size; i++) {
+               cle = hashtable_classloader->ptr[i];
+
+               while (cle) {
+
+                       /* thread the classloader */
+                       refptr = &( cle->object );
+                       ref = *( refptr );
+                       GC_LOG2( printf("\tclassloader from hashtable at %p\n", (void *) ref); );
+                       GC_THREAD(ref, refptr, start, end);
+
+                       cle = cle->hashlink;
+               }
+       }
+
        /* walk through all classinfo blocks */
        for (c = sys_start; c < (classinfo *) sys_end; c++) {
 
+               /* thread the classloader */
+               /*refptr = &( c->classloader );
+               ref = *( refptr );
+               GC_LOG2( printf("\tclassloader from classinfo at %p\n", (void *) ref); );
+               GC_THREAD(ref, refptr, start, end);*/
+
                /* walk through all fields */
                f = c->fields;
                for (i = 0; i < c->fieldscount; i++, f++) {
@@ -141,7 +165,7 @@ void compact_thread_classes(void *start, void *end)
                                } else if (GC_IS_THREADED(ref->vftbl)) {
                                        printf("(threaded)\n");
                                } else {
-                                               heap_print_object(ref); printf("\n");
+                                       heap_print_object(ref); printf("\n");
                                }
                        );*/
 
@@ -271,19 +295,21 @@ void compact_move(u1 *old, u1 *new, u4 size)
        GC_ASSERT(new < old);
 
        /* check if locations overlap */
-       if (old + size >= new) {
+       if (new + size < old) {
                /* overlapping: NO */
 
                /* copy old object content to new location */
                MCOPY(new, old, u1, size);
 
+#if !defined(NDEBUG)
                /* invalidate old object */
-               MSET(old, 0x44, u1, size);
+               MSET(old, MEMORY_CLEAR_BYTE, u1, size);
+#endif
 
        } else {
                /* overlapping: YES */
 
-               GC_LOG( dolog("GC: OVERLAPPING!!!") );
+               GC_LOG2( printf("\tcompact_move(old=%p, new=%p, size=0x%x) overlapps!", old, new, size) );
 
                /* copy old object content to new location */
                MMOVE(new, old, u1, size);
@@ -324,14 +350,11 @@ void compact_me(rootset_t *rs, regioninfo_t *region)
         *  - thread all references
         *  - update forward references */
        ptr = region->base; ptr_new = region->base;
-       while (ptr < (u1 *) region->ptr) {
+       while (ptr < region->ptr) {
                o = (java_objectheader *) ptr;
 
-               /* TODO: uncollectable items should never be compacted, but for now we do it */
-               /*GC_ASSERT(!GC_TEST_FLAGS(o, GC_FLAG_UNCOLLECTABLE));*/
-               /*if (GC_TEST_FLAGS(o, GC_FLAG_UNCOLLECTABLE)) {
-                       GC_SET_MARKED(o);
-               }*/
+               /* uncollectable items should never be compacted */
+               GC_ASSERT(!GC_TEST_FLAGS(o, GC_FLAG_UNCOLLECTABLE));
 
                /* if this object is already part of a threaded chain ... */
                if (GC_IS_THREADED(o->vftbl)) {
@@ -366,7 +389,7 @@ void compact_me(rootset_t *rs, regioninfo_t *region)
         *  - move the objects */
        used = 0;
        ptr = region->base; ptr_new = region->base;
-       while (ptr < (u1 *) region->ptr) {
+       while (ptr < region->ptr) {
                o = (java_objectheader *) ptr;
 
                /* if this object is still part of a threaded chain ... */
@@ -404,6 +427,7 @@ void compact_me(rootset_t *rs, regioninfo_t *region)
        GC_LOG( dolog("GC: Compaction finished."); );
 
        GC_LOG( printf("Region-Used: %d -> %d\n", region->size - region->free, used); )
+       GC_LOG( printf("Region-Free: %d -> %d\n", region->free, region->size - used); )
 
        /* update the region information */
        region->ptr = ptr_new;
index 578d21947cffb8eedbdba8d6e16d678d97459c36..3dc75a6df017864dc91a10e48addb7ead37d9b1b 100644 (file)
@@ -1,6 +1,6 @@
 /* src/mm/cacao-gc/gc.c - main garbage collector methods
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   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
 
 #include "config.h"
 #include <signal.h>
-#include <stdlib.h>
 #include "vm/types.h"
 
 #if defined(ENABLE_THREADS)
 # include "threads/native/threads.h"
 #else
-# include "threads/none/threads.h"
+/*# include "threads/none/threads.h"*/
 #endif
 
+#include "compact.h"
 #include "gc.h"
 #include "heap.h"
 #include "mark.h"
+#include "region.h"
 #include "mm/memory.h"
 #include "toolbox/logging.h"
 #include "vm/exceptions.h"
-#include "vm/options.h"
-
-
-/* Development Break **********************************************************/
-
-#if defined(ENABLE_THREADS)
-# error "GC does not work with threads enabled!"
-#endif
-
-#if defined(ENABLE_INTRP)
-# error "GC does not work with interpreter enabled!"
-#endif
-
-#if defined(ENABLE_JVMTI)
-# error "GC does not work with JVMTI enabled!"
-#endif
+/*#include "vm/options.h"*/
 
 
 /* gc_init *********************************************************************
 
 *******************************************************************************/
 
+#define GC_SYS_SIZE (20*1024*1024)
+
 void gc_init(u4 heapmaxsize, u4 heapstartsize)
 {
        if (opt_verbosegc)
                dolog("GC: Initialising with heap-size %d (max. %d)",
                        heapstartsize, heapmaxsize);
 
-       heap_base = malloc(heapstartsize);
-
-       if (heap_base == NULL)
+       /* region for uncollectable objects */
+       heap_region_sys = NEW(regioninfo_t);
+       if (!region_create(heap_region_sys, GC_SYS_SIZE))
                exceptions_throw_outofmemory_exit();
 
-       /* this is needed for linear allocation */
-       heap_ptr = heap_base;
+       /* region for java objects */
+       heap_region_main = NEW(regioninfo_t);
+       if (!region_create(heap_region_main, heapstartsize))
+               exceptions_throw_outofmemory_exit();
 
        heap_current_size = heapstartsize;
        heap_maximal_size = heapmaxsize;
+
+       /* TODO: remove these */
        heap_free_size = heap_current_size;
        heap_used_size = 0;
 }
 
 
-/* gc_call *********************************************************************
+/* gc_collect ******************************************************************
 
-   Forces a full collection of the whole Java Heap.
-   This is the function which is called by System.VMRuntime.gc()
+   This is the main machinery which manages a collection. It should be run by
+   the thread which triggered the collection.
 
-*******************************************************************************/
+   IN:
+     XXX
 
-void gc_call(void)
-{
-       rootset_t *rs;
-       s4         dumpsize;
+   STEPS OF A COLLECTION:
+     XXX
 
-       if (opt_verbosegc)
-               dolog("GC: Forced Collection ...");
+*******************************************************************************/
 
-       /* TODO: move the following to gc_collect() */
+void gc_collect(s4 level)
+{
+       rootset_t    *rs;
+       regioninfo_t *src, *dst;
+       s4            dumpsize;
 
        /* remember start of dump memory area */
        dumpsize = dump_size();
@@ -116,23 +110,68 @@ void gc_call(void)
        GC_LOG( heap_println_usage(); );
        /*GC_LOG( heap_dump_region(heap_base, heap_ptr, false); );*/
 
-       /* find the rootset for the current thread */
+       /* find the global rootset and the rootset for the current thread */
        rs = DNEW(rootset_t);
+       /*TODO: mark_rootset_create(rs);*/
+       /*TODO: mark_rootset_from_globals(rs);*/
        mark_rootset_from_thread(THREADOBJECT, rs);
+       GC_LOG( mark_rootset_print(rs); );
+
+#if 1
 
        /* mark the objects considering the given rootset */
        mark_me(rs);
-       GC_LOG( heap_dump_region(heap_base, heap_ptr, true); );
+       /*GC_LOG( heap_dump_region(heap_region_main, true); );*/
 
        /* compact the heap */
-       /*compact_me(rs, heap_base, heap_ptr);*/
+       compact_me(rs, heap_region_main);
+       /*GC_LOG( heap_dump_region(heap_region_main, false); );
+       GC_LOG( mark_rootset_print(rs); );*/
+
+#if defined(ENABLE_MEMCHECK)
+       /* invalidate the rest of the main region */
+       region_invalidate(heap_region_main);
+#endif
+
+#else
+
+       /* copy the heap to new region */
+       dst = DNEW(regioninfo_t);
+       region_init(dst, heap_current_size);
+       gc_copy(heap_region_main, dst, rs);
+
+       /* invalidate old heap */
+       /*memset(heap_base, 0x5a, heap_current_size);*/
+
+#endif
 
        /* TODO: check my return value! */
        /*heap_increase_size();*/
 
+       /* write back the rootset to update root references */
+       GC_LOG( mark_rootset_print(rs); );
+       mark_rootset_writeback(rs);
+
     /* free dump memory area */
     dump_release(dumpsize);
 
+}
+
+
+/* gc_call *********************************************************************
+
+   Forces a full collection of the whole Java Heap.
+   This is the function which is called by System.VMRuntime.gc()
+
+*******************************************************************************/
+
+void gc_call(void)
+{
+       if (opt_verbosegc)
+               dolog("GC: Forced Collection ...");
+
+       gc_collect(0);
+
        if (opt_verbosegc)
                dolog("GC: Forced Collection finished.");
 }
index fce60c889b107293fa45b8e8d3343c96c949bce7..a6af0e06ad7fa9abfc524e837b8bae822d7e7b37 100644 (file)
@@ -1,6 +1,6 @@
 /* src/mm/cacao-gc/gc.h - main garbage collector header
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   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
 /* Debugging ******************************************************************/
 
 #define GC_DEBUGGING
+#define GC_DEBUGGING2
 
 #if !defined(NDEBUG) && defined(GC_DEBUGGING)
 # include <assert.h>
+# include "vmcore/options.h"
 # define GC_LOG(code) if (opt_verbosegc) { code; }
 # define GC_ASSERT(assertion) assert(assertion)
 #else
 # define GC_ASSERT(assertion)
 #endif
 
+#if !defined(NDEBUG) && defined(GC_DEBUGGING2)
+# define GC_LOG2(code) GC_LOG(code)
+#else
+# define GC_LOG2(code)
+#endif
+
+
+/* Development Break **********************************************************/
+
+#if 1 && defined(ENABLE_THREADS)
+# error "GC does not work with threads enabled!"
+#endif
+
+#if 1 && defined(ENABLE_INTRP)
+# error "GC does not work with interpreter enabled!"
+#endif
+
+#if 1 && defined(ENABLE_JVMTI)
+# error "GC does not work with JVMTI enabled!"
+#endif
+
+#if 1 && !defined(ENABLE_REPLACEMENT)
+# error "GC does only work with replacement enabled!"
+#endif
+
+#if 1 && !defined(__I386__)
+# error "GC was only ported to i386 so far!"
+#endif
+
+
+/* Global Variables ***********************************************************/
+
+static bool gc_pending;
+
 
 /* Helper Macros **************************************************************/
 
diff --git a/src/mm/cacao-gc/heap.c b/src/mm/cacao-gc/heap.c
new file mode 100644 (file)
index 0000000..30ddded
--- /dev/null
@@ -0,0 +1,537 @@
+/* mm/cacao-gc/heap.c - GC module for heap management
+
+   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
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Contact: cacao@cacaojvm.org
+
+   Authors: Michael Starzinger
+
+   $Id$
+
+*/
+
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "gc.h"
+#include "heap.h"
+#include "mark.h"
+#include "region.h"
+#include "mm/memory.h"
+#include "native/jni.h"
+#include "src/native/include/java_lang_String.h" /* TODO: fix me! */
+#include "toolbox/logging.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+/*#include "vm/options.h"*/
+#include "vm/jit/stacktrace.h"
+
+
+/* Global Variables ***********************************************************/
+
+/*void *heap_base;*/       /* pointer to the base of the heap */
+/*void *heap_ptr;*/        /* current allocation ptr for linear alloc */
+s4 heap_current_size;  /* current size of the heap */
+s4 heap_maximal_size;  /* maximal size of the heap */
+s4 heap_free_size;     /* free bytes on the heap */
+s4 heap_used_size;     /* used bytes on the heap */
+regioninfo_t *heap_region_sys;
+regioninfo_t *heap_region_main;
+
+
+/* Helper Macros **************************************************************/
+
+#define GC_ALIGN_SIZE SIZEOF_VOID_P
+#define GC_ALIGN(length,size) ((((length) + (size) - 1) / (size)) * (size))
+
+
+void heap_init_objectheader(java_objectheader *o, u4 bytelength)
+{
+       u4 wordcount;
+
+       /* initialize the header flags */
+       o->hdrflags = 0;
+
+       /* align the size */
+       /* TODO */
+
+       /* set the hash bits in the header */
+       /* TODO: improve this!!! */
+       GC_SET_HASH(o, (s4) o);
+
+       /* calculate the wordcount as stored in the header */
+    /* TODO: improve this to save wordcount and without header bytes */
+    if ((bytelength & 0x03) == 0) {
+        GC_ASSERT((bytelength & 0x03) == 0);
+        wordcount = (bytelength >> 2);
+        GC_ASSERT(wordcount != 0);
+    } else {
+        wordcount = GC_SIZE_DUMMY;
+    }
+
+       /* set the wordcount in the header */
+    if (wordcount >= GC_SIZE_DUMMY) {
+        GC_SET_SIZE(o, GC_SIZE_DUMMY);
+    } else {
+        GC_SET_SIZE(o, wordcount);
+    }
+
+}
+
+
+s4 heap_increase_size() {
+       void *p;
+       s4    increasesize;
+       s4    newsize;
+
+       /* TODO: locking for threads!!! */
+
+       /* only a quick sanity check */
+       GC_ASSERT(heap_current_size <= heap_maximal_size);
+
+       /* check if we are allowed to enlarge the heap */
+       if (heap_current_size == heap_maximal_size)
+               exceptions_throw_outofmemory_exit();
+
+       /* 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); );
+
+       /* allocate new heap from the system */
+       newsize = heap_current_size + increasesize;
+       p = malloc(newsize);
+
+       /* check if the newly allocated heap exists */
+       if (p == NULL)
+               exceptions_throw_outofmemory_exit(); 
+
+       /* 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 */
+
+       /* set the new values */
+       /*heap_ptr = p + (heap_ptr - heap_base);
+       heap_base = p;*/
+       heap_current_size = newsize;
+       heap_free_size += increasesize;
+
+       GC_LOG( dolog("GC: Increasing Heap Size was successful");
+                       heap_println_usage(); );
+
+       /* only a quick sanity check */
+       GC_ASSERT(heap_current_size <= heap_maximal_size);
+
+       return increasesize;
+}
+
+
+s4 heap_get_hashcode(java_objectheader *o)
+{
+       s4 hashcode;
+
+       if (!o)
+               return 0;
+
+       /* TODO: improve this heavily! */
+       hashcode = GC_GET_HASH(o);
+
+       /*GC_LOG( printf("Hash taken: %d (0x%08x)\n", hashcode, hashcode); );*/
+
+       return hashcode;
+}
+
+
+java_objectheader *heap_alloc_intern(u4 bytelength, regioninfo_t *region)
+{
+       java_objectheader *p;
+
+       /* only a quick sanity check */
+       GC_ASSERT(region);
+       GC_ASSERT(bytelength >= sizeof(java_objectheader));
+
+       /* align objects in memory */
+       bytelength = GC_ALIGN(bytelength, GC_ALIGN_SIZE);
+
+       /* check for sufficient free space */
+       if (bytelength > region->free) {
+               dolog("GC: Region out of memory!");
+               /* TODO: change this to gc_collect() !!! */
+               /*gc_call();*/
+               return NULL;
+       }
+
+       /* allocate the object in this region */
+       p = region->ptr;
+       region->ptr += bytelength;
+       region->free -= bytelength;
+
+       /*heap_free_size -= bytelength;
+       heap_used_size += bytelength;*/
+
+       /* clear allocated memory region */
+       GC_ASSERT(p);
+       MSET(p, 0, u1, bytelength);
+
+       /* set the header information */
+       heap_init_objectheader(p, bytelength);
+
+       return p;
+}
+
+
+/* heap_allocate ***************************************************************
+
+   Allocates memory on the Java heap.
+
+*******************************************************************************/
+
+void *heap_allocate(u4 bytelength, u4 references, methodinfo *finalizer)
+{
+       java_objectheader *p;
+
+       /* We can't use a bool here for references, as it's passed as a
+          bitmask in builtin_new.  Thus we check for != 0. */
+
+       p = heap_alloc_intern(bytelength, heap_region_main);
+
+       if (p == NULL)
+               return NULL;
+
+       /* TODO: can this be overwritten by cloning??? */
+       if (finalizer != NULL) {
+               GC_LOG( log_text("GC: Finalizer not yet implemented!"); );
+               GC_SET_FLAGS(p, GC_FLAG_FINALIZER);
+       }
+
+       return p;
+}
+
+
+void *heap_alloc_uncollectable(u4 bytelength)
+{
+       java_objectheader *p;
+
+       /* loader.c does this a lot for classes with fieldscount equal zero */
+       if (bytelength == 0)
+               return NULL;
+
+       p = heap_alloc_intern(bytelength, heap_region_sys);
+
+       if (p == NULL)
+               return NULL;
+
+       /* TODO: can this be overwritten by cloning??? */
+       /* remember this object as uncollectable */
+       GC_SET_FLAGS(p, GC_FLAG_UNCOLLECTABLE);
+
+       return p;
+}
+
+
+void heap_free(void *p)
+{
+       GC_LOG( dolog("GC: Free %p", p); );
+       GC_ASSERT(0);
+}
+
+
+/* Debugging ******************************************************************/
+
+#if !defined(NDEBUG)
+void heap_println_usage()
+{
+       printf("Current Heap Usage: Size=%d Free=%d Used=%d\n",
+                       heap_current_size, heap_free_size, heap_used_size);
+
+       GC_ASSERT(heap_current_size == heap_free_size + heap_used_size);
+}
+#endif
+
+
+#if !defined(NDEBUG)
+void heap_print_object_flags(java_objectheader *o)
+{
+       printf("0x%02x 0x%08x [%s%s%s]",
+               GC_GET_SIZE(o), GC_GET_HASH(o),
+               GC_TEST_FLAGS(o, GC_FLAG_FINALIZER)     ? "F" : " ",
+               GC_TEST_FLAGS(o, GC_FLAG_UNCOLLECTABLE) ? "U" : " ",
+               GC_TEST_FLAGS(o, GC_FLAG_MARKED)        ? "M" : " ");
+}
+#endif
+
+
+#if !defined(NDEBUG)
+void heap_print_object(java_objectheader *o)
+{
+       java_arrayheader  *a;
+       classinfo         *c;
+
+       /* check for null pointers */
+       if (o == NULL) {
+               printf("(NULL)");
+               return;
+       }
+
+       /* print general information */
+       printf("%p: ", (void *) o);
+       heap_print_object_flags(o);
+       printf(" ");
+
+       /* TODO */
+       /* maybe this is not really an object */
+       if (/*IS_REFTABLE*/ o->vftbl == 0x10) {
+               /* printf information */
+               printf("LRT");
+
+       } else if (/*IS_CLASS*/ o->vftbl->class == class_java_lang_Class) {
+
+               /* get the class information */
+               c = (classinfo *) o;
+
+               /* print the class information */
+               printf("CLS ");
+               class_print(c);
+
+       } else if (/*IS_ARRAY*/ o->vftbl->arraydesc != NULL) {
+
+               /* get the array information */
+               a = (java_arrayheader *) o;
+               c = o->vftbl->class;
+
+               /* print the array information */
+               printf("ARR ");
+               /*class_print(c);*/
+               utf_display_printable_ascii_classname(c->name);
+               printf(" (size=%d)", a->size);
+
+       } else /*IS_OBJECT*/ {
+
+               /* get the object class */
+               c = o->vftbl->class;
+
+               /* print the object information */
+               printf("OBJ ");
+               /*class_print(c);*/
+               utf_display_printable_ascii_classname(c->name);
+               if (c == class_java_lang_String) {
+                       printf(" (string=\"");
+                       utf_display_printable_ascii(
+                                       javastring_toutf((java_lang_String *) o, false));
+                       printf("\")");
+               }
+
+       }
+}
+#endif
+
+#if !defined(NDEBUG)
+void heap_dump_region(regioninfo_t *region, bool marked_only)
+{
+       java_objectheader *o;
+       u4                 o_size;
+
+       /* some basic sanity checks */
+       GC_ASSERT(region->base < region->ptr);
+
+       printf("Heap-Dump:\n");
+
+       /* walk the region in a linear style */
+       o = region->base;
+       while ((void *) o < region->ptr) {
+
+               if (!marked_only || GC_IS_MARKED(o)) {
+                       printf("\t");
+                       heap_print_object(o);
+                       printf("\n");
+               }
+
+               /* get size of object */
+               o_size = get_object_size(o);
+
+               /* walk to next object */
+               GC_ASSERT(o_size != 0);
+               o = ((u1 *) o) + o_size;
+       }
+
+       printf("Heap-Dump finished.\n");
+}
+#endif
+
+
+s4 get_object_size(java_objectheader *o)
+{
+       java_arrayheader *a;
+       classinfo        *c;
+       s4                o_size;
+
+       /* we can assume someone initialized the header */
+       GC_ASSERT(o->hdrflags != 0);
+
+       /* get the wordcount from the header */
+       o_size = GC_GET_SIZE(o);
+
+       /* maybe we need to calculate the size by hand */
+       if (o_size != GC_SIZE_DUMMY) {
+               GC_ASSERT(o_size != 0);
+               o_size = o_size << 2;
+       } else {
+
+               /* TODO */
+               /* maybe this is not really an object */
+               if (/*IS_REFTABLE*/ o->vftbl == 0x10) {
+                       /* TODO: this will not work for long */
+                       o_size = sizeof(localref_table);
+
+               } else if (/*IS_CLASS*/ o->vftbl->class == class_java_lang_Class) {
+                       /* we know the size of a classinfo */
+                       o_size = sizeof(classinfo);
+
+               } else if (/*IS_ARRAY*/ o->vftbl->arraydesc != NULL) {
+                       /* compute size of this array */
+                       a = (java_arrayheader *) o;
+                       c = o->vftbl->class;
+                       o_size = c->vftbl->arraydesc->dataoffset +
+                                       a->size * c->vftbl->arraydesc->componentsize;
+
+               } else /*IS_OBJECT*/ {
+                       /* get the object size */
+                       c = o->vftbl->class;
+                       o_size = c->instancesize;
+                       GC_LOG( dolog("Got size (from Class): %d bytes", o_size); );
+               }
+       
+       }
+
+       /* align the size */
+       o_size = GC_ALIGN(o_size, GC_ALIGN_SIZE);
+
+       return o_size;
+}
+
+
+java_objectheader *next;
+
+void *gc_copy_forward(java_objectheader *o, void *src_start, void *src_end)
+{
+       s4 o_size;
+
+       if (POINTS_INTO(o, src_start, src_end)) {
+
+               /* update all references which point into the source region */
+
+               /* NOTE: we use the marking bit here to mark object which have already
+                * been copied; in such a case the *vftbl contains the location of
+                * the copy */ 
+               if (GC_IS_MARKED(o)) {
+
+                       /* return the location of an already existing copy */
+                       return o->vftbl;
+
+               } else {
+
+                       /* calculate the size of the object to be copied */
+                       o_size = get_object_size(o);
+
+                       /* copy the object pointed to by O to location NEXT */
+                       memcpy(next, o, o_size);
+
+                       /* remember where the copy is located */
+                       o->vftbl = (void *) next;
+
+                       /* increment NEXT to point past the copy of the object */
+                       next = ((u1 *) next) + o_size;
+
+                       /* return the location of the copy */
+                       return o->vftbl;
+
+               }
+
+       } else {
+
+               /* do not change references not pointing into the source region */
+               return o;
+
+       }
+}
+
+
+void gc_copy(regioninfo_t *src, regioninfo_t *dst, rootset_t *rs)
+{
+       java_objectheader *scan;
+       /*java_objectheader *next;*/
+       /*classinfo         *c;*/
+       java_objectheader *ref_old;
+       java_objectheader *ref_new;
+       int i;
+
+       /* initialize the scan and next pointer */
+       scan = (java_objectheader *) dst->base;
+       next = (java_objectheader *) dst->base;
+
+       /* for each root pointer R: replace R with forward(R) */
+       for (i = 0; i < rs->refcount; i++) {
+
+               ref_old = *( rs->refs[i] );
+               GC_LOG( printf("Will forward: ");
+                               heap_print_object(ref_old);
+                               printf("\n"); );
+
+               ref_new = gc_copy_forward(ref_old, src->base, src->end);
+
+               *( rs->refs[i] ) = ref_new;
+               GC_LOG( printf("New location: ");
+                               heap_print_object(ref_new);
+                               printf("\n"); );
+       }
+
+       /* update all references for objects in the destination region.
+        * when scan catches up with next, the algorithm is finished */
+       while (scan < next)
+       {
+               /* TODO: implement me! */
+               GC_LOG( printf("Will also forward pointers in ");
+                               heap_print_object(scan); printf("\n"); );
+
+               scan = ((u1 *) scan) + get_object_size(scan); 
+       }
+
+       /* some basic assumptions */
+       GC_ASSERT(scan == next);
+       GC_ASSERT(scan < dst->end);
+}
+
+
+/*
+ * 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:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/mm/cacao-gc/heap.h b/src/mm/cacao-gc/heap.h
new file mode 100644 (file)
index 0000000..ae32073
--- /dev/null
@@ -0,0 +1,148 @@
+/* mm/cacao-gc/heap.h - GC header for heap management
+
+   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
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Contact: cacao@cacaojvm.org
+
+   Authors: Michael Starzinger
+
+   $Id$
+
+*/
+
+
+#ifndef _HEAP_H
+#define _HEAP_H
+
+#include "vm/types.h"
+
+#include "gc.h"
+#include "region.h"
+
+
+
+/* TODO: maybe move this to global.h */
+#define GC_FLAG_FINALIZER     0x10
+#define GC_FLAG_UNCOLLECTABLE HDRFLAG_UNCOLLECTABLE
+#define GC_FLAG_MARKED        (HDRFLAG_MARK1 | HDRFLAG_MARK2)
+
+#define GC_IS_MARKED(obj)    GC_TEST_FLAGS(obj, GC_FLAG_MARKED)
+#define GC_SET_MARKED(obj)   GC_SET_FLAGS(obj, GC_FLAG_MARKED)
+#define GC_CLEAR_MARKED(obj) GC_CLEAR_FLAGS(obj, GC_FLAG_MARKED)
+
+
+#define GC_SIZE_DUMMY 0xff
+
+
+#if SIZEOF_VOID_P == 8
+# define GC_GET_SIZE(obj)       ((u4) (((obj)->hdrflags >> 56) & 0xff))
+# define GC_SET_SIZE(obj, size) ((obj)->hdrflags |= ((u8) ((size) & 0xff)) << 56)
+# define GC_GET_HASH(obj)       ((obj)->hdrflags)
+#else
+# define GC_GET_SIZE(obj)       ((u4) (((obj)->hdrflags >> 24) & 0xff))
+# define GC_SET_SIZE(obj, size) ((obj)->hdrflags |= ((u4) ((size) & 0xff)) << 24)
+# define GC_GET_HASH(obj)       ((obj)->hdrflags)
+# define GC_SET_HASH(obj, hash) ((obj)->hdrflags |= ((hash) << 8) & 0x00ffff00)
+#endif
+
+
+/*extern void *heap_base;
+extern void *heap_ptr;*/
+extern s4 heap_current_size;
+extern s4 heap_maximal_size;
+extern s4 heap_free_size;
+extern s4 heap_used_size;
+extern regioninfo_t *heap_region_sys;
+extern regioninfo_t *heap_region_main;
+
+
+s4 get_object_size(java_objectheader *o);
+
+
+#if !defined(NDEBUG)
+void heap_print_object(java_objectheader *o);
+void heap_dump_region(regioninfo_t *region, bool marked_only);
+#endif
+
+
+/* walking macros */
+#define IS_ARRAY(o) ((o)->vftbl->arraydesc != NULL)
+#define FOREACH_ARRAY_REF(o,ref,refptr,code) \
+       { \
+               java_objectarray *a = (java_objectarray *) o; \
+               arraydescriptor  *desc = o->vftbl->arraydesc; \
+               int i; \
+               \
+               GC_ASSERT(desc); \
+               \
+               if (desc->arraytype == ARRAYTYPE_OBJECT) { \
+                       for (i = 0; i < a->header.size; i++) { \
+                               \
+                               refptr = &( a->data[i] ); \
+                               ref = (java_objectheader *) (a->data[i]); \
+                               \
+                               code; \
+                       } \
+               } \
+       }
+
+#define FOREACH_OBJECT_REF(o,ref,refptr,code) \
+       { \
+               classinfo *c = o->vftbl->class; \
+               fieldinfo *f; \
+               int i; \
+               \
+               GC_ASSERT(c); \
+               \
+               for (; c; c = c->super.cls) { \
+                       for (i = 0; i < c->fieldscount; i++) { \
+                               f = &(c->fields[i]); \
+                               \
+                               if (!IS_ADR_TYPE(f->type) || (f->flags & ACC_STATIC)) \
+                                       continue; \
+                               \
+                               refptr = (java_objectheader **) ((s1 *) o + f->offset); \
+                               ref = *( refptr ); \
+                               \
+                               code; \
+                       } \
+               } \
+       }
+
+
+
+#endif /* _HEAP_H */
+
+/*
+ * 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:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index c42cd9fe218b7cad737bfdce3ea5b3019d2800cb..8830b4aa102ad8be07874197af2ec6c075c0acec 100644 (file)
@@ -1,6 +1,6 @@
 /* mm/cacao-gc/mark.c - GC module for marking heap objects
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   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
 
 #include "config.h"
 
+#if defined(ENABLE_THREADS)
+# include "threads/native/threads.h"
+#else
+/*# include "threads/none/threads.h"*/
+#endif
+
+#include "gc.h"
 #include "heap.h"
+#include "mark.h"
+#include "mm/memory.h"
 #include "toolbox/logging.h"
 #include "vm/global.h"
-#include "vm/linker.h"
-#include "vm/options.h"
+/*#include "vm/options.h"*/
+#include "vm/jit/replace.h"
+#include "vm/jit/stacktrace.h"
+#include "vmcore/linker.h"
 
 
 /* Debugging ******************************************************************/
 
+/* TODO: move this whole thing to gc.c */
 int mark_depth;
 int mark_depth_max;
+int mark_count;
+#define MARK_COUNT_INIT { mark_count = 0; }
+#define MARK_COUNT { mark_count++; }
 #define MARK_DEPTH_INIT { mark_depth = 0; mark_depth_max = 0; }
 #define MARK_DEPTH_INC { mark_depth++; if (mark_depth>mark_depth_max) mark_depth_max=mark_depth; }
 #define MARK_DEPTH_DEC { mark_depth--; GC_ASSERT(mark_depth >= 0); }
 void mark_println_stats()
 {
-       printf("Maximal marking depth: %d\n", mark_depth_max);
+       printf("Marking Statistics:\n");
+       printf("\t# of objects marked: %d\n", mark_count);
+       printf("\tMaximal marking depth: %d\n", mark_depth_max);
+}
+
+
+/* mark_rootset_from_globals ***************************************************
+
+   Searches global variables to compile the global root set out of references
+   contained in them.
+
+   SEARCHES IN:
+     - global reference table (jni.c)
+
+*******************************************************************************/
+
+void mark_rootset_from_globals(rootset_t *rs)
+{
+       GC_ASSERT(0);
+}
+
+
+/* mark_rootset_from_thread ****************************************************
+
+   Searches the stack of the current thread for references and compiles a
+   root set out of them.
+
+   NOTE: uses dump memory!
+
+   IN:
+         TODO!!!
+
+   OUT:
+         TODO!!!
+
+*******************************************************************************/
+
+stacktracebuffer *stacktrace_create(threadobject* thread, bool rplpoints);
+void replace_read_executionstate(rplpoint *rp,
+                                        executionstate_t *es,
+                                        sourcestate_t *ss,
+                                        bool topframe);
+void replace_write_executionstate(rplpoint *rp,
+                                                                                executionstate_t *es,
+                                                                                sourcestate_t *ss,
+                                                                                bool topframe);
+
+void mark_rootset_from_thread(threadobject *thread, rootset_t *rs)
+{
+       stacktrace_entry *ste;
+       stacktracebuffer *stb;
+       executionstate_t *es;
+       sourcestate_t    *ss;
+       sourceframe_t    *sf;
+       rplpoint         *rp;
+       rplpoint         *rp_search;
+       s4                rpcount;
+       int               i;
+
+       /* TODO: remove these */
+    java_objectheader *o;
+    int refcount;
+
+       GC_LOG( printf("Walking down stack of current thread:\n");
+                       stacktrace_dump_trace(thread); );
+
+#if 0
+       /* get the stacktrace with replacement points */
+       /* NOTE: stacktrace_create uses dump memory! */
+       stb = stacktrace_create(thread, true);
+       GC_ASSERT(stb);
+
+       /* this is where our source state will be placed */
+       ss = DNEW(sourcestate_t);
+       ss->frames = NULL;
+
+       /* walk through the stacktracebuffer to find source state for all methods */
+       ste = &(stb->entries[0]);
+       for (i = 0; i < stb->used; i++, ste++) {
+
+               /* try to get an execution state for this entry */
+               es = ste->es;
+               if (!es)
+                       continue;
+
+               /* get the replacement points for this code */
+               GC_ASSERT(es->code);
+               rp = es->code->rplpoints;
+               GC_ASSERT(rp);
+
+               /* search for the replacement point right in front of the return
+                  address. this should be the one associated with the taken call. */
+               rp_search = rp;
+               rp = NULL;
+               for (rpcount = 0; rpcount < es->code->rplpointcount; rpcount++) {
+
+                       GC_LOG2( printf("(%d) Checking %p > %p\n",
+                                       rpcount, es->pc, rp_search->pc); );
+
+                       if (rp_search->pc < es->pc)
+                               rp = rp_search;
+
+                       rp_search++;
+               }
+
+               /* this is the replacement point of our call */
+               GC_ASSERT(rp);
+               GC_ASSERT(rp->type == RPLPOINT_TYPE_CALL);
+               GC_ASSERT(rp->pc < es->pc);
+               GC_ASSERT(rp->pc + rp->callsize >= es->pc);
+
+               /* add this execution state to the sourcestate */
+               replace_read_executionstate(rp, es, ss, false);
+
+               /* print our results */
+               GC_LOG(
+                               printf("Found RPL point:\n");
+                               replace_replacement_point_println(rp, 1);
+                               replace_executionstate_println(es);
+               );
+
+       }
+#else
+       /* create empty execution state */
+       es = DNEW(executionstate_t);
+       es->pc = 0;
+       es->sp = 0;
+       es->pv = 0;
+       es->code = NULL;
+
+       /* TODO: we assume we are in a native and in current thread! */
+       ss = replace_recover_source_state(NULL, NULL, es);
+#endif
+
+       /* print our full source state */
+       GC_LOG( replace_sourcestate_println(ss); );
+
+       /* initialize the rootset struct */
+       GC_ASSERT(rs);
+       rs->thread = thread;
+       rs->ss = ss;
+       rs->es = es;
+       rs->stb = stb;
+       rs->refcount = 0;
+
+       /* now inspect the source state to compile the root set */
+       refcount = rs->refcount;
+       for (sf = ss->frames; sf != NULL; sf = sf->down) {
+
+               GC_ASSERT(sf->javastackdepth == 0);
+
+               for (i = 0; i < sf->javalocalcount; i++) {
+
+                       if (sf->javalocaltype[i] != TYPE_ADR)
+                               continue;
+
+                       o = sf->javalocals[i].a;
+
+                       /* check for outside or null pointer */
+                       if (!POINTS_INTO(o, heap_region_main->base, heap_region_main->ptr))
+                               continue;
+
+                       /* add this reference to the root set */
+                       GC_LOG2( printf("Found Reference: %p\n", (void *) o); );
+                       GC_ASSERT(refcount < RS_REFS); /* TODO: UGLY!!! */
+                       rs->refs[refcount] = (java_objectheader **) &( sf->javalocals[i] );
+
+                       refcount++;
+
+               }
+
+       }
+
+       /* remeber how many references there are inside this root set */
+       rs->refcount = refcount;
+
+       GC_LOG( printf("Walking done.\n"); );
+}
+
+
+void mark_rootset_writeback(rootset_t *rs)
+{
+       sourcestate_t    *ss;
+       executionstate_t *es;
+       rplpoint         *rp;
+       stacktracebuffer *stb;
+       stacktrace_entry *ste;
+       int i;
+
+#if 0
+       ss = rs->ss;
+       stb = rs->stb;
+
+       /* walk through the stacktracebuffer to find execution state
+        * for all methods */
+       i = stb->used;
+       while (i > 0) {
+               i--;
+               ste = &(stb->entries[i]);
+
+               /* try to get an execution state for this entry */
+               es = ste->es;
+               if (!es)
+                       continue;
+
+               /* write back the execution state at this replacement point */
+               rp = ss->frames->fromrp;
+               replace_write_executionstate(rp, es, ss, false);
+
+       }
+#else
+       ss = rs->ss;
+       es = rs->es;
+
+       replace_build_execution_state_intern(ss, es);
+#endif
+
 }
 
 
@@ -70,14 +301,22 @@ void mark_recursive(java_objectheader *o)
        java_objectarray  *oa;
        arraydescriptor   *desc;
        java_objectheader *ref;
+       void *start, *end;
        int i;
 
+       /* TODO: this needs cleanup!!! */
+       start = heap_region_main->base;
+       end = heap_region_main->ptr;
+
        /* uncollectable objects should never get marked this way */
+       /* the reference should point into the heap */
        GC_ASSERT(o);
        GC_ASSERT(!GC_TEST_FLAGS(o, GC_FLAG_UNCOLLECTABLE));
+       GC_ASSERT(POINTS_INTO(o, start, end));
 
        /* mark this object */
        GC_SET_MARKED(o);
+       MARK_COUNT;
 
        /* get the class of this object */
        /* TODO: maybe we do not need this yet, look to move down! */
@@ -110,10 +349,10 @@ void mark_recursive(java_objectheader *o)
                        ref = (java_objectheader *) (oa->data[i]);
 
                        /* check for outside or null pointers */
-                       if (!POINTS_INTO(ref, heap_base, heap_ptr))
+                       if (!POINTS_INTO(ref, start, end))
                                continue;
 
-                       GC_LOG( printf("Found (%p) from Array\n", (void *) ref); );
+                       GC_LOG2( printf("Found (%p) from Array\n", (void *) ref); );
 
                        /* do the recursive marking */
                        if (!GC_IS_MARKED(ref)) {
@@ -128,6 +367,7 @@ void mark_recursive(java_objectheader *o)
                /* this is an OBJECT */
 
                /* for objects we need to check all (non-static) fields */
+               for (; c; c = c->super.cls) {
                for (i = 0; i < c->fieldscount; i++) {
                        f = &(c->fields[i]);
 
@@ -139,10 +379,10 @@ void mark_recursive(java_objectheader *o)
                        ref = *( (java_objectheader **) ((s1 *) o + f->offset) );
 
                        /* check for outside or null pointers */
-                       if (!POINTS_INTO(ref, heap_base, heap_ptr))
+                       if (!POINTS_INTO(ref, start, end))
                                continue;
 
-                       GC_LOG( printf("Found (%p) from Field ", (void *) ref);
+                       GC_LOG2( printf("Found (%p) from Field ", (void *) ref);
                                        field_print(f); printf("\n"); );
 
                        /* do the recursive marking */
@@ -153,38 +393,87 @@ void mark_recursive(java_objectheader *o)
                        }
 
                }
+               }
 
        }
 
 }
 
 
-/* mark ************************************************************************
+void mark_classes(void *start, void *end)
+{
+       java_objectheader *ref;
+       classinfo         *c;
+       fieldinfo         *f;
+       void *sys_start, *sys_end;
+       int i;
+
+       GC_LOG( printf("Marking from classes\n"); );
+
+       /* TODO: cleanup!!! */
+       sys_start = heap_region_sys->base;
+       sys_end = heap_region_sys->ptr;
+
+       /* walk through all classinfo blocks */
+       for (c = sys_start; c < (classinfo *) sys_end; c++) {
+
+               /* walk through all fields */
+               f = c->fields;
+               for (i = 0; i < c->fieldscount; i++, f++) {
+
+                       /* check if this is a static reference */
+                       if (!IS_ADR_TYPE(f->type) || !(f->flags & ACC_STATIC))
+                               continue;
+
+                       /* load the reference */
+                       ref = (java_objectheader *) (f->value.a);
+
+                       /* check for outside or null pointers */
+                       if (!POINTS_INTO(ref, start, end))
+                               continue;
+
+                       /* mark the reference */
+                       mark_recursive(ref);
+
+               }
+
+       }
+
+}
+
+
+/* mark_me *********************************************************************
 
    Marks all Heap Objects which are reachable from a given root-set.
 
-*******************************************************************************/
+   IN:
+         rs.....root set containing the references
 
-/* rootset is passed as array of pointers, which point to the location of
-   the reference */
-/* TODO: this definitely has to change!!! */
-typedef java_objectheader** rootset_t;
+*******************************************************************************/
 
-void mark(rootset_t *rootset, int rootset_size)
+void mark_me(rootset_t *rs)
 {
        java_objectheader *ref;
        int i;
 
+       MARK_COUNT_INIT;
+       MARK_DEPTH_INIT;        
+
+       /* recursively mark all references from classes */
+       mark_classes(heap_region_main->base, heap_region_main->ptr);
+
+       GC_LOG( printf("Marking from rootset (%d entries)\n", rs->refcount); );
+
        /* recursively mark all references of the rootset */
-       MARK_DEPTH_INIT;
        MARK_DEPTH_INC;
-       for (i = 0; i < rootset_size; i++) {
+       for (i = 0; i < rs->refcount; i++) {
 
-               ref = *( rootset[i] );
+               ref = *( rs->refs[i] );
                mark_recursive(ref);
 
        }
        MARK_DEPTH_DEC;
+
        GC_ASSERT(mark_depth == 0);
        GC_ASSERT(mark_depth_max > 0);
 
@@ -192,6 +481,32 @@ void mark(rootset_t *rootset, int rootset_size)
 }
 
 
+#if !defined(NDEBUG)
+void mark_rootset_print(rootset_t *rs)
+{
+       java_objectheader *o;
+       int i;
+
+       printf("Root Set:\n");
+
+       printf("\tThread: %p\n", rs->thread);
+       printf("\tReferences (%d):\n", rs->refcount);
+
+       for (i = 0; i < rs->refcount; i++) {
+
+               o = *( rs->refs[i] );
+
+               /*printf("\t\tReference at %p points to ...\n", (void *) rs->refs[i]);*/
+               printf("\t\t");
+               heap_print_object(o);
+               printf("\n");
+
+       }
+
+}
+#endif
+
+
 /*
  * 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
diff --git a/src/mm/cacao-gc/mark.h b/src/mm/cacao-gc/mark.h
new file mode 100644 (file)
index 0000000..24ffb4f
--- /dev/null
@@ -0,0 +1,91 @@
+/* mm/cacao-gc/mark.h - GC header for marking heap objects
+
+   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
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Contact: cacao@cacaojvm.org
+
+   Authors: Michael Starzinger
+
+   $Id$
+
+*/
+
+
+#ifndef _MARK_H
+#define _MARK_H
+
+typedef struct rootset_t rootset_t;
+
+#include "config.h"
+#include "vm/types.h"
+
+#if defined(ENABLE_THREADS)
+# include "threads/native/threads.h"
+#else
+/*# include "threads/none/threads.h"*/
+#endif
+
+#include "vm/jit/replace.h"
+#include "vm/jit/stacktrace.h"
+
+#include "vmcore/method.h"
+
+
+/* Structures *****************************************************************/
+
+#define RS_REFS 10
+
+/* rootset is passed as array of pointers, which point to the location of
+   the reference */
+
+struct rootset_t {
+       threadobject       *thread;         /* thread this rootset belongs to */
+       sourcestate_t      *ss;             /* sourcestate of the thread */
+       executionstate_t   *es;             /* executionstate of the thread */
+       stacktracebuffer   *stb;            /* stacktrace of the thread */
+       s4                  refcount;       /* number of references */
+       java_objectheader **refs[RS_REFS];  /* list of references */
+};
+
+
+/* Prototypes *****************************************************************/
+
+void mark_rootset_from_thread(threadobject *thread, rootset_t *rs);
+void mark_me(rootset_t *rs);
+
+
+#endif /* _MARK_H */
+
+/*
+ * 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:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/mm/cacao-gc/region.c b/src/mm/cacao-gc/region.c
new file mode 100644 (file)
index 0000000..4430126
--- /dev/null
@@ -0,0 +1,114 @@
+/* mm/cacao-gc/region.c - GC module for region management
+
+   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
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Contact: cacao@cacaojvm.org
+
+   Authors: Michael Starzinger
+
+   $Id$
+
+*/
+
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "region.h"
+#include "mm/memory.h"
+#include "toolbox/logging.h"
+
+
+/* region_init *****************************************************************
+
+   Allocates the memory for a heap region and initiates the regioninfo struct
+   accordingly.
+
+*******************************************************************************/
+
+void *region_create(regioninfo_t *region, u4 size)
+{
+       u1 *ptr;
+
+       /* some sanity check */
+       GC_ASSERT(region);
+
+       /* allocate memory for the region */
+       ptr = MNEW(u1, size);
+
+       if (ptr == NULL)
+               return NULL;
+
+       /* initiate structure */
+       region->base = ptr;
+       region->end  = ptr + size;
+       region->ptr  = ptr;
+       region->size = size;
+       region->free = size;
+
+#if defined(ENABLE_MEMCHECK)
+       /* poison this region */
+       /* TODO: this should really be done MNEW above! */
+       region_invalidate(region);
+#endif
+
+       GC_LOG( dolog("GC: Region allocated at [ %p ; %p ]", region->base, region->end); );
+
+       return ptr;
+}
+
+
+/* region_invalidate ***********************************************************
+
+   Invalidates the free memory area inside a heap region by overwriting it with
+   the clear byte.
+
+   REMEMBER: The region has to be compacted for this to work properly.
+
+*******************************************************************************/
+
+#if defined(ENABLE_MEMCHECK)
+void region_invalidate(regioninfo_t *region)
+{
+       /* some sanity check */
+       GC_ASSERT(region->free == region->end - region->ptr);
+
+       /* invalidate free memory */
+       memset(region->ptr, MEMORY_CLEAR_BYTE, region->free);
+}
+#endif /* defined(ENABLE_MEMCHECK) */
+
+
+/*
+ * 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:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/mm/cacao-gc/region.h b/src/mm/cacao-gc/region.h
new file mode 100644 (file)
index 0000000..f3f226d
--- /dev/null
@@ -0,0 +1,69 @@
+/* mm/cacao-gc/region.h - GC header for region management
+
+   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
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Contact: cacao@cacaojvm.org
+
+   Authors: Michael Starzinger
+
+   $Id$
+
+*/
+
+
+#ifndef _REGION_H
+#define _REGION_H
+
+typedef struct regioninfo_t regioninfo_t;
+
+#include "vm/types.h"
+
+#include "gc.h"
+
+
+/* Structures *****************************************************************/
+
+struct regioninfo_t {
+       u1 *base;     /* pointer to the start of this region */
+       u1 *end;      /* pointer to the end of this region */
+       u1 *ptr;      /* pointer to the beginning of the free space */
+       s4  size;     /* total size of the region (end - ptr) */
+       s4  free;     /* free space in this region */
+};
+
+
+#endif /* _REGION_H */
+
+/*
+ * 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:
+ * vim:noexpandtab:sw=4:ts=4:
+ */