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
18 #include <java/lang/Class.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.
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
);
36 // FIXME: this should probably be defined in some GC header.
38 # define GC_GENERIC_MALLOC(Size, Type) \
39 GC_debug_generic_malloc (Size, Type, GC_EXTRAS)
41 # define GC_GENERIC_MALLOC(Size, Type) GC_generic_malloc (Size, Type)
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)
50 #define ObjectClass _CL_Q34java4lang6Object
51 extern java::lang::Class ObjectClass
;
52 #define ClassClass _CL_Q34java4lang5Class
53 extern java::lang::Class ClassClass
;
57 // Nonzero if this module has been initialized.
58 static int initialized
= 0;
60 // `kind' index used when allocating Java objects.
61 static int obj_kind_x
;
63 // `kind' index used when allocating Java arrays.
64 static int array_kind_x
;
66 // Freelist used for Java objects.
67 static ptr_t
*obj_free_list
;
69 // Freelist used for Java arrays.
70 static ptr_t
*array_free_list
;
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.
78 _Jv_MarkObj (void *addr
, void *msp
, void *msl
, void * /*env*/)
80 mse
*mark_stack_ptr
= (mse
*) msp
;
81 mse
*mark_stack_limit
= (mse
*) msl
;
82 jobject obj
= (jobject
) addr
;
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.
88 return mark_stack_ptr
;
89 jclass klass
= dt
->clas
;
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.
96 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, obj
, o2label
);
98 if (klass
== &ClassClass
)
100 jclass c
= (jclass
) addr
;
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
107 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, c2label
);
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
)
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
);
122 if (_Jv_IsInterpretedClass (c
))
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
);
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
);
138 if (! c
->isArray() && ! c
->isPrimitive())
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
)
144 w
= (word
) c
->methods
[i
].name
;
145 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
,
147 w
= (word
) c
->methods
[i
].signature
;
148 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
,
151 // FIXME: `ncode' entry?
154 // The interpreter installs a heap-allocated
155 // trampoline here, so we'll mark it.
156 if (_Jv_IsInterpretedClass (c
))
158 w
= (word
) c
->methods
[i
].ncode
;
159 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
,
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
)
171 _Jv_Field
* field
= &c
->fields
[i
];
173 #ifndef COMPACT_FIELDS
174 w
= (word
) field
->name
;
175 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, c8alabel
);
177 w
= (word
) field
->type
;
178 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, c8blabel
);
180 // For the interpreter, we also need to mark the memory
181 // containing static members
182 if (field
->flags
& 0x0008)
184 w
= (word
) field
->u
.addr
;
185 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, c8clabel
);
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
191 if (JvFieldIsRef (field
) && field
->isResolved())
193 jobject val
= *(jobject
*) field
->u
.addr
;
195 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
,
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
)
207 w
= (word
) c
->interfaces
[i
];
208 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, cClabel
);
210 w
= (word
) c
->loader
;
211 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, cBlabel
);
214 if (_Jv_IsInterpretedClass (c
))
216 _Jv_InterpClass
* ic
= (_Jv_InterpClass
*)c
;
218 w
= (word
) ic
->interpreted_methods
;
219 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, ic
, cElabel
);
221 for (int i
= 0; i
< c
->method_count
; i
++)
223 w
= (word
) ic
->interpreted_methods
[i
];
224 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, ic
, \
228 w
= (word
) ic
->field_initializers
;
229 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, ic
, cGlabel
);
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
)
247 jfieldID field
= JvGetFirstInstanceField (klass
);
248 jint max
= JvNumInstanceFields (klass
);
250 for (int i
= 0; i
< max
; ++i
)
252 if (JvFieldIsRef (field
))
254 jobject val
= JvGetObjectField (obj
, field
);
256 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
,
259 field
= field
->getNextInstanceField ();
261 klass
= klass
->getSuperclass();
265 return mark_stack_ptr
;
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.
272 _Jv_MarkArray (void *addr
, void *msp
, void *msl
, void * /*env*/)
274 mse
*mark_stack_ptr
= (mse
*) msp
;
275 mse
*mark_stack_limit
= (mse
*) msl
;
276 jobjectArray array
= (jobjectArray
) addr
;
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.
282 return mark_stack_ptr
;
283 jclass klass
= dt
->clas
;
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.
290 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, obj
, o2label
);
292 for (int i
= 0; i
< JvGetArrayLength (array
); ++i
)
294 jobject obj
= elements (array
)[i
];
296 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, array
, e2label
);
299 return mark_stack_ptr
;
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
307 _Jv_AllocObj (jsize size
)
309 return GC_GENERIC_MALLOC (size
, obj_kind_x
);
312 // Allocate space for a new Java array. FIXME: again, this might be
313 // the wrong interface.
315 _Jv_AllocArray (jsize size
)
317 return GC_GENERIC_MALLOC (size
, array_kind_x
);
320 // Allocate some space that is known to be pointer-free.
322 _Jv_AllocBytes (jsize size
)
324 return GC_GENERIC_MALLOC (size
, PTRFREE
);
328 call_finalizer (GC_PTR obj
, GC_PTR client_data
)
330 _Jv_FinalizerFunc
*fn
= (_Jv_FinalizerFunc
*) client_data
;
331 jobject jobj
= (jobject
) obj
;
337 _Jv_RegisterFinalizer (void *object
, _Jv_FinalizerFunc
*meth
)
339 GC_REGISTER_FINALIZER_NO_ORDER (object
, call_finalizer
, (GC_PTR
) meth
,
344 _Jv_RunFinalizers (void)
346 GC_invoke_finalizers ();
350 _Jv_RunAllFinalizers (void)
362 _Jv_GCTotalMemory (void)
364 return GC_get_heap_size ();
368 _Jv_GCFreeMemory (void)
370 return GC_get_free_bytes ();
374 _Jv_GCSetInitialHeapSize (size_t size
)
376 size_t current
= GC_get_heap_size ();
378 GC_expand_hp (size
- current
);
382 _Jv_GCSetMaximumHeapSize (size_t size
)
384 GC_set_max_heap_size ((GC_word
) size
);
404 GC_java_finalization
= 1;
406 // Set up state for marking and allocation of Java objects.
407 obj_free_list
= (ptr_t
*) GC_generic_malloc_inner ((MAXOBJSZ
+ 1)
410 memset (obj_free_list
, 0, (MAXOBJSZ
+ 1) * sizeof (ptr_t
));
412 proc
= GC_n_mark_procs
++;
413 GC_mark_procs
[proc
] = (mark_proc
) _Jv_MarkObj
;
415 obj_kind_x
= GC_n_kinds
++;
416 GC_obj_kinds
[obj_kind_x
].ok_freelist
= obj_free_list
;
417 GC_obj_kinds
[obj_kind_x
].ok_reclaim_list
= 0;
418 GC_obj_kinds
[obj_kind_x
].ok_descriptor
= MAKE_PROC (proc
, 0);
419 GC_obj_kinds
[obj_kind_x
].ok_relocate_descr
= FALSE
;
420 GC_obj_kinds
[obj_kind_x
].ok_init
= TRUE
;
422 // Set up state for marking and allocation of arrays of Java
424 array_free_list
= (ptr_t
*) GC_generic_malloc_inner ((MAXOBJSZ
+ 1)
427 memset (array_free_list
, 0, (MAXOBJSZ
+ 1) * sizeof (ptr_t
));
429 proc
= GC_n_mark_procs
++;
430 GC_mark_procs
[proc
] = (mark_proc
) _Jv_MarkArray
;
432 array_kind_x
= GC_n_kinds
++;
433 GC_obj_kinds
[array_kind_x
].ok_freelist
= array_free_list
;
434 GC_obj_kinds
[array_kind_x
].ok_reclaim_list
= 0;
435 GC_obj_kinds
[array_kind_x
].ok_descriptor
= MAKE_PROC (proc
, 0);
436 GC_obj_kinds
[array_kind_x
].ok_relocate_descr
= FALSE
;
437 GC_obj_kinds
[array_kind_x
].ok_init
= TRUE
;