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
16 #include <java/lang/Class.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.
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.
31 #include <boehm-config.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.
42 # define GC_GENERIC_MALLOC(Size, Type) \
43 GC_debug_generic_malloc (Size, Type, GC_EXTRAS)
45 # define GC_GENERIC_MALLOC(Size, Type) GC_generic_malloc (Size, Type)
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.
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.
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.
100 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, obj
, o2label
);
102 if (klass
== &ClassClass
)
104 jclass c
= (jclass
) addr
;
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
111 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, c2label
);
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
);
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
);
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
,
151 w
= (word
) c
->methods
[i
].signature
;
152 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
,
155 // FIXME: `ncode' entry?
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
,
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
);
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
195 if (JvFieldIsRef (field
) && field
->isResolved())
197 jobject val
= *(jobject
*) field
->u
.addr
;
199 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
,
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
);
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
, \
232 w
= (word
) ic
->field_initializers
;
233 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, ic
, cGlabel
);
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
);
260 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
,
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.
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.
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.
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
];
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
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.
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.
326 _Jv_AllocBytes (jsize size
)
328 return GC_GENERIC_MALLOC (size
, PTRFREE
);
332 call_finalizer (GC_PTR obj
, GC_PTR client_data
)
334 _Jv_FinalizerFunc
*fn
= (_Jv_FinalizerFunc
*) client_data
;
335 jobject jobj
= (jobject
) obj
;
341 _Jv_RegisterFinalizer (void *object
, _Jv_FinalizerFunc
*meth
)
343 GC_REGISTER_FINALIZER_NO_ORDER (object
, call_finalizer
, (GC_PTR
) meth
,
348 _Jv_RunFinalizers (void)
350 GC_invoke_finalizers ();
354 _Jv_RunAllFinalizers (void)
366 _Jv_GCTotalMemory (void)
368 return GC_get_heap_size ();
371 /* Sum size of each hblk. */
373 sum_blocks (struct hblk
*h
, word arg
)
375 long *sump
= (long *) arg
;
376 /* This evil computation is from boehm-gc/checksums.c. */
378 int bytes
= WORDS_TO_BYTES (hhdr
->hb_sz
);
379 bytes
+= HDR_BYTES
+ HBLKSIZE
- 1;
380 bytes
&= ~ (HBLKSIZE
- 1);
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. */
388 _Jv_GCFreeMemory (void)
391 GC_apply_to_all_blocks (sum_blocks
, &sum
);
412 // Set up state for marking and allocation of Java objects.
413 obj_free_list
= (ptr_t
*) GC_generic_malloc_inner ((MAXOBJSZ
+ 1)
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
430 array_free_list
= (ptr_t
*) GC_generic_malloc_inner ((MAXOBJSZ
+ 1)
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
;