1 /* mm/cacao-gc/compact.c - GC module for compacting heap regions
3 Copyright (C) 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Michael Starzinger
40 #include "mm/memory.h"
41 #include "toolbox/logging.h"
44 /* Threading macros ***********************************************************/
46 #define GC_THREAD_BIT 0x01
48 #define GC_IS_THREADED(ptr) (((ptrint) ptr) & GC_THREAD_BIT)
49 #define GC_REMOVE_THREAD_BIT(ptr) (((ptrint) ptr) & ~GC_THREAD_BIT)
50 #define GC_SET_THREAD_BIT(ptr) (((ptrint) ptr) | GC_THREAD_BIT)
52 #define GC_THREAD(ref, refptr, start, end) \
53 if (POINTS_INTO(ref, start, end)) { \
54 GC_ASSERT(GC_IS_MARKED(ref)); \
55 *refptr = (java_objectheader *) ref->vftbl; \
56 ref->vftbl = (struct _vftbl *) GC_SET_THREAD_BIT(refptr); \
60 /* compact_thread_rootset ******************************************************
62 Threads all the references in the rootset
65 rs........Rootset containing the references to be threaded.
66 start.....Region to be compacted start here
67 end.......Region to be compacted ends here
69 *******************************************************************************/
71 void compact_thread_rootset(rootset_t *rs, void *start, void *end)
73 java_objectheader *ref;
74 java_objectheader **refptr;
77 GC_LOG2( printf("threading in rootset\n"); );
79 /* walk through the references of this rootset */
80 for (i = 0; i < rs->refcount; i++) {
82 /* load the reference */
86 GC_LOG2( printf("\troot pointer to %p\n", (void *) ref); );
88 /* thread the references */
89 GC_THREAD(ref, refptr, start, end);
95 /* compact_thread_classes ******************************************************
97 Threads all the references from classinfo structures (static fields)
100 start.....Region to be compacted start here
101 end.......Region to be compacted ends here
103 *******************************************************************************/
105 void compact_thread_classes(void *start, void *end)
107 java_objectheader *ref;
108 java_objectheader **refptr;
111 void *sys_start, *sys_end;
114 GC_LOG2( printf("threading in classes\n"); );
116 /* TODO: cleanup!!! */
117 sys_start = heap_region_sys->base;
118 sys_end = heap_region_sys->ptr;
120 /* walk through all classinfo blocks */
121 for (c = sys_start; c < (classinfo *) sys_end; c++) {
123 /* walk through all fields */
125 for (i = 0; i < c->fieldscount; i++, f++) {
127 /* check if this is a static reference */
128 if (!IS_ADR_TYPE(f->type) || !(f->flags & ACC_STATIC))
131 /* load the reference */
132 refptr = (java_objectheader **) &(f->value);
135 GC_LOG2( printf("\tclass-field points to %p\n", (void *) ref); );
137 printf("\tfield: "); field_print(f); printf("\n");
138 printf("\tclass-field points to ");
141 } else if (GC_IS_THREADED(ref->vftbl)) {
142 printf("(threaded)\n");
144 heap_print_object(ref); printf("\n");
148 /* thread the reference */
149 GC_THREAD(ref, refptr, start, end);
158 /* compact_thread_references ***************************************************
160 Threads all the references of an object.
163 o.........Object containing the references to be threaded.
164 start.....Region to be compacted start here
165 end.......Region to be compacted ends here
167 *******************************************************************************/
169 void compact_thread_references(java_objectheader *o, void *start, void *end)
171 java_objectheader *ref;
172 java_objectheader **refptr;
174 GC_LOG2( printf("threading in ");
175 heap_print_object(o); printf("\n"); );
179 /* walk through the references of an Array */
180 FOREACH_ARRAY_REF(o,ref,refptr,
182 GC_LOG2( printf("\tarray-entry points to %p\n", (void *) ref); );
184 GC_THREAD(ref, refptr, start, end);
190 /* walk through the references of an Object */
191 FOREACH_OBJECT_REF(o,ref,refptr,
193 GC_LOG2( printf("\tobject-field points to %p\n", (void *) ref); );
195 GC_THREAD(ref, refptr, start, end);
203 /* compact_unthread_references *************************************************
205 Unthreads all the references which previousely pointed to an object. The
206 object itself is the head of the threading chain. All the references in the
207 chain once pointed to the object and will point to it's new location
211 o.......Head of the threading chain
212 new.....New Location of the object after compaction
214 *******************************************************************************/
216 void compact_unthread_references(java_objectheader *o, void *new)
218 java_objectheader **refptr;
221 GC_LOG2( printf("unthreading in ...\n"); );
223 /* some quick sanity checks */
225 GC_ASSERT(GC_IS_THREADED(o->vftbl));
227 /* walk down the threaded chain */
228 refptr = (java_objectheader **) (ptrint) o->vftbl;
229 while (GC_IS_THREADED(refptr)) {
231 /* remove the threading bit */
232 refptr = (java_objectheader **) GC_REMOVE_THREAD_BIT(refptr);
234 GC_LOG2( printf("\treference at %p\n", (void *) refptr); );
236 /* update the reference in the chain */
237 tmp = (ptrint) *refptr;
238 *refptr = (java_objectheader *) (ptrint) new;
240 /* skip to the next chain value */
241 refptr = (java_objectheader **) tmp;
245 /* finally restore the original vftbl pointer */
246 o->vftbl = (struct _vftbl *) refptr;
249 GC_LOG2( printf("\t... pointed to "); heap_print_object(o); printf("\n"); );
250 GC_LOG2( printf("\t... now points to %p\n", (void *) new); );
255 /* compact_move ****************************************************************
257 Moves the content (including header) of an object around in memory
259 NOTE: Memory locations may overlap!
262 old......Old Location of the object before compaction
263 new......New Location of the object after compaction
264 size.....Size of the object in bytes
266 *******************************************************************************/
268 void compact_move(u1 *old, u1 *new, u4 size)
271 GC_ASSERT(new < old);
273 /* check if locations overlap */
274 if (old + size >= new) {
275 /* overlapping: NO */
277 /* copy old object content to new location */
278 MCOPY(new, old, u1, size);
280 /* invalidate old object */
281 MSET(old, 0x44, u1, size);
284 /* overlapping: YES */
286 GC_LOG( dolog("GC: OVERLAPPING!!!") );
288 /* copy old object content to new location */
289 MMOVE(new, old, u1, size);
295 /* compact_me ******************************************************************
297 This function actually does the compaction in two passes. Look at the source
298 for further details about the passes.
301 rs.........Rootset, needed to update the root references
302 region.....Region to be compacted
304 *******************************************************************************/
306 void compact_me(rootset_t *rs, regioninfo_t *region)
310 java_objectheader *o;
314 GC_LOG( dolog("GC: Compaction Phase 1 started ..."); );
317 * - thread all references in classes
318 * - thread all references in the rootset */
319 compact_thread_classes(region->base, region->ptr);
320 compact_thread_rootset(rs, region->base, region->ptr);
324 * - thread all references
325 * - update forward references */
326 ptr = region->base; ptr_new = region->base;
327 while (ptr < (u1 *) region->ptr) {
328 o = (java_objectheader *) ptr;
330 /* TODO: uncollectable items should never be compacted, but for now we do it */
331 /*GC_ASSERT(!GC_TEST_FLAGS(o, GC_FLAG_UNCOLLECTABLE));*/
332 /*if (GC_TEST_FLAGS(o, GC_FLAG_UNCOLLECTABLE)) {
336 /* if this object is already part of a threaded chain ... */
337 if (GC_IS_THREADED(o->vftbl)) {
339 /* ... unthread the reference chain */
340 compact_unthread_references(o, ptr_new);
344 /* get the object size (objectheader is now unthreaded) */
345 o_size = get_object_size(o);
347 /* only marked objects survive */
348 if (GC_IS_MARKED(o)) {
350 /* thread all the references in this object */
351 compact_thread_references(o, region->base, region->ptr);
353 /* object survives, place next object behind it */
357 /* skip to next object */
361 GC_LOG( dolog("GC: Compaction Phase 2 started ..."); );
364 * - scan the heap again
365 * - update backward references
366 * - move the objects */
368 ptr = region->base; ptr_new = region->base;
369 while (ptr < (u1 *) region->ptr) {
370 o = (java_objectheader *) ptr;
372 /* if this object is still part of a threaded chain ... */
373 if (GC_IS_THREADED(o->vftbl)) {
375 /* ... unthread the reference chain */
376 compact_unthread_references(o, ptr_new);
380 /* get the object size (objectheader is now unthreaded) */
381 o_size = get_object_size(o);
383 /* move the surviving objects */
384 if (GC_IS_MARKED(o)) {
386 GC_LOG2( printf("moving: %08x -> %08x (%d bytes)\n",
387 (ptrint) ptr, (ptrint) ptr_new, o_size); );
389 /* unmark the object */
392 /* move the object */
393 compact_move(ptr, ptr_new, o_size);
395 /* object survives, place next object behind it */
400 /* skip to next object */
404 GC_LOG( dolog("GC: Compaction finished."); );
406 GC_LOG( printf("Region-Used: %d -> %d\n", region->size - region->free, used); )
408 /* update the region information */
409 region->ptr = ptr_new;
410 region->free = region->size - used;
416 * These are local overrides for various environment variables in Emacs.
417 * Please do not remove this and leave it at the end of the file, where
418 * Emacs will automagically detect them.
419 * ---------------------------------------------------------------------
422 * indent-tabs-mode: t
426 * vim:noexpandtab:sw=4:ts=4: