only initialize class when necessary to avoid deadlock

Previously, we would attempt to initialize a class (e.g. call its
static initializer) whenever a method in that class was called, as
well as in any of the cases listed in
http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.

However, the above approach may lead to deadlock in an app which
relies on being able to call non-static methods in parallel with a
static initializer invocation in the same class.  Thus, this commit
ensures that we initialize classes only in the cases defined by the
standard.
This commit is contained in:
Joel Dice 2013-04-30 22:48:43 -06:00
parent ed96693166
commit bbc5d7fb50
2 changed files with 6 additions and 12 deletions

View File

@ -4790,9 +4790,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp,
PROTECT(t, field); PROTECT(t, field);
if (fieldClass(t, field) != methodClass(t, context->method) if (classNeedsInit(t, fieldClass(t, field))) {
and classNeedsInit(t, fieldClass(t, field)))
{
c->call c->call
(c->constant (c->constant
(getThunk(t, tryInitClassThunk), Compiler::AddressType), (getThunk(t, tryInitClassThunk), Compiler::AddressType),
@ -5970,9 +5968,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp,
if (instruction == putstatic) { if (instruction == putstatic) {
checkField(t, field, true); checkField(t, field, true);
if (fieldClass(t, field) != methodClass(t, context->method) if (classNeedsInit(t, fieldClass(t, field))) {
and classNeedsInit(t, fieldClass(t, field)))
{
PROTECT(t, field); PROTECT(t, field);
c->call c->call
@ -10440,7 +10436,7 @@ compile(MyThread* t, FixedAllocator* allocator, BootContext* bootContext,
{ {
PROTECT(t, method); PROTECT(t, method);
if (bootContext == 0) { if (bootContext == 0 and methodFlags(t, method) & ACC_STATIC) {
initClass(t, methodClass(t, method)); initClass(t, methodClass(t, method));
} }

View File

@ -791,8 +791,6 @@ interpret3(Thread* t, const int base)
goto throw_; goto throw_;
} }
initClass(t, methodClass(t, frameMethod(t, frame)));
loop: loop:
instruction = codeBody(t, code, ip++); instruction = codeBody(t, code, ip++);
@ -1907,8 +1905,6 @@ interpret3(Thread* t, const int base)
PROTECT(t, method); PROTECT(t, method);
PROTECT(t, class_); PROTECT(t, class_);
initClass(t, class_);
code = findVirtualMethod(t, method, class_); code = findVirtualMethod(t, method, class_);
goto invoke; goto invoke;
} else { } else {
@ -2909,7 +2905,9 @@ invoke(Thread* t, object method)
class_ = methodClass(t, method); class_ = methodClass(t, method);
} }
if (methodFlags(t, method) & ACC_STATIC) {
initClass(t, class_); initClass(t, class_);
}
object result = 0; object result = 0;