1 /* src/mm/cacao-gc/mark.c - GC module for marking heap objects
3 Copyright (C) 2006, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
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.
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.
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
33 #include "mm/memory.h"
34 #include "toolbox/logging.h"
36 #include "vm/global.h"
37 #include "vm/linker.h"
41 /* Helper Macros **************************************************************/
44 GCSTAT_COUNT_MAX(gcstat_mark_depth, gcstat_mark_depth_max); \
46 GCSTAT_DEC(gcstat_mark_depth);
49 /* mark_recursive **************************************************************
51 Recursively mark all objects (including this) which are referenced.
53 TODO, XXX: We need to implement a non-recursive version of this!!!
56 o.....heap-object to be marked (either OBJECT or ARRAY)
58 *******************************************************************************/
60 void mark_recursive(java_object_t *o)
65 java_objectarray_t *oa;
66 arraydescriptor *desc;
71 /* TODO: this needs cleanup!!! */
72 start = heap_region_main->base;
73 end = heap_region_main->ptr;
75 /* uncollectable objects should never get marked this way */
76 /* the reference should point into the heap */
78 GC_ASSERT(!GC_TEST_FLAGS(o, HDRFLAG_UNCOLLECTABLE));
79 GC_ASSERT(POINTS_INTO(o, start, end));
81 /* mark this object */
83 GCSTAT_COUNT(gcstat_mark_count);
85 /* get the class of this object */
86 /* TODO: maybe we do not need this yet, look to move down! */
92 #if defined(GCCONF_HDRFLAG_REFERENCING)
93 /* does this object has pointers? */
94 /* TODO: check how often this happens, maybe remove this check! */
95 if (!GC_TEST_FLAGS(o, HDRFLAG_REFERENCING))
99 /* check if we are marking an array */
100 if ((desc = t->arraydesc) != NULL) {
101 /* this is an ARRAY */
103 /* check if the array contains references */
104 if (desc->arraytype != ARRAYTYPE_OBJECT)
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++) {
111 /* load the reference value */
112 ref = (java_object_t *) (oa->data[i]);
114 /* check for outside or null pointers */
115 if (!POINTS_INTO(ref, start, end))
118 GC_LOG2( printf("Found (%p) from Array\n", (void *) ref); );
120 /* do the recursive marking */
121 if (!GC_IS_MARKED(ref)) {
122 GCSTAT_COUNT_MAX(gcstat_mark_depth, gcstat_mark_depth_max);
124 GCSTAT_DEC(gcstat_mark_depth);
130 /* this is an OBJECT */
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++) {
137 /* check if this field contains a non-static reference */
138 if (!IS_ADR_TYPE(f->type) || (f->flags & ACC_STATIC))
141 /* load the reference value */
142 ref = *( (java_object_t **) ((s1 *) o + f->offset) );
144 /* check for outside or null pointers */
145 if (!POINTS_INTO(ref, start, end))
148 GC_LOG2( printf("Found (%p) from Field ", (void *) ref);
149 field_print(f); printf("\n"); );
151 /* do the recursive marking */
152 if (!GC_IS_MARKED(ref)) {
153 GCSTAT_COUNT_MAX(gcstat_mark_depth, gcstat_mark_depth_max);
155 GCSTAT_DEC(gcstat_mark_depth);
166 /* mark_post *******************************************************************
168 Perform some post-marking cleanup tasks.
171 - mark unmarked objects with Finalizers
172 - clear unmarked Weak References
174 *******************************************************************************/
176 void mark_post(rootset_t *rs)
179 #if defined(GCCONF_FINALIZER)
180 list_final_entry_t *fe;
186 /* TODO: this needs cleanup!!! */
187 start = heap_region_main->base;
188 end = heap_region_main->ptr;
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 */
194 /* REMEMBER: All threads are stopped, so we don't have to lock the
197 fe = list_first(final_list);
203 /* we do not care about objects which have been marked already */
204 if (!GC_IS_MARKED(ref)) {
208 case FINAL_REACHABLE: /* object was reachable before */
209 GC_LOG2( printf("Finalizer triggered for: ");
210 heap_print_object(ref); printf("\n"); );
212 /* object is now reclaimable */
213 fe->type = FINAL_RECLAIMABLE;
215 /* notify the finalizer after collection finished */
216 gc_notify_finalizer = true;
218 /* keep the object alive until finalizer finishes */
222 case FINAL_RECLAIMABLE: /* object not yet finalized */
223 GC_LOG( printf("Finalizer not yet started for: ");
224 heap_print_object(ref); printf("\n"); );
226 /* keep the object alive until finalizer finishes */
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"); );
235 /* keep the object alive until finalizer finishes */
240 default: /* case not yet covered */
241 vm_abort("mark_post: uncovered case (type=%d)", f_type);
246 fe = list_next(final_list, fe);
248 #endif /*defined(GCCONF_FINALIZER)*/
250 /* Clear all references in the rootset which have not yet been
251 marked. This applies to registered weak references. */
254 GC_LOG( dolog("GC: Clearing in rootset (%d entries) ...", rs->refcount); );
256 /* mark all references of the rootset */
257 for (i = 0; i < rs->refcount; i++) {
259 /* load the reference */
260 ref = *( rs->refs[i].ref );
262 /* check for outside or null pointers */
263 if (!POINTS_INTO(ref, start, end))
266 /* is this a marking reference? */
267 if (rs->refs[i].marks) {
268 assert(GC_IS_MARKED(ref));
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]); );
275 *( rs->refs[i].ref ) = NULL;
286 /* mark_me *********************************************************************
288 Marks all Heap Objects which are reachable from a given root-set.
290 REMEMBER: Assumes all threads are stopped!
293 rs.....root set containing the references
295 *******************************************************************************/
297 void mark_me(rootset_t *rs)
304 /* TODO: this needs cleanup!!! */
305 start = heap_region_main->base;
306 end = heap_region_main->ptr;
309 GCSTAT_INIT(gcstat_mark_count);
310 GCSTAT_INIT(gcstat_mark_depth);
311 GCSTAT_INIT(gcstat_mark_depth_max);
314 GC_LOG( dolog("GC: Marking from rootset (%d entries) ...", rs->refcount); );
316 /* mark all references of the rootset */
317 for (i = 0; i < rs->refcount; i++) {
319 /* is this a marking reference? */
320 if (!rs->refs[i].marks)
323 /* load the reference */
324 ref = *( rs->refs[i].ref );
326 /* check for outside or null pointers */
327 if (!POINTS_INTO(ref, start, end))
330 /* do the marking here */
338 GC_LOG( dolog("GC: Marking postprocessing ..."); );
340 /* perform some post processing of the marked heap */
343 GC_LOG( dolog("GC: Marking finished."); );
345 #if defined(ENABLE_STATISTICS)
346 GC_ASSERT(gcstat_mark_depth == 0);
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 * ---------------------------------------------------------------------
358 * indent-tabs-mode: t
362 * vim:noexpandtab:sw=4:ts=4: