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