1 /* mm/cacao-gc/mark.c - GC module for marking heap objects
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
35 #include "mm/memory.h"
36 #include "toolbox/logging.h"
37 #include "vm/global.h"
39 #include "vmcore/linker.h"
42 /* Helper Macros **************************************************************/
45 GCSTAT_COUNT_MAX(gcstat_mark_depth, gcstat_mark_depth_max); \
47 GCSTAT_DEC(gcstat_mark_depth);
50 /* mark_recursive **************************************************************
52 Recursively mark all objects (including this) which are referenced.
54 TODO, XXX: We need to implement a non-recursive version of this!!!
57 o.....heap-object to be marked (either OBJECT or ARRAY)
59 *******************************************************************************/
61 void mark_recursive(java_object_t *o)
66 java_objectarray_t *oa;
67 arraydescriptor *desc;
72 /* TODO: this needs cleanup!!! */
73 start = heap_region_main->base;
74 end = heap_region_main->ptr;
76 /* uncollectable objects should never get marked this way */
77 /* the reference should point into the heap */
79 GC_ASSERT(!GC_TEST_FLAGS(o, HDRFLAG_UNCOLLECTABLE));
80 GC_ASSERT(POINTS_INTO(o, start, end));
82 /* mark this object */
84 GCSTAT_COUNT(gcstat_mark_count);
86 /* get the class of this object */
87 /* TODO: maybe we do not need this yet, look to move down! */
93 #if defined(GCCONF_HDRFLAG_REFERENCING)
94 /* does this object has pointers? */
95 /* TODO: check how often this happens, maybe remove this check! */
96 if (!GC_TEST_FLAGS(o, HDRFLAG_REFERENCING))
100 /* check if we are marking an array */
101 if ((desc = t->arraydesc) != NULL) {
102 /* this is an ARRAY */
104 /* check if the array contains references */
105 if (desc->arraytype != ARRAYTYPE_OBJECT)
108 /* for object-arrays we need to check every entry */
109 oa = (java_objectarray_t *) o;
110 for (i = 0; i < oa->header.size; i++) {
112 /* load the reference value */
113 ref = (java_object_t *) (oa->data[i]);
115 /* check for outside or null pointers */
116 if (!POINTS_INTO(ref, start, end))
119 GC_LOG2( printf("Found (%p) from Array\n", (void *) ref); );
121 /* do the recursive marking */
122 if (!GC_IS_MARKED(ref)) {
123 GCSTAT_COUNT_MAX(gcstat_mark_depth, gcstat_mark_depth_max);
125 GCSTAT_DEC(gcstat_mark_depth);
131 /* this is an OBJECT */
133 /* for objects we need to check all (non-static) fields */
134 for (; c; c = c->super) {
135 for (i = 0; i < c->fieldscount; i++) {
138 /* check if this field contains a non-static reference */
139 if (!IS_ADR_TYPE(f->type) || (f->flags & ACC_STATIC))
142 /* load the reference value */
143 ref = *( (java_object_t **) ((s1 *) o + f->offset) );
145 /* check for outside or null pointers */
146 if (!POINTS_INTO(ref, start, end))
149 GC_LOG2( printf("Found (%p) from Field ", (void *) ref);
150 field_print(f); printf("\n"); );
152 /* do the recursive marking */
153 if (!GC_IS_MARKED(ref)) {
154 GCSTAT_COUNT_MAX(gcstat_mark_depth, gcstat_mark_depth_max);
156 GCSTAT_DEC(gcstat_mark_depth);
167 /* mark_post *******************************************************************
169 Perform some post-marking cleanup tasks.
172 - mark unmarked objects with Finalizers
173 - clear unmarked Weak References
175 *******************************************************************************/
177 void mark_post(rootset_t *rs)
180 #if defined(GCCONF_FINALIZER)
181 list_final_entry_t *fe;
187 /* TODO: this needs cleanup!!! */
188 start = heap_region_main->base;
189 end = heap_region_main->ptr;
191 #if defined(GCCONF_FINALIZER)
192 /* objects with finalizers will also be marked here. if they have not been
193 marked before the finalization is triggered */
194 /* REMEMBER: all threads are stopped, so we can use unsynced access here */
195 fe = list_first_unsynced(final_list);
200 /* we do not care about objects which have been marked already */
201 if (!GC_IS_MARKED(ref)) {
205 case FINAL_REACHABLE: /* object was reachable before */
206 GC_LOG2( printf("Finalizer triggered for: ");
207 heap_print_object(ref); printf("\n"); );
209 /* object is now reclaimable */
210 fe->type = FINAL_RECLAIMABLE;
212 /* notify the finalizer after collection finished */
213 gc_notify_finalizer = true;
215 /* keep the object alive until finalizer finishes */
219 case FINAL_RECLAIMABLE: /* object not yet finalized */
220 GC_LOG( printf("Finalizer not yet started for: ");
221 heap_print_object(ref); printf("\n"); );
223 /* keep the object alive until finalizer finishes */
228 case FINAL_FINALIZING: /* object is still being finalized */
229 GC_LOG( printf("Finalizer not yet finished for: ");
230 heap_print_object(ref); printf("\n"); );
232 /* keep the object alive until finalizer finishes */
237 default: /* case not yet covered */
238 vm_abort("mark_post: uncovered case (type=%d)", f_type);
243 fe = list_next_unsynced(final_list, fe);
245 #endif /*defined(GCCONF_FINALIZER)*/
247 /* Clear all references in the rootset which have not yet been
248 marked. This applies to registered weak references. */
251 GC_LOG( dolog("GC: Clearing in rootset (%d entries) ...", rs->refcount); );
253 /* mark all references of the rootset */
254 for (i = 0; i < rs->refcount; i++) {
256 /* load the reference */
257 ref = *( rs->refs[i].ref );
259 /* check for outside or null pointers */
260 if (!POINTS_INTO(ref, start, end))
263 /* is this a marking reference? */
264 if (rs->refs[i].marks) {
265 assert(GC_IS_MARKED(ref));
268 /* clear unmarked references */
269 if (!GC_IS_MARKED(ref)) {
270 GC_LOG( printf("Clearing Weak Reference %p at %p\n", ref, rs->refs[i]); );
272 *( rs->refs[i].ref ) = NULL;
283 /* mark_me *********************************************************************
285 Marks all Heap Objects which are reachable from a given root-set.
287 REMEMBER: Assumes all threads are stopped!
290 rs.....root set containing the references
292 *******************************************************************************/
294 void mark_me(rootset_t *rs)
301 /* TODO: this needs cleanup!!! */
302 start = heap_region_main->base;
303 end = heap_region_main->ptr;
306 GCSTAT_INIT(gcstat_mark_count);
307 GCSTAT_INIT(gcstat_mark_depth);
308 GCSTAT_INIT(gcstat_mark_depth_max);
311 GC_LOG( dolog("GC: Marking from rootset (%d entries) ...", rs->refcount); );
313 /* mark all references of the rootset */
314 for (i = 0; i < rs->refcount; i++) {
316 /* is this a marking reference? */
317 if (!rs->refs[i].marks)
320 /* load the reference */
321 ref = *( rs->refs[i].ref );
323 /* check for outside or null pointers */
324 if (!POINTS_INTO(ref, start, end))
327 /* do the marking here */
335 GC_LOG( dolog("GC: Marking postprocessing ..."); );
337 /* perform some post processing of the marked heap */
340 GC_LOG( dolog("GC: Marking finished."); );
342 #if defined(ENABLE_STATISTICS)
343 GC_ASSERT(gcstat_mark_depth == 0);
349 * These are local overrides for various environment variables in Emacs.
350 * Please do not remove this and leave it at the end of the file, where
351 * Emacs will automagically detect them.
352 * ---------------------------------------------------------------------
355 * indent-tabs-mode: t
359 * vim:noexpandtab:sw=4:ts=4: