OSDN Git Service

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