CACAO
compact.c
Go to the documentation of this file.
1 /* mm/cacao-gc/compact.c - GC module for compacting heap regions
2 
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
7 
8  This file is part of CACAO.
9 
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.
14 
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.
19 
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
23  02110-1301, USA.
24 
25 */
26 
27 
28 #include "config.h"
29 #include "vm/types.hpp"
30 
31 #include "gc.h"
32 #include "heap.h"
33 #include "mark.h"
34 #include "mm/memory.hpp"
35 #include "toolbox/logging.hpp"
36 
37 
38 /* Threading macros ***********************************************************/
39 
40 #define GC_THREAD_BIT 0x01
41 
42 #define GC_IS_THREADED(ptr) (((ptrint) ptr) & GC_THREAD_BIT)
43 #define GC_REMOVE_THREAD_BIT(ptr) (((ptrint) ptr) & ~GC_THREAD_BIT)
44 #define GC_SET_THREAD_BIT(ptr) (((ptrint) ptr) | GC_THREAD_BIT)
45 
46 #define GC_THREAD(ref, refptr, start, end) \
47  if (POINTS_INTO(ref, start, end)) { \
48  GC_ASSERT(GC_IS_MARKED(ref)); \
49  *refptr = (java_object_t *) ref->vftbl; \
50  ref->vftbl = (struct _vftbl *) GC_SET_THREAD_BIT(refptr); \
51  }
52 
53 
54 /* compact_thread_rootset ******************************************************
55 
56  Threads all the references in the rootset
57 
58  IN:
59  rs........Rootset containing the references to be threaded.
60  start.....Region to be compacted start here
61  end.......Region to be compacted ends here
62 
63 *******************************************************************************/
64 
65 static void compact_thread_rootset(rootset_t *rs, void *start, void *end)
66 {
67  java_object_t *ref;
68  java_object_t **refptr;
69  int i;
70 
71  GC_LOG2( printf("threading in rootsets\n"); );
72 
73  /* walk through all rootsets */
74  while (rs) {
75 
76  /* walk through the references of this rootset */
77  for (i = 0; i < rs->refcount; i++) {
78 
79  /* load the reference */
80  refptr = rs->refs[i].ref;
81  ref = *( refptr );
82 
83  GC_LOG2( printf("\troot pointer to %p\n", (void *) ref); );
84 
85  /* thread the references */
86  GC_THREAD(ref, refptr, start, end);
87 
88  }
89 
90  /* skip to next rootset in chain */
91  rs = rs->next;
92 
93  }
94 }
95 
96 
97 /* compact_thread_references ***************************************************
98 
99  Threads all the references of an object.
100 
101  IN:
102  o.........Object containing the references to be threaded.
103  start.....Region to be compacted start here
104  end.......Region to be compacted ends here
105 
106 *******************************************************************************/
107 
108 static void compact_thread_references(java_object_t *o, void *start, void *end)
109 {
110  java_object_t *ref;
111  java_object_t **refptr;
112 
113  GC_LOG2( printf("threading in ");
114  heap_print_object(o); printf("\n"); );
115 
116  if (IS_ARRAY(o)) {
117 
118  /* walk through the references of an Array */
119  FOREACH_ARRAY_REF(o,ref,refptr,
120 
121  GC_LOG2( printf("\tarray-entry points to %p\n", (void *) ref); );
122 
123  GC_THREAD(ref, refptr, start, end);
124 
125  );
126 
127  } else {
128 
129  /* walk through the references of an Object */
130  FOREACH_OBJECT_REF(o,ref,refptr,
131 
132  GC_LOG2( printf("\tobject-field points to %p\n", (void *) ref); );
133 
134  GC_THREAD(ref, refptr, start, end);
135 
136  );
137 
138  }
139 }
140 
141 
142 /* compact_unthread_references *************************************************
143 
144  Unthreads all the references which previousely pointed to an object. The
145  object itself is the head of the threading chain. All the references in the
146  chain once pointed to the object and will point to it's new location
147  afterwards.
148 
149  IN:
150  o.......Head of the threading chain
151  new.....New Location of the object after compaction
152 
153 *******************************************************************************/
154 
155 static void compact_unthread_references(java_object_t *o, void *new)
156 {
157  java_object_t **refptr;
158  ptrint tmp;
159 
160  GC_LOG2( printf("unthreading in ...\n"); );
161 
162  /* some quick sanity checks */
163  GC_ASSERT(o);
165 
166  /* walk down the threaded chain */
167  refptr = (java_object_t **) (ptrint) o->vftbl;
168  while (GC_IS_THREADED(refptr)) {
169 
170  /* remove the threading bit */
171  refptr = (java_object_t **) GC_REMOVE_THREAD_BIT(refptr);
172 
173  GC_LOG2( printf("\treference at %p\n", (void *) refptr); );
174 
175  /* update the reference in the chain */
176  tmp = (ptrint) *refptr;
177  *refptr = (java_object_t *) (ptrint) new;
178 
179  /* skip to the next chain value */
180  refptr = (java_object_t **) tmp;
181 
182  }
183 
184  /* finally restore the original vftbl pointer */
185  o->vftbl = (struct _vftbl *) refptr;
186  GC_ASSERT(o->vftbl);
187 
188  GC_LOG2( printf("\t... pointed to "); heap_print_object(o); printf("\n"); );
189  GC_LOG2( printf("\t... now points to %p\n", (void *) new); );
190 
191 }
192 
193 
194 /* compact_move ****************************************************************
195 
196  Moves the content (including header) of an object around in memory
197 
198  NOTE: Memory locations may overlap!
199  NOTE: The size of the object can change by moving it around (hashcode)!
200 
201  IN:
202  old......Old Location of the object before compaction
203  new......New Location of the object after compaction
204  size.....Size of the object in bytes
205 
206  OUT:
207  New size of the object after moving it
208 
209 *******************************************************************************/
210 
211 static u4 compact_move(u1 *old, u1 *new, u4 size)
212 {
213  s4 hashcode;
214  u4 new_size;
215 
216  GC_ASSERT(new <= old);
217 
218  /* check if locations overlap */
219  if (new + size < old) {
220  /* overlapping: NO */
221 
222  /* copy old object content to new location */
223  MCOPY(new, old, u1, size);
224 
225 #if defined(ENABLE_MEMCHECK)
226  /* invalidate old object */
227  MSET(old, MEMORY_CLEAR_BYTE, u1, size);
228 #endif
229 
230  } else {
231  /* overlapping: YES */
232 
233  GC_LOG2( printf("\tcompact_move(old=%p, new=%p, size=0x%x) overlapps!", old, new, size) );
234 
235  /* copy old object content to new location */
236  MMOVE(new, old, u1, size);
237 
238  }
239 
240  new_size = size;
241 
242  /* check if we need to attach the hashcode to the object */
244 
245  /* TODO: move this whole bunch to heap_attach_hashcode() */
246 
247  /* change the flags accordingly */
250 
251  /* attach the hashcode at the end of the object */
252  new_size += SIZEOF_VOID_P;
253  hashcode = (s4) (ptrint) old;
254  *( (s4 *) (new + new_size - SIZEOF_VOID_P) ) = hashcode; /* TODO: clean this up */
255 
256  GC_ASSERT(new + SIZEOF_VOID_P < old);
257  GC_LOG2( dolog("GC: Hash attached: %d (0x%08x) to new object at %p", hashcode, hashcode, new); );
258 
259  }
260 
261  return new_size;
262 }
263 
264 
265 /* compact_me ******************************************************************
266 
267  This function actually does the compaction in two passes. Look at the source
268  for further details about the passes.
269 
270  IN:
271  rs.........Rootset, needed to update the root references
272  region.....Region to be compacted
273 
274 *******************************************************************************/
275 
277 {
278  u1 *ptr;
279  u1 *ptr_new;
280  java_object_t *o;
281  u4 o_size;
282  u4 o_size_new;
283  u4 used;
284 
285  GC_LOG( dolog("GC: Compaction Phase 0 started ..."); );
286 
287  /* Phase 0:
288  * - thread all references in the rootset */
289  compact_thread_rootset(rs, region->base, region->ptr);
290 
291  GC_LOG( dolog("GC: Compaction Phase 1 started ..."); );
292 
293  /* Phase 1:
294  * - scan the heap
295  * - thread all references
296  * - update forward references */
297  ptr = region->base; ptr_new = region->base;
298  while (ptr < region->ptr) {
299  o = (java_object_t *) ptr;
300 
301  /* uncollectable items should never be compacted */
303 
304  /* if this object is already part of a threaded chain ... */
305  if (GC_IS_THREADED(o->vftbl)) {
306 
307  /* ... unthread the reference chain */
308  compact_unthread_references(o, ptr_new);
309 
310  }
311 
312  /* get the object size (objectheader is now unthreaded) */
313  o_size = get_object_size(o);
314 
315  /* only marked objects survive */
316  if (GC_IS_MARKED(o)) {
317 
318 #if defined(GCCONF_HDRFLAG_REFERENCING)
319  /* check if this objects contains references */
321 #endif
322 
323  /* thread all the references in this object */
324  compact_thread_references(o, region->base, region->ptr);
325 
326  /* object survives, place next object behind it */
327  ptr_new += o_size;
328 
329  /* size might change because of attached hashcode */
331  ptr_new += SIZEOF_VOID_P;
332  }
333 
334  /* skip to next object */
335  ptr += o_size;
336  }
337 
338  GC_LOG( dolog("GC: Compaction Phase 2 started ..."); );
339 
340  /* Phase 2:
341  * - scan the heap again
342  * - update backward references
343  * - move the objects */
344  used = 0;
345  ptr = region->base; ptr_new = region->base;
346  while (ptr < region->ptr) {
347  o = (java_object_t *) ptr;
348 
349  /* if this object is still part of a threaded chain ... */
350  if (GC_IS_THREADED(o->vftbl)) {
351 
352  /* ... unthread the reference chain */
353  compact_unthread_references(o, ptr_new);
354 
355  }
356 
357  /* get the object size (objectheader is now unthreaded) */
358  o_size = get_object_size(o);
359 
360  /* move the surviving objects */
361  if (GC_IS_MARKED(o)) {
362 
363  GC_LOG2( printf("moving: %08x -> %08x (%d bytes)\n",
364  (ptrint) ptr, (ptrint) ptr_new, o_size); );
365 
366  /* unmark the object */
367  GC_CLEAR_MARKED(o);
368 
369  /* move the object (size can change) */
370  o_size_new = compact_move(ptr, ptr_new, o_size);
371 
372  /* object survives, place next object behind it */
373  ptr_new += o_size_new;
374  used += o_size_new;
375  }
376 
377  /* skip to next object */
378  ptr += o_size;
379  }
380 
381  GC_LOG( dolog("GC: Compaction finished."); );
382 
383  GC_LOG( printf("Region-Used: %d -> %d\n", region->size - region->free, used); )
384  GC_LOG( printf("Region-Free: %d -> %d\n", region->free, region->size - used); )
385 
386  /* update the region information */
387  region->ptr = ptr_new;
388  region->free = region->size - used;
389 
390 }
391 
392 
393 /*
394  * These are local overrides for various environment variables in Emacs.
395  * Please do not remove this and leave it at the end of the file, where
396  * Emacs will automagically detect them.
397  * ---------------------------------------------------------------------
398  * Local variables:
399  * mode: c
400  * indent-tabs-mode: t
401  * c-basic-offset: 4
402  * tab-width: 4
403  * End:
404  * vim:noexpandtab:sw=4:ts=4:
405  */
#define dolog
Definition: logging.hpp:171
#define GC_CLEAR_MARKED(obj)
Definition: mark.h:44
#define GC_IS_MARKED(obj)
Definition: mark.h:42
#define IS_ARRAY(o)
Definition: heap.h:65
rootset_t * next
Definition: rootset.h:60
rootset_entry_t refs[ROOTSET_INITIAL_CAPACITY]
Definition: rootset.h:64
#define MSET(ptr, byte, type, num)
Definition: memory.hpp:104
#define GC_LOG(code)
Definition: gc.h:58
static void compact_thread_references(java_object_t *o, void *start, void *end)
Definition: compact.c:108
uint8_t u1
Definition: types.hpp:40
static u4 compact_move(u1 *old, u1 *new, u4 size)
Definition: compact.c:211
JNIEnv jthread jobject jclass jlong size
Definition: jvmti.h:387
#define FOREACH_OBJECT_REF(o, ref, refptr, code)
Definition: heap.h:85
u1 * base
Definition: region.h:48
#define GC_ASSERT(assertion)
Definition: gc.h:59
java_object_t ** ref
Definition: rootset.h:51
#define GC_LOG2(code)
Definition: gc.h:68
#define GC_REMOVE_THREAD_BIT(ptr)
Definition: compact.c:43
Instruction::InstID tmp[]
Definition: Matcher.cpp:55
static void compact_unthread_references(java_object_t *o, void *new)
Definition: compact.c:155
s4 get_object_size(java_object_t *o)
Definition: heap.c:509
u1 * ptr
Definition: region.h:50
void compact_me(rootset_t *rs, regioninfo_t *region)
Definition: compact.c:276
#define MMOVE(dest, src, type, num)
Definition: memory.hpp:106
#define GC_SET_FLAGS(obj, flags)
Definition: gc.h:101
MIIterator i
int32_t s4
Definition: types.hpp:45
#define GC_TEST_FLAGS(obj, flags)
Definition: gc.h:103
void heap_print_object(java_object_t *o)
Definition: heap.c:400
uint32_t u4
Definition: types.hpp:46
#define FOREACH_ARRAY_REF(o, ref, refptr, code)
Definition: heap.h:66
static void compact_thread_rootset(rootset_t *rs, void *start, void *end)
Definition: compact.c:65
#define GC_IS_THREADED(ptr)
Definition: compact.c:42
#define GC_THREAD(ref, refptr, start, end)
Definition: compact.c:46
#define MCOPY(dest, src, type, num)
Definition: memory.hpp:103
s4 refcount
Definition: rootset.h:63
uintptr_t ptrint
Definition: types.hpp:54
vftbl_t * vftbl
Definition: global.hpp:264
#define printf(...)
Definition: ssa2.cpp:40
#define GC_CLEAR_FLAGS(obj, flags)
Definition: gc.h:102