--- old/test/compiler/rtm/locking/TestRTMAbortRatio.java 2015-04-28 16:18:49.470034926 +0300 +++ new/test/compiler/rtm/locking/TestRTMAbortRatio.java 2015-04-28 16:18:49.394034928 +0300 @@ -126,10 +126,7 @@ @Override public String[] getMethodsToCompileNames() { - return new String[] { - getMethodWithLockName(), - Unsafe.class.getName() + "::addressSize" - }; + return new String[] { getMethodWithLockName() }; } public void lock(boolean abort) { @@ -147,10 +144,12 @@ public static void main(String args[]) throws Throwable { Asserts.assertGTE(args.length, 1, "One argument required."); Test t = new Test(); - if (Boolean.valueOf(args[0])) { + boolean shouldBeInflated = Boolean.valueOf(args[0]); + if (shouldBeInflated) { AbortProvoker.inflateMonitor(t.monitor); } for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) { + AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated); t.lock(i >= Test.WARMUP_ITERATIONS); } } --- old/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java 2015-04-28 16:18:49.862034913 +0300 +++ new/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java 2015-04-28 16:18:49.786034916 +0300 @@ -156,10 +156,7 @@ @Override public String[] getMethodsToCompileNames() { - return new String[] { - getMethodWithLockName(), - sun.misc.Unsafe.class.getName() + "::forceAbort" - }; + return new String[] { getMethodWithLockName() }; } public void forceAbort(int a[], boolean abort) { @@ -182,13 +179,15 @@ public static void main(String args[]) throws Throwable { Test t = new Test(); - if (Boolean.valueOf(args[0])) { + boolean shouldBeInflated = Boolean.valueOf(args[0]); + if (shouldBeInflated) { AbortProvoker.inflateMonitor(t.monitor); } int tmp[] = new int[1]; for (int i = 0; i < Test.ITERATIONS; i++ ) { + AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated); if (i == Test.RANGE_CHECK_AT) { t.forceAbort(new int[0], false); } else { --- old/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java 2015-04-28 16:18:50.178034903 +0300 +++ new/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java 2015-04-28 16:18:50.098034906 +0300 @@ -129,10 +129,7 @@ @Override public String[] getMethodsToCompileNames() { - return new String[] { - getMethodWithLockName(), - sun.misc.Unsafe.class.getName() + "::addressSize" - }; + return new String[] { getMethodWithLockName() }; } public void forceAbort(boolean abort) { @@ -150,11 +147,12 @@ public static void main(String args[]) throws Throwable { Asserts.assertGTE(args.length, 1, "One argument required."); Test t = new Test(); - - if (Boolean.valueOf(args[0])) { + boolean shouldBeInflated = Boolean.valueOf(args[0]); + if (shouldBeInflated) { AbortProvoker.inflateMonitor(t.monitor); } for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) { + AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated); t.forceAbort( i == TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD); } --- old/test/compiler/rtm/locking/TestRTMLockingThreshold.java 2015-04-28 16:18:50.510034892 +0300 +++ new/test/compiler/rtm/locking/TestRTMLockingThreshold.java 2015-04-28 16:18:50.434034895 +0300 @@ -142,10 +142,7 @@ @Override public String[] getMethodsToCompileNames() { - return new String[] { - getMethodWithLockName(), - sun.misc.Unsafe.class.getName() + "::addressSize" - }; + return new String[] { getMethodWithLockName() }; } public void lock(boolean abort) { @@ -163,11 +160,12 @@ public static void main(String args[]) throws Throwable { Asserts.assertGTE(args.length, 1, "One argument required."); Test t = new Test(); - - if (Boolean.valueOf(args[0])) { + boolean shouldBeInflated = Boolean.valueOf(args[0]); + if (shouldBeInflated) { AbortProvoker.inflateMonitor(t.monitor); } for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) { + AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated); t.lock(i % 2 == 1); } } --- old/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java 2015-04-28 16:18:50.826034882 +0300 +++ new/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java 2015-04-28 16:18:50.754034884 +0300 @@ -116,9 +116,7 @@ @Override public String[] getMethodsToCompileNames() { - return new String[] { - getMethodWithLockName() - }; + return new String[] { getMethodWithLockName() }; } public void lock() { @@ -134,11 +132,13 @@ public static void main(String args[]) throws Throwable { Asserts.assertGTE(args.length, 1, "One argument required."); Test test = new Test(); - - if (Boolean.valueOf(args[0])) { + boolean shouldBeInflated = Boolean.valueOf(args[0]); + if (shouldBeInflated) { AbortProvoker.inflateMonitor(test.monitor); } for (long i = 0L; i < Test.TOTAL_ITERATIONS; i++) { + AbortProvoker.verifyMonitorState(test.monitor, + shouldBeInflated); test.lock(); } } --- old/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java 2015-04-28 16:18:51.158034871 +0300 +++ new/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java 2015-04-28 16:18:51.082034874 +0300 @@ -51,7 +51,7 @@ * Compiled method invoked {@code AbortProvoker.DEFAULT_ITERATIONS} times before * lock inflation and the same amount of times after inflation. * As a result total locks count should be equal to - * {@code 2*AbortProvoker.DEFAULT_ITERATIONS}. + * {@code 2 * AbortProvoker.DEFAULT_ITERATIONS}. * It is a pretty strict assertion which could fail if some retriable abort * happened: it could be {@code AbortType.RETRIABLE} or * {@code AbortType.MEM_CONFLICT}, but unfortunately abort can has both these @@ -100,7 +100,6 @@ } public static class Test { - /** * Usage: * Test <provoker type> @@ -112,10 +111,12 @@ AbortProvoker provoker = AbortType.lookup(Integer.valueOf(args[0])).provoker(); for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) { + AbortProvoker.verifyMonitorState(provoker, false /*deflated*/); provoker.forceAbort(); } provoker.inflateMonitor(); for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) { + AbortProvoker.verifyMonitorState(provoker, true /*inflated*/); provoker.forceAbort(); } } --- old/test/compiler/testlibrary/rtm/AbortProvoker.java 2015-04-28 16:18:51.470034861 +0300 +++ new/test/compiler/testlibrary/rtm/AbortProvoker.java 2015-04-28 16:18:51.398034864 +0300 @@ -29,8 +29,7 @@ import java.util.concurrent.CyclicBarrier; import com.oracle.java.testlibrary.Asserts; -import com.oracle.java.testlibrary.Utils; -import sun.misc.Unsafe; +import sun.hotspot.WhiteBox; /** * Base class for different transactional execution abortion @@ -38,6 +37,9 @@ */ public abstract class AbortProvoker implements CompilableTest { public static final long DEFAULT_ITERATIONS = 10000L; + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + @SuppressWarnings("unused") + private static int sharedState = 0; /** * Inflates monitor associated with object {@code monitor}. * Inflation is forced by entering the same monitor from @@ -48,36 +50,76 @@ * @throws Exception if something went wrong. */ public static Object inflateMonitor(Object monitor) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); CyclicBarrier barrier = new CyclicBarrier(2); Runnable inflatingRunnable = () -> { - unsafe.monitorEnter(monitor); - try { - barrier.await(); - barrier.await(); - } catch (InterruptedException | BrokenBarrierException e) { - throw new RuntimeException( - "Synchronization issue occurred.", e); - } finally { - unsafe.monitorExit(monitor); + synchronized (monitor) { + try { + barrier.await(); + } catch (BrokenBarrierException | InterruptedException e) { + throw new RuntimeException( + "Synchronization issue occurred.", e); + } + try { + monitor.wait(); + } catch (InterruptedException e) { + throw new AssertionError("The thread waiting on an" + + " inflated monitor was interrupted, thus test" + + " results may be incorrect.", e); + } } }; Thread t = new Thread(inflatingRunnable); + t.setDaemon(true); t.start(); // Wait until thread t enters the monitor. barrier.await(); - // At this point monitor will be owned by thread t, - // so our attempt to enter the same monitor will force - // monitor inflation. - Asserts.assertFalse(unsafe.tryMonitorEnter(monitor), - "Not supposed to enter the monitor first"); - barrier.await(); - t.join(); + synchronized (monitor) { + // At this point thread t is already waiting on the monitor. + // Modifying static field just to avoid lock's elimination. + sharedState++; + } + verifyMonitorState(monitor, true /* inflated */); return monitor; } + /** + * Verifies that {@code monitor} is a stack-lock or inflated lock depending + * on {@code shouldBeInflated} value. If {@code monitor} is inflated while + * it is expected that it should be a stack-lock, then this method attempts + * to deflate it by forcing a safepoint and then verifies the state once + * again. + * + * @param monitor monitor to be verified. + * @param shouldBeInflated flag indicating whether or not monitor is + * expected to be inflated. + * @throws RuntimeException if the {@code monitor} in a wrong state. + */ + public static void verifyMonitorState(Object monitor, + boolean shouldBeInflated) { + if (!shouldBeInflated && WHITE_BOX.isMonitorInflated(monitor)) { + WHITE_BOX.forceSafepoint(); + } + Asserts.assertEQ(WHITE_BOX.isMonitorInflated(monitor), shouldBeInflated, + "Monitor in a wrong state."); + } + /** + * Verifies that monitor used by the {@code provoker} is a stack-lock or + * inflated lock depending on {@code shouldBeInflated} value. If such + * monitor is inflated while it is expected that it should be a stack-lock, + * then this method attempts to deflate it by forcing a safepoint and then + * verifies the state once again. + * + * @param provoker AbortProvoker whose monitor's state should be verified. + * @param shouldBeInflated flag indicating whether or not monitor is + * expected to be inflated. + * @throws RuntimeException if the {@code monitor} in a wrong state. + */ + public static void verifyMonitorState(AbortProvoker provoker, + boolean shouldBeInflated) { + verifyMonitorState(provoker.monitor, shouldBeInflated); + } /** * Get instance of specified AbortProvoker, inflate associated monitor @@ -120,6 +162,7 @@ } for (long i = 0; i < iterations; i++) { + AbortProvoker.verifyMonitorState(provoker, monitorShouldBeInflated); provoker.forceAbort(); } } --- old/test/compiler/testlibrary/rtm/BusyLock.java 2015-04-28 16:18:51.818034850 +0300 +++ new/test/compiler/testlibrary/rtm/BusyLock.java 2015-04-28 16:18:51.734034853 +0300 @@ -77,7 +77,7 @@ } } - public void test() { + public void syncAndTest() { try { barrier.await(); // wait until monitor is locked by a ::run method @@ -85,6 +85,10 @@ } catch (InterruptedException | BrokenBarrierException e) { throw new RuntimeException("Synchronization error happened.", e); } + test(); + } + + public void test() { synchronized(monitor) { BusyLock.field++; } @@ -130,7 +134,7 @@ Thread t = new Thread(busyLock); t.start(); - busyLock.test(); + busyLock.syncAndTest(); t.join(); } } --- old/test/compiler/testlibrary/rtm/MemoryConflictProvoker.java 2015-04-28 16:18:52.170034839 +0300 +++ new/test/compiler/testlibrary/rtm/MemoryConflictProvoker.java 2015-04-28 16:18:52.090034841 +0300 @@ -69,11 +69,6 @@ * Accesses and modifies memory region from within the transaction. */ public void transactionalRegion() { - try { - barrier.await(); - } catch (InterruptedException | BrokenBarrierException e) { - throw new RuntimeException(e); - } for (int i = 0; i < MemoryConflictProvoker.INNER_ITERATIONS; i++) { synchronized(monitor) { MemoryConflictProvoker.field--; @@ -86,6 +81,11 @@ try { Thread t = new Thread(conflictingThread); t.start(); + try { + barrier.await(); + } catch (InterruptedException | BrokenBarrierException e) { + throw new RuntimeException(e); + } transactionalRegion(); t.join(); } catch (Exception e) { --- old/test/compiler/testlibrary/rtm/RTMTestBase.java 2015-04-28 16:18:52.526034827 +0300 +++ new/test/compiler/testlibrary/rtm/RTMTestBase.java 2015-04-28 16:18:52.442034830 +0300 @@ -238,10 +238,10 @@ String[] filteredVMOpts = Utils.getFilteredTestJavaOpts(filters); Collections.addAll(finalVMOpts, filteredVMOpts); Collections.addAll(finalVMOpts, "-Xcomp", "-server", - "-XX:-TieredCompilation", + "-XX:-TieredCompilation", "-XX:+UseRTMLocking", CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-XX:+UseRTMLocking"); + "-Xbootclasspath/a:.", "-XX:+WhiteBoxAPI"); if (test != null) { for (String method : test.getMethodsToCompileNames()) {