synchronize on Java class rather than VM class in static synchronized methods

Previously, the following code would throw an IllegalMonitorStateException:

public class Test {
  public static synchronized void main(String[] args) {
    Test.class.notify();
  }
}

The problem stems from the fact that for a long time Avian has had two
representations of a given class: avian.VMClass and java.lang.Class.
It used to be that there was only one, java.lang.Class, but that
didn't play nicely with OpenJDK's class library, so we split it into
two.  Unfortunately, we forgot to update the JIT and interpreter
accordingly, so a static synchronized method would acquire the
avian.VMClass instance, whereas Foo.class.notify() would be invoked on
the java.lang.Class instance.

This commit fixes it.
This commit is contained in:
Joel Dice 2016-01-16 08:26:12 -07:00
parent 451700fad7
commit b5308c4866
3 changed files with 12 additions and 6 deletions

View File

@ -2146,7 +2146,7 @@ void releaseLock(MyThread* t, GcMethod* method, void* stack)
if (t->methodLockIsClean) {
object lock;
if (method->flags() & ACC_STATIC) {
lock = method->class_();
lock = getJClass(t, method->class_());
} else {
lock = *localObject(t,
stackForFrame(t, stack, method),
@ -3377,7 +3377,7 @@ void handleMonitorEvent(MyThread* t, Frame* frame, intptr_t function)
if (method->flags() & ACC_STATIC) {
PROTECT(t, method);
lock = frame->append(method->class_());
lock = frame->append(getJClass(t, method->class_()));
} else {
lock = loadLocal(
frame->context, 1, ir::Type::object(), savedTargetIndex(t, method));
@ -7588,7 +7588,7 @@ uint64_t invokeNativeSlow(MyThread* t, GcMethod* method, void* function)
if (method->flags() & ACC_SYNCHRONIZED) {
if (method->flags() & ACC_STATIC) {
acquire(t, method->class_());
acquire(t, getJClass(t, method->class_()));
} else {
acquire(t, *reinterpret_cast<object*>(RUNTIME_ARRAY_BODY(args)[1]));
}
@ -7613,7 +7613,7 @@ uint64_t invokeNativeSlow(MyThread* t, GcMethod* method, void* function)
if (method->flags() & ACC_SYNCHRONIZED) {
if (method->flags() & ACC_STATIC) {
release(t, method->class_());
release(t, getJClass(t, method->class_()));
} else {
release(t, *reinterpret_cast<object*>(RUNTIME_ARRAY_BODY(args)[1]));
}

View File

@ -294,7 +294,7 @@ void pushFrame(Thread* t, GcMethod* method)
// to release a monitor we never successfully acquired when we try
// to pop the frame back off.
if (method->flags() & ACC_STATIC) {
acquire(t, method->class_());
acquire(t, getJClass(t, method->class_()));
} else {
acquire(t, peekObject(t, base));
}
@ -332,7 +332,7 @@ void popFrame(Thread* t)
if (method->flags() & ACC_SYNCHRONIZED) {
if (method->flags() & ACC_STATIC) {
release(t, method->class_());
release(t, getJClass(t, method->class_()));
} else {
release(t, peekObject(t, frameBase(t, t->frame)));
}

View File

@ -145,6 +145,10 @@ public class Misc {
}
}
private static synchronized void testStaticNotify() {
Misc.class.notify();
}
public static void main(String[] args) throws Exception {
zam();
@ -165,6 +169,8 @@ public class Misc {
ClassLoader.getSystemClassLoader().toString();
testStaticNotify();
{ Misc m = new Misc();
m.toString();