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/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.
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.
39 # define GC_GENERIC_MALLOC(Size, Type) \
40 GC_debug_generic_malloc (Size, Type, GC_EXTRAS)
42 # define GC_GENERIC_MALLOC(Size, Type) GC_generic_malloc (Size, Type)
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.
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.
100 MAYBE_MARK (p
, mark_stack_ptr
, mark_stack_limit
, obj
, o2label
);
102 if (__builtin_expect (klass
== &ClassClass
, false))
104 jclass c
= (jclass
) addr
;
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
);
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
);
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
,
143 p
= (ptr_t
) c
->methods
[i
].signature
;
144 MAYBE_MARK (p
, mark_stack_ptr
, mark_stack_limit
, c
,
147 // FIXME: `ncode' entry?
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
,
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
);
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
187 if (JvFieldIsRef (field
) && field
->isResolved())
189 jobject val
= *(jobject
*) field
->u
.addr
;
191 MAYBE_MARK (p
, mark_stack_ptr
, mark_stack_limit
,
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
);
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
, \
224 p
= (ptr_t
) ic
->field_initializers
;
225 MAYBE_MARK (p
, mark_stack_ptr
, mark_stack_limit
, ic
, cGlabel
);
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
);
252 MAYBE_MARK (p
, mark_stack_ptr
, mark_stack_limit
,
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.
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.
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
];
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
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.
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.
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
))
331 call_finalizer (GC_PTR obj
, GC_PTR client_data
)
333 _Jv_FinalizerFunc
*fn
= (_Jv_FinalizerFunc
*) client_data
;
334 jobject jobj
= (jobject
) obj
;
340 _Jv_RegisterFinalizer (void *object
, _Jv_FinalizerFunc
*meth
)
342 GC_REGISTER_FINALIZER_NO_ORDER (object
, call_finalizer
, (GC_PTR
) meth
,
347 _Jv_RunFinalizers (void)
349 GC_invoke_finalizers ();
353 _Jv_RunAllFinalizers (void)
365 _Jv_GCTotalMemory (void)
367 return GC_get_heap_size ();
371 _Jv_GCFreeMemory (void)
373 return GC_get_free_bytes ();
377 _Jv_GCSetInitialHeapSize (size_t size
)
379 size_t current
= GC_get_heap_size ();
381 GC_expand_hp (size
- current
);
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();
397 _Jv_MutexLock (&disable_gc_mutex
);
399 _Jv_MutexUnlock (&disable_gc_mutex
);
405 _Jv_MutexLock (&disable_gc_mutex
);
407 _Jv_MutexUnlock (&disable_gc_mutex
);
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)
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
447 array_free_list
= (ptr_t
*) GC_generic_malloc_inner ((MAXOBJSZ
+ 1)
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
);