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:
Joel Dice 2010-08-04 18:27:54 -06:00
parent 064c3b7c33
commit fca98df55b
4 changed files with 39 additions and 13 deletions

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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.

View File

@ -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;