1 // boehm.cc - interface between libjava and Boehm GC.
3 /* Copyright (C) 1998, 1999, 2000 Free Software Foundation
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
18 #include <java/lang/Class.h>
19 #include <java-interp.h>
21 // More nastiness: the GC wants to define TRUE and FALSE. We don't
22 // need the Java definitions (themselves a hack), so we undefine them.
31 // These aren't declared in any Boehm GC header.
32 void GC_finalize_all (void);
33 ptr_t GC_debug_generic_malloc (size_t size, int k, GC_EXTRA_PARAMS);
36 // FIXME: this should probably be defined in some GC header.
38 # define GC_GENERIC_MALLOC(Size, Type) \
39 GC_debug_generic_malloc (Size, Type, GC_EXTRAS)
41 # define GC_GENERIC_MALLOC(Size, Type) GC_generic_malloc (Size, Type)
44 // We must check for plausibility ourselves.
45 #define MAYBE_MARK(Obj, Top, Limit, Source, Exit) \
46 if ((ptr_t) (Obj) >= GC_least_plausible_heap_addr \
47 && (ptr_t) (Obj) <= GC_greatest_plausible_heap_addr) \
48 PUSH_CONTENTS (Obj, Top, Limit, Source, Exit)
50 #define ObjectClass _CL_Q34java4lang6Object
51 extern java::lang::Class ObjectClass;
52 #define ClassClass _CL_Q34java4lang5Class
53 extern java::lang::Class ClassClass;
57 // Nonzero if this module has been initialized.
58 static int initialized = 0;
60 // `kind' index used when allocating Java objects.
61 static int obj_kind_x;
63 // `kind' index used when allocating Java arrays.
64 static int array_kind_x;
66 // Freelist used for Java objects.
67 static ptr_t *obj_free_list;
69 // Freelist used for Java arrays.
70 static ptr_t *array_free_list;
72 // Lock used to protect access to Boehm's GC_enable/GC_disable functions.
73 static _Jv_Mutex_t disable_gc_mutex;
77 // This is called by the GC during the mark phase. It marks a Java
78 // object. We use `void *' arguments and return, and not what the
79 // Boehm GC wants, to avoid pollution in our headers.
81 _Jv_MarkObj (void *addr, void *msp, void *msl, void * /*env*/)
83 mse *mark_stack_ptr = (mse *) msp;
84 mse *mark_stack_limit = (mse *) msl;
85 jobject obj = (jobject) addr;
87 _Jv_VTable *dt = *(_Jv_VTable **) addr;
88 // We check this in case a GC occurs before the vtbl is set. FIXME:
89 // should use allocation lock while initializing object.
90 if (__builtin_expect (! dt, 0))
91 return mark_stack_ptr;
92 jclass klass = dt->clas;
94 // Every object has a sync_info pointer.
95 ptr_t p = (ptr_t) obj->sync_info;
96 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj, o1label);
97 // Mark the object's class.
99 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj, o2label);
101 if (__builtin_expect (klass == &ClassClass, 0))
103 jclass c = (jclass) addr;
106 // The next field should probably not be marked, since this is
107 // only used in the class hash table. Marking this field
108 // basically prohibits class unloading. --Kresten
110 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c2label);
114 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c3label);
115 p = (ptr_t) c->superclass;
116 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c4label);
117 for (int i = 0; i < c->constants.size; ++i)
119 /* FIXME: We could make this more precise by using the tags -KKT */
120 p = (ptr_t) c->constants.data[i].p;
121 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5label);
125 if (_Jv_IsInterpretedClass (c))
127 p = (ptr_t) c->constants.tags;
128 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5alabel);
129 p = (ptr_t) c->constants.data;
130 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5blabel);
134 // If the class is an array, then the methods field holds a
135 // pointer to the element class. If the class is primitive,
136 // then the methods field holds a pointer to the array class.
137 p = (ptr_t) c->methods;
138 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c6label);
141 if (! c->isArray() && ! c->isPrimitive())
143 // Scan each method in the cases where `methods' really
144 // points to a methods structure.
145 for (int i = 0; i < c->method_count; ++i)
147 p = (ptr_t) c->methods[i].name;
148 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c,
150 p = (ptr_t) c->methods[i].signature;
151 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c,
154 // FIXME: `ncode' entry?
157 // The interpreter installs a heap-allocated
158 // trampoline here, so we'll mark it.
159 if (_Jv_IsInterpretedClass (c))
161 p = (ptr_t) c->methods[i].ncode;
162 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c,
169 // Mark all the fields.
170 p = (ptr_t) c->fields;
171 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8label);
172 for (int i = 0; i < c->field_count; ++i)
174 _Jv_Field* field = &c->fields[i];
176 #ifndef COMPACT_FIELDS
177 p = (ptr_t) field->name;
178 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8alabel);
180 p = (ptr_t) field->type;
181 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8blabel);
183 // For the interpreter, we also need to mark the memory
184 // containing static members
185 if (field->flags & 0x0008)
187 p = (ptr_t) field->u.addr;
188 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8clabel);
190 // also, if the static member is a reference,
191 // mark also the value pointed to. We check for isResolved
192 // since marking can happen before memory is allocated for
194 if (JvFieldIsRef (field) && field->isResolved())
196 jobject val = *(jobject*) field->u.addr;
198 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit,
204 p = (ptr_t) c->vtable;
205 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c9label);
206 p = (ptr_t) c->interfaces;
207 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cAlabel);
208 for (int i = 0; i < c->interface_count; ++i)
210 p = (ptr_t) c->interfaces[i];
211 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cClabel);
213 p = (ptr_t) c->loader;
214 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cBlabel);
217 if (_Jv_IsInterpretedClass (c))
219 _Jv_InterpClass* ic = (_Jv_InterpClass*)c;
221 p = (ptr_t) ic->interpreted_methods;
222 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic, cElabel);
224 for (int i = 0; i < c->method_count; i++)
226 p = (ptr_t) ic->interpreted_methods[i];
227 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic, \
231 p = (ptr_t) ic->field_initializers;
232 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic, cGlabel);
240 // NOTE: each class only holds information about the class
241 // itself. So we must do the marking for the entire inheritance
242 // tree in order to mark all fields. FIXME: what about
243 // interfaces? We skip Object here, because Object only has a
244 // sync_info, and we handled that earlier.
245 // Note: occasionally `klass' can be null. For instance, this
246 // can happen if a GC occurs between the point where an object
247 // is allocated and where the vtbl slot is set.
248 while (klass && klass != &ObjectClass)
250 jfieldID field = JvGetFirstInstanceField (klass);
251 jint max = JvNumInstanceFields (klass);
253 for (int i = 0; i < max; ++i)
255 if (JvFieldIsRef (field))
257 jobject val = JvGetObjectField (obj, field);
259 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit,
262 field = field->getNextField ();
264 klass = klass->getSuperclass();
268 return mark_stack_ptr;
271 // This is called by the GC during the mark phase. It marks a Java
272 // array (of objects). We use `void *' arguments and return, and not
273 // what the Boehm GC wants, to avoid pollution in our headers.
275 _Jv_MarkArray (void *addr, void *msp, void *msl, void * /*env*/)
277 mse *mark_stack_ptr = (mse *) msp;
278 mse *mark_stack_limit = (mse *) msl;
279 jobjectArray array = (jobjectArray) addr;
281 _Jv_VTable *dt = *(_Jv_VTable **) addr;
282 // We check this in case a GC occurs before the vtbl is set. FIXME:
283 // should use allocation lock while initializing object.
284 if (__builtin_expect (! dt, 0))
285 return mark_stack_ptr;
286 jclass klass = dt->clas;
288 // Every object has a sync_info pointer.
289 ptr_t p = (ptr_t) array->sync_info;
290 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array, e1label);
291 // Mark the object's class.
293 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj, o2label);
295 for (int i = 0; i < JvGetArrayLength (array); ++i)
297 jobject obj = elements (array)[i];
299 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array, e2label);
302 return mark_stack_ptr;
305 // Allocate space for a new Java object. FIXME: this might be the
306 // wrong interface; we might prefer to pass in the object type as
307 // well. It isn't important for this collector, but it might be for
310 _Jv_AllocObj (jsize size)
312 return GC_GENERIC_MALLOC (size, obj_kind_x);
315 // Allocate space for a new Java array. FIXME: again, this might be
316 // the wrong interface.
318 _Jv_AllocArray (jsize size)
320 return GC_GENERIC_MALLOC (size, array_kind_x);
323 // Allocate some space that is known to be pointer-free.
325 _Jv_AllocBytes (jsize size)
327 void *r = GC_GENERIC_MALLOC (size, PTRFREE);
328 // We have to explicitly zero memory here, as the GC doesn't
329 // guarantee that PTRFREE allocations are zeroed. Note that we
330 // don't have to do this for other allocation types because we set
331 // the `ok_init' flag in the type descriptor.
332 if (__builtin_expect (r != NULL, !NULL))
338 call_finalizer (GC_PTR obj, GC_PTR client_data)
340 _Jv_FinalizerFunc *fn = (_Jv_FinalizerFunc *) client_data;
341 jobject jobj = (jobject) obj;
347 _Jv_RegisterFinalizer (void *object, _Jv_FinalizerFunc *meth)
349 GC_REGISTER_FINALIZER_NO_ORDER (object, call_finalizer, (GC_PTR) meth,
354 _Jv_RunFinalizers (void)
356 GC_invoke_finalizers ();
360 _Jv_RunAllFinalizers (void)
372 _Jv_GCTotalMemory (void)
374 return GC_get_heap_size ();
378 _Jv_GCFreeMemory (void)
380 return GC_get_free_bytes ();
384 _Jv_GCSetInitialHeapSize (size_t size)
386 size_t current = GC_get_heap_size ();
388 GC_expand_hp (size - current);
392 _Jv_GCSetMaximumHeapSize (size_t size)
394 GC_set_max_heap_size ((GC_word) size);
397 // From boehm's misc.c
398 extern "C" void GC_enable();
399 extern "C" void GC_disable();
404 _Jv_MutexLock (&disable_gc_mutex);
406 _Jv_MutexUnlock (&disable_gc_mutex);
412 _Jv_MutexLock (&disable_gc_mutex);
414 _Jv_MutexUnlock (&disable_gc_mutex);
434 GC_java_finalization = 1;
436 // Set up state for marking and allocation of Java objects.
437 obj_free_list = (ptr_t *) GC_generic_malloc_inner ((MAXOBJSZ + 1)
440 memset (obj_free_list, 0, (MAXOBJSZ + 1) * sizeof (ptr_t));
442 proc = GC_n_mark_procs++;
443 GC_mark_procs[proc] = (mark_proc) _Jv_MarkObj;
445 obj_kind_x = GC_n_kinds++;
446 GC_obj_kinds[obj_kind_x].ok_freelist = obj_free_list;
447 GC_obj_kinds[obj_kind_x].ok_reclaim_list = 0;
448 GC_obj_kinds[obj_kind_x].ok_descriptor = MAKE_PROC (proc, 0);
449 GC_obj_kinds[obj_kind_x].ok_relocate_descr = FALSE;
450 GC_obj_kinds[obj_kind_x].ok_init = TRUE;
452 // Set up state for marking and allocation of arrays of Java
454 array_free_list = (ptr_t *) GC_generic_malloc_inner ((MAXOBJSZ + 1)
457 memset (array_free_list, 0, (MAXOBJSZ + 1) * sizeof (ptr_t));
459 proc = GC_n_mark_procs++;
460 GC_mark_procs[proc] = (mark_proc) _Jv_MarkArray;
462 array_kind_x = GC_n_kinds++;
463 GC_obj_kinds[array_kind_x].ok_freelist = array_free_list;
464 GC_obj_kinds[array_kind_x].ok_reclaim_list = 0;
465 GC_obj_kinds[array_kind_x].ok_descriptor = MAKE_PROC (proc, 0);
466 GC_obj_kinds[array_kind_x].ok_relocate_descr = FALSE;
467 GC_obj_kinds[array_kind_x].ok_init = TRUE;
469 _Jv_MutexInit (&disable_gc_mutex);