* Makefile.in (PREPROCESSOR_DEFINES): New macro.
[official-gcc.git] / libjava / boehm.cc
blob8d1e97442e9941ffead054bb437228ace7451b2f
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
9 details. */
11 #include <config.h>
13 #include <stdio.h>
15 #include <cni.h>
16 #include <java/lang/Class.h>
17 #include <jvm.h>
18 #include <java-field.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.
23 #undef TRUE
24 #undef FALSE
26 // We need to include gc_priv.h. However, it tries to include
27 // config.h if it hasn't already been included. So we force the
28 // inclusion of the Boehm config.h.
29 extern "C"
31 #include <boehm-config.h>
32 #include <gc_priv.h>
33 #include <gc_mark.h>
35 // These aren't declared in any Boehm GC header.
36 void GC_finalize_all (void);
37 ptr_t GC_debug_generic_malloc (size_t size, int k, GC_EXTRA_PARAMS);
40 // FIXME: this should probably be defined in some GC header.
41 #ifdef GC_DEBUG
42 # define GC_GENERIC_MALLOC(Size, Type) \
43 GC_debug_generic_malloc (Size, Type, GC_EXTRAS)
44 #else
45 # define GC_GENERIC_MALLOC(Size, Type) GC_generic_malloc (Size, Type)
46 #endif
48 // We must check for plausibility ourselves.
49 #define MAYBE_MARK(Obj, Top, Limit, Source, Exit) \
50 if ((ptr_t) (Obj) >= GC_least_plausible_heap_addr \
51 && (ptr_t) (Obj) <= GC_greatest_plausible_heap_addr) \
52 PUSH_CONTENTS (Obj, Top, Limit, Source, Exit)
54 #define ObjectClass _CL_Q34java4lang6Object
55 extern java::lang::Class ObjectClass;
56 #define ClassClass _CL_Q34java4lang5Class
57 extern java::lang::Class ClassClass;
61 // Nonzero if this module has been initialized.
62 static int initialized = 0;
64 // `kind' index used when allocating Java objects.
65 static int obj_kind_x;
67 // `kind' index used when allocating Java arrays.
68 static int array_kind_x;
70 // Freelist used for Java objects.
71 static ptr_t *obj_free_list;
73 // Freelist used for Java arrays.
74 static ptr_t *array_free_list;
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 (! dt)
92 return mark_stack_ptr;
93 jclass klass = dt->clas;
95 // Every object has a sync_info pointer.
96 word w = (word) obj->sync_info;
97 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, obj, o1label);
98 // Mark the object's class.
99 w = (word) klass;
100 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, obj, o2label);
102 if (klass == &ClassClass)
104 jclass c = (jclass) addr;
106 #if 0
107 // The next field should probably not be marked, since this is
108 // only used in the class hash table. Marking this field
109 // basically prohibits class unloading. --Kresten
110 w = (word) c->next;
111 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c2label);
112 #endif
114 w = (word) c->name;
115 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c3label);
116 w = (word) c->superclass;
117 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c4label);
118 for (int i = 0; i < c->constants.size; ++i)
120 /* FIXME: We could make this more precise by using the tags -KKT */
121 w = (word) c->constants.data[i].p;
122 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c5label);
125 #ifdef INTERPRETER
126 if (_Jv_IsInterpretedClass (c))
128 w = (word) c->constants.tags;
129 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c5alabel);
130 w = (word) c->constants.data;
131 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c5blabel);
133 #endif
135 // If the class is an array, then the methods field holds a
136 // pointer to the element class. If the class is primitive,
137 // then the methods field holds a pointer to the array class.
138 w = (word) c->methods;
139 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c6label);
142 if (! c->isArray() && ! c->isPrimitive())
144 // Scan each method in the cases where `methods' really
145 // points to a methods structure.
146 for (int i = 0; i < c->method_count; ++i)
148 w = (word) c->methods[i].name;
149 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c,
150 cm1label);
151 w = (word) c->methods[i].signature;
152 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c,
153 cm2label);
155 // FIXME: `ncode' entry?
157 #ifdef INTERPRETER
158 // The interpreter installs a heap-allocated
159 // trampoline here, so we'll mark it.
160 if (_Jv_IsInterpretedClass (c))
162 w = (word) c->methods[i].ncode;
163 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c,
164 cm3label);
166 #endif
170 // Mark all the fields.
171 w = (word) c->fields;
172 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8label);
173 for (int i = 0; i < c->field_count; ++i)
175 _Jv_Field* field = &c->fields[i];
177 #ifndef COMPACT_FIELDS
178 w = (word) field->name;
179 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8alabel);
180 #endif
181 w = (word) field->type;
182 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8blabel);
184 // For the interpreter, we also need to mark the memory
185 // containing static members
186 if (field->flags & 0x0008)
188 w = (word) field->u.addr;
189 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8clabel);
191 // also, if the static member is a reference,
192 // mark also the value pointed to. We check for isResolved
193 // since marking can happen before memory is allocated for
194 // static members.
195 if (JvFieldIsRef (field) && field->isResolved())
197 jobject val = *(jobject*) field->u.addr;
198 w = (word) val;
199 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit,
200 c, c8elabel);
205 w = (word) c->vtable;
206 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c9label);
207 w = (word) c->interfaces;
208 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, cAlabel);
209 for (int i = 0; i < c->interface_count; ++i)
211 w = (word) c->interfaces[i];
212 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, cClabel);
214 w = (word) c->loader;
215 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, cBlabel);
217 #ifdef INTERPRETER
218 if (_Jv_IsInterpretedClass (c))
220 _Jv_InterpClass* ic = (_Jv_InterpClass*)c;
222 w = (word) ic->interpreted_methods;
223 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, ic, cElabel);
225 for (int i = 0; i < c->method_count; i++)
227 w = (word) ic->interpreted_methods[i];
228 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, ic, \
229 cFlabel);
232 w = (word) ic->field_initializers;
233 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, ic, cGlabel);
236 #endif
239 else
241 // NOTE: each class only holds information about the class
242 // itself. So we must do the marking for the entire inheritance
243 // tree in order to mark all fields. FIXME: what about
244 // interfaces? We skip Object here, because Object only has a
245 // sync_info, and we handled that earlier.
246 // Note: occasionally `klass' can be null. For instance, this
247 // can happen if a GC occurs between the point where an object
248 // is allocated and where the vtbl slot is set.
249 while (klass && klass != &ObjectClass)
251 jfieldID field = JvGetFirstInstanceField (klass);
252 jint max = JvNumInstanceFields (klass);
254 for (int i = 0; i < max; ++i)
256 if (JvFieldIsRef (field))
258 jobject val = JvGetObjectField (obj, field);
259 w = (word) val;
260 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit,
261 obj, elabel);
263 field = field->getNextInstanceField ();
265 klass = klass->getSuperclass();
269 return mark_stack_ptr;
272 // This is called by the GC during the mark phase. It marks a Java
273 // array (of objects). We use `void *' arguments and return, and not
274 // what the Boehm GC wants, to avoid pollution in our headers.
275 void *
276 _Jv_MarkArray (void *addr, void *msp, void *msl, void * /*env*/)
278 mse *mark_stack_ptr = (mse *) msp;
279 mse *mark_stack_limit = (mse *) msl;
280 jobjectArray array = (jobjectArray) addr;
282 _Jv_VTable *dt = *(_Jv_VTable **) addr;
283 // We check this in case a GC occurs before the vtbl is set. FIXME:
284 // should use allocation lock while initializing object.
285 if (! dt)
286 return mark_stack_ptr;
287 jclass klass = dt->clas;
289 // Every object has a sync_info pointer.
290 word w = (word) array->sync_info;
291 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, array, e1label);
292 // Mark the object's class.
293 w = (word) klass;
294 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, obj, o2label);
296 for (int i = 0; i < JvGetArrayLength (array); ++i)
298 jobject obj = elements (array)[i];
299 w = (word) obj;
300 MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, array, e2label);
303 return mark_stack_ptr;
306 // Allocate space for a new Java object. FIXME: this might be the
307 // wrong interface; we might prefer to pass in the object type as
308 // well. It isn't important for this collector, but it might be for
309 // other collectors.
310 void *
311 _Jv_AllocObj (jsize size)
313 return GC_GENERIC_MALLOC (size, obj_kind_x);
316 // Allocate space for a new Java array. FIXME: again, this might be
317 // the wrong interface.
318 void *
319 _Jv_AllocArray (jsize size)
321 return GC_GENERIC_MALLOC (size, array_kind_x);
324 // Allocate some space that is known to be pointer-free.
325 void *
326 _Jv_AllocBytes (jsize size)
328 return GC_GENERIC_MALLOC (size, PTRFREE);
331 static void
332 call_finalizer (GC_PTR obj, GC_PTR client_data)
334 _Jv_FinalizerFunc *fn = (_Jv_FinalizerFunc *) client_data;
335 jobject jobj = (jobject) obj;
337 (*fn) (jobj);
340 void
341 _Jv_RegisterFinalizer (void *object, _Jv_FinalizerFunc *meth)
343 GC_REGISTER_FINALIZER_NO_ORDER (object, call_finalizer, (GC_PTR) meth,
344 NULL, NULL);
347 void
348 _Jv_RunFinalizers (void)
350 GC_invoke_finalizers ();
353 void
354 _Jv_RunAllFinalizers (void)
356 GC_finalize_all ();
359 void
360 _Jv_RunGC (void)
362 GC_gcollect ();
365 long
366 _Jv_GCTotalMemory (void)
368 return GC_get_heap_size ();
371 /* Sum size of each hblk. */
372 static void
373 sum_blocks (struct hblk *h, word arg)
375 long *sump = (long *) arg;
376 /* This evil computation is from boehm-gc/checksums.c. */
377 hdr *hhdr = HDR (h);
378 int bytes = WORDS_TO_BYTES (hhdr->hb_sz);
379 bytes += HDR_BYTES + HBLKSIZE - 1;
380 bytes &= ~ (HBLKSIZE - 1);
381 *sump += bytes;
384 /* This turns out to be expensive to implement. For now, we don't
385 care. We could make it less expensive, perhaps, but that would
386 require some changes to the collector. */
387 long
388 _Jv_GCFreeMemory (void)
390 long sum = 0;
391 GC_apply_to_all_blocks (sum_blocks, &sum);
392 return sum;
395 void
396 _Jv_InitGC (void)
398 int proc;
399 DCL_LOCK_STATE;
401 DISABLE_SIGNALS ();
402 LOCK ();
404 if (initialized)
406 UNLOCK ();
407 ENABLE_SIGNALS ();
408 return;
410 initialized = 1;
412 // Set up state for marking and allocation of Java objects.
413 obj_free_list = (ptr_t *) GC_generic_malloc_inner ((MAXOBJSZ + 1)
414 * sizeof (ptr_t),
415 PTRFREE);
416 memset (obj_free_list, 0, (MAXOBJSZ + 1) * sizeof (ptr_t));
418 proc = GC_n_mark_procs++;
419 GC_mark_procs[proc] = (mark_proc) _Jv_MarkObj;
421 obj_kind_x = GC_n_kinds++;
422 GC_obj_kinds[obj_kind_x].ok_freelist = obj_free_list;
423 GC_obj_kinds[obj_kind_x].ok_reclaim_list = 0;
424 GC_obj_kinds[obj_kind_x].ok_descriptor = MAKE_PROC (proc, 0);
425 GC_obj_kinds[obj_kind_x].ok_relocate_descr = FALSE;
426 GC_obj_kinds[obj_kind_x].ok_init = TRUE;
428 // Set up state for marking and allocation of arrays of Java
429 // objects.
430 array_free_list = (ptr_t *) GC_generic_malloc_inner ((MAXOBJSZ + 1)
431 * sizeof (ptr_t),
432 PTRFREE);
433 memset (array_free_list, 0, (MAXOBJSZ + 1) * sizeof (ptr_t));
435 proc = GC_n_mark_procs++;
436 GC_mark_procs[proc] = (mark_proc) _Jv_MarkArray;
438 array_kind_x = GC_n_kinds++;
439 GC_obj_kinds[array_kind_x].ok_freelist = array_free_list;
440 GC_obj_kinds[array_kind_x].ok_reclaim_list = 0;
441 GC_obj_kinds[array_kind_x].ok_descriptor = MAKE_PROC (proc, 0);
442 GC_obj_kinds[array_kind_x].ok_relocate_descr = FALSE;
443 GC_obj_kinds[array_kind_x].ok_init = TRUE;
445 UNLOCK ();
446 ENABLE_SIGNALS ();