fix deadlocks and other misbehaviors in class initialization code

This commit is contained in:
Joel Dice
2009-07-20 14:12:38 -06:00
parent 9975a556fa
commit 514d0bf7e5
6 changed files with 179 additions and 64 deletions

View File

@ -26,6 +26,8 @@ const unsigned FrameMethodOffset = 2;
const unsigned FrameIpOffset = 3;
const unsigned FrameFootprint = 4;
class ClassInitList;
class Thread: public vm::Thread {
public:
static const unsigned StackSizeInBytes = 64 * 1024;
@ -36,16 +38,39 @@ class Thread: public vm::Thread {
ip(0),
sp(0),
frame(-1),
code(0)
code(0),
classInitList(0)
{ }
unsigned ip;
unsigned sp;
int frame;
object code;
ClassInitList* classInitList;
uintptr_t stack[StackSizeInWords];
};
class ClassInitList {
public:
ClassInitList(Thread* t, object class_, ClassInitList* next):
t(t), class_(class_), next(next)
{ }
static void push(Thread* t, object class_) {
t->classInitList = new (t->m->heap->allocate(sizeof(ClassInitList)))
ClassInitList(t, class_, t->classInitList);
}
void pop() {
t->classInitList = next;
t->m->heap->free(this, sizeof(ClassInitList));
}
Thread* t;
object class_;
ClassInitList* next;
};
inline void
pushObject(Thread* t, object o)
{
@ -348,12 +373,14 @@ popFrame(Thread* t)
}
}
if (UNLIKELY(methodVmFlags(t, method) & ClassInitFlag)) {
if (t->exception) {
t->exception = makeExceptionInInitializerError(t, t->exception);
}
classVmFlags(t, methodClass(t, method)) &= ~(NeedInitFlag | InitFlag);
release(t, t->m->classLock);
if (UNLIKELY(methodVmFlags(t, method) & ClassInitFlag)
and t->classInitList)
{
assert(t, t->classInitList->class_ == methodClass(t, method));
t->classInitList->pop();
postInitClass(t, methodClass(t, method));
}
t->sp = frameBase(t, t->frame);
@ -732,17 +759,21 @@ invokeNative(Thread* t, object method)
bool
classInit2(Thread* t, object class_, unsigned ipOffset)
{
for (ClassInitList* list = t->classInitList; list; list = list->next) {
if (list->class_ == class_) {
return false;
}
}
PROTECT(t, class_);
acquire(t, t->m->classLock);
if (classVmFlags(t, class_) & NeedInitFlag
and (classVmFlags(t, class_) & InitFlag) == 0)
{
classVmFlags(t, class_) |= InitFlag;
if (preInitClass(t, class_)) {
ClassInitList::push(t, class_);
t->code = classInitializer(t, class_);
t->ip -= ipOffset;
return true;
} else {
release(t, t->m->classLock);
return false;
}
}
@ -3070,22 +3101,6 @@ class MyProcessor: public Processor {
// ignore
}
virtual void
initClass(vm::Thread* t, object c)
{
PROTECT(t, c);
acquire(t, t->m->classLock);
if (classVmFlags(t, c) & NeedInitFlag
and (classVmFlags(t, c) & InitFlag) == 0)
{
classVmFlags(t, c) |= InitFlag;
invoke(t, classInitializer(t, c), 0);
} else {
release(t, t->m->classLock);
}
}
virtual void
visitObjects(vm::Thread* vmt, Heap::Visitor* v)
{
@ -3098,6 +3113,10 @@ class MyProcessor: public Processor {
v->visit(reinterpret_cast<object*>(t->stack + (i * 2) + 1));
}
}
for (ClassInitList* list = t->classInitList; list; list = list->next) {
v->visit(reinterpret_cast<object*>(&(list->class_)));
}
}
virtual void