summaryrefslogtreecommitdiff
path: root/libjava/boehm.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/boehm.cc')
-rw-r--r--libjava/boehm.cc201
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