Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Michael Starzinger
-
-
*/
#define GC_THREAD(ref, refptr, start, end) \
if (POINTS_INTO(ref, start, end)) { \
GC_ASSERT(GC_IS_MARKED(ref)); \
- *refptr = (java_objectheader *) ref->vftbl; \
+ *refptr = (java_object_t *) ref->vftbl; \
ref->vftbl = (struct _vftbl *) GC_SET_THREAD_BIT(refptr); \
}
*******************************************************************************/
-void compact_thread_rootset(rootset_t *rs, void *start, void *end)
+static void compact_thread_rootset(rootset_t *rs, void *start, void *end)
{
- java_objectheader *ref;
- java_objectheader **refptr;
+ java_object_t *ref;
+ java_object_t **refptr;
int i;
- GC_LOG2( printf("threading in rootset\n"); );
+ GC_LOG2( printf("threading in rootsets\n"); );
- /* walk through the references of this rootset */
- for (i = 0; i < rs->refcount; i++) {
+ /* walk through all rootsets */
+ while (rs) {
- /* load the reference */
- refptr = rs->refs[i];
- ref = *( refptr );
+ /* 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); );
+ GC_LOG2( printf("\troot pointer to %p\n", (void *) ref); );
- /* thread the references */
- GC_THREAD(ref, refptr, start, end);
+ /* thread the references */
+ GC_THREAD(ref, refptr, start, end);
+
+ }
+
+ /* skip to next rootset in chain */
+ rs = rs->next;
}
}
*******************************************************************************/
-void compact_thread_classes(void *start, void *end)
+static void compact_thread_classes(void *start, void *end)
{
- java_objectheader *ref;
- java_objectheader **refptr;
- classinfo *c;
- fieldinfo *f;
+ java_object_t *ref;
+ java_object_t **refptr;
+ classinfo *c;
+ fieldinfo *f;
+ /*hashtable_classloader_entry *cle;*/
void *sys_start, *sys_end;
int i;
sys_start = heap_region_sys->base;
sys_end = heap_region_sys->ptr;
+#if 0
+ /* 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;
+ }
+ }
+#endif
+
/* 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++) {
continue;
/* load the reference */
- refptr = (java_objectheader **) &(f->value);
+ refptr = (java_object_t **) &(f->value);
ref = *( refptr );
GC_LOG2( printf("\tclass-field points to %p\n", (void *) ref); );
} else if (GC_IS_THREADED(ref->vftbl)) {
printf("(threaded)\n");
} else {
- heap_print_object(ref); printf("\n");
+ heap_print_object(ref); printf("\n");
}
);*/
*******************************************************************************/
-void compact_thread_references(java_objectheader *o, void *start, void *end)
+static void compact_thread_references(java_object_t *o, void *start, void *end)
{
- java_objectheader *ref;
- java_objectheader **refptr;
+ java_object_t *ref;
+ java_object_t **refptr;
GC_LOG2( printf("threading in ");
heap_print_object(o); printf("\n"); );
*******************************************************************************/
-void compact_unthread_references(java_objectheader *o, void *new)
+static void compact_unthread_references(java_object_t *o, void *new)
{
- java_objectheader **refptr;
+ java_object_t **refptr;
ptrint tmp;
GC_LOG2( printf("unthreading in ...\n"); );
GC_ASSERT(GC_IS_THREADED(o->vftbl));
/* walk down the threaded chain */
- refptr = (java_objectheader **) (ptrint) o->vftbl;
+ refptr = (java_object_t **) (ptrint) o->vftbl;
while (GC_IS_THREADED(refptr)) {
/* remove the threading bit */
- refptr = (java_objectheader **) GC_REMOVE_THREAD_BIT(refptr);
+ refptr = (java_object_t **) GC_REMOVE_THREAD_BIT(refptr);
GC_LOG2( printf("\treference at %p\n", (void *) refptr); );
/* update the reference in the chain */
tmp = (ptrint) *refptr;
- *refptr = (java_objectheader *) (ptrint) new;
+ *refptr = (java_object_t *) (ptrint) new;
/* skip to the next chain value */
- refptr = (java_objectheader **) tmp;
+ refptr = (java_object_t **) tmp;
}
Moves the content (including header) of an object around in memory
NOTE: Memory locations may overlap!
+ NOTE: The size of the object can change by moving it around (hashcode)!
IN:
old......Old Location of the object before compaction
new......New Location of the object after compaction
size.....Size of the object in bytes
+ OUT:
+ New size of the object after moving it
+
*******************************************************************************/
-void compact_move(u1 *old, u1 *new, u4 size)
+static u4 compact_move(u1 *old, u1 *new, u4 size)
{
+ s4 hashcode;
+ u4 new_size;
- GC_ASSERT(new < old);
+ 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(ENABLE_MEMCHECK)
/* 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);
}
+
+ new_size = size;
+
+ /* check if we need to attach the hashcode to the object */
+ if (GC_TEST_FLAGS((java_object_t *) new, HDRFLAG_HASH_TAKEN)) {
+
+ /* TODO: move this whole bunch to heap_attach_hashcode() */
+
+ /* change the flags accordingly */
+ GC_CLEAR_FLAGS((java_object_t *) new, HDRFLAG_HASH_TAKEN);
+ GC_SET_FLAGS((java_object_t *) new, HDRFLAG_HASH_ATTACHED);
+
+ /* attach the hashcode at the end of the object */
+ new_size += SIZEOF_VOID_P;
+ hashcode = (s4) (ptrint) old;
+ *( (s4 *) (new + new_size - SIZEOF_VOID_P) ) = hashcode; /* TODO: clean this up */
+
+ GC_ASSERT(new + SIZEOF_VOID_P < old);
+ GC_LOG2( dolog("GC: Hash attached: %d (0x%08x) to new object at %p", hashcode, hashcode, new); );
+
+ }
+
+ return new_size;
}
{
u1 *ptr;
u1 *ptr_new;
- java_objectheader *o;
+ java_object_t *o;
u4 o_size;
+ u4 o_size_new;
u4 used;
- GC_LOG( dolog("GC: Compaction Phase 1 started ..."); );
+ GC_LOG( dolog("GC: Compaction Phase 0 started ..."); );
/* Phase 0:
* - thread all references in classes
* - thread all references in the rootset */
- compact_thread_classes(region->base, region->ptr);
+ /*compact_thread_classes(region->base, region->ptr);*/
compact_thread_rootset(rs, region->base, region->ptr);
+ GC_LOG( dolog("GC: Compaction Phase 1 started ..."); );
+
/* Phase 1:
* - scan the heap
* - thread all references
* - update forward references */
ptr = region->base; ptr_new = region->base;
- while (ptr < (u1 *) region->ptr) {
- o = (java_objectheader *) ptr;
+ while (ptr < region->ptr) {
+ o = (java_object_t *) 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, HDRFLAG_UNCOLLECTABLE));
/* if this object is already part of a threaded chain ... */
if (GC_IS_THREADED(o->vftbl)) {
/* only marked objects survive */
if (GC_IS_MARKED(o)) {
+#if defined(GCCONF_HDRFLAG_REFERENCING)
+ /* check if this objects contains references */
+ if (GC_TEST_FLAGS(o, HDRFLAG_REFERENCING))
+#endif
+
/* thread all the references in this object */
compact_thread_references(o, region->base, region->ptr);
/* object survives, place next object behind it */
ptr_new += o_size;
+
+ /* size might change because of attached hashcode */
+ if (GC_TEST_FLAGS(o, HDRFLAG_HASH_TAKEN))
+ ptr_new += SIZEOF_VOID_P;
}
/* skip to next object */
* - move the objects */
used = 0;
ptr = region->base; ptr_new = region->base;
- while (ptr < (u1 *) region->ptr) {
- o = (java_objectheader *) ptr;
+ while (ptr < region->ptr) {
+ o = (java_object_t *) ptr;
/* if this object is still part of a threaded chain ... */
if (GC_IS_THREADED(o->vftbl)) {
/* unmark the object */
GC_CLEAR_MARKED(o);
- /* move the object */
- compact_move(ptr, ptr_new, o_size);
+ /* move the object (size can change) */
+ o_size_new = compact_move(ptr, ptr_new, o_size);
/* object survives, place next object behind it */
- ptr_new += o_size;
- used += o_size;
+ ptr_new += o_size_new;
+ used += o_size_new;
}
/* skip to next object */
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;