mirror of
https://github.com/corda/corda.git
synced 2025-06-13 04:38:19 +00:00
fix deadlocks and other misbehaviors in class initialization code
This commit is contained in:
@ -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
|
||||
|
Reference in New Issue
Block a user