]>
Commit | Line | Data |
---|---|---|
ee9dd372 TT |
1 | // boehm.cc - interface between libjava and Boehm GC. |
2 | ||
18fa3240 | 3 | /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 |
36739040 | 4 | Free Software Foundation |
ee9dd372 TT |
5 | |
6 | This file is part of libgcj. | |
7 | ||
8 | This software is copyrighted work licensed under the terms of the | |
9 | Libgcj License. Please consult the file "LIBGCJ_LICENSE" for | |
10 | details. */ | |
11 | ||
12 | #include <config.h> | |
13 | ||
36739040 TT |
14 | #include <stdio.h> |
15 | #include <limits.h> | |
16 | ||
17 | #include <jvm.h> | |
18 | #include <gcj/cni.h> | |
19 | ||
20 | #include <java/lang/Class.h> | |
21 | #include <java/lang/reflect/Modifier.h> | |
22 | #include <java-interp.h> | |
23 | ||
24 | // More nastiness: the GC wants to define TRUE and FALSE. We don't | |
25 | // need the Java definitions (themselves a hack), so we undefine them. | |
26 | #undef TRUE | |
27 | #undef FALSE | |
28 | ||
1349c688 BM |
29 | // We include two autoconf headers. Avoid multiple definition warnings. |
30 | #undef PACKAGE_NAME | |
31 | #undef PACKAGE_STRING | |
32 | #undef PACKAGE_TARNAME | |
33 | #undef PACKAGE_VERSION | |
34 | ||
621ae65d AH |
35 | #ifdef HAVE_DLFCN_H |
36 | #undef _GNU_SOURCE | |
37 | #define _GNU_SOURCE | |
38 | #include <dlfcn.h> | |
621ae65d AH |
39 | #endif |
40 | ||
ee9dd372 TT |
41 | extern "C" |
42 | { | |
ed347998 HB |
43 | #include <gc_config.h> |
44 | ||
45 | // Set GC_DEBUG before including gc.h! | |
46 | #ifdef LIBGCJ_GC_DEBUG | |
47 | # define GC_DEBUG | |
48 | #endif | |
49 | ||
50 | #include <gc_mark.h> | |
1f4eb17d | 51 | #include <gc_gcj.h> |
ed347998 | 52 | #include <javaxfc.h> // GC_finalize_all declaration. |
ee9dd372 | 53 | |
eed56669 HB |
54 | #ifdef THREAD_LOCAL_ALLOC |
55 | # define GC_REDIRECT_TO_LOCAL | |
56 | # include <gc_local_alloc.h> | |
57 | #endif | |
ee9dd372 | 58 | |
36739040 TT |
59 | // From boehm's misc.c |
60 | void GC_enable(); | |
61 | void GC_disable(); | |
62 | }; | |
ed347998 | 63 | |
36739040 TT |
64 | #define MAYBE_MARK(Obj, Top, Limit, Source) \ |
65 | Top=GC_MARK_AND_PUSH((GC_PTR) Obj, Top, Limit, (GC_PTR *) Source) | |
ee9dd372 | 66 | |
bf3b8e42 HB |
67 | // `kind' index used when allocating Java arrays. |
68 | static int array_kind_x; | |
ee9dd372 TT |
69 | |
70 | // Freelist used for Java arrays. | |
36739040 | 71 | static void **array_free_list; |
54c2f04b | 72 | |
621ae65d AH |
73 | static int _Jv_GC_has_static_roots (const char *filename, void *, size_t); |
74 | ||
ee9dd372 TT |
75 | \f |
76 | ||
77 | // This is called by the GC during the mark phase. It marks a Java | |
78 | // object. We use `void *' arguments and return, and not what the | |
79 | // Boehm GC wants, to avoid pollution in our headers. | |
80 | void * | |
36739040 | 81 | _Jv_MarkObj (void *addr, void *msp, void *msl, void *env) |
ee9dd372 | 82 | { |
ed347998 HB |
83 | struct GC_ms_entry *mark_stack_ptr = (struct GC_ms_entry *)msp; |
84 | struct GC_ms_entry *mark_stack_limit = (struct GC_ms_entry *)msl; | |
ee9dd372 | 85 | |
ed347998 HB |
86 | if (env == (void *)1) /* Object allocated with debug allocator. */ |
87 | addr = (GC_PTR)GC_USR_PTR_FROM_BASE(addr); | |
88 | jobject obj = (jobject) addr; | |
bf3b8e42 | 89 | |
ee9dd372 | 90 | _Jv_VTable *dt = *(_Jv_VTable **) addr; |
bf3b8e42 HB |
91 | // The object might not yet have its vtable set, or it might |
92 | // really be an object on the freelist. In either case, the vtable slot | |
93 | // will either be 0, or it will point to a cleared object. | |
94 | // This assumes Java objects have size at least 3 words, | |
95 | // including the header. But this should remain true, since this | |
96 | // should only be used with debugging allocation or with large objects. | |
97 | if (__builtin_expect (! dt || !(dt -> get_finalizer()), false)) | |
ee9dd372 TT |
98 | return mark_stack_ptr; |
99 | jclass klass = dt->clas; | |
ed347998 | 100 | GC_PTR p; |
ee9dd372 | 101 | |
8b1753e3 TT |
102 | p = (GC_PTR) dt; |
103 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj); | |
104 | ||
3610e0d5 TT |
105 | # ifndef JV_HASH_SYNCHRONIZATION |
106 | // Every object has a sync_info pointer. | |
ed347998 | 107 | p = (GC_PTR) obj->sync_info; |
36739040 | 108 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj); |
3610e0d5 | 109 | # endif |
ee9dd372 | 110 | |
1d336a09 | 111 | if (__builtin_expect (klass == &java::lang::Class::class$, false)) |
ee9dd372 | 112 | { |
bf3b8e42 HB |
113 | // Currently we allocate some of the memory referenced from class objects |
114 | // as pointerfree memory, and then mark it more intelligently here. | |
115 | // We ensure that the ClassClass mark descriptor forces invocation of | |
116 | // this procedure. | |
117 | // Correctness of this is subtle, but it looks OK to me for now. For the incremental | |
118 | // collector, we need to make sure that the class object is written whenever | |
119 | // any of the subobjects are altered and may need rescanning. This may be tricky | |
120 | // during construction, and this may not be the right way to do this with | |
121 | // incremental collection. | |
122 | // If we overflow the mark stack, we will rescan the class object, so we should | |
123 | // be OK. The same applies if we redo the mark phase because win32 unmapped part | |
124 | // of our root set. - HB | |
ee9dd372 TT |
125 | jclass c = (jclass) addr; |
126 | ||
ed347998 | 127 | p = (GC_PTR) c->name; |
36739040 | 128 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); |
ed347998 | 129 | p = (GC_PTR) c->superclass; |
36739040 | 130 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); |
58eb6e7c | 131 | |
8b1753e3 TT |
132 | p = (GC_PTR) c->constants.tags; |
133 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); | |
134 | p = (GC_PTR) c->constants.data; | |
36739040 TT |
135 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); |
136 | ||
ee9dd372 TT |
137 | // If the class is an array, then the methods field holds a |
138 | // pointer to the element class. If the class is primitive, | |
139 | // then the methods field holds a pointer to the array class. | |
ed347998 | 140 | p = (GC_PTR) c->methods; |
36739040 | 141 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); |
ee9dd372 | 142 | |
ed347998 | 143 | p = (GC_PTR) c->fields; |
36739040 | 144 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); |
ee9dd372 | 145 | |
8b1753e3 | 146 | // The vtable might be allocated even for compiled code. |
ed347998 | 147 | p = (GC_PTR) c->vtable; |
36739040 | 148 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); |
8b1753e3 | 149 | |
ed347998 | 150 | p = (GC_PTR) c->interfaces; |
36739040 | 151 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); |
ed347998 | 152 | p = (GC_PTR) c->loader; |
36739040 TT |
153 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); |
154 | ||
155 | // The dispatch tables can be allocated at runtime. | |
156 | p = (GC_PTR) c->ancestors; | |
157 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); | |
36739040 | 158 | |
8b1753e3 TT |
159 | p = (GC_PTR) c->idt; |
160 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); | |
36739040 | 161 | |
ed347998 | 162 | p = (GC_PTR) c->arrayclass; |
36739040 | 163 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); |
ed347998 | 164 | p = (GC_PTR) c->protectionDomain; |
36739040 | 165 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); |
ed347998 | 166 | p = (GC_PTR) c->hack_signers; |
36739040 | 167 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); |
ed347998 | 168 | p = (GC_PTR) c->aux_info; |
36739040 | 169 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); |
0ac5ccd1 | 170 | |
97b8365c TT |
171 | p = (GC_PTR) c->reflection_data; |
172 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); | |
173 | ||
0ac5ccd1 BM |
174 | // The class chain must be marked for runtime-allocated Classes |
175 | // loaded by the bootstrap ClassLoader. | |
176 | p = (GC_PTR) c->next_or_version; | |
177 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); | |
ee9dd372 TT |
178 | } |
179 | else | |
180 | { | |
181 | // NOTE: each class only holds information about the class | |
182 | // itself. So we must do the marking for the entire inheritance | |
183 | // tree in order to mark all fields. FIXME: what about | |
184 | // interfaces? We skip Object here, because Object only has a | |
185 | // sync_info, and we handled that earlier. | |
186 | // Note: occasionally `klass' can be null. For instance, this | |
187 | // can happen if a GC occurs between the point where an object | |
188 | // is allocated and where the vtbl slot is set. | |
1d336a09 | 189 | while (klass && klass != &java::lang::Object::class$) |
ee9dd372 TT |
190 | { |
191 | jfieldID field = JvGetFirstInstanceField (klass); | |
192 | jint max = JvNumInstanceFields (klass); | |
193 | ||
194 | for (int i = 0; i < max; ++i) | |
195 | { | |
196 | if (JvFieldIsRef (field)) | |
197 | { | |
198 | jobject val = JvGetObjectField (obj, field); | |
ed347998 | 199 | p = (GC_PTR) val; |
36739040 | 200 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj); |
ee9dd372 | 201 | } |
8a922095 | 202 | field = field->getNextField (); |
ee9dd372 TT |
203 | } |
204 | klass = klass->getSuperclass(); | |
205 | } | |
206 | } | |
207 | ||
208 | return mark_stack_ptr; | |
209 | } | |
210 | ||
211 | // This is called by the GC during the mark phase. It marks a Java | |
212 | // array (of objects). We use `void *' arguments and return, and not | |
213 | // what the Boehm GC wants, to avoid pollution in our headers. | |
214 | void * | |
36739040 | 215 | _Jv_MarkArray (void *addr, void *msp, void *msl, void *env) |
ee9dd372 | 216 | { |
ed347998 HB |
217 | struct GC_ms_entry *mark_stack_ptr = (struct GC_ms_entry *)msp; |
218 | struct GC_ms_entry *mark_stack_limit = (struct GC_ms_entry *)msl; | |
219 | ||
220 | if (env == (void *)1) /* Object allocated with debug allocator. */ | |
221 | addr = (void *)GC_USR_PTR_FROM_BASE(addr); | |
ee9dd372 TT |
222 | jobjectArray array = (jobjectArray) addr; |
223 | ||
224 | _Jv_VTable *dt = *(_Jv_VTable **) addr; | |
bf3b8e42 HB |
225 | // Assumes size >= 3 words. That's currently true since arrays have |
226 | // a vtable, sync pointer, and size. If the sync pointer goes away, | |
227 | // we may need to round up the size. | |
228 | if (__builtin_expect (! dt || !(dt -> get_finalizer()), false)) | |
ee9dd372 | 229 | return mark_stack_ptr; |
ed347998 | 230 | GC_PTR p; |
ee9dd372 | 231 | |
8b1753e3 TT |
232 | p = (GC_PTR) dt; |
233 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array); | |
234 | ||
3610e0d5 TT |
235 | # ifndef JV_HASH_SYNCHRONIZATION |
236 | // Every object has a sync_info pointer. | |
ed347998 | 237 | p = (GC_PTR) array->sync_info; |
36739040 | 238 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array); |
3610e0d5 | 239 | # endif |
ee9dd372 TT |
240 | |
241 | for (int i = 0; i < JvGetArrayLength (array); ++i) | |
242 | { | |
243 | jobject obj = elements (array)[i]; | |
ed347998 | 244 | p = (GC_PTR) obj; |
36739040 | 245 | MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array); |
ee9dd372 TT |
246 | } |
247 | ||
248 | return mark_stack_ptr; | |
249 | } | |
250 | ||
619c238c BM |
251 | // Generate a GC marking descriptor for a class. |
252 | // | |
bf3b8e42 HB |
253 | // We assume that the gcj mark proc has index 0. This is a dubious assumption, |
254 | // since another one could be registered first. But the compiler also | |
255 | // knows this, so in that case everything else will break, too. | |
1f4eb17d | 256 | #define GCJ_DEFAULT_DESCR GC_MAKE_PROC(GC_GCJ_RESERVED_MARK_PROC_INDEX,0) |
e1a4d10f | 257 | |
bf3b8e42 | 258 | void * |
e1a4d10f | 259 | _Jv_BuildGCDescr(jclass self) |
bf3b8e42 | 260 | { |
e1a4d10f | 261 | jlong desc = 0; |
e7c4333b | 262 | jint bits_per_word = CHAR_BIT * sizeof (void *); |
e1a4d10f TT |
263 | |
264 | // Note: for now we only consider a bitmap mark descriptor. We | |
265 | // could also handle the case where the first N fields of a type are | |
266 | // references. However, this is not very likely to be used by many | |
267 | // classes, and it is easier to compute things this way. | |
268 | ||
e7c4333b BM |
269 | // The vtable pointer. |
270 | desc |= 1ULL << (bits_per_word - 1); | |
271 | #ifndef JV_HASH_SYNCHRONIZATION | |
272 | // The sync_info field. | |
273 | desc |= 1ULL << (bits_per_word - 2); | |
274 | #endif | |
275 | ||
e1a4d10f TT |
276 | for (jclass klass = self; klass != NULL; klass = klass->getSuperclass()) |
277 | { | |
278 | jfieldID field = JvGetFirstInstanceField(klass); | |
279 | int count = JvNumInstanceFields(klass); | |
280 | ||
281 | for (int i = 0; i < count; ++i) | |
282 | { | |
283 | if (field->isRef()) | |
284 | { | |
285 | unsigned int off = field->getOffset(); | |
286 | // If we run into a weird situation, we bail. | |
287 | if (off % sizeof (void *) != 0) | |
288 | return (void *) (GCJ_DEFAULT_DESCR); | |
289 | off /= sizeof (void *); | |
e1a4d10f | 290 | // If we find a field outside the range of our bitmap, |
e7c4333b BM |
291 | // fall back to procedure marker. The bottom 2 bits are |
292 | // reserved. | |
36739040 | 293 | if (off >= (unsigned) bits_per_word - 2) |
e1a4d10f | 294 | return (void *) (GCJ_DEFAULT_DESCR); |
e7c4333b | 295 | desc |= 1ULL << (bits_per_word - off - 1); |
e1a4d10f TT |
296 | } |
297 | ||
298 | field = field->getNextField(); | |
299 | } | |
300 | } | |
301 | ||
302 | // For bitmap mark type, bottom bits are 01. | |
303 | desc |= 1; | |
304 | // Bogus warning avoidance (on many platforms). | |
305 | return (void *) (unsigned long) desc; | |
bf3b8e42 | 306 | } |
bf3b8e42 | 307 | |
3610e0d5 | 308 | // Allocate some space that is known to be pointer-free. |
ee9dd372 | 309 | void * |
3610e0d5 | 310 | _Jv_AllocBytes (jsize size) |
ee9dd372 | 311 | { |
3610e0d5 TT |
312 | void *r = GC_MALLOC_ATOMIC (size); |
313 | // We have to explicitly zero memory here, as the GC doesn't | |
314 | // guarantee that PTRFREE allocations are zeroed. Note that we | |
315 | // don't have to do this for other allocation types because we set | |
316 | // the `ok_init' flag in the type descriptor. | |
317 | memset (r, 0, size); | |
318 | return r; | |
ee9dd372 TT |
319 | } |
320 | ||
ed347998 HB |
321 | #ifdef LIBGCJ_GC_DEBUG |
322 | ||
323 | void * | |
324 | _Jv_AllocObj (jsize size, jclass klass) | |
325 | { | |
326 | return GC_GCJ_MALLOC (size, klass->vtable); | |
327 | } | |
328 | ||
329 | void * | |
330 | _Jv_AllocPtrFreeObj (jsize size, jclass klass) | |
331 | { | |
332 | #ifdef JV_HASH_SYNCHRONIZATION | |
333 | void * obj = GC_MALLOC_ATOMIC(size); | |
334 | *((_Jv_VTable **) obj) = klass->vtable; | |
335 | #else | |
336 | void * obj = GC_GCJ_MALLOC(size, klass->vtable); | |
337 | #endif | |
338 | return obj; | |
339 | } | |
340 | ||
341 | #endif /* LIBGCJ_GC_DEBUG */ | |
342 | // In the non-debug case, the above two functions are defined | |
343 | // as inline functions in boehm-gc.h. In the debug case we | |
344 | // really want to take advantage of the definitions in gc_gcj.h. | |
345 | ||
bf3b8e42 HB |
346 | // Allocate space for a new Java array. |
347 | // Used only for arrays of objects. | |
ee9dd372 | 348 | void * |
bf3b8e42 | 349 | _Jv_AllocArray (jsize size, jclass klass) |
ee9dd372 | 350 | { |
bf3b8e42 | 351 | void *obj; |
ed347998 HB |
352 | |
353 | #ifdef LIBGCJ_GC_DEBUG | |
354 | // There isn't much to lose by scanning this conservatively. | |
355 | // If we didn't, the mark proc would have to understand that | |
356 | // it needed to skip the header. | |
357 | obj = GC_MALLOC(size); | |
358 | #else | |
bf3b8e42 HB |
359 | const jsize min_heap_addr = 16*1024; |
360 | // A heuristic. If size is less than this value, the size | |
361 | // stored in the array can't possibly be misinterpreted as | |
362 | // a pointer. Thus we lose nothing by scanning the object | |
363 | // completely conservatively, since no misidentification can | |
364 | // take place. | |
365 | ||
bf3b8e42 HB |
366 | if (size < min_heap_addr) |
367 | obj = GC_MALLOC(size); | |
368 | else | |
eed56669 | 369 | obj = GC_generic_malloc (size, array_kind_x); |
bf3b8e42 HB |
370 | #endif |
371 | *((_Jv_VTable **) obj) = klass->vtable; | |
372 | return obj; | |
ee9dd372 TT |
373 | } |
374 | ||
7866a458 BM |
375 | /* Allocate space for a new non-Java object, which does not have the usual |
376 | Java object header but may contain pointers to other GC'ed objects. */ | |
377 | void * | |
378 | _Jv_AllocRawObj (jsize size) | |
379 | { | |
8b1753e3 | 380 | return (void *) GC_MALLOC (size ? size : 1); |
7866a458 BM |
381 | } |
382 | ||
18fa3240 AO |
383 | typedef _Jv_ClosureList *closure_list_pointer; |
384 | ||
385 | /* Release closures in a _Jv_ClosureList. */ | |
386 | static void | |
387 | finalize_closure_list (GC_PTR obj, GC_PTR) | |
388 | { | |
389 | _Jv_ClosureList **clpp = (_Jv_ClosureList **)obj; | |
390 | _Jv_ClosureList::releaseClosures (clpp); | |
391 | } | |
392 | ||
393 | /* Allocate a double-indirect pointer to a _Jv_ClosureList that will | |
394 | get garbage-collected after this double-indirect pointer becomes | |
395 | unreachable by any other objects, including finalizable ones. */ | |
396 | _Jv_ClosureList ** | |
397 | _Jv_ClosureListFinalizer () | |
398 | { | |
399 | _Jv_ClosureList **clpp; | |
400 | clpp = (_Jv_ClosureList **)_Jv_AllocBytes (sizeof (*clpp)); | |
401 | GC_REGISTER_FINALIZER_UNREACHABLE (clpp, finalize_closure_list, | |
402 | NULL, NULL, NULL); | |
403 | return clpp; | |
404 | } | |
405 | ||
ee9dd372 TT |
406 | static void |
407 | call_finalizer (GC_PTR obj, GC_PTR client_data) | |
408 | { | |
409 | _Jv_FinalizerFunc *fn = (_Jv_FinalizerFunc *) client_data; | |
410 | jobject jobj = (jobject) obj; | |
411 | ||
412 | (*fn) (jobj); | |
413 | } | |
414 | ||
415 | void | |
416 | _Jv_RegisterFinalizer (void *object, _Jv_FinalizerFunc *meth) | |
417 | { | |
25fef12b | 418 | GC_REGISTER_FINALIZER_NO_ORDER (object, call_finalizer, (GC_PTR) meth, |
ee9dd372 TT |
419 | NULL, NULL); |
420 | } | |
421 | ||
422 | void | |
423 | _Jv_RunFinalizers (void) | |
424 | { | |
425 | GC_invoke_finalizers (); | |
426 | } | |
427 | ||
428 | void | |
429 | _Jv_RunAllFinalizers (void) | |
430 | { | |
431 | GC_finalize_all (); | |
432 | } | |
433 | ||
434 | void | |
435 | _Jv_RunGC (void) | |
436 | { | |
437 | GC_gcollect (); | |
438 | } | |
439 | ||
440 | long | |
441 | _Jv_GCTotalMemory (void) | |
442 | { | |
443 | return GC_get_heap_size (); | |
444 | } | |
445 | ||
ee9dd372 TT |
446 | long |
447 | _Jv_GCFreeMemory (void) | |
448 | { | |
e40217a7 | 449 | return GC_get_free_bytes (); |
ee9dd372 TT |
450 | } |
451 | ||
b8c3c4f0 TT |
452 | void |
453 | _Jv_GCSetInitialHeapSize (size_t size) | |
454 | { | |
455 | size_t current = GC_get_heap_size (); | |
456 | if (size > current) | |
3948f9d0 | 457 | GC_expand_hp (size - current); |
b8c3c4f0 TT |
458 | } |
459 | ||
460 | void | |
461 | _Jv_GCSetMaximumHeapSize (size_t size) | |
462 | { | |
463 | GC_set_max_heap_size ((GC_word) size); | |
464 | } | |
465 | ||
54c2f04b AG |
466 | void |
467 | _Jv_DisableGC (void) | |
468 | { | |
54c2f04b | 469 | GC_disable(); |
54c2f04b AG |
470 | } |
471 | ||
472 | void | |
473 | _Jv_EnableGC (void) | |
474 | { | |
54c2f04b | 475 | GC_enable(); |
54c2f04b AG |
476 | } |
477 | ||
3610e0d5 TT |
478 | static void * handle_out_of_memory(size_t) |
479 | { | |
480 | _Jv_ThrowNoMemory(); | |
481 | } | |
482 | ||
ed347998 HB |
483 | static void |
484 | gcj_describe_type_fn(void *obj, char *out_buf) | |
485 | { | |
486 | _Jv_VTable *dt = *(_Jv_VTable **) obj; | |
487 | ||
488 | if (! dt /* Shouldn't happen */) | |
489 | { | |
490 | strcpy(out_buf, "GCJ (bad)"); | |
491 | return; | |
492 | } | |
493 | jclass klass = dt->clas; | |
494 | if (!klass /* shouldn't happen */) | |
495 | { | |
496 | strcpy(out_buf, "GCJ (bad)"); | |
497 | return; | |
498 | } | |
499 | jstring name = klass -> getName(); | |
500 | size_t len = name -> length(); | |
501 | if (len >= GC_TYPE_DESCR_LEN) len = GC_TYPE_DESCR_LEN - 1; | |
502 | JvGetStringUTFRegion (name, 0, len, out_buf); | |
503 | out_buf[len] = '\0'; | |
504 | } | |
505 | ||
ee9dd372 TT |
506 | void |
507 | _Jv_InitGC (void) | |
508 | { | |
509 | int proc; | |
621ae65d AH |
510 | static bool gc_initialized; |
511 | ||
512 | if (gc_initialized) | |
513 | return; | |
514 | ||
515 | gc_initialized = 1; | |
ee9dd372 | 516 | |
88c38cc1 BM |
517 | // Ignore pointers that do not point to the start of an object. |
518 | GC_all_interior_pointers = 0; | |
bf3b8e42 | 519 | |
f0913ab8 | 520 | #if defined (HAVE_DLFCN_H) && defined (HAVE_DLADDR) |
621ae65d AH |
521 | // Tell the collector to ask us before scanning DSOs. |
522 | GC_register_has_static_roots_callback (_Jv_GC_has_static_roots); | |
523 | #endif | |
524 | ||
bf3b8e42 HB |
525 | // Configure the collector to use the bitmap marking descriptors that we |
526 | // stash in the class vtable. | |
ed347998 HB |
527 | // We always use mark proc descriptor 0, since the compiler knows |
528 | // about it. | |
bf3b8e42 HB |
529 | GC_init_gcj_malloc (0, (void *) _Jv_MarkObj); |
530 | ||
3610e0d5 TT |
531 | // Cause an out of memory error to be thrown from the allocators, |
532 | // instead of returning 0. This is cheaper than checking on allocation. | |
533 | GC_oom_fn = handle_out_of_memory; | |
534 | ||
bf3b8e42 HB |
535 | GC_java_finalization = 1; |
536 | ||
537 | // We use a different mark procedure for object arrays. This code | |
538 | // configures a different object `kind' for object array allocation and | |
ed347998 HB |
539 | // marking. |
540 | array_free_list = GC_new_free_list(); | |
541 | proc = GC_new_proc((GC_mark_proc)_Jv_MarkArray); | |
542 | array_kind_x = GC_new_kind(array_free_list, GC_MAKE_PROC (proc, 0), 0, 1); | |
543 | ||
36739040 | 544 | // Arrange to have the GC print Java class names in backtraces, etc. |
ed347998 HB |
545 | GC_register_describe_type_fn(GC_gcj_kind, gcj_describe_type_fn); |
546 | GC_register_describe_type_fn(GC_gcj_debug_kind, gcj_describe_type_fn); | |
bf3b8e42 HB |
547 | } |
548 | ||
3610e0d5 TT |
549 | #ifdef JV_HASH_SYNCHRONIZATION |
550 | // Allocate an object with a fake vtable pointer, which causes only | |
551 | // the first field (beyond the fake vtable pointer) to be traced. | |
552 | // Eventually this should probably be generalized. | |
553 | ||
554 | static _Jv_VTable trace_one_vtable = { | |
555 | 0, // class pointer | |
556 | (void *)(2 * sizeof(void *)), | |
557 | // descriptor; scan 2 words incl. vtable ptr. | |
558 | // Least significant bits must be zero to | |
3a8da024 | 559 | // identify this as a length descriptor |
3610e0d5 TT |
560 | {0} // First method |
561 | }; | |
562 | ||
563 | void * | |
564 | _Jv_AllocTraceOne (jsize size /* includes vtable slot */) | |
565 | { | |
566 | return GC_GCJ_MALLOC (size, &trace_one_vtable); | |
567 | } | |
568 | ||
3a8da024 HB |
569 | // Ditto for two words. |
570 | // the first field (beyond the fake vtable pointer) to be traced. | |
571 | // Eventually this should probably be generalized. | |
572 | ||
573 | static _Jv_VTable trace_two_vtable = | |
574 | { | |
575 | 0, // class pointer | |
576 | (void *)(3 * sizeof(void *)), | |
577 | // descriptor; scan 3 words incl. vtable ptr. | |
578 | {0} // First method | |
579 | }; | |
580 | ||
581 | void * | |
582 | _Jv_AllocTraceTwo (jsize size /* includes vtable slot */) | |
583 | { | |
584 | return GC_GCJ_MALLOC (size, &trace_two_vtable); | |
585 | } | |
586 | ||
3610e0d5 TT |
587 | #endif /* JV_HASH_SYNCHRONIZATION */ |
588 | ||
eeedeb5a TT |
589 | void |
590 | _Jv_GCInitializeFinalizers (void (*notifier) (void)) | |
591 | { | |
592 | GC_finalize_on_demand = 1; | |
593 | GC_finalizer_notifier = notifier; | |
594 | } | |
595 | ||
2b3d3db6 TT |
596 | void |
597 | _Jv_GCRegisterDisappearingLink (jobject *objp) | |
598 | { | |
36739040 TT |
599 | // This test helps to ensure that we meet a precondition of |
600 | // GC_general_register_disappearing_link, viz. "Obj must be a | |
601 | // pointer to the first word of an object we allocated." | |
602 | if (GC_base(*objp)) | |
603 | GC_general_register_disappearing_link ((GC_PTR *) objp, (GC_PTR) *objp); | |
2b3d3db6 TT |
604 | } |
605 | ||
606 | jboolean | |
96a1ceb3 | 607 | _Jv_GCCanReclaimSoftReference (jobject) |
2b3d3db6 TT |
608 | { |
609 | // For now, always reclaim soft references. FIXME. | |
610 | return true; | |
611 | } | |
621ae65d AH |
612 | |
613 | \f | |
614 | ||
f0913ab8 | 615 | #if defined (HAVE_DLFCN_H) && defined (HAVE_DLADDR) |
621ae65d AH |
616 | |
617 | // We keep a store of the filenames of DSOs that need to be | |
618 | // conservatively scanned by the garbage collector. During collection | |
619 | // the gc calls _Jv_GC_has_static_roots() to see if the data segment | |
620 | // of a DSO should be scanned. | |
621 | typedef struct filename_node | |
622 | { | |
623 | char *name; | |
624 | struct filename_node *link; | |
625 | } filename_node; | |
626 | ||
627 | #define FILENAME_STORE_SIZE 17 | |
628 | static filename_node *filename_store[FILENAME_STORE_SIZE]; | |
629 | ||
630 | // Find a filename in filename_store. | |
631 | static filename_node ** | |
632 | find_file (const char *filename) | |
633 | { | |
634 | int index = strlen (filename) % FILENAME_STORE_SIZE; | |
635 | filename_node **node = &filename_store[index]; | |
636 | ||
637 | while (*node) | |
638 | { | |
639 | if (strcmp ((*node)->name, filename) == 0) | |
640 | return node; | |
641 | node = &(*node)->link; | |
642 | } | |
643 | ||
644 | return node; | |
645 | } | |
646 | ||
647 | // Print the store of filenames of DSOs that need collection. | |
648 | void | |
649 | _Jv_print_gc_store (void) | |
650 | { | |
651 | for (int i = 0; i < FILENAME_STORE_SIZE; i++) | |
652 | { | |
653 | filename_node *node = filename_store[i]; | |
654 | while (node) | |
655 | { | |
656 | fprintf (stderr, "%s\n", node->name); | |
657 | node = node->link; | |
658 | } | |
659 | } | |
660 | } | |
661 | ||
662 | // Create a new node in the store of libraries to collect. | |
663 | static filename_node * | |
664 | new_node (const char *filename) | |
665 | { | |
666 | filename_node *node = (filename_node*)_Jv_Malloc (sizeof (filename_node)); | |
667 | node->name = (char *)_Jv_Malloc (strlen (filename) + 1); | |
668 | node->link = NULL; | |
669 | strcpy (node->name, filename); | |
670 | ||
671 | return node; | |
672 | } | |
673 | ||
674 | // Nonzero if the gc should scan this lib. | |
675 | static int | |
676 | _Jv_GC_has_static_roots (const char *filename, void *, size_t) | |
677 | { | |
678 | if (filename == NULL || strlen (filename) == 0) | |
679 | // No filename; better safe than sorry. | |
680 | return 1; | |
681 | ||
682 | filename_node **node = find_file (filename); | |
683 | if (*node) | |
684 | return 1; | |
685 | ||
686 | return 0; | |
687 | } | |
688 | ||
689 | #endif | |
690 | ||
691 | // Register the DSO that contains p for collection. | |
692 | void | |
693 | _Jv_RegisterLibForGc (const void *p __attribute__ ((__unused__))) | |
694 | { | |
f0913ab8 | 695 | #if defined (HAVE_DLFCN_H) && defined (HAVE_DLADDR) |
621ae65d | 696 | Dl_info info; |
52337535 AH |
697 | |
698 | if (dladdr (const_cast<void *>(p), &info) != 0) | |
621ae65d AH |
699 | { |
700 | filename_node **node = find_file (info.dli_fname); | |
701 | if (! *node) | |
702 | *node = new_node (info.dli_fname); | |
703 | } | |
704 | #endif | |
705 | } | |
706 | ||
9330cba6 KS |
707 | void |
708 | _Jv_SuspendThread (_Jv_Thread_t *thread) | |
709 | { | |
303f32cc KS |
710 | #if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \ |
711 | && !defined(GC_WIN32_THREADS) && !defined(GC_DARWIN_THREADS) | |
9330cba6 | 712 | GC_suspend_thread (_Jv_GetPlatformThreadID (thread)); |
303f32cc | 713 | #endif |
9330cba6 KS |
714 | } |
715 | ||
716 | void | |
717 | _Jv_ResumeThread (_Jv_Thread_t *thread) | |
718 | { | |
303f32cc KS |
719 | #if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \ |
720 | && !defined(GC_WIN32_THREADS) && !defined(GC_DARWIN_THREADS) | |
9330cba6 | 721 | GC_resume_thread (_Jv_GetPlatformThreadID (thread)); |
776862dd | 722 | #endif |
303f32cc | 723 | } |
7ddf92a8 | 724 | |
22099c59 KS |
725 | int |
726 | _Jv_IsThreadSuspended (_Jv_Thread_t *thread) | |
727 | { | |
728 | #if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \ | |
729 | && !defined(GC_WIN32_THREADS) && !defined(GC_DARWIN_THREADS) | |
730 | return GC_is_thread_suspended (_Jv_GetPlatformThreadID (thread)); | |
731 | #else | |
732 | return 0; | |
733 | #endif | |
734 | } | |
735 | ||
7ddf92a8 BM |
736 | void |
737 | _Jv_GCAttachThread () | |
738 | { | |
739 | // The registration interface is only defined on posixy systems and | |
740 | // only actually works if pthread_getattr_np is defined. | |
975147a4 TT |
741 | // FIXME: until gc7 it is simpler to disable this on solaris. |
742 | #if defined(HAVE_PTHREAD_GETATTR_NP) && !defined(GC_SOLARIS_THREADS) | |
7ddf92a8 BM |
743 | GC_register_my_thread (); |
744 | #endif | |
745 | } | |
746 | ||
747 | void | |
748 | _Jv_GCDetachThread () | |
749 | { | |
975147a4 | 750 | #if defined(HAVE_PTHREAD_GETATTR_NP) && !defined(GC_SOLARIS_THREADS) |
7ddf92a8 BM |
751 | GC_unregister_my_thread (); |
752 | #endif | |
753 | } |