2000-05-31 Alexandre Petit-Bianco <apbianco@cygnus.com>
[official-gcc.git] / libjava / boehm.cc
blob14c4263cd270656b300b7a4818315873fcb11c39
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
9 details. */
11 #include <config.h>
13 #include <stdio.h>
15 #include <jvm.h>
16 #include <gcj/cni.h>
18 #include <java/lang/Class.h>
19 #include <java/lang/reflect/Modifier.h>
20 #include <java-interp.h>
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
27 extern "C"
29 #include <gc_priv.h>
30 #include <gc_mark.h>
32 // These aren't declared in any Boehm GC header.
33 void GC_finalize_all (void);
34 ptr_t GC_debug_generic_malloc (size_t size, int k, GC_EXTRA_PARAMS);
37 // FIXME: this should probably be defined in some GC header.
38 #ifdef GC_DEBUG
39 # define GC_GENERIC_MALLOC(Size, Type) \
40 GC_debug_generic_malloc (Size, Type, GC_EXTRAS)
41 #else
42 # define GC_GENERIC_MALLOC(Size, Type) GC_generic_malloc (Size, Type)
43 #endif
45 // We must check for plausibility ourselves.
46 #define MAYBE_MARK(Obj, Top, Limit, Source, Exit) \
47 if ((ptr_t) (Obj) >= GC_least_plausible_heap_addr \
48 && (ptr_t) (Obj) <= GC_greatest_plausible_heap_addr) \
49 PUSH_CONTENTS (Obj, Top, Limit, Source, Exit)
51 #define ObjectClass _CL_Q34java4lang6Object
52 extern java::lang::Class ObjectClass;
53 #define ClassClass _CL_Q34java4lang5Class
54 extern java::lang::Class ClassClass;
58 // Nonzero if this module has been initialized.
59 static int initialized = 0;
61 // `kind' index used when allocating Java objects.
62 static int obj_kind_x;
64 // `kind' index used when allocating Java arrays.
65 static int array_kind_x;
67 // Freelist used for Java objects.
68 static ptr_t *obj_free_list;
70 // Freelist used for Java arrays.
71 static ptr_t *array_free_list;
73 // Lock used to protect access to Boehm's GC_enable/GC_disable functions.
74 static _Jv_Mutex_t disable_gc_mutex;
78 // This is called by the GC during the mark phase. It marks a Java
79 // object. We use `void *' arguments and return, and not what the
80 // Boehm GC wants, to avoid pollution in our headers.
81 void *
82 _Jv_MarkObj (void *addr, void *msp, void *msl, void * /*env*/)
84 mse *mark_stack_ptr = (mse *) msp;
85 mse *mark_stack_limit = (mse *) msl;
86 jobject obj = (jobject) addr;
88 _Jv_VTable *dt = *(_Jv_VTable **) addr;
89 // We check this in case a GC occurs before the vtbl is set. FIXME:
90 // should use allocation lock while initializing object.
91 if (__builtin_expect (! dt, false))
92 return mark_stack_ptr;
93 jclass klass = dt->clas;
95 // Every object has a sync_info pointer.
96 ptr_t p = (ptr_t) obj->sync_info;
97 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj, o1label);
98 // Mark the object's class.
99 p = (ptr_t) klass;
100 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj, o2label);
102 if (__builtin_expect (klass == &ClassClass, false))
104 jclass c = (jclass) addr;
106 p = (ptr_t) c->name;
107 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c3label);
108 p = (ptr_t) c->superclass;
109 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c4label);
110 for (int i = 0; i < c->constants.size; ++i)
112 /* FIXME: We could make this more precise by using the tags -KKT */
113 p = (ptr_t) c->constants.data[i].p;
114 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5label);
117 #ifdef INTERPRETER
118 if (_Jv_IsInterpretedClass (c))
120 p = (ptr_t) c->constants.tags;
121 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5alabel);
122 p = (ptr_t) c->constants.data;
123 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5blabel);
125 #endif
127 // If the class is an array, then the methods field holds a
128 // pointer to the element class. If the class is primitive,
129 // then the methods field holds a pointer to the array class.
130 p = (ptr_t) c->methods;
131 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c6label);
134 if (! c->isArray() && ! c->isPrimitive())
136 // Scan each method in the cases where `methods' really
137 // points to a methods structure.
138 for (int i = 0; i < c->method_count; ++i)
140 p = (ptr_t) c->methods[i].name;
141 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c,
142 cm1label);
143 p = (ptr_t) c->methods[i].signature;
144 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c,
145 cm2label);
147 // FIXME: `ncode' entry?
149 #ifdef INTERPRETER
150 // The interpreter installs a heap-allocated
151 // trampoline here, so we'll mark it.
152 if (_Jv_IsInterpretedClass (c))
154 p = (ptr_t) c->methods[i].ncode;
155 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c,
156 cm3label);
158 #endif
162 // Mark all the fields.
163 p = (ptr_t) c->fields;
164 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8label);
165 for (int i = 0; i < c->field_count; ++i)
167 _Jv_Field* field = &c->fields[i];
169 #ifndef COMPACT_FIELDS
170 p = (ptr_t) field->name;
171 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8alabel);
172 #endif
173 p = (ptr_t) field->type;
174 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8blabel);
176 // For the interpreter, we also need to mark the memory
177 // containing static members
178 if ((field->flags & java::lang::reflect::Modifier::STATIC))
180 p = (ptr_t) field->u.addr;
181 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8clabel);
183 // also, if the static member is a reference,
184 // mark also the value pointed to. We check for isResolved
185 // since marking can happen before memory is allocated for
186 // static members.
187 if (JvFieldIsRef (field) && field->isResolved())
189 jobject val = *(jobject*) field->u.addr;
190 p = (ptr_t) val;
191 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit,
192 c, c8elabel);
197 p = (ptr_t) c->vtable;
198 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c9label);
199 p = (ptr_t) c->interfaces;
200 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cAlabel);
201 for (int i = 0; i < c->interface_count; ++i)
203 p = (ptr_t) c->interfaces[i];
204 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cClabel);
206 p = (ptr_t) c->loader;
207 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cBlabel);
209 #ifdef INTERPRETER
210 if (_Jv_IsInterpretedClass (c))
212 _Jv_InterpClass* ic = (_Jv_InterpClass*)c;
214 p = (ptr_t) ic->interpreted_methods;
215 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic, cElabel);
217 for (int i = 0; i < c->method_count; i++)
219 p = (ptr_t) ic->interpreted_methods[i];
220 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic, \
221 cFlabel);
224 p = (ptr_t) ic->field_initializers;
225 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic, cGlabel);
228 #endif
231 else
233 // NOTE: each class only holds information about the class
234 // itself. So we must do the marking for the entire inheritance
235 // tree in order to mark all fields. FIXME: what about
236 // interfaces? We skip Object here, because Object only has a
237 // sync_info, and we handled that earlier.
238 // Note: occasionally `klass' can be null. For instance, this
239 // can happen if a GC occurs between the point where an object
240 // is allocated and where the vtbl slot is set.
241 while (klass && klass != &ObjectClass)
243 jfieldID field = JvGetFirstInstanceField (klass);
244 jint max = JvNumInstanceFields (klass);
246 for (int i = 0; i < max; ++i)
248 if (JvFieldIsRef (field))
250 jobject val = JvGetObjectField (obj, field);
251 p = (ptr_t) val;
252 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit,
253 obj, elabel);
255 field = field->getNextField ();
257 klass = klass->getSuperclass();
261 return mark_stack_ptr;
264 // This is called by the GC during the mark phase. It marks a Java
265 // array (of objects). We use `void *' arguments and return, and not
266 // what the Boehm GC wants, to avoid pollution in our headers.
267 void *
268 _Jv_MarkArray (void *addr, void *msp, void *msl, void * /*env*/)
270 mse *mark_stack_ptr = (mse *) msp;
271 mse *mark_stack_limit = (mse *) msl;
272 jobjectArray array = (jobjectArray) addr;
274 _Jv_VTable *dt = *(_Jv_VTable **) addr;
275 // We check this in case a GC occurs before the vtbl is set. FIXME:
276 // should use allocation lock while initializing object.
277 if (__builtin_expect (! dt, false))
278 return mark_stack_ptr;
279 jclass klass = dt->clas;
281 // Every object has a sync_info pointer.
282 ptr_t p = (ptr_t) array->sync_info;
283 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array, e1label);
284 // Mark the object's class.
285 p = (ptr_t) klass;
286 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj, o2label);
288 for (int i = 0; i < JvGetArrayLength (array); ++i)
290 jobject obj = elements (array)[i];
291 p = (ptr_t) obj;
292 MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array, e2label);
295 return mark_stack_ptr;
298 // Allocate space for a new Java object. FIXME: this might be the
299 // wrong interface; we might prefer to pass in the object type as
300 // well. It isn't important for this collector, but it might be for
301 // other collectors.
302 void *
303 _Jv_AllocObj (jsize size)
305 return GC_GENERIC_MALLOC (size, obj_kind_x);
308 // Allocate space for a new Java array. FIXME: again, this might be
309 // the wrong interface.
310 void *
311 _Jv_AllocArray (jsize size)
313 return GC_GENERIC_MALLOC (size, array_kind_x);
316 // Allocate some space that is known to be pointer-free.
317 void *
318 _Jv_AllocBytes (jsize size)
320 void *r = GC_GENERIC_MALLOC (size, PTRFREE);
321 // We have to explicitly zero memory here, as the GC doesn't
322 // guarantee that PTRFREE allocations are zeroed. Note that we
323 // don't have to do this for other allocation types because we set
324 // the `ok_init' flag in the type descriptor.
325 if (__builtin_expect (r != NULL, !NULL))
326 memset (r, 0, size);
327 return r;
330 static void
331 call_finalizer (GC_PTR obj, GC_PTR client_data)
333 _Jv_FinalizerFunc *fn = (_Jv_FinalizerFunc *) client_data;
334 jobject jobj = (jobject) obj;
336 (*fn) (jobj);
339 void
340 _Jv_RegisterFinalizer (void *object, _Jv_FinalizerFunc *meth)
342 GC_REGISTER_FINALIZER_NO_ORDER (object, call_finalizer, (GC_PTR) meth,
343 NULL, NULL);
346 void
347 _Jv_RunFinalizers (void)
349 GC_invoke_finalizers ();
352 void
353 _Jv_RunAllFinalizers (void)
355 GC_finalize_all ();
358 void
359 _Jv_RunGC (void)
361 GC_gcollect ();
364 long
365 _Jv_GCTotalMemory (void)
367 return GC_get_heap_size ();
370 long
371 _Jv_GCFreeMemory (void)
373 return GC_get_free_bytes ();
376 void
377 _Jv_GCSetInitialHeapSize (size_t size)
379 size_t current = GC_get_heap_size ();
380 if (size > current)
381 GC_expand_hp (size - current);
384 void
385 _Jv_GCSetMaximumHeapSize (size_t size)
387 GC_set_max_heap_size ((GC_word) size);
390 // From boehm's misc.c
391 extern "C" void GC_enable();
392 extern "C" void GC_disable();
394 void
395 _Jv_DisableGC (void)
397 _Jv_MutexLock (&disable_gc_mutex);
398 GC_disable();
399 _Jv_MutexUnlock (&disable_gc_mutex);
402 void
403 _Jv_EnableGC (void)
405 _Jv_MutexLock (&disable_gc_mutex);
406 GC_enable();
407 _Jv_MutexUnlock (&disable_gc_mutex);
410 void
411 _Jv_InitGC (void)
413 int proc;
414 DCL_LOCK_STATE;
416 DISABLE_SIGNALS ();
417 LOCK ();
419 if (initialized)
421 UNLOCK ();
422 ENABLE_SIGNALS ();
423 return;
425 initialized = 1;
427 GC_java_finalization = 1;
429 // Set up state for marking and allocation of Java objects.
430 obj_free_list = (ptr_t *) GC_generic_malloc_inner ((MAXOBJSZ + 1)
431 * sizeof (ptr_t),
432 PTRFREE);
433 memset (obj_free_list, 0, (MAXOBJSZ + 1) * sizeof (ptr_t));
435 proc = GC_n_mark_procs++;
436 GC_mark_procs[proc] = (mark_proc) _Jv_MarkObj;
438 obj_kind_x = GC_n_kinds++;
439 GC_obj_kinds[obj_kind_x].ok_freelist = obj_free_list;
440 GC_obj_kinds[obj_kind_x].ok_reclaim_list = 0;
441 GC_obj_kinds[obj_kind_x].ok_descriptor = MAKE_PROC (proc, 0);
442 GC_obj_kinds[obj_kind_x].ok_relocate_descr = FALSE;
443 GC_obj_kinds[obj_kind_x].ok_init = TRUE;
445 // Set up state for marking and allocation of arrays of Java
446 // objects.
447 array_free_list = (ptr_t *) GC_generic_malloc_inner ((MAXOBJSZ + 1)
448 * sizeof (ptr_t),
449 PTRFREE);
450 memset (array_free_list, 0, (MAXOBJSZ + 1) * sizeof (ptr_t));
452 proc = GC_n_mark_procs++;
453 GC_mark_procs[proc] = (mark_proc) _Jv_MarkArray;
455 array_kind_x = GC_n_kinds++;
456 GC_obj_kinds[array_kind_x].ok_freelist = array_free_list;
457 GC_obj_kinds[array_kind_x].ok_reclaim_list = 0;
458 GC_obj_kinds[array_kind_x].ok_descriptor = MAKE_PROC (proc, 0);
459 GC_obj_kinds[array_kind_x].ok_relocate_descr = FALSE;
460 GC_obj_kinds[array_kind_x].ok_init = TRUE;
462 _Jv_MutexInit (&disable_gc_mutex);
464 UNLOCK ();
465 ENABLE_SIGNALS ();