Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id$
-
*/
#include "config.h"
#include "vm/types.h"
-#if defined(ENABLE_THREADS)
-# include "threads/native/lock.h"
-#else
-# include "threads/none/lock.h"
-#endif
+#include "threads/lock-common.h"
#include "gc.h"
+#include "final.h"
#include "heap.h"
#include "mark.h"
#include "region.h"
#include "mm/memory.h"
-#include "src/native/include/java_lang_String.h" /* TODO: fix me! */
+#include "native/include/java_lang_String.h"
+#include "native/llni.h"
#include "toolbox/logging.h"
#include "vm/global.h"
+#include "vm/stringlocal.h"
+#include "vm/vm.hpp"
+#include "vmcore/options.h"
#include "vmcore/rt-timing.h"
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)
+void heap_init_objectheader(java_object_t *o, u4 bytelength)
{
u4 wordcount;
}
-s4 heap_increase_size() {
- void *p;
- s4 increasesize;
- s4 newsize;
+void heap_update_references(rootset_t *rs, regioninfo_t *region, u4 offset)
+{
+ java_object_t *o;
+ java_object_t *ref;
+ java_object_t **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;
+ 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,
+
+ GC_LOG2( printf("\tarray-entry %p -> %p\n", (void *) ref, ((u1 *) ref) + offset); );
+
+ if (POINTS_INTO(ref, start, end))
+ *refptr = ((u1 *) ref) + offset;
+
+ );
+
+ } else {
- /* TODO: locking for threads!!! */
+ /* 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);
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); );
-
- /* allocate new heap from the system */
- newsize = heap_current_size + increasesize;
- p = malloc(newsize);
+ /* 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); );
- /* 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");
/* only a quick sanity check */
GC_ASSERT(heap_current_size <= heap_maximal_size);
- return increasesize;
}
-s4 heap_get_hashcode(java_objectheader *o)
+s4 heap_get_hashcode(java_object_t *o)
{
s4 hashcode;
}
-static java_objectheader *heap_alloc_intern(u4 bytelength, regioninfo_t *region, bool collect)
+static java_object_t *heap_alloc_intern(u4 bytelength, regioninfo_t *region, bool collect)
{
- java_objectheader *p;
+ java_object_t *p;
/* only a quick sanity check */
GC_ASSERT(region);
- GC_ASSERT(bytelength >= sizeof(java_objectheader));
+ GC_ASSERT(bytelength >= sizeof(java_object_t));
+
+#if !defined(NDEBUG) && defined(ENABLE_THREADS)
+ /* check the current VM state for sanity */
+ GC_ASSERT(!THREADOBJECT->gc_critical);
+ GC_ASSERT(THREADOBJECT->flags & THREAD_FLAG_IN_NATIVE);
+#endif
/* align objects in memory */
bytelength = GC_ALIGN(bytelength, GC_ALIGN_SIZE);
/* lock the region */
LOCK_MONITOR_ENTER(region);
+#if !defined(NDEBUG)
+ /* heavy stress test */
+ if (opt_GCStress && collect)
+ gc_collect(0);
+#endif
+
/* check for sufficient free space */
if (bytelength > region->free) {
- dolog("GC: Region out of memory!");
+ dolog("GC: Region out of memory! (collect=%d)", collect);
if (collect) {
- gc_collect();
+ gc_collect(0);
+#if 0
GC_ASSERT(region->free >= bytelength);
+#else
+ if (region->free < bytelength) {
+ dolog("GC: OOM OOM OOM OOM OOM OOM OOM OOM OOM OOM");
+ exceptions_throw_outofmemoryerror();
+ return NULL;
+ }
+#endif
} else
return NULL;
}
/* allocate the object in this region */
- p = (java_objectheader *) region->ptr;
+ p = (java_object_t *) region->ptr;
region->ptr += bytelength;
region->free -= bytelength;
/* unlock the region */
LOCK_MONITOR_EXIT(region);
- GC_LOG( region = NULL; );
/* clear allocated memory region */
GC_ASSERT(p);
void *heap_alloc(u4 size, u4 references, methodinfo *finalizer, bool collect)
{
- java_objectheader *p;
+ java_object_t *p;
+ java_handle_t *h;
#if defined(ENABLE_RT_TIMING)
struct timespec time_start, time_end;
#endif
}
#endif
- /* take care of finalization stuff */
+ /* register the finalizer for this object */
if (finalizer != NULL) {
-
- /* set the header bit */
- /* TODO: do we really need this??? */
- /* TODO: can this be overwritten by cloning??? */
- GC_SET_FLAGS(p, GC_FLAG_FINALIZER);
-
- /* register the finalizer for this object */
final_register(p, finalizer);
}
+ h = LLNI_WRAP(p);
+
RT_TIMING_GET_TIME(time_end);
RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_GC_ALLOC);
- return p;
+ return h;
}
void *heap_alloc_uncollectable(u4 size)
{
- java_objectheader *p;
+ java_object_t *p;
/* loader.c does this a lot for classes with fieldscount equal zero */
if (size == 0)
#if !defined(NDEBUG)
-void heap_print_object_flags(java_objectheader *o)
+void heap_print_object_flags(java_object_t *o)
{
- printf("0x%02x [%s%s%s%s%s]",
+ printf("0x%02x [%s%s%s%s]",
GC_GET_SIZE(o),
- GC_TEST_FLAGS(o, GC_FLAG_FINALIZER) ? "F" : " ",
GC_TEST_FLAGS(o, HDRFLAG_HASH_ATTACHED) ? "A" : " ",
GC_TEST_FLAGS(o, HDRFLAG_HASH_TAKEN) ? "T" : " ",
GC_TEST_FLAGS(o, HDRFLAG_UNCOLLECTABLE) ? "U" : " ",
#if !defined(NDEBUG)
-void heap_print_object(java_objectheader *o)
+void heap_print_object(java_object_t *o)
{
- java_arrayheader *a;
- classinfo *c;
+ java_array_t *a;
+ classinfo *c;
/* check for null pointers */
if (o == NULL) {
#else
printf("0x%08lx: ", (unsigned long) o);
#endif
+
+ /* check for invalid heap references */
+ if (!POINTS_INTO(o, heap_region_main->base, heap_region_main->end) &&
+ !POINTS_INTO(o, heap_region_sys->base, heap_region_sys->end))
+ {
+ printf("<<< No Heap Reference >>>");
+ return;
+ }
+
+ /* print object flags */
heap_print_object_flags(o);
printf(" ");
+ GC_ASSERT(o->vftbl);
+
/* TODO */
/* maybe this is not really an object */
if (/*IS_CLASS*/ o->vftbl->class == class_java_lang_Class) {
} else if (/*IS_ARRAY*/ o->vftbl->arraydesc != NULL) {
/* get the array information */
- a = (java_arrayheader *) o;
+ a = (java_array_t *) o;
c = o->vftbl->class;
/* print the array information */
#if !defined(NDEBUG)
void heap_dump_region(regioninfo_t *region, bool marked_only)
{
- java_objectheader *o;
- u4 o_size;
+ java_object_t *o;
+ u4 o_size;
/* some basic sanity checks */
- GC_ASSERT(region->base < region->ptr);
+ GC_ASSERT(region->base <= region->ptr);
printf("Heap-Dump:\n");
/* walk the region in a linear style */
- o = (java_objectheader *) region->base;
+ o = (java_object_t *) region->base;
while (o < region->ptr) {
if (!marked_only || GC_IS_MARKED(o)) {
#endif
-s4 get_object_size(java_objectheader *o)
+s4 get_object_size(java_object_t *o)
{
- java_arrayheader *a;
- classinfo *c;
- s4 o_size;
+ java_array_t *a;
+ classinfo *c;
+ s4 o_size;
/* we can assume someone initialized the header */
GC_ASSERT(o->hdrflags != 0);
} else if (/*IS_ARRAY*/ o->vftbl->arraydesc != NULL) {
/* compute size of this array */
- a = (java_arrayheader *) o;
+ a = (java_array_t *) o;
c = o->vftbl->class;
o_size = c->vftbl->arraydesc->dataoffset +
a->size * c->vftbl->arraydesc->componentsize;