c42cd9fe218b7cad737bfdce3ea5b3019d2800cb
[cacao.git] / src / mm / cacao-gc / mark.c
1 /* mm/cacao-gc/mark.c - GC module for marking heap objects
2
3    Copyright (C) 1996-2005, 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    Contact: cacao@cacaojvm.org
26
27    Authors: Michael Starzinger
28
29    $Id$
30
31 */
32
33
34 #include "config.h"
35
36 #include "heap.h"
37 #include "toolbox/logging.h"
38 #include "vm/global.h"
39 #include "vm/linker.h"
40 #include "vm/options.h"
41
42
43 /* Debugging ******************************************************************/
44
45 int mark_depth;
46 int mark_depth_max;
47 #define MARK_DEPTH_INIT { mark_depth = 0; mark_depth_max = 0; }
48 #define MARK_DEPTH_INC { mark_depth++; if (mark_depth>mark_depth_max) mark_depth_max=mark_depth; }
49 #define MARK_DEPTH_DEC { mark_depth--; GC_ASSERT(mark_depth >= 0); }
50 void mark_println_stats()
51 {
52         printf("Maximal marking depth: %d\n", mark_depth_max);
53 }
54
55
56 /* mark_recursice **************************************************************
57
58    Recursively mark all objects (including this) which are referenced.
59
60    IN:
61           o.....heap-object to be marked (either OBJECT or ARRAY)
62
63 *******************************************************************************/
64
65 void mark_recursive(java_objectheader *o)
66 {
67         vftbl_t           *t;
68         classinfo         *c;
69         fieldinfo         *f;
70         java_objectarray  *oa;
71         arraydescriptor   *desc;
72         java_objectheader *ref;
73         int i;
74
75         /* uncollectable objects should never get marked this way */
76         GC_ASSERT(o);
77         GC_ASSERT(!GC_TEST_FLAGS(o, GC_FLAG_UNCOLLECTABLE));
78
79         /* mark this object */
80         GC_SET_MARKED(o);
81
82         /* get the class of this object */
83         /* TODO: maybe we do not need this yet, look to move down! */
84         t = o->vftbl;
85         GC_ASSERT(t);
86         c = t->class;
87         GC_ASSERT(c);
88
89         /* TODO: should we mark the class of the object as well? */
90         /*GC_ASSERT(GC_IS_MARKED((java_objectheader *) c));*/
91
92         /* does this object has pointers? */
93         /* TODO: check how often this happens, maybe remove this check! */
94         /*if (!GC_IS_REFERENCING(o))
95                 return;*/
96
97         /* check if we are marking an array */
98         if ((desc = t->arraydesc) != NULL) {
99                 /* this is an ARRAY */
100
101                 /* check if the array contains references */
102                 if (desc->arraytype != ARRAYTYPE_OBJECT)
103                         return;
104
105                 /* for object-arrays we need to check every entry */
106                 oa = (java_objectarray *) o;
107                 for (i = 0; i < oa->header.size; i++) {
108
109                         /* load the reference value */
110                         ref = (java_objectheader *) (oa->data[i]);
111
112                         /* check for outside or null pointers */
113                         if (!POINTS_INTO(ref, heap_base, heap_ptr))
114                                 continue;
115
116                         GC_LOG( printf("Found (%p) from Array\n", (void *) ref); );
117
118                         /* do the recursive marking */
119                         if (!GC_IS_MARKED(ref)) {
120                                 MARK_DEPTH_INC;
121                                 mark_recursive(ref);
122                                 MARK_DEPTH_DEC;
123                         }
124
125                 }
126
127         } else {
128                 /* this is an OBJECT */
129
130                 /* for objects we need to check all (non-static) fields */
131                 for (i = 0; i < c->fieldscount; i++) {
132                         f = &(c->fields[i]);
133
134                         /* check if this field contains a non-static reference */
135                         if (!IS_ADR_TYPE(f->type) || (f->flags & ACC_STATIC))
136                                 continue;
137
138                         /* load the reference value */
139                         ref = *( (java_objectheader **) ((s1 *) o + f->offset) );
140
141                         /* check for outside or null pointers */
142                         if (!POINTS_INTO(ref, heap_base, heap_ptr))
143                                 continue;
144
145                         GC_LOG( printf("Found (%p) from Field ", (void *) ref);
146                                         field_print(f); printf("\n"); );
147
148                         /* do the recursive marking */
149                         if (!GC_IS_MARKED(ref)) {
150                                 MARK_DEPTH_INC;
151                                 mark_recursive(ref);
152                                 MARK_DEPTH_DEC;
153                         }
154
155                 }
156
157         }
158
159 }
160
161
162 /* mark ************************************************************************
163
164    Marks all Heap Objects which are reachable from a given root-set.
165
166 *******************************************************************************/
167
168 /* rootset is passed as array of pointers, which point to the location of
169    the reference */
170 /* TODO: this definitely has to change!!! */
171 typedef java_objectheader** rootset_t;
172
173 void mark(rootset_t *rootset, int rootset_size)
174 {
175         java_objectheader *ref;
176         int i;
177
178         /* recursively mark all references of the rootset */
179         MARK_DEPTH_INIT;
180         MARK_DEPTH_INC;
181         for (i = 0; i < rootset_size; i++) {
182
183                 ref = *( rootset[i] );
184                 mark_recursive(ref);
185
186         }
187         MARK_DEPTH_DEC;
188         GC_ASSERT(mark_depth == 0);
189         GC_ASSERT(mark_depth_max > 0);
190
191         GC_LOG( mark_println_stats(); );
192 }
193
194
195 /*
196  * These are local overrides for various environment variables in Emacs.
197  * Please do not remove this and leave it at the end of the file, where
198  * Emacs will automagically detect them.
199  * ---------------------------------------------------------------------
200  * Local variables:
201  * mode: c
202  * indent-tabs-mode: t
203  * c-basic-offset: 4
204  * tab-width: 4
205  * End:
206  * vim:noexpandtab:sw=4:ts=4:
207  */