From b5308c4866a028495cc5340bb6ca7b2dbfe9c92e Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 16 Jan 2016 08:26:12 -0700 Subject: [PATCH] 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. --- src/compile.cpp | 8 ++++---- src/interpret.cpp | 4 ++-- test/Misc.java | 6 ++++++ 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index b9899d3124..8e40cb32b5 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -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(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(RUNTIME_ARRAY_BODY(args)[1])); } diff --git a/src/interpret.cpp b/src/interpret.cpp index 7dac9262b7..6ed8fefe03 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -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))); } diff --git a/test/Misc.java b/test/Misc.java index 42d452a37a..ab69d7490b 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -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();