CACAO
mark.c
Go to the documentation of this file.
1 /* src/mm/cacao-gc/mark.c - GC module for marking heap objects
2 
3  Copyright (C) 2006, 2008
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 
6  This file is part of CACAO.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2, or (at
11  your option) any later version.
12 
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301, USA.
22 
23 */
24 
25 
26 #include "config.h"
27 
28 #include "gc.h"
29 #include "final.h"
30 #include "heap.h"
31 #include "mark.h"
32 #include "rootset.h"
33 #include "mm/memory.hpp"
34 #include "toolbox/logging.hpp"
35 
36 #include "vm/global.hpp"
37 #include "vm/linker.hpp"
38 #include "vm/vm.hpp"
39 
40 
41 /* Helper Macros **************************************************************/
42 
43 #define MARK(o) \
44  GCSTAT_COUNT_MAX(gcstat_mark_depth, gcstat_mark_depth_max); \
45  mark_recursive(o); \
46  GCSTAT_DEC(gcstat_mark_depth);
47 
48 
49 /* mark_recursive **************************************************************
50 
51  Recursively mark all objects (including this) which are referenced.
52 
53  TODO, XXX: We need to implement a non-recursive version of this!!!
54 
55  IN:
56  o.....heap-object to be marked (either OBJECT or ARRAY)
57 
58 *******************************************************************************/
59 
61 {
62  vftbl_t *t;
63  classinfo *c;
64  fieldinfo *f;
66  arraydescriptor *desc;
67  java_object_t *ref;
68  void *start, *end;
69  int i;
70 
71  /* TODO: this needs cleanup!!! */
72  start = heap_region_main->base;
73  end = heap_region_main->ptr;
74 
75  /* uncollectable objects should never get marked this way */
76  /* the reference should point into the heap */
77  GC_ASSERT(o);
79  GC_ASSERT(POINTS_INTO(o, start, end));
80 
81  /* mark this object */
82  GC_SET_MARKED(o);
83  GCSTAT_COUNT(gcstat_mark_count);
84 
85  /* get the class of this object */
86  /* TODO: maybe we do not need this yet, look to move down! */
87  t = o->vftbl;
88  GC_ASSERT(t);
89  c = t->class;
90  GC_ASSERT(c);
91 
92 #if defined(GCCONF_HDRFLAG_REFERENCING)
93  /* does this object has pointers? */
94  /* TODO: check how often this happens, maybe remove this check! */
96  return;
97 #endif
98 
99  /* check if we are marking an array */
100  if ((desc = t->arraydesc) != NULL) {
101  /* this is an ARRAY */
102 
103  /* check if the array contains references */
104  if (desc->arraytype != ARRAYTYPE_OBJECT)
105  return;
106 
107  /* for object-arrays we need to check every entry */
108  oa = (java_objectarray_t *) o;
109  for (i = 0; i < oa->header.size; i++) {
110 
111  /* load the reference value */
112  ref = (java_object_t *) (oa->data[i]);
113 
114  /* check for outside or null pointers */
115  if (!POINTS_INTO(ref, start, end))
116  continue;
117 
118  GC_LOG2( printf("Found (%p) from Array\n", (void *) ref); );
119 
120  /* do the recursive marking */
121  if (!GC_IS_MARKED(ref)) {
122  GCSTAT_COUNT_MAX(gcstat_mark_depth, gcstat_mark_depth_max);
123  mark_recursive(ref);
124  GCSTAT_DEC(gcstat_mark_depth);
125  }
126 
127  }
128 
129  } else {
130  /* this is an OBJECT */
131 
132  /* for objects we need to check all (non-static) fields */
133  for (; c; c = c->super) {
134  for (i = 0; i < c->fieldscount; i++) {
135  f = &(c->fields[i]);
136 
137  /* check if this field contains a non-static reference */
138  if (!IS_ADR_TYPE(f->type) || (f->flags & ACC_STATIC))
139  continue;
140 
141  /* load the reference value */
142  ref = *( (java_object_t **) ((s1 *) o + f->offset) );
143 
144  /* check for outside or null pointers */
145  if (!POINTS_INTO(ref, start, end))
146  continue;
147 
148  GC_LOG2( printf("Found (%p) from Field ", (void *) ref);
149  field_print(f); printf("\n"); );
150 
151  /* do the recursive marking */
152  if (!GC_IS_MARKED(ref)) {
153  GCSTAT_COUNT_MAX(gcstat_mark_depth, gcstat_mark_depth_max);
154  mark_recursive(ref);
155  GCSTAT_DEC(gcstat_mark_depth);
156  }
157 
158  }
159  }
160 
161  }
162 
163 }
164 
165 
166 /* mark_post *******************************************************************
167 
168  Perform some post-marking cleanup tasks.
169 
170  TASKS:
171  - mark unmarked objects with Finalizers
172  - clear unmarked Weak References
173 
174 *******************************************************************************/
175 
177 {
178  java_object_t *ref;
179 #if defined(GCCONF_FINALIZER)
180  list_final_entry_t *fe;
181  u4 f_type;
182 #endif
183  void *start, *end;
184  int i;
185 
186  /* TODO: this needs cleanup!!! */
187  start = heap_region_main->base;
188  end = heap_region_main->ptr;
189 
190 #if defined(GCCONF_FINALIZER)
191  /* objects with finalizers will also be marked here. if they have not been
192  marked before the finalization is triggered */
193 
194  /* REMEMBER: All threads are stopped, so we don't have to lock the
195  list here. */
196 
197  fe = list_first(final_list);
198 
199  while (fe) {
200  f_type = fe->type;
201  ref = fe->o;
202 
203  /* we do not care about objects which have been marked already */
204  if (!GC_IS_MARKED(ref)) {
205 
206  switch (f_type) {
207 
208  case FINAL_REACHABLE: /* object was reachable before */
209  GC_LOG2( printf("Finalizer triggered for: ");
210  heap_print_object(ref); printf("\n"); );
211 
212  /* object is now reclaimable */
213  fe->type = FINAL_RECLAIMABLE;
214 
215  /* notify the finalizer after collection finished */
216  gc_notify_finalizer = true;
217 
218  /* keep the object alive until finalizer finishes */
219  MARK(ref);
220  break;
221 
222  case FINAL_RECLAIMABLE: /* object not yet finalized */
223  GC_LOG( printf("Finalizer not yet started for: ");
224  heap_print_object(ref); printf("\n"); );
225 
226  /* keep the object alive until finalizer finishes */
227  MARK(ref);
228  break;
229 
230 #if 0
231  case FINAL_FINALIZING: /* object is still being finalized */
232  GC_LOG( printf("Finalizer not yet finished for: ");
233  heap_print_object(ref); printf("\n"); );
234 
235  /* keep the object alive until finalizer finishes */
236  MARK(ref);
237  break;
238 #endif
239 
240  default: /* case not yet covered */
241  vm_abort("mark_post: uncovered case (type=%d)", f_type);
242 
243  }
244  }
245 
246  fe = list_next(final_list, fe);
247  }
248 #endif /*defined(GCCONF_FINALIZER)*/
249 
250  /* Clear all references in the rootset which have not yet been
251  marked. This applies to registered weak references. */
252 
253  while (rs) {
254  GC_LOG( dolog("GC: Clearing in rootset (%d entries) ...", rs->refcount); );
255 
256  /* mark all references of the rootset */
257  for (i = 0; i < rs->refcount; i++) {
258 
259  /* load the reference */
260  ref = *( rs->refs[i].ref );
261 
262  /* check for outside or null pointers */
263  if (!POINTS_INTO(ref, start, end))
264  continue;
265 
266  /* is this a marking reference? */
267  if (rs->refs[i].marks) {
268  assert(GC_IS_MARKED(ref));
269  } else {
270 
271  /* clear unmarked references */
272  if (!GC_IS_MARKED(ref)) {
273  GC_LOG( printf("Clearing Weak Reference %p at %p\n", ref, rs->refs[i]); );
274 
275  *( rs->refs[i].ref ) = NULL;
276  }
277  }
278  }
279 
280  rs = rs->next;
281  }
282 
283 }
284 
285 
286 /* mark_me *********************************************************************
287 
288  Marks all Heap Objects which are reachable from a given root-set.
289 
290  REMEMBER: Assumes all threads are stopped!
291 
292  IN:
293  rs.....root set containing the references
294 
295 *******************************************************************************/
296 
298 {
299  rootset_t *rstop;
300  java_object_t *ref;
301  void *start, *end;
302  int i;
303 
304  /* TODO: this needs cleanup!!! */
305  start = heap_region_main->base;
306  end = heap_region_main->ptr;
307  rstop = rs;
308 
309  GCSTAT_INIT(gcstat_mark_count);
310  GCSTAT_INIT(gcstat_mark_depth);
311  GCSTAT_INIT(gcstat_mark_depth_max);
312 
313  while (rs) {
314  GC_LOG( dolog("GC: Marking from rootset (%d entries) ...", rs->refcount); );
315 
316  /* mark all references of the rootset */
317  for (i = 0; i < rs->refcount; i++) {
318 
319  /* is this a marking reference? */
320  if (!rs->refs[i].marks)
321  continue;
322 
323  /* load the reference */
324  ref = *( rs->refs[i].ref );
325 
326  /* check for outside or null pointers */
327  if (!POINTS_INTO(ref, start, end))
328  continue;
329 
330  /* do the marking here */
331  MARK(ref);
332 
333  }
334 
335  rs = rs->next;
336  }
337 
338  GC_LOG( dolog("GC: Marking postprocessing ..."); );
339 
340  /* perform some post processing of the marked heap */
341  mark_post(rstop);
342 
343  GC_LOG( dolog("GC: Marking finished."); );
344 
345 #if defined(ENABLE_STATISTICS)
346  GC_ASSERT(gcstat_mark_depth == 0);
347 #endif
348 }
349 
350 
351 /*
352  * These are local overrides for various environment variables in Emacs.
353  * Please do not remove this and leave it at the end of the file, where
354  * Emacs will automagically detect them.
355  * ---------------------------------------------------------------------
356  * Local variables:
357  * mode: c
358  * indent-tabs-mode: t
359  * c-basic-offset: 4
360  * tab-width: 4
361  * End:
362  * vim:noexpandtab:sw=4:ts=4:
363  */
#define dolog
Definition: logging.hpp:171
java_object_t * data[1]
Definition: global.hpp:342
#define GC_IS_MARKED(obj)
Definition: mark.h:42
void mark_post(rootset_t *rs)
Definition: mark.c:176
java_array_t header
Definition: global.hpp:341
rootset_t * next
Definition: rootset.h:60
rootset_entry_t refs[ROOTSET_INITIAL_CAPACITY]
Definition: rootset.h:64
#define GCSTAT_DEC(cnt)
Definition: gc.h:190
bool gc_notify_finalizer
Definition: gc.c:56
#define GCSTAT_COUNT_MAX(cnt, max)
Definition: gc.h:191
java_object_t * o
Definition: final.h:53
classinfo * super
Definition: class.hpp:102
void mark_recursive(java_object_t *o)
Definition: mark.c:60
#define GC_LOG(code)
Definition: gc.h:58
#define POINTS_INTO(ptr, ptr_start, ptr_end)
Definition: gc.h:105
#define GCSTAT_COUNT(cnt)
Definition: gc.h:189
#define GC_SET_MARKED(obj)
Definition: mark.h:43
u4 type
Definition: final.h:52
Definition: final.h:50
void vm_abort(const char *text,...)
Definition: vm.cpp:2586
int32_t fieldscount
Definition: class.hpp:109
fieldinfo * fields
Definition: class.hpp:110
regioninfo_t * heap_region_main
Definition: heap.c:53
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
int32_t offset
Definition: field.hpp:66
void field_print(fieldinfo *f)
Definition: field.cpp:479
u1 * ptr
Definition: region.h:50
#define FINAL_REACHABLE
Definition: final.h:45
s4 flags
Definition: field.hpp:59
MIIterator i
#define GC_TEST_FLAGS(obj, flags)
Definition: gc.h:103
void heap_print_object(java_object_t *o)
Definition: heap.c:400
#define MARK(o)
Definition: mark.c:43
arraydescriptor * arraydesc
Definition: vftbl.hpp:101
#define IS_ADR_TYPE(a)
Definition: global.hpp:138
uint32_t u4
Definition: types.hpp:46
list_t * final_list
Definition: final.c:38
s4 type
Definition: field.hpp:60
#define FINAL_RECLAIMABLE
Definition: final.h:46
#define GCSTAT_INIT(cnt)
Definition: gc.h:188
ArrayType arraytype
Definition: array.hpp:75
int8_t s1
Definition: types.hpp:39
#define FINAL_FINALIZING
Definition: final.h:47
s4 refcount
Definition: rootset.h:63
void mark_me(rootset_t *rs)
Definition: mark.c:297
vftbl_t * vftbl
Definition: global.hpp:264
#define printf(...)
Definition: ssa2.cpp:40
bool marks
Definition: rootset.h:52