1 // boehm.cc - interface between libjava and Boehm GC.
3 /* Copyright (C) 1998, 1999 Cygnus Solutions
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
16 #include <java/lang/Class.h>
18 #include <java-field.h>
19 #include <java-interp.h>
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.
26 #include <boehm-config.h>
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);
35 // FIXME: this should probably be defined in some GC header.
37 # define GC_GENERIC_MALLOC(Size, Type) \
38 GC_debug_generic_malloc (Size, Type, GC_EXTRAS)
40 # define GC_GENERIC_MALLOC(Size, Type) GC_generic_malloc (Size, Type)
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)
49 #define ObjectClass _CL_Q34java4lang6Object
50 extern java::lang::Class ObjectClass;
51 #define ClassClass _CL_Q34java4lang5Class
52 extern java::lang::Class ClassClass;
56 // Nonzero if this module has been initialized.
57 static int initialized = 0;
59 // `kind' index used when allocating Java objects.
60 static int obj_kind_x;
62 // `kind' index used when allocating Java arrays.
63 static int array_kind_x;
65 // Freelist used for Java objects.
66 static ptr_t *obj_free_list;
68 // Freelist used for Java arrays.
69 static ptr_t *array_free_list;
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.
77 _Jv_MarkObj (void *addr, void *msp, void *msl, void * /*env*/)
79 mse *mark_stack_ptr = (mse *) msp;
80 mse *mark_stack_limit = (mse *) msl;
81 jobject obj = (jobject) addr;
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.
87 return mark_stack_ptr;
88 jclass klass = dt->clas;
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.
95 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, obj, o2label);
97 if (klass == &ClassClass)
99 jclass c = (jclass) addr;
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
106 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c2label);
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)
115 w = (word) c->constants.data[i];
116 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c5label);
120 if (_Jv_IsInterpretedClass (c))
122 w = (word) c->constants.tags;
123 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c5alabel);
124 w = (word) c->constants.data;
125 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c5blabel);
129 // If the class is an array, then the methods field holds a
130 // pointer to the element class. If the class is primitive,
131 // then the methods field holds a pointer to the array class.
132 w = (word) c->methods;
133 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c6label);
136 if (! c->isArray() && ! c->isPrimitive())
138 // Scan each method in the cases where `methods' really
139 // points to a methods structure.
140 for (int i = 0; i < c->method_count; ++i)
142 w = (word) c->methods[i].name;
143 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c,
145 w = (word) c->methods[i].signature;
146 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c,
149 // FIXME: `ncode' entry?
152 // The interpreter installs a heap-allocated
153 // trampoline here, so we'll mark it.
154 if (_Jv_IsInterpretedClass (c))
156 w = (word) c->methods[i].ncode;
157 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c,
164 // Mark all the fields.
165 w = (word) c->fields;
166 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8label);
167 for (int i = 0; i < c->field_count; ++i)
169 _Jv_Field* field = &c->fields[i];
171 #ifndef COMPACT_FIELDS
172 w = (word) field->name;
173 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8alabel);
175 w = (word) field->type;
176 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8blabel);
178 // For the interpreter, we also need to mark the memory
179 // containing static members
180 if (field->flags & 0x0008)
182 w = (word) field->u.addr;
183 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8clabel);
185 // also, if the static member is a reference,
186 // mark also the value pointed to. We check for isResolved
187 // since marking can happen before memory is allocated for
189 if (JvFieldIsRef (field) && field->isResolved())
191 jobject val = *(jobject*) field->u.addr;
193 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit,
199 w = (word) c->vtable;
200 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c9label);
201 w = (word) c->interfaces;
202 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, cAlabel);
203 for (int i = 0; i < c->interface_count; ++i)
205 w = (word) c->interfaces[i];
206 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, cClabel);
208 w = (word) c->loader;
209 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, cBlabel);
212 if (_Jv_IsInterpretedClass (c))
214 _Jv_InterpClass* ic = (_Jv_InterpClass*)c;
216 w = (word) ic->interpreted_methods;
217 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, ic, cElabel);
219 for (int i = 0; i < c->method_count; i++)
221 w = (word) ic->interpreted_methods[i];
222 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, ic, \
226 w = (word) ic->field_initializers;
227 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, ic, cGlabel);
235 // NOTE: each class only holds information about the class
236 // itself. So we must do the marking for the entire inheritance
237 // tree in order to mark all fields. FIXME: what about
238 // interfaces? We skip Object here, because Object only has a
239 // sync_info, and we handled that earlier.
240 // Note: occasionally `klass' can be null. For instance, this
241 // can happen if a GC occurs between the point where an object
242 // is allocated and where the vtbl slot is set.
243 while (klass && klass != &ObjectClass)
245 jfieldID field = JvGetFirstInstanceField (klass);
246 jint max = JvNumInstanceFields (klass);
248 for (int i = 0; i < max; ++i)
250 if (JvFieldIsRef (field))
252 jobject val = JvGetObjectField (obj, field);
254 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit,
257 field = field->getNextInstanceField ();
259 klass = klass->getSuperclass();
263 return mark_stack_ptr;
266 // This is called by the GC during the mark phase. It marks a Java
267 // array (of objects). We use `void *' arguments and return, and not
268 // what the Boehm GC wants, to avoid pollution in our headers.
270 _Jv_MarkArray (void *addr, void *msp, void *msl, void * /*env*/)
272 mse *mark_stack_ptr = (mse *) msp;
273 mse *mark_stack_limit = (mse *) msl;
274 jobjectArray array = (jobjectArray) addr;
276 _Jv_VTable *dt = *(_Jv_VTable **) addr;
277 // We check this in case a GC occurs before the vtbl is set. FIXME:
278 // should use allocation lock while initializing object.
280 return mark_stack_ptr;
281 jclass klass = dt->clas;
283 // Every object has a sync_info pointer.
284 word w = (word) array->sync_info;
285 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, array, e1label);
286 // Mark the object's class.
288 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, obj, o2label);
290 for (int i = 0; i < JvGetArrayLength (array); ++i)
292 jobject obj = elements (array)[i];
294 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, array, e2label);
297 return mark_stack_ptr;
300 // Allocate space for a new Java object. FIXME: this might be the
301 // wrong interface; we might prefer to pass in the object type as
302 // well. It isn't important for this collector, but it might be for
305 _Jv_AllocObj (jsize size)
307 return GC_GENERIC_MALLOC (size, obj_kind_x);
310 // Allocate space for a new Java array. FIXME: again, this might be
311 // the wrong interface.
313 _Jv_AllocArray (jsize size)
315 return GC_GENERIC_MALLOC (size, array_kind_x);
318 // Allocate some space that is known to be pointer-free.
320 _Jv_AllocBytes (jsize size)
322 return GC_GENERIC_MALLOC (size, PTRFREE);
326 call_finalizer (GC_PTR obj, GC_PTR client_data)
328 _Jv_FinalizerFunc *fn = (_Jv_FinalizerFunc *) client_data;
329 jobject jobj = (jobject) obj;
335 _Jv_RegisterFinalizer (void *object, _Jv_FinalizerFunc *meth)
337 GC_REGISTER_FINALIZER_NO_ORDER (object, call_finalizer, (GC_PTR) meth,
342 _Jv_RunFinalizers (void)
344 GC_invoke_finalizers ();
348 _Jv_RunAllFinalizers (void)
360 _Jv_GCTotalMemory (void)
362 return GC_get_heap_size ();
365 /* Sum size of each hblk. */
367 sum_blocks (struct hblk *h, word arg)
369 long *sump = (long *) arg;
370 /* This evil computation is from boehm-gc/checksums.c. */
372 int bytes = WORDS_TO_BYTES (hhdr->hb_sz);
373 bytes += HDR_BYTES + HBLKSIZE - 1;
374 bytes &= ~ (HBLKSIZE - 1);
378 /* This turns out to be expensive to implement. For now, we don't
379 care. We could make it less expensive, perhaps, but that would
380 require some changes to the collector. */
382 _Jv_GCFreeMemory (void)
385 GC_apply_to_all_blocks (sum_blocks, &sum);
406 // Set up state for marking and allocation of Java objects.
407 obj_free_list = (ptr_t *) GC_generic_malloc_inner ((MAXOBJSZ + 1)
410 memset (obj_free_list, 0, (MAXOBJSZ + 1) * sizeof (ptr_t));
412 proc = GC_n_mark_procs++;
413 GC_mark_procs[proc] = (mark_proc) _Jv_MarkObj;
415 obj_kind_x = GC_n_kinds++;
416 GC_obj_kinds[obj_kind_x].ok_freelist = obj_free_list;
417 GC_obj_kinds[obj_kind_x].ok_reclaim_list = 0;
418 GC_obj_kinds[obj_kind_x].ok_descriptor = MAKE_PROC (proc, 0);
419 GC_obj_kinds[obj_kind_x].ok_relocate_descr = FALSE;
420 GC_obj_kinds[obj_kind_x].ok_init = TRUE;
422 // Set up state for marking and allocation of arrays of Java
424 array_free_list = (ptr_t *) GC_generic_malloc_inner ((MAXOBJSZ + 1)
427 memset (array_free_list, 0, (MAXOBJSZ + 1) * sizeof (ptr_t));
429 proc = GC_n_mark_procs++;
430 GC_mark_procs[proc] = (mark_proc) _Jv_MarkArray;
432 array_kind_x = GC_n_kinds++;
433 GC_obj_kinds[array_kind_x].ok_freelist = array_free_list;
434 GC_obj_kinds[array_kind_x].ok_reclaim_list = 0;
435 GC_obj_kinds[array_kind_x].ok_descriptor = MAKE_PROC (proc, 0);
436 GC_obj_kinds[array_kind_x].ok_relocate_descr = FALSE;
437 GC_obj_kinds[array_kind_x].ok_init = TRUE;