OSDN Git Service

c41dab94387ca1df21052da53931eb291d49a5b9
[pf3gnuchains/gcc-fork.git] / libjava / boehm.cc
1 // boehm.cc - interface between libjava and Boehm GC.
2
3 /* Copyright (C) 1998, 1999  Cygnus Solutions
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 <cni.h>
16 #include <java/lang/Class.h>
17 #include <jvm.h>
18 #include <java-field.h>
19
20 // We need to include gc_priv.h.  However, it tries to include
21 // config.h if it hasn't already been included.  So we force the
22 // inclusion of the Boehm config.h.
23 extern "C"
24 {
25 #include <boehm-config.h>
26 #include <gc_priv.h>
27 #include <gc_mark.h>
28
29   // These aren't declared in any Boehm GC header.
30   void GC_finalize_all (void);
31   ptr_t GC_debug_generic_malloc (size_t size, int k, GC_EXTRA_PARAMS);
32 };
33
34 // FIXME: this should probably be defined in some GC header.
35 #ifdef GC_DEBUG
36 #  define GC_GENERIC_MALLOC(Size, Type) \
37     GC_debug_generic_malloc (Size, Type, GC_EXTRAS)
38 #else
39 #  define GC_GENERIC_MALLOC(Size, Type) GC_generic_malloc (Size, Type)
40 #endif
41
42 // We must check for plausibility ourselves.
43 #define MAYBE_MARK(Obj, Top, Limit, Source, Exit)  \
44       if ((ptr_t) (Obj) >= GC_least_plausible_heap_addr \
45           && (ptr_t) (Obj) <= GC_greatest_plausible_heap_addr) \
46         PUSH_CONTENTS (Obj, Top, Limit, Source, Exit)
47
48 #define ObjectClass _CL_Q34java4lang6Object
49 extern java::lang::Class ObjectClass;
50 #define ClassClass _CL_Q34java4lang5Class
51 extern java::lang::Class ClassClass;
52
53 \f
54
55 // Nonzero if this module has been initialized.
56 static int initialized = 0;
57
58 // `kind' index used when allocating Java objects.
59 static int obj_kind_x;
60
61 // `kind' index used when allocating Java arrays.
62 static int array_kind_x;
63
64 // Freelist used for Java objects.
65 static ptr_t *obj_free_list;
66
67 // Freelist used for Java arrays.
68 static ptr_t *array_free_list;
69
70 \f
71
72 // This is called by the GC during the mark phase.  It marks a Java
73 // object.  We use `void *' arguments and return, and not what the
74 // Boehm GC wants, to avoid pollution in our headers.
75 void *
76 _Jv_MarkObj (void *addr, void *msp, void *msl, void * /*env*/)
77 {
78   mse *mark_stack_ptr = (mse *) msp;
79   mse *mark_stack_limit = (mse *) msl;
80   jobject obj = (jobject) addr;
81
82   _Jv_VTable *dt = *(_Jv_VTable **) addr;
83   // We check this in case a GC occurs before the vtbl is set.  FIXME:
84   // should use allocation lock while initializing object.
85   if (! dt)
86     return mark_stack_ptr;
87   jclass klass = dt->clas;
88
89   // Every object has a sync_info pointer.
90   word w = (word) obj->sync_info;
91   MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, obj, o1label);
92   // Mark the object's class.
93   w = (word) klass;
94   MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, obj, o2label);
95
96   if (klass == &ClassClass)
97     {
98       jclass c = (jclass) addr;
99
100       w = (word) c->next;
101       MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c2label);
102       w = (word) c->name;
103       MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c3label);
104       w = (word) c->superclass;
105       MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c4label);
106       for (int i = 0; i < c->constants.size; ++i)
107         {
108           w = (word) c->constants.data[i];
109           MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c5label);
110         }
111
112       // If the class is an array, then the methods field holds a
113       // pointer to the element class.  If the class is primitive,
114       // then the methods field holds a pointer to the array class.
115       w = (word) c->methods;
116       MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c6label);
117
118       if (! c->isArray() && ! c->isPrimitive())
119         {
120           // Scan each method in the cases where `methods' really
121           // points to a methods structure.
122           for (int i = 0; i < c->method_count; ++i)
123             {
124               w = (word) c->methods[i].name;
125               MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c,
126                              cm1label);
127               w = (word) c->methods[i].signature;
128               MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c,
129                              cm2label);
130               // FIXME: `ncode' entry?
131             }
132         }
133
134       // Mark all the fields.
135       w = (word) c->fields;
136       MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8label);
137       for (int i = 0; i < c->field_count; ++i)
138         {
139 #ifndef COMPACT_FIELDS
140           w = (word) c->fields[i].name;
141           MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8alabel);
142 #endif
143           w = (word) c->fields[i].type;
144           MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c8blabel);
145         }
146
147       w = (word) c->vtable;
148       MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, c9label);
149       w = (word) c->interfaces;
150       MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, cAlabel);
151       for (int i = 0; i < c->interface_count; ++i)
152         {
153           w = (word) c->interfaces[i];
154           MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, cClabel);
155         }
156       w = (word) c->loader;
157       MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, c, cBlabel);
158     }
159   else
160     {
161       // NOTE: each class only holds information about the class
162       // itself.  So we must do the marking for the entire inheritance
163       // tree in order to mark all fields.  FIXME: what about
164       // interfaces?  We skip Object here, because Object only has a
165       // sync_info, and we handled that earlier.
166       // Note: occasionally `klass' can be null.  For instance, this
167       // can happen if a GC occurs between the point where an object
168       // is allocated and where the vtbl slot is set.
169       while (klass && klass != &ObjectClass)
170         {
171           jfieldID field = JvGetFirstInstanceField (klass);
172           jint max = JvNumInstanceFields (klass);
173
174           for (int i = 0; i < max; ++i)
175             {
176               if (JvFieldIsRef (field))
177                 {
178                   jobject val = JvGetObjectField (obj, field);
179                   w = (word) val;
180                   MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit,
181                               obj, elabel);
182                 }
183               field = field->getNextInstanceField ();
184             }
185           klass = klass->getSuperclass();
186         }
187     }
188
189   return mark_stack_ptr;
190 }
191
192 // This is called by the GC during the mark phase.  It marks a Java
193 // array (of objects).  We use `void *' arguments and return, and not
194 // what the Boehm GC wants, to avoid pollution in our headers.
195 void *
196 _Jv_MarkArray (void *addr, void *msp, void *msl, void * /*env*/)
197 {
198   mse *mark_stack_ptr = (mse *) msp;
199   mse *mark_stack_limit = (mse *) msl;
200   jobjectArray array = (jobjectArray) addr;
201
202   _Jv_VTable *dt = *(_Jv_VTable **) addr;
203   // We check this in case a GC occurs before the vtbl is set.  FIXME:
204   // should use allocation lock while initializing object.
205   if (! dt)
206     return mark_stack_ptr;
207   jclass klass = dt->clas;
208
209   // Every object has a sync_info pointer.
210   word w = (word) array->sync_info;
211   MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, array, e1label);
212   // Mark the object's class.
213   w = (word) klass;
214   MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, obj, o2label);
215
216   for (int i = 0; i < JvGetArrayLength (array); ++i)
217     {
218       jobject obj = elements (array)[i];
219       w = (word) obj;
220       MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit, array, e2label);
221     }
222
223   return mark_stack_ptr;
224 }
225
226 // Allocate space for a new Java object.  FIXME: this might be the
227 // wrong interface; we might prefer to pass in the object type as
228 // well.  It isn't important for this collector, but it might be for
229 // other collectors.
230 void *
231 _Jv_AllocObj (jsize size)
232 {
233   return GC_GENERIC_MALLOC (size, obj_kind_x);
234 }
235
236 // Allocate space for a new Java array.  FIXME: again, this might be
237 // the wrong interface.
238 void *
239 _Jv_AllocArray (jsize size)
240 {
241   return GC_GENERIC_MALLOC (size, array_kind_x);
242 }
243
244 // Allocate some space that is known to be pointer-free.
245 void *
246 _Jv_AllocBytes (jsize size)
247 {
248   return GC_GENERIC_MALLOC (size, PTRFREE);
249 }
250
251 static void
252 call_finalizer (GC_PTR obj, GC_PTR client_data)
253 {
254   _Jv_FinalizerFunc *fn = (_Jv_FinalizerFunc *) client_data;
255   jobject jobj = (jobject) obj;
256
257   (*fn) (jobj);
258 }
259
260 void
261 _Jv_RegisterFinalizer (void *object, _Jv_FinalizerFunc *meth)
262 {
263   GC_REGISTER_FINALIZER_NO_ORDER (object, call_finalizer, meth,
264                                   NULL, NULL);
265 }
266
267 void
268 _Jv_RunFinalizers (void)
269 {
270   GC_invoke_finalizers ();
271 }
272
273 void
274 _Jv_RunAllFinalizers (void)
275 {
276   GC_finalize_all ();
277 }
278
279 void
280 _Jv_RunGC (void)
281 {
282   GC_gcollect ();
283 }
284
285 long
286 _Jv_GCTotalMemory (void)
287 {
288   return GC_get_heap_size ();
289 }
290
291 /* Sum size of each hblk.  */
292 static void
293 sum_blocks (struct hblk *h, word arg)
294 {
295   long *sump = (long *) arg;
296   /* This evil computation is from boehm-gc/checksums.c.  */
297   hdr *hhdr = HDR (h);
298   int bytes = WORDS_TO_BYTES (hhdr->hb_sz);
299   bytes += HDR_BYTES + HBLKSIZE - 1;
300   bytes &= ~ (HBLKSIZE - 1);
301   *sump += bytes;
302 }
303
304 /* This turns out to be expensive to implement.  For now, we don't
305    care.  We could make it less expensive, perhaps, but that would
306    require some changes to the collector.  */
307 long
308 _Jv_GCFreeMemory (void)
309 {
310   long sum = 0;
311   GC_apply_to_all_blocks (sum_blocks, &sum);
312   return sum;
313 }
314
315 void
316 _Jv_InitGC (void)
317 {
318   int proc;
319   DCL_LOCK_STATE;
320
321   DISABLE_SIGNALS ();
322   LOCK ();
323
324   if (initialized)
325     {
326       UNLOCK ();
327       ENABLE_SIGNALS ();
328       return;
329     }
330   initialized = 1;
331
332   // Set up state for marking and allocation of Java objects.
333   obj_free_list = (ptr_t *) GC_generic_malloc_inner ((MAXOBJSZ + 1)
334                                                      * sizeof (ptr_t),
335                                                      PTRFREE);
336   memset (obj_free_list, 0, (MAXOBJSZ + 1) * sizeof (ptr_t));
337
338   proc = GC_n_mark_procs++;
339   GC_mark_procs[proc] = (mark_proc) _Jv_MarkObj;
340
341   obj_kind_x = GC_n_kinds++;
342   GC_obj_kinds[obj_kind_x].ok_freelist = obj_free_list;
343   GC_obj_kinds[obj_kind_x].ok_reclaim_list = 0;
344   GC_obj_kinds[obj_kind_x].ok_descriptor = MAKE_PROC (proc, 0);
345   GC_obj_kinds[obj_kind_x].ok_relocate_descr = FALSE;
346   GC_obj_kinds[obj_kind_x].ok_init = TRUE;
347
348   // Set up state for marking and allocation of arrays of Java
349   // objects.
350   array_free_list = (ptr_t *) GC_generic_malloc_inner ((MAXOBJSZ + 1)
351                                                        * sizeof (ptr_t),
352                                                        PTRFREE);
353   memset (array_free_list, 0, (MAXOBJSZ + 1) * sizeof (ptr_t));
354
355   proc = GC_n_mark_procs++;
356   GC_mark_procs[proc] = (mark_proc) _Jv_MarkArray;
357
358   array_kind_x = GC_n_kinds++;
359   GC_obj_kinds[array_kind_x].ok_freelist = array_free_list;
360   GC_obj_kinds[array_kind_x].ok_reclaim_list = 0;
361   GC_obj_kinds[array_kind_x].ok_descriptor = MAKE_PROC (proc, 0);
362   GC_obj_kinds[array_kind_x].ok_relocate_descr = FALSE;
363   GC_obj_kinds[array_kind_x].ok_init = TRUE;
364
365   UNLOCK ();
366   ENABLE_SIGNALS ();
367 }