diff options
Diffstat (limited to 'libjava/boehm.cc')
-rw-r--r-- | libjava/boehm.cc | 201 |
1 files changed, 127 insertions, 74 deletions
diff --git a/libjava/boehm.cc b/libjava/boehm.cc index c2a93a57b04..d2902326e81 100644 --- a/libjava/boehm.cc +++ b/libjava/boehm.cc @@ -1,6 +1,7 @@ // boehm.cc - interface between libjava and Boehm GC. -/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation +/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 + Free Software Foundation This file is part of libgcj. @@ -10,6 +11,21 @@ details. */ #include <config.h> +#include <stdio.h> +#include <limits.h> + +#include <jvm.h> +#include <gcj/cni.h> + +#include <java/lang/Class.h> +#include <java/lang/reflect/Modifier.h> +#include <java-interp.h> + +// More nastiness: the GC wants to define TRUE and FALSE. We don't +// need the Java definitions (themselves a hack), so we undefine them. +#undef TRUE +#undef FALSE + extern "C" { #include <gc_config.h> @@ -27,26 +43,20 @@ extern "C" # define GC_REDIRECT_TO_LOCAL # include <gc_local_alloc.h> #endif -}; -#include <stdio.h> -#include <limits.h> - -#include <jvm.h> -#include <gcj/cni.h> - -#include <java/lang/Class.h> -#include <java/lang/reflect/Modifier.h> -#include <java-interp.h> + // From boehm's misc.c + void GC_enable(); + void GC_disable(); +}; -#define MAYBE_MARK(Obj, Top, Limit, Source, Exit) \ - Top=GC_MARK_AND_PUSH((GC_PTR)Obj, Top, Limit, (GC_PTR *)Source) +#define MAYBE_MARK(Obj, Top, Limit, Source) \ + Top=GC_MARK_AND_PUSH((GC_PTR) Obj, Top, Limit, (GC_PTR *) Source) // `kind' index used when allocating Java arrays. static int array_kind_x; // Freelist used for Java arrays. -static void * *array_free_list; +static void **array_free_list; @@ -54,7 +64,7 @@ static void * *array_free_list; // object. We use `void *' arguments and return, and not what the // Boehm GC wants, to avoid pollution in our headers. void * -_Jv_MarkObj (void *addr, void *msp, void *msl, void * env) +_Jv_MarkObj (void *addr, void *msp, void *msl, void *env) { struct GC_ms_entry *mark_stack_ptr = (struct GC_ms_entry *)msp; struct GC_ms_entry *mark_stack_limit = (struct GC_ms_entry *)msl; @@ -78,11 +88,11 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * env) # ifndef JV_HASH_SYNCHRONIZATION // Every object has a sync_info pointer. p = (GC_PTR) obj->sync_info; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj, o1label); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj); # endif // Mark the object's class. p = (GC_PTR) klass; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj, o2label); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj); if (__builtin_expect (klass == &java::lang::Class::class$, false)) { @@ -101,33 +111,35 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * env) jclass c = (jclass) addr; p = (GC_PTR) c->name; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c3label); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); p = (GC_PTR) c->superclass; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c4label); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); for (int i = 0; i < c->constants.size; ++i) { /* FIXME: We could make this more precise by using the tags -KKT */ p = (GC_PTR) c->constants.data[i].p; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5label); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); } #ifdef INTERPRETER if (_Jv_IsInterpretedClass (c)) { p = (GC_PTR) c->constants.tags; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5alabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); p = (GC_PTR) c->constants.data; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5blabel); - p = (GC_PTR) c->vtable; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5clabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); } #endif + // The vtable might be allocated even for compiled code. + p = (GC_PTR) c->vtable; + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); + // If the class is an array, then the methods field holds a // pointer to the element class. If the class is primitive, // then the methods field holds a pointer to the array class. p = (GC_PTR) c->methods; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c6label); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); // The vtable might have been set, but the rest of the class // could still be uninitialized. If this is the case, then @@ -143,34 +155,35 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * env) for (int i = 0; i < c->method_count; ++i) { p = (GC_PTR) c->methods[i].name; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, - cm1label); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); p = (GC_PTR) c->methods[i].signature; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, - cm2label); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); + + // Note that we don't have to mark each individual throw + // separately, as these are stored in the constant pool. + p = (GC_PTR) c->methods[i].throws; + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); } } // Mark all the fields. p = (GC_PTR) c->fields; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8label); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); for (int i = 0; i < c->field_count; ++i) { _Jv_Field* field = &c->fields[i]; -#ifndef COMPACT_FIELDS p = (GC_PTR) field->name; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8alabel); -#endif + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); p = (GC_PTR) field->type; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8blabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); // For the interpreter, we also need to mark the memory // containing static members if ((field->flags & java::lang::reflect::Modifier::STATIC)) { p = (GC_PTR) field->u.addr; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8clabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); // also, if the static member is a reference, // mark also the value pointed to. We check for isResolved @@ -180,69 +193,110 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * env) { jobject val = *(jobject*) field->u.addr; p = (GC_PTR) val; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, - c, c8elabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); } } } p = (GC_PTR) c->vtable; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c9label); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); p = (GC_PTR) c->interfaces; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cAlabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); for (int i = 0; i < c->interface_count; ++i) { p = (GC_PTR) c->interfaces[i]; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cClabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); } p = (GC_PTR) c->loader; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cBlabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); + + // The dispatch tables can be allocated at runtime. + p = (GC_PTR) c->ancestors; + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); + if (c->idt) + { + p = (GC_PTR) c->idt; + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); + + if (c->isInterface()) + { + p = (GC_PTR) c->idt->iface.ioffsets; + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c->idt); + } + else if (! c->isPrimitive()) + { + // This field is only valid for ordinary classes. + p = (GC_PTR) c->idt->cls.itable; + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c->idt); + } + } + p = (GC_PTR) c->arrayclass; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cDlabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); p = (GC_PTR) c->protectionDomain; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cPlabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); p = (GC_PTR) c->hack_signers; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cSlabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); p = (GC_PTR) c->aux_info; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cTlabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); #ifdef INTERPRETER - if (_Jv_IsInterpretedClass (c)) + if (_Jv_IsInterpretedClass (c) && c->aux_info) { _Jv_InterpClass* ic = (_Jv_InterpClass*) c->aux_info; p = (GC_PTR) ic->interpreted_methods; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic, cElabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic); for (int i = 0; i < c->method_count; i++) { + // The interpreter installs a heap-allocated trampoline + // here, so we'll mark it. + p = (GC_PTR) c->methods[i].ncode; + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c); + + using namespace java::lang::reflect; + + // Mark the direct-threaded code. Note a subtlety here: + // when we add Miranda methods to a class, we don't + // resize its interpreted_methods array. If we try to + // reference one of these methods, we may crash. + // However, we know these are all abstract, and we know + // that abstract methods have nothing useful in this + // array. So, we skip all abstract methods to avoid the + // problem. FIXME: this is pretty obscure, it may be + // better to add a methods to the execution engine and + // resize the array. + if ((c->methods[i].accflags & Modifier::ABSTRACT) != 0) + continue; + p = (GC_PTR) ic->interpreted_methods[i]; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic, \ - cFlabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic); - // Mark the direct-threaded code. - if ((c->methods[i].accflags - & java::lang::reflect::Modifier::NATIVE) == 0) + if ((c->methods[i].accflags & Modifier::NATIVE) != 0) + { + _Jv_JNIMethod *jm + = (_Jv_JNIMethod *) ic->interpreted_methods[i]; + if (jm) + { + p = (GC_PTR) jm->jni_arg_types; + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, p); + } + } + else { _Jv_InterpMethod *im = (_Jv_InterpMethod *) ic->interpreted_methods[i]; if (im) { p = (GC_PTR) im->prepared; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic, \ - cFlabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic); } } - - // The interpreter installs a heap-allocated trampoline - // here, so we'll mark it. - p = (GC_PTR) c->methods[i].ncode; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, - cm3label); } p = (GC_PTR) ic->field_initializers; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic, cGlabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic); } #endif @@ -269,8 +323,7 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * env) { jobject val = JvGetObjectField (obj, field); p = (GC_PTR) val; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, - obj, elabel); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj); } field = field->getNextField (); } @@ -285,7 +338,7 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * env) // array (of objects). We use `void *' arguments and return, and not // what the Boehm GC wants, to avoid pollution in our headers. void * -_Jv_MarkArray (void *addr, void *msp, void *msl, void * env) +_Jv_MarkArray (void *addr, void *msp, void *msl, void *env) { struct GC_ms_entry *mark_stack_ptr = (struct GC_ms_entry *)msp; struct GC_ms_entry *mark_stack_limit = (struct GC_ms_entry *)msl; @@ -306,17 +359,17 @@ _Jv_MarkArray (void *addr, void *msp, void *msl, void * env) # ifndef JV_HASH_SYNCHRONIZATION // Every object has a sync_info pointer. p = (GC_PTR) array->sync_info; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array, e1label); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array); # endif // Mark the object's class. p = (GC_PTR) klass; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, &(dt -> clas), o2label); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, &(dt -> clas)); for (int i = 0; i < JvGetArrayLength (array); ++i) { jobject obj = elements (array)[i]; p = (GC_PTR) obj; - MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array, e2label); + MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array); } return mark_stack_ptr; @@ -364,7 +417,7 @@ _Jv_BuildGCDescr(jclass self) // If we find a field outside the range of our bitmap, // fall back to procedure marker. The bottom 2 bits are // reserved. - if (off >= (unsigned)bits_per_word - 2) + if (off >= (unsigned) bits_per_word - 2) return (void *) (GCJ_DEFAULT_DESCR); desc |= 1ULL << (bits_per_word - off - 1); } @@ -514,10 +567,6 @@ _Jv_GCSetMaximumHeapSize (size_t size) GC_set_max_heap_size ((GC_word) size); } -// From boehm's misc.c -extern "C" void GC_enable(); -extern "C" void GC_disable(); - void _Jv_DisableGC (void) { @@ -585,7 +634,7 @@ _Jv_InitGC (void) proc = GC_new_proc((GC_mark_proc)_Jv_MarkArray); array_kind_x = GC_new_kind(array_free_list, GC_MAKE_PROC (proc, 0), 0, 1); - /* Arrange to have the GC print Java class names in backtraces, etc. */ + // Arrange to have the GC print Java class names in backtraces, etc. GC_register_describe_type_fn(GC_gcj_kind, gcj_describe_type_fn); GC_register_describe_type_fn(GC_gcj_debug_kind, gcj_describe_type_fn); } @@ -640,7 +689,11 @@ _Jv_GCInitializeFinalizers (void (*notifier) (void)) void _Jv_GCRegisterDisappearingLink (jobject *objp) { - GC_general_register_disappearing_link ((GC_PTR *) objp, (GC_PTR) *objp); + // This test helps to ensure that we meet a precondition of + // GC_general_register_disappearing_link, viz. "Obj must be a + // pointer to the first word of an object we allocated." + if (GC_base(*objp)) + GC_general_register_disappearing_link ((GC_PTR *) objp, (GC_PTR) *objp); } jboolean |