mirror of
https://github.com/corda/corda.git
synced 2025-01-03 19:54:13 +00:00
fix process=interpret class initialization regression
A long time ago, I refactored the class initialization code in the VM, but did not notice until today that it had caused the process=interpret build to break on certain recursive initializations. In particular, we were not always detecting when a thread recursively tried to initialize a class it was already in the process of initializing, leading to the mistaken assumption that another thread was initializing it and that we should wait until it was done, in which case we would wait forever. This commit ensures that we always detect recursive initialization and short-circuit it.
This commit is contained in:
parent
064c3b7c33
commit
fca98df55b
@ -7332,6 +7332,17 @@ class MyProcessor: public Processor {
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool
|
||||
isInitializing(Thread* t, object c)
|
||||
{
|
||||
for (Thread::ClassInitStack* s = t->classInitStack; s; s = s->next) {
|
||||
if (s->class_ == c) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void
|
||||
visitObjects(Thread* vmt, Heap::Visitor* v)
|
||||
{
|
||||
|
@ -761,12 +761,6 @@ 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_);
|
||||
|
||||
if (preInitClass(t, class_)) {
|
||||
@ -3111,6 +3105,26 @@ class MyProcessor: public Processor {
|
||||
// ignore
|
||||
}
|
||||
|
||||
virtual bool
|
||||
isInitializing(vm::Thread* vmt, object c)
|
||||
{
|
||||
Thread* t = static_cast<Thread*>(vmt);
|
||||
|
||||
for (ClassInitList* list = t->classInitList; list; list = list->next) {
|
||||
if (list->class_ == c) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (Thread::ClassInitStack* s = t->classInitStack; s; s = s->next) {
|
||||
if (s->class_ == c) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void
|
||||
visitObjects(vm::Thread* vmt, Heap::Visitor* v)
|
||||
{
|
||||
|
@ -3309,13 +3309,11 @@ preInitClass(Thread* t, object c)
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
if (classVmFlags(t, c) & NeedInitFlag) {
|
||||
if (classVmFlags(t, c) & InitFlag) {
|
||||
// the class is currently being initialized. If this the
|
||||
// thread which is initializing it, we should not try to
|
||||
// initialize it recursively.
|
||||
for (Thread::ClassInitStack* s = t->classInitStack; s; s = s->next) {
|
||||
if (s->class_ == c) {
|
||||
return false;
|
||||
}
|
||||
// If the class is currently being initialized and this the thread
|
||||
// which is initializing it, we should not try to initialize it
|
||||
// recursively.
|
||||
if (t->m->processor->isInitializing(t, c)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// some other thread is on the job - wait for it to finish.
|
||||
|
@ -81,6 +81,9 @@ class Processor {
|
||||
virtual void
|
||||
initVtable(Thread* t, object c) = 0;
|
||||
|
||||
virtual bool
|
||||
isInitializing(Thread* t, object c) = 0;
|
||||
|
||||
virtual void
|
||||
visitObjects(Thread* t, Heap::Visitor* v) = 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user