f73bf868017c8ffe8706c4b8478b6036695937e2
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 // We need to include gc_priv.h. However, it tries to include
22 // config.h if it hasn't already been included. So we force the
23 // inclusion of the Boehm config.h.
26 #include <boehm-config.h>
30 // These aren't declared in any Boehm GC header.
31 void GC_finalize_all (void);
32 ptr_t
GC_debug_generic_malloc (size_t size
, int k
, GC_EXTRA_PARAMS
);
35 // FIXME: this should probably be defined in some GC header.
37 # define GC_GENERIC_MALLOC(Size, Type) \
38 GC_debug_generic_malloc (Size, Type, GC_EXTRAS)
40 # define GC_GENERIC_MALLOC(Size, Type) GC_generic_malloc (Size, Type)
43 // We must check for plausibility ourselves.
44 #define MAYBE_MARK(Obj, Top, Limit, Source, Exit) \
45 if ((ptr_t) (Obj) >= GC_least_plausible_heap_addr \
46 && (ptr_t) (Obj) <= GC_greatest_plausible_heap_addr) \
47 PUSH_CONTENTS (Obj, Top, Limit, Source, Exit)
49 #define ObjectClass _CL_Q34java4lang6Object
50 extern java::lang::Class ObjectClass
;
51 #define ClassClass _CL_Q34java4lang5Class
52 extern java::lang::Class ClassClass
;
56 // Nonzero if this module has been initialized.
57 static int initialized
= 0;
59 // `kind' index used when allocating Java objects.
60 static int obj_kind_x
;
62 // `kind' index used when allocating Java arrays.
63 static int array_kind_x
;
65 // Freelist used for Java objects.
66 static ptr_t
*obj_free_list
;
68 // Freelist used for Java arrays.
69 static ptr_t
*array_free_list
;
73 // This is called by the GC during the mark phase. It marks a Java
74 // object. We use `void *' arguments and return, and not what the
75 // Boehm GC wants, to avoid pollution in our headers.
77 _Jv_MarkObj (void *addr
, void *msp
, void *msl
, void * /*env*/)
79 mse
*mark_stack_ptr
= (mse
*) msp
;
80 mse
*mark_stack_limit
= (mse
*) msl
;
81 jobject obj
= (jobject
) addr
;
83 _Jv_VTable
*dt
= *(_Jv_VTable
**) addr
;
84 // We check this in case a GC occurs before the vtbl is set. FIXME:
85 // should use allocation lock while initializing object.
87 return mark_stack_ptr
;
88 jclass klass
= dt
->clas
;
90 // Every object has a sync_info pointer.
91 word w
= (word
) obj
->sync_info
;
92 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, obj
, o1label
);
93 // Mark the object's class.
95 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, obj
, o2label
);
97 if (klass
== &ClassClass
)
99 jclass c
= (jclass
) addr
;
102 // The next field should probably not be marked, since this is
103 // only used in the class hash table. Marking this field
104 // basically prohibits class unloading. --Kresten
106 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, c2label
);
110 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, c3label
);
111 w
= (word
) c
->superclass
;
112 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, c4label
);
113 for (int i
= 0; i
< c
->constants
.size
; ++i
)
115 /* FIXME: We could make this more precise by using the tags -KKT */
116 w
= (word
) c
->constants
.data
[i
].p
;
117 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, c5label
);
121 if (_Jv_IsInterpretedClass (c
))
123 w
= (word
) c
->constants
.tags
;
124 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, c5alabel
);
125 w
= (word
) c
->constants
.data
;
126 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, c5blabel
);
130 // If the class is an array, then the methods field holds a
131 // pointer to the element class. If the class is primitive,
132 // then the methods field holds a pointer to the array class.
133 w
= (word
) c
->methods
;
134 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, c6label
);
137 if (! c
->isArray() && ! c
->isPrimitive())
139 // Scan each method in the cases where `methods' really
140 // points to a methods structure.
141 for (int i
= 0; i
< c
->method_count
; ++i
)
143 w
= (word
) c
->methods
[i
].name
;
144 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
,
146 w
= (word
) c
->methods
[i
].signature
;
147 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
,
150 // FIXME: `ncode' entry?
153 // The interpreter installs a heap-allocated
154 // trampoline here, so we'll mark it.
155 if (_Jv_IsInterpretedClass (c
))
157 w
= (word
) c
->methods
[i
].ncode
;
158 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
,
165 // Mark all the fields.
166 w
= (word
) c
->fields
;
167 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, c8label
);
168 for (int i
= 0; i
< c
->field_count
; ++i
)
170 _Jv_Field
* field
= &c
->fields
[i
];
172 #ifndef COMPACT_FIELDS
173 w
= (word
) field
->name
;
174 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, c8alabel
);
176 w
= (word
) field
->type
;
177 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, c8blabel
);
179 // For the interpreter, we also need to mark the memory
180 // containing static members
181 if (field
->flags
& 0x0008)
183 w
= (word
) field
->u
.addr
;
184 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, c8clabel
);
186 // also, if the static member is a reference,
187 // mark also the value pointed to. We check for isResolved
188 // since marking can happen before memory is allocated for
190 if (JvFieldIsRef (field
) && field
->isResolved())
192 jobject val
= *(jobject
*) field
->u
.addr
;
194 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
,
200 w
= (word
) c
->vtable
;
201 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, c9label
);
202 w
= (word
) c
->interfaces
;
203 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, cAlabel
);
204 for (int i
= 0; i
< c
->interface_count
; ++i
)
206 w
= (word
) c
->interfaces
[i
];
207 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, cClabel
);
209 w
= (word
) c
->loader
;
210 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, c
, cBlabel
);
213 if (_Jv_IsInterpretedClass (c
))
215 _Jv_InterpClass
* ic
= (_Jv_InterpClass
*)c
;
217 w
= (word
) ic
->interpreted_methods
;
218 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, ic
, cElabel
);
220 for (int i
= 0; i
< c
->method_count
; i
++)
222 w
= (word
) ic
->interpreted_methods
[i
];
223 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, ic
, \
227 w
= (word
) ic
->field_initializers
;
228 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, ic
, cGlabel
);
236 // NOTE: each class only holds information about the class
237 // itself. So we must do the marking for the entire inheritance
238 // tree in order to mark all fields. FIXME: what about
239 // interfaces? We skip Object here, because Object only has a
240 // sync_info, and we handled that earlier.
241 // Note: occasionally `klass' can be null. For instance, this
242 // can happen if a GC occurs between the point where an object
243 // is allocated and where the vtbl slot is set.
244 while (klass
&& klass
!= &ObjectClass
)
246 jfieldID field
= JvGetFirstInstanceField (klass
);
247 jint max
= JvNumInstanceFields (klass
);
249 for (int i
= 0; i
< max
; ++i
)
251 if (JvFieldIsRef (field
))
253 jobject val
= JvGetObjectField (obj
, field
);
255 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
,
258 field
= field
->getNextInstanceField ();
260 klass
= klass
->getSuperclass();
264 return mark_stack_ptr
;
267 // This is called by the GC during the mark phase. It marks a Java
268 // array (of objects). We use `void *' arguments and return, and not
269 // what the Boehm GC wants, to avoid pollution in our headers.
271 _Jv_MarkArray (void *addr
, void *msp
, void *msl
, void * /*env*/)
273 mse
*mark_stack_ptr
= (mse
*) msp
;
274 mse
*mark_stack_limit
= (mse
*) msl
;
275 jobjectArray array
= (jobjectArray
) addr
;
277 _Jv_VTable
*dt
= *(_Jv_VTable
**) addr
;
278 // We check this in case a GC occurs before the vtbl is set. FIXME:
279 // should use allocation lock while initializing object.
281 return mark_stack_ptr
;
282 jclass klass
= dt
->clas
;
284 // Every object has a sync_info pointer.
285 word w
= (word
) array
->sync_info
;
286 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, array
, e1label
);
287 // Mark the object's class.
289 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, obj
, o2label
);
291 for (int i
= 0; i
< JvGetArrayLength (array
); ++i
)
293 jobject obj
= elements (array
)[i
];
295 MAYBE_MARK (w
, mark_stack_ptr
, mark_stack_limit
, array
, e2label
);
298 return mark_stack_ptr
;
301 // Allocate space for a new Java object. FIXME: this might be the
302 // wrong interface; we might prefer to pass in the object type as
303 // well. It isn't important for this collector, but it might be for
306 _Jv_AllocObj (jsize size
)
308 return GC_GENERIC_MALLOC (size
, obj_kind_x
);
311 // Allocate space for a new Java array. FIXME: again, this might be
312 // the wrong interface.
314 _Jv_AllocArray (jsize size
)
316 return GC_GENERIC_MALLOC (size
, array_kind_x
);
319 // Allocate some space that is known to be pointer-free.
321 _Jv_AllocBytes (jsize size
)
323 return GC_GENERIC_MALLOC (size
, PTRFREE
);
327 call_finalizer (GC_PTR obj
, GC_PTR client_data
)
329 _Jv_FinalizerFunc
*fn
= (_Jv_FinalizerFunc
*) client_data
;
330 jobject jobj
= (jobject
) obj
;
336 _Jv_RegisterFinalizer (void *object
, _Jv_FinalizerFunc
*meth
)
338 GC_REGISTER_FINALIZER_NO_ORDER (object
, call_finalizer
, (GC_PTR
) meth
,
343 _Jv_RunFinalizers (void)
345 GC_invoke_finalizers ();
349 _Jv_RunAllFinalizers (void)
361 _Jv_GCTotalMemory (void)
363 return GC_get_heap_size ();
366 /* Sum size of each hblk. */
368 sum_blocks (struct hblk
*h
, word arg
)
370 long *sump
= (long *) arg
;
371 /* This evil computation is from boehm-gc/checksums.c. */
373 int bytes
= WORDS_TO_BYTES (hhdr
->hb_sz
);
374 bytes
+= HDR_BYTES
+ HBLKSIZE
- 1;
375 bytes
&= ~ (HBLKSIZE
- 1);
379 /* This turns out to be expensive to implement. For now, we don't
380 care. We could make it less expensive, perhaps, but that would
381 require some changes to the collector. */
383 _Jv_GCFreeMemory (void)
386 GC_apply_to_all_blocks (sum_blocks
, &sum
);
407 // Set up state for marking and allocation of Java objects.
408 obj_free_list
= (ptr_t
*) GC_generic_malloc_inner ((MAXOBJSZ
+ 1)
411 memset (obj_free_list
, 0, (MAXOBJSZ
+ 1) * sizeof (ptr_t
));
413 proc
= GC_n_mark_procs
++;
414 GC_mark_procs
[proc
] = (mark_proc
) _Jv_MarkObj
;
416 obj_kind_x
= GC_n_kinds
++;
417 GC_obj_kinds
[obj_kind_x
].ok_freelist
= obj_free_list
;
418 GC_obj_kinds
[obj_kind_x
].ok_reclaim_list
= 0;
419 GC_obj_kinds
[obj_kind_x
].ok_descriptor
= MAKE_PROC (proc
, 0);
420 GC_obj_kinds
[obj_kind_x
].ok_relocate_descr
= FALSE
;
421 GC_obj_kinds
[obj_kind_x
].ok_init
= TRUE
;
423 // Set up state for marking and allocation of arrays of Java
425 array_free_list
= (ptr_t
*) GC_generic_malloc_inner ((MAXOBJSZ
+ 1)
428 memset (array_free_list
, 0, (MAXOBJSZ
+ 1) * sizeof (ptr_t
));
430 proc
= GC_n_mark_procs
++;
431 GC_mark_procs
[proc
] = (mark_proc
) _Jv_MarkArray
;
433 array_kind_x
= GC_n_kinds
++;
434 GC_obj_kinds
[array_kind_x
].ok_freelist
= array_free_list
;
435 GC_obj_kinds
[array_kind_x
].ok_reclaim_list
= 0;
436 GC_obj_kinds
[array_kind_x
].ok_descriptor
= MAKE_PROC (proc
, 0);
437 GC_obj_kinds
[array_kind_x
].ok_relocate_descr
= FALSE
;
438 GC_obj_kinds
[array_kind_x
].ok_init
= TRUE
;