source: trunk/src/gcc/libjava/boehm.cc@ 1519

Last change on this file since 1519 was 1392, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 16.4 KB
Line 
1// boehm.cc - interface between libjava and Boehm GC.
2
3/* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation
4
5 This file is part of libgcj.
6
7This software is copyrighted work licensed under the terms of the
8Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9details. */
10
11#include <config.h>
12
13#include <stdio.h>
14
15#include <jvm.h>
16#include <gcj/cni.h>
17
18#include <java/lang/Class.h>
19#include <java/lang/reflect/Modifier.h>
20#include <java-interp.h>
21
22// More nastiness: the GC wants to define TRUE and FALSE. We don't
23// need the Java definitions (themselves a hack), so we undefine them.
24#undef TRUE
25#undef FALSE
26
27extern "C"
28{
29#include <private/gc_pmark.h>
30#include <gc_gcj.h>
31
32#ifdef THREAD_LOCAL_ALLOC
33# define GC_REDIRECT_TO_LOCAL
34# include <gc_local_alloc.h>
35#endif
36
37 // These aren't declared in any Boehm GC header.
38 void GC_finalize_all (void);
39 ptr_t GC_debug_generic_malloc (size_t size, int k, GC_EXTRA_PARAMS);
40};
41
42#define MAYBE_MARK(Obj, Top, Limit, Source, Exit) \
43 Top=GC_MARK_AND_PUSH((GC_PTR)Obj, Top, Limit, (GC_PTR *)Source)
44
45// `kind' index used when allocating Java arrays.
46static int array_kind_x;
47
48// Freelist used for Java arrays.
49static ptr_t *array_free_list;
50
51// Lock used to protect access to Boehm's GC_enable/GC_disable functions.
52static _Jv_Mutex_t disable_gc_mutex;
53
54
55
56
57// This is called by the GC during the mark phase. It marks a Java
58// object. We use `void *' arguments and return, and not what the
59// Boehm GC wants, to avoid pollution in our headers.
60void *
61_Jv_MarkObj (void *addr, void *msp, void *msl, void * /* env */)
62{
63 mse *mark_stack_ptr = (mse *) msp;
64 mse *mark_stack_limit = (mse *) msl;
65 jobject obj = (jobject) addr;
66
67 // FIXME: if env is 1, this object was allocated through the debug
68 // interface, and addr points to the beginning of the debug header.
69 // In that case, we should really add the size of the header to addr.
70
71 _Jv_VTable *dt = *(_Jv_VTable **) addr;
72 // The object might not yet have its vtable set, or it might
73 // really be an object on the freelist. In either case, the vtable slot
74 // will either be 0, or it will point to a cleared object.
75 // This assumes Java objects have size at least 3 words,
76 // including the header. But this should remain true, since this
77 // should only be used with debugging allocation or with large objects.
78 if (__builtin_expect (! dt || !(dt -> get_finalizer()), false))
79 return mark_stack_ptr;
80 jclass klass = dt->clas;
81 ptr_t p;
82
83# ifndef JV_HASH_SYNCHRONIZATION
84 // Every object has a sync_info pointer.
85 p = (ptr_t) obj->sync_info;
86 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj, o1label);
87# endif
88 // Mark the object's class.
89 p = (ptr_t) klass;
90 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj, o2label);
91
92 if (__builtin_expect (klass == &java::lang::Class::class$, false))
93 {
94 // Currently we allocate some of the memory referenced from class objects
95 // as pointerfree memory, and then mark it more intelligently here.
96 // We ensure that the ClassClass mark descriptor forces invocation of
97 // this procedure.
98 // Correctness of this is subtle, but it looks OK to me for now. For the incremental
99 // collector, we need to make sure that the class object is written whenever
100 // any of the subobjects are altered and may need rescanning. This may be tricky
101 // during construction, and this may not be the right way to do this with
102 // incremental collection.
103 // If we overflow the mark stack, we will rescan the class object, so we should
104 // be OK. The same applies if we redo the mark phase because win32 unmapped part
105 // of our root set. - HB
106 jclass c = (jclass) addr;
107
108 p = (ptr_t) c->name;
109 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c3label);
110 p = (ptr_t) c->superclass;
111 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c4label);
112 for (int i = 0; i < c->constants.size; ++i)
113 {
114 /* FIXME: We could make this more precise by using the tags -KKT */
115 p = (ptr_t) c->constants.data[i].p;
116 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5label);
117 }
118
119#ifdef INTERPRETER
120 if (_Jv_IsInterpretedClass (c))
121 {
122 p = (ptr_t) c->constants.tags;
123 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5alabel);
124 p = (ptr_t) c->constants.data;
125 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5blabel);
126 p = (ptr_t) c->vtable;
127 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5clabel);
128 }
129#endif
130
131 // If the class is an array, then the methods field holds a
132 // pointer to the element class. If the class is primitive,
133 // then the methods field holds a pointer to the array class.
134 p = (ptr_t) c->methods;
135 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c6label);
136
137 // The vtable might have been set, but the rest of the class
138 // could still be uninitialized. If this is the case, then
139 // c.isArray will SEGV. We check for this, and if it is the
140 // case we just return.
141 if (__builtin_expect (c->name == NULL, false))
142 return mark_stack_ptr;
143
144 if (! c->isArray() && ! c->isPrimitive())
145 {
146 // Scan each method in the cases where `methods' really
147 // points to a methods structure.
148 for (int i = 0; i < c->method_count; ++i)
149 {
150 p = (ptr_t) c->methods[i].name;
151 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c,
152 cm1label);
153 p = (ptr_t) c->methods[i].signature;
154 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c,
155 cm2label);
156 }
157 }
158
159 // Mark all the fields.
160 p = (ptr_t) c->fields;
161 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8label);
162 for (int i = 0; i < c->field_count; ++i)
163 {
164 _Jv_Field* field = &c->fields[i];
165
166#ifndef COMPACT_FIELDS
167 p = (ptr_t) field->name;
168 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8alabel);
169#endif
170 p = (ptr_t) field->type;
171 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8blabel);
172
173 // For the interpreter, we also need to mark the memory
174 // containing static members
175 if ((field->flags & java::lang::reflect::Modifier::STATIC))
176 {
177 p = (ptr_t) field->u.addr;
178 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8clabel);
179
180 // also, if the static member is a reference,
181 // mark also the value pointed to. We check for isResolved
182 // since marking can happen before memory is allocated for
183 // static members.
184 if (JvFieldIsRef (field) && field->isResolved())
185 {
186 jobject val = *(jobject*) field->u.addr;
187 p = (ptr_t) val;
188 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit,
189 c, c8elabel);
190 }
191 }
192 }
193
194 p = (ptr_t) c->vtable;
195 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c9label);
196 p = (ptr_t) c->interfaces;
197 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cAlabel);
198 for (int i = 0; i < c->interface_count; ++i)
199 {
200 p = (ptr_t) c->interfaces[i];
201 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cClabel);
202 }
203 p = (ptr_t) c->loader;
204 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cBlabel);
205 p = (ptr_t) c->arrayclass;
206 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cDlabel);
207 p = (ptr_t) c->protectionDomain;
208 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cPlabel);
209
210#ifdef INTERPRETER
211 if (_Jv_IsInterpretedClass (c))
212 {
213 _Jv_InterpClass* ic = (_Jv_InterpClass*) c;
214
215 p = (ptr_t) ic->interpreted_methods;
216 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic, cElabel);
217
218 for (int i = 0; i < c->method_count; i++)
219 {
220 p = (ptr_t) ic->interpreted_methods[i];
221 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic, \
222 cFlabel);
223
224 // Mark the direct-threaded code.
225 if ((c->methods[i].accflags
226 & java::lang::reflect::Modifier::NATIVE) == 0)
227 {
228 _Jv_InterpMethod *im
229 = (_Jv_InterpMethod *) ic->interpreted_methods[i];
230 if (im)
231 {
232 p = (ptr_t) im->prepared;
233 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic, \
234 cFlabel);
235 }
236 }
237
238 // The interpreter installs a heap-allocated trampoline
239 // here, so we'll mark it.
240 p = (ptr_t) c->methods[i].ncode;
241 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c,
242 cm3label);
243 }
244
245 p = (ptr_t) ic->field_initializers;
246 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic, cGlabel);
247
248 }
249#endif
250
251 }
252 else
253 {
254 // NOTE: each class only holds information about the class
255 // itself. So we must do the marking for the entire inheritance
256 // tree in order to mark all fields. FIXME: what about
257 // interfaces? We skip Object here, because Object only has a
258 // sync_info, and we handled that earlier.
259 // Note: occasionally `klass' can be null. For instance, this
260 // can happen if a GC occurs between the point where an object
261 // is allocated and where the vtbl slot is set.
262 while (klass && klass != &java::lang::Object::class$)
263 {
264 jfieldID field = JvGetFirstInstanceField (klass);
265 jint max = JvNumInstanceFields (klass);
266
267 for (int i = 0; i < max; ++i)
268 {
269 if (JvFieldIsRef (field))
270 {
271 jobject val = JvGetObjectField (obj, field);
272 p = (ptr_t) val;
273 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit,
274 obj, elabel);
275 }
276 field = field->getNextField ();
277 }
278 klass = klass->getSuperclass();
279 }
280 }
281
282 return mark_stack_ptr;
283}
284
285// This is called by the GC during the mark phase. It marks a Java
286// array (of objects). We use `void *' arguments and return, and not
287// what the Boehm GC wants, to avoid pollution in our headers.
288void *
289_Jv_MarkArray (void *addr, void *msp, void *msl, void * /*env*/)
290{
291 mse *mark_stack_ptr = (mse *) msp;
292 mse *mark_stack_limit = (mse *) msl;
293 jobjectArray array = (jobjectArray) addr;
294
295 _Jv_VTable *dt = *(_Jv_VTable **) addr;
296 // Assumes size >= 3 words. That's currently true since arrays have
297 // a vtable, sync pointer, and size. If the sync pointer goes away,
298 // we may need to round up the size.
299 if (__builtin_expect (! dt || !(dt -> get_finalizer()), false))
300 return mark_stack_ptr;
301 jclass klass = dt->clas;
302 ptr_t p;
303
304# ifndef JV_HASH_SYNCHRONIZATION
305 // Every object has a sync_info pointer.
306 p = (ptr_t) array->sync_info;
307 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array, e1label);
308# endif
309 // Mark the object's class.
310 p = (ptr_t) klass;
311 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, &(dt -> clas), o2label);
312
313 for (int i = 0; i < JvGetArrayLength (array); ++i)
314 {
315 jobject obj = elements (array)[i];
316 p = (ptr_t) obj;
317 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array, e2label);
318 }
319
320 return mark_stack_ptr;