f73bf868017c8ffe8706c4b8478b6036695937e2
[gcc.git] / libjava / boehm.cc
1 // boehm.cc - interface between libjava and Boehm GC.
2
3 /* Copyright (C) 1998, 1999 Cygnus Solutions
4
5 This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
10
11 #include <config.h>
12
13 #include <stdio.h>
14
15 #include <cni.h>
16 #include <java/lang/Class.h>
17 #include <jvm.h>
18 #include <java-field.h>
19 #include <java-interp.h>
20
21 // We need to include gc_priv.h. However, it tries to include
22 // config.h if it hasn't already been included. So we force the
23 // inclusion of the Boehm config.h.
24 extern "C"
25 {
26 #include <boehm-config.h>
27 #include <gc_priv.h>
28 #include <gc_mark.h>
29
30 // These aren't declared in any Boehm GC header.
31 void GC_finalize_all (void);
32 ptr_t GC_debug_generic_malloc (size_t size, int k, GC_EXTRA_PARAMS);
33 };
34
35 // FIXME: this should probably be defined in some GC header.
36 #ifdef GC_DEBUG
37 # define GC_GENERIC_MALLOC(Size, Type) \
38 GC_debug_generic_malloc (Size, Type, GC_EXTRAS)
39 #else
40 # define GC_GENERIC_MALLOC(Size, Type) GC_generic_malloc (Size, Type)
41 #endif
42
43 // We must check for plausibility ourselves.
44 #define MAYBE_MARK(Obj, Top, Limit, Source, Exit) \
45 if ((ptr_t) (Obj) >= GC_least_plausible_heap_addr \
46 && (ptr_t) (Obj) <= GC_greatest_plausible_heap_addr) \
47 PUSH_CONTENTS (Obj, Top, Limit, Source, Exit)
48
49 #define ObjectClass _CL_Q34java4lang6Object
50 extern java::lang::Class ObjectClass;
51 #define ClassClass _CL_Q34java4lang5Class
52 extern java::lang::Class ClassClass;
53
54 \f
55
56 // Nonzero if this module has been initialized.
57 static int initialized = 0;
58
59 // `kind' index used when allocating Java objects.
60 static int obj_kind_x;
61
62 // `kind' index used when allocating Java arrays.
63 static int array_kind_x;
64
65 // Freelist used for Java objects.
66 static ptr_t *obj_free_list;
67
68 // Freelist used for Java arrays.
69 static ptr_t *array_free_list;
70
71 \f
72
73 // This is called by the GC during the mark phase. It marks a Java
74 // object. We use `void *' arguments and return, and not what the
75 // Boehm GC wants, to avoid pollution in our headers.
76 void *
77 _Jv_MarkObj (void *addr, void *msp, void *msl, void * /*env*/)
78 {
79 mse *mark_stack_ptr = (mse *) msp;
80 mse *mark_stack_limit = (mse *) msl;
81 jobject obj = (jobject) addr;
82
83 _Jv_VTable *dt = *(_Jv_VTable **) addr;
84 // We check this in case a GC occurs before the vtbl is set. FIXME:
85 // should use allocation lock while initializing object.
86 if (! dt)
87 return mark_stack_ptr;
88 jclass klass = dt->clas;
89
90 // Every object has a sync_info pointer.
91 word w = (word) obj->sync_info;
92 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, obj, o1label);
93 // Mark the object's class.
94 w = (word) klass;
95 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, obj, o2label);
96
97 if (klass == &ClassClass)
98 {
99 jclass c = (jclass) addr;
100
101 #if 0
102 // The next field should probably not be marked, since this is
103 // only used in the class hash table. Marking this field
104 // basically prohibits class unloading. --Kresten
105 w = (word) c->next;
106 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c2label);
107 #endif
108
109 w = (word) c->name;
110 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c3label);
111 w = (word) c->superclass;
112 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c4label);
113 for (int i = 0; i < c->constants.size; ++i)
114 {
115 /* FIXME: We could make this more precise by using the tags -KKT */
116 w = (word) c->constants.data[i].p;
117 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c5label);
118 }
119
120 #ifdef INTERPRETER
121 if (_Jv_IsInterpretedClass (c))
122 {
123 w = (word) c->constants.tags;
124 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c5alabel);
125 w = (word) c->constants.data;
126 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c5blabel);
127 }
128 #endif
129
130 // If the class is an array, then the methods field holds a
131 // pointer to the element class. If the class is primitive,
132 // then the methods field holds a pointer to the array class.
133 w = (word) c->methods;
134 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c6label);
135
136
137 if (! c->isArray() && ! c->isPrimitive())
138 {
139 // Scan each method in the cases where `methods' really
140 // points to a methods structure.
141 for (int i = 0; i < c->method_count; ++i)
142 {
143 w = (word) c->methods[i].name;
144 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c,
145 cm1label);
146 w = (word) c->methods[i].signature;
147 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c,
148 cm2label);
149
150 // FIXME: `ncode' entry?
151
152 #ifdef INTERPRETER
153 // The interpreter installs a heap-allocated
154 // trampoline here, so we'll mark it.
155 if (_Jv_IsInterpretedClass (c))
156 {
157 w = (word) c->methods[i].ncode;
158 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c,
159 cm3label);
160 }
161 #endif
162 }
163 }
164
165 // Mark all the fields.
166 w = (word) c->fields;
167 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8label);
168 for (int i = 0; i < c->field_count; ++i)
169 {
170 _Jv_Field* field = &c->fields[i];
171
172 #ifndef COMPACT_FIELDS
173 w = (word) field->name;
174 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8alabel);
175 #endif
176 w = (word) field->type;
177 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8blabel);
178
179 // For the interpreter, we also need to mark the memory
180 // containing static members
181 if (field->flags & 0x0008)
182 {
183 w = (word) field->u.addr;
184 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8clabel);
185
186 // also, if the static member is a reference,
187 // mark also the value pointed to. We check for isResolved
188 // since marking can happen before memory is allocated for
189 // static members.
190 if (JvFieldIsRef (field) && field->isResolved())
191 {
192 jobject val = *(jobject*) field->u.addr;
193 w = (word) val;
194 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit,
195 c, c8elabel);
196 }
197 }
198 }
199
200 w = (word) c->vtable;
201 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c9label);
202 w = (word) c->interfaces;
203 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, cAlabel);
204 for (int i = 0; i < c->interface_count; ++i)
205 {
206 w = (word) c->interfaces[i];
207 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, cClabel);
208 }
209 w = (word) c->loader;
210 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, cBlabel);
211
212 #ifdef INTERPRETER
213 if (_Jv_IsInterpretedClass (c))
214 {
215 _Jv_InterpClass* ic = (_Jv_InterpClass*)c;
216
217 w = (word) ic->interpreted_methods;
218 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, ic, cElabel);
219
220 for (int i = 0; i < c->method_count; i++)
221 {
222 w = (word) ic->interpreted_methods[i];
223 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, ic, \
224 cFlabel);
225 }
226
227 w = (word) ic->field_initializers;
228 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, ic, cGlabel);
229
230 }
231 #endif
232
233 }
234 else
235 {
236 // NOTE: each class only holds information about the class
237 // itself. So we must do the marking for the entire inheritance
238 // tree in order to mark all fields. FIXME: what about
239 // interfaces? We skip Object here, because Object only has a
240 // sync_info, and we handled that earlier.
241 // Note: occasionally `klass' can be null. For instance, this
242 // can happen if a GC occurs between the point where an object
243 // is allocated and where the vtbl slot is set.
244 while (klass && klass != &ObjectClass)
245 {
246 jfieldID field = JvGetFirstInstanceField (klass);
247 jint max = JvNumInstanceFields (klass);
248
249 for (int i = 0; i < max; ++i)
250 {
251 if (JvFieldIsRef (field))
252 {
253 jobject val = JvGetObjectField (obj, field);
254 w = (word) val;
255 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit,
256 obj, elabel);
257 }
258 field = field->getNextInstanceField ();
259 }
260 klass = klass->getSuperclass();
261 }
262 }
263
264 return mark_stack_ptr;
265 }
266
267 // This is called by the GC during the mark phase. It marks a Java
268 // array (of objects). We use `void *' arguments and return, and not
269 // what the Boehm GC wants, to avoid pollution in our headers.
270 void *
271 _Jv_MarkArray (void *addr, void *msp, void *msl, void * /*env*/)
272 {
273 mse *mark_stack_ptr = (mse *) msp;
274 mse *mark_stack_limit = (mse *) msl;
275 jobjectArray array = (jobjectArray) addr;
276
277 _Jv_VTable *dt = *(_Jv_VTable **) addr;
278 // We check this in case a GC occurs before the vtbl is set. FIXME:
279 // should use allocation lock while initializing object.
280 if (! dt)
281 return mark_stack_ptr;
282 jclass klass = dt->clas;
283
284 // Every object has a sync_info pointer.
285 word w = (word) array->sync_info;
286 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, array, e1label);
287 // Mark the object's class.
288 w = (word) klass;
289 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, obj, o2label);
290
291 for (int i = 0; i < JvGetArrayLength (array); ++i)
292 {
293 jobject obj = elements (array)[i];
294 w = (word) obj;
295 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, array, e2label);
296 }
297
298 return mark_stack_ptr;
299 }
300
301 // Allocate space for a new Java object. FIXME: this might be the
302 // wrong interface; we might prefer to pass in the object type as
303 // well. It isn't important for this collector, but it might be for
304 // other collectors.
305 void *
306 _Jv_AllocObj (jsize size)
307 {
308 return GC_GENERIC_MALLOC (size, obj_kind_x);
309 }
310
311 // Allocate space for a new Java array. FIXME: again, this might be
312 // the wrong interface.
313 void *
314 _Jv_AllocArray (jsize size)
315 {
316 return GC_GENERIC_MALLOC (size, array_kind_x);
317 }
318
319 // Allocate some space that is known to be pointer-free.
320 void *
321 _Jv_AllocBytes (jsize size)
322 {
323 return GC_GENERIC_MALLOC (size, PTRFREE);
324 }
325
326 static void
327 call_finalizer (GC_PTR obj, GC_PTR client_data)
328 {
329 _Jv_FinalizerFunc *fn = (_Jv_FinalizerFunc *) client_data;
330 jobject jobj = (jobject) obj;
331
332 (*fn) (jobj);
333 }
334
335 void
336 _Jv_RegisterFinalizer (void *object, _Jv_FinalizerFunc *meth)
337 {
338 GC_REGISTER_FINALIZER_NO_ORDER (object, call_finalizer, (GC_PTR) meth,
339 NULL, NULL);
340 }
341
342 void
343 _Jv_RunFinalizers (void)
344 {
345 GC_invoke_finalizers ();
346 }
347
348 void
349 _Jv_RunAllFinalizers (void)
350 {
351 GC_finalize_all ();
352 }
353
354 void
355 _Jv_RunGC (void)
356 {
357 GC_gcollect ();
358 }
359
360 long
361 _Jv_GCTotalMemory (void)
362 {
363 return GC_get_heap_size ();
364 }
365
366 /* Sum size of each hblk. */
367 static void
368 sum_blocks (struct hblk *h, word arg)
369 {
370 long *sump = (long *) arg;
371 /* This evil computation is from boehm-gc/checksums.c. */
372 hdr *hhdr = HDR (h);
373 int bytes = WORDS_TO_BYTES (hhdr->hb_sz);
374 bytes += HDR_BYTES + HBLKSIZE - 1;
375 bytes &= ~ (HBLKSIZE - 1);
376 *sump += bytes;
377 }
378
379 /* This turns out to be expensive to implement. For now, we don't
380 care. We could make it less expensive, perhaps, but that would
381 require some changes to the collector. */
382 long
383 _Jv_GCFreeMemory (void)
384 {
385 long sum = 0;
386 GC_apply_to_all_blocks (sum_blocks, &sum);
387 return sum;
388 }
389
390 void
391 _Jv_InitGC (void)
392 {
393 int proc;
394 DCL_LOCK_STATE;
395
396 DISABLE_SIGNALS ();
397 LOCK ();
398
399 if (initialized)
400 {
401 UNLOCK ();
402 ENABLE_SIGNALS ();
403 return;
404 }
405 initialized = 1;
406
407 // Set up state for marking and allocation of Java objects.
408 obj_free_list = (ptr_t *) GC_generic_malloc_inner ((MAXOBJSZ + 1)
409 * sizeof (ptr_t),
410 PTRFREE);
411 memset (obj_free_list, 0, (MAXOBJSZ + 1) * sizeof (ptr_t));
412
413 proc = GC_n_mark_procs++;
414 GC_mark_procs[proc] = (mark_proc) _Jv_MarkObj;
415
416 obj_kind_x = GC_n_kinds++;
417 GC_obj_kinds[obj_kind_x].ok_freelist = obj_free_list;
418 GC_obj_kinds[obj_kind_x].ok_reclaim_list = 0;
419 GC_obj_kinds[obj_kind_x].ok_descriptor = MAKE_PROC (proc, 0);
420 GC_obj_kinds[obj_kind_x].ok_relocate_descr = FALSE;
421 GC_obj_kinds[obj_kind_x].ok_init = TRUE;
422
423 // Set up state for marking and allocation of arrays of Java
424 // objects.
425 array_free_list = (ptr_t *) GC_generic_malloc_inner ((MAXOBJSZ + 1)
426 * sizeof (ptr_t),
427 PTRFREE);
428 memset (array_free_list, 0, (MAXOBJSZ + 1) * sizeof (ptr_t));
429
430 proc = GC_n_mark_procs++;
431 GC_mark_procs[proc] = (mark_proc) _Jv_MarkArray;
432
433 array_kind_x = GC_n_kinds++;
434 GC_obj_kinds[array_kind_x].ok_freelist = array_free_list;
435 GC_obj_kinds[array_kind_x].ok_reclaim_list = 0;
436 GC_obj_kinds[array_kind_x].ok_descriptor = MAKE_PROC (proc, 0);
437 GC_obj_kinds[array_kind_x].ok_relocate_descr = FALSE;
438 GC_obj_kinds[array_kind_x].ok_init = TRUE;
439
440 UNLOCK ();
441 ENABLE_SIGNALS ();
442 }