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