提交 3703b394 编写于 作者: B bmoloden

8050486: compiler/rtm/ tests fail due to monitor deflation at safepoint synchronization

Reviewed-by: kvn, iignatyev
上级 5cfedb9d
...@@ -126,10 +126,7 @@ public class TestRTMAbortRatio extends CommandLineOptionTest { ...@@ -126,10 +126,7 @@ public class TestRTMAbortRatio extends CommandLineOptionTest {
@Override @Override
public String[] getMethodsToCompileNames() { public String[] getMethodsToCompileNames() {
return new String[] { return new String[] { getMethodWithLockName() };
getMethodWithLockName(),
Unsafe.class.getName() + "::addressSize"
};
} }
public void lock(boolean abort) { public void lock(boolean abort) {
...@@ -147,10 +144,12 @@ public class TestRTMAbortRatio extends CommandLineOptionTest { ...@@ -147,10 +144,12 @@ public class TestRTMAbortRatio extends CommandLineOptionTest {
public static void main(String args[]) throws Throwable { public static void main(String args[]) throws Throwable {
Asserts.assertGTE(args.length, 1, "One argument required."); Asserts.assertGTE(args.length, 1, "One argument required.");
Test t = new Test(); Test t = new Test();
if (Boolean.valueOf(args[0])) { boolean shouldBeInflated = Boolean.valueOf(args[0]);
if (shouldBeInflated) {
AbortProvoker.inflateMonitor(t.monitor); AbortProvoker.inflateMonitor(t.monitor);
} }
for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) { for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) {
AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated);
t.lock(i >= Test.WARMUP_ITERATIONS); t.lock(i >= Test.WARMUP_ITERATIONS);
} }
} }
......
...@@ -156,10 +156,7 @@ public class TestRTMAfterNonRTMDeopt extends CommandLineOptionTest { ...@@ -156,10 +156,7 @@ public class TestRTMAfterNonRTMDeopt extends CommandLineOptionTest {
@Override @Override
public String[] getMethodsToCompileNames() { public String[] getMethodsToCompileNames() {
return new String[] { return new String[] { getMethodWithLockName() };
getMethodWithLockName(),
sun.misc.Unsafe.class.getName() + "::forceAbort"
};
} }
public void forceAbort(int a[], boolean abort) { public void forceAbort(int a[], boolean abort) {
...@@ -182,13 +179,15 @@ public class TestRTMAfterNonRTMDeopt extends CommandLineOptionTest { ...@@ -182,13 +179,15 @@ public class TestRTMAfterNonRTMDeopt extends CommandLineOptionTest {
public static void main(String args[]) throws Throwable { public static void main(String args[]) throws Throwable {
Test t = new Test(); Test t = new Test();
if (Boolean.valueOf(args[0])) { boolean shouldBeInflated = Boolean.valueOf(args[0]);
if (shouldBeInflated) {
AbortProvoker.inflateMonitor(t.monitor); AbortProvoker.inflateMonitor(t.monitor);
} }
int tmp[] = new int[1]; int tmp[] = new int[1];
for (int i = 0; i < Test.ITERATIONS; i++ ) { for (int i = 0; i < Test.ITERATIONS; i++ ) {
AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated);
if (i == Test.RANGE_CHECK_AT) { if (i == Test.RANGE_CHECK_AT) {
t.forceAbort(new int[0], false); t.forceAbort(new int[0], false);
} else { } else {
......
...@@ -129,10 +129,7 @@ public class TestRTMDeoptOnLowAbortRatio extends CommandLineOptionTest { ...@@ -129,10 +129,7 @@ public class TestRTMDeoptOnLowAbortRatio extends CommandLineOptionTest {
@Override @Override
public String[] getMethodsToCompileNames() { public String[] getMethodsToCompileNames() {
return new String[] { return new String[] { getMethodWithLockName() };
getMethodWithLockName(),
sun.misc.Unsafe.class.getName() + "::addressSize"
};
} }
public void forceAbort(boolean abort) { public void forceAbort(boolean abort) {
...@@ -150,11 +147,12 @@ public class TestRTMDeoptOnLowAbortRatio extends CommandLineOptionTest { ...@@ -150,11 +147,12 @@ public class TestRTMDeoptOnLowAbortRatio extends CommandLineOptionTest {
public static void main(String args[]) throws Throwable { public static void main(String args[]) throws Throwable {
Asserts.assertGTE(args.length, 1, "One argument required."); Asserts.assertGTE(args.length, 1, "One argument required.");
Test t = new Test(); Test t = new Test();
boolean shouldBeInflated = Boolean.valueOf(args[0]);
if (Boolean.valueOf(args[0])) { if (shouldBeInflated) {
AbortProvoker.inflateMonitor(t.monitor); AbortProvoker.inflateMonitor(t.monitor);
} }
for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) { for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) {
AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated);
t.forceAbort( t.forceAbort(
i == TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD); i == TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD);
} }
......
...@@ -142,10 +142,7 @@ public class TestRTMLockingThreshold extends CommandLineOptionTest { ...@@ -142,10 +142,7 @@ public class TestRTMLockingThreshold extends CommandLineOptionTest {
@Override @Override
public String[] getMethodsToCompileNames() { public String[] getMethodsToCompileNames() {
return new String[] { return new String[] { getMethodWithLockName() };
getMethodWithLockName(),
sun.misc.Unsafe.class.getName() + "::addressSize"
};
} }
public void lock(boolean abort) { public void lock(boolean abort) {
...@@ -163,11 +160,12 @@ public class TestRTMLockingThreshold extends CommandLineOptionTest { ...@@ -163,11 +160,12 @@ public class TestRTMLockingThreshold extends CommandLineOptionTest {
public static void main(String args[]) throws Throwable { public static void main(String args[]) throws Throwable {
Asserts.assertGTE(args.length, 1, "One argument required."); Asserts.assertGTE(args.length, 1, "One argument required.");
Test t = new Test(); Test t = new Test();
boolean shouldBeInflated = Boolean.valueOf(args[0]);
if (Boolean.valueOf(args[0])) { if (shouldBeInflated) {
AbortProvoker.inflateMonitor(t.monitor); AbortProvoker.inflateMonitor(t.monitor);
} }
for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) { for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) {
AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated);
t.lock(i % 2 == 1); t.lock(i % 2 == 1);
} }
} }
......
...@@ -116,9 +116,7 @@ public class TestRTMTotalCountIncrRate extends CommandLineOptionTest { ...@@ -116,9 +116,7 @@ public class TestRTMTotalCountIncrRate extends CommandLineOptionTest {
@Override @Override
public String[] getMethodsToCompileNames() { public String[] getMethodsToCompileNames() {
return new String[] { return new String[] { getMethodWithLockName() };
getMethodWithLockName()
};
} }
public void lock() { public void lock() {
...@@ -134,11 +132,13 @@ public class TestRTMTotalCountIncrRate extends CommandLineOptionTest { ...@@ -134,11 +132,13 @@ public class TestRTMTotalCountIncrRate extends CommandLineOptionTest {
public static void main(String args[]) throws Throwable { public static void main(String args[]) throws Throwable {
Asserts.assertGTE(args.length, 1, "One argument required."); Asserts.assertGTE(args.length, 1, "One argument required.");
Test test = new Test(); Test test = new Test();
boolean shouldBeInflated = Boolean.valueOf(args[0]);
if (Boolean.valueOf(args[0])) { if (shouldBeInflated) {
AbortProvoker.inflateMonitor(test.monitor); AbortProvoker.inflateMonitor(test.monitor);
} }
for (long i = 0L; i < Test.TOTAL_ITERATIONS; i++) { for (long i = 0L; i < Test.TOTAL_ITERATIONS; i++) {
AbortProvoker.verifyMonitorState(test.monitor,
shouldBeInflated);
test.lock(); test.lock();
} }
} }
......
...@@ -51,7 +51,7 @@ import rtm.predicate.SupportedVM; ...@@ -51,7 +51,7 @@ import rtm.predicate.SupportedVM;
* Compiled method invoked {@code AbortProvoker.DEFAULT_ITERATIONS} times before * Compiled method invoked {@code AbortProvoker.DEFAULT_ITERATIONS} times before
* lock inflation and the same amount of times after inflation. * lock inflation and the same amount of times after inflation.
* As a result total locks count should be equal to * 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 * It is a pretty strict assertion which could fail if some retriable abort
* happened: it could be {@code AbortType.RETRIABLE} or * happened: it could be {@code AbortType.RETRIABLE} or
* {@code AbortType.MEM_CONFLICT}, but unfortunately abort can has both these * {@code AbortType.MEM_CONFLICT}, but unfortunately abort can has both these
...@@ -100,7 +100,6 @@ public class TestUseRTMAfterLockInflation extends CommandLineOptionTest { ...@@ -100,7 +100,6 @@ public class TestUseRTMAfterLockInflation extends CommandLineOptionTest {
} }
public static class Test { public static class Test {
/** /**
* Usage: * Usage:
* Test &lt;provoker type&gt; * Test &lt;provoker type&gt;
...@@ -112,10 +111,12 @@ public class TestUseRTMAfterLockInflation extends CommandLineOptionTest { ...@@ -112,10 +111,12 @@ public class TestUseRTMAfterLockInflation extends CommandLineOptionTest {
AbortProvoker provoker AbortProvoker provoker
= AbortType.lookup(Integer.valueOf(args[0])).provoker(); = AbortType.lookup(Integer.valueOf(args[0])).provoker();
for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) { for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) {
AbortProvoker.verifyMonitorState(provoker, false /*deflated*/);
provoker.forceAbort(); provoker.forceAbort();
} }
provoker.inflateMonitor(); provoker.inflateMonitor();
for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) { for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) {
AbortProvoker.verifyMonitorState(provoker, true /*inflated*/);
provoker.forceAbort(); provoker.forceAbort();
} }
} }
......
...@@ -29,8 +29,7 @@ import java.util.concurrent.BrokenBarrierException; ...@@ -29,8 +29,7 @@ import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier; import java.util.concurrent.CyclicBarrier;
import com.oracle.java.testlibrary.Asserts; import com.oracle.java.testlibrary.Asserts;
import com.oracle.java.testlibrary.Utils; import sun.hotspot.WhiteBox;
import sun.misc.Unsafe;
/** /**
* Base class for different transactional execution abortion * Base class for different transactional execution abortion
...@@ -38,6 +37,9 @@ import sun.misc.Unsafe; ...@@ -38,6 +37,9 @@ import sun.misc.Unsafe;
*/ */
public abstract class AbortProvoker implements CompilableTest { public abstract class AbortProvoker implements CompilableTest {
public static final long DEFAULT_ITERATIONS = 10000L; 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}. * Inflates monitor associated with object {@code monitor}.
* Inflation is forced by entering the same monitor from * Inflation is forced by entering the same monitor from
...@@ -48,36 +50,76 @@ public abstract class AbortProvoker implements CompilableTest { ...@@ -48,36 +50,76 @@ public abstract class AbortProvoker implements CompilableTest {
* @throws Exception if something went wrong. * @throws Exception if something went wrong.
*/ */
public static Object inflateMonitor(Object monitor) throws Exception { public static Object inflateMonitor(Object monitor) throws Exception {
Unsafe unsafe = Utils.getUnsafe();
CyclicBarrier barrier = new CyclicBarrier(2); CyclicBarrier barrier = new CyclicBarrier(2);
Runnable inflatingRunnable = () -> { Runnable inflatingRunnable = () -> {
unsafe.monitorEnter(monitor); synchronized (monitor) {
try { try {
barrier.await(); barrier.await();
barrier.await(); } catch (BrokenBarrierException | InterruptedException e) {
} catch (InterruptedException | BrokenBarrierException e) {
throw new RuntimeException( throw new RuntimeException(
"Synchronization issue occurred.", e); "Synchronization issue occurred.", e);
} finally { }
unsafe.monitorExit(monitor); 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); Thread t = new Thread(inflatingRunnable);
t.setDaemon(true);
t.start(); t.start();
// Wait until thread t enters the monitor. // Wait until thread t enters the monitor.
barrier.await(); barrier.await();
// At this point monitor will be owned by thread t, synchronized (monitor) {
// so our attempt to enter the same monitor will force // At this point thread t is already waiting on the monitor.
// monitor inflation. // Modifying static field just to avoid lock's elimination.
Asserts.assertFalse(unsafe.tryMonitorEnter(monitor), sharedState++;
"Not supposed to enter the monitor first"); }
barrier.await(); verifyMonitorState(monitor, true /* inflated */);
t.join();
return monitor; 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 * Get instance of specified AbortProvoker, inflate associated monitor
...@@ -120,6 +162,7 @@ public abstract class AbortProvoker implements CompilableTest { ...@@ -120,6 +162,7 @@ public abstract class AbortProvoker implements CompilableTest {
} }
for (long i = 0; i < iterations; i++) { for (long i = 0; i < iterations; i++) {
AbortProvoker.verifyMonitorState(provoker, monitorShouldBeInflated);
provoker.forceAbort(); provoker.forceAbort();
} }
} }
......
...@@ -77,7 +77,7 @@ public class BusyLock implements CompilableTest, Runnable { ...@@ -77,7 +77,7 @@ public class BusyLock implements CompilableTest, Runnable {
} }
} }
public void test() { public void syncAndTest() {
try { try {
barrier.await(); barrier.await();
// wait until monitor is locked by a ::run method // wait until monitor is locked by a ::run method
...@@ -85,6 +85,10 @@ public class BusyLock implements CompilableTest, Runnable { ...@@ -85,6 +85,10 @@ public class BusyLock implements CompilableTest, Runnable {
} catch (InterruptedException | BrokenBarrierException e) { } catch (InterruptedException | BrokenBarrierException e) {
throw new RuntimeException("Synchronization error happened.", e); throw new RuntimeException("Synchronization error happened.", e);
} }
test();
}
public void test() {
synchronized(monitor) { synchronized(monitor) {
BusyLock.field++; BusyLock.field++;
} }
...@@ -130,7 +134,7 @@ public class BusyLock implements CompilableTest, Runnable { ...@@ -130,7 +134,7 @@ public class BusyLock implements CompilableTest, Runnable {
Thread t = new Thread(busyLock); Thread t = new Thread(busyLock);
t.start(); t.start();
busyLock.test(); busyLock.syncAndTest();
t.join(); t.join();
} }
} }
...@@ -69,11 +69,6 @@ class MemoryConflictProvoker extends AbortProvoker { ...@@ -69,11 +69,6 @@ class MemoryConflictProvoker extends AbortProvoker {
* Accesses and modifies memory region from within the transaction. * Accesses and modifies memory region from within the transaction.
*/ */
public void transactionalRegion() { public void transactionalRegion() {
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
throw new RuntimeException(e);
}
for (int i = 0; i < MemoryConflictProvoker.INNER_ITERATIONS; i++) { for (int i = 0; i < MemoryConflictProvoker.INNER_ITERATIONS; i++) {
synchronized(monitor) { synchronized(monitor) {
MemoryConflictProvoker.field--; MemoryConflictProvoker.field--;
...@@ -86,6 +81,11 @@ class MemoryConflictProvoker extends AbortProvoker { ...@@ -86,6 +81,11 @@ class MemoryConflictProvoker extends AbortProvoker {
try { try {
Thread t = new Thread(conflictingThread); Thread t = new Thread(conflictingThread);
t.start(); t.start();
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
throw new RuntimeException(e);
}
transactionalRegion(); transactionalRegion();
t.join(); t.join();
} catch (Exception e) { } catch (Exception e) {
......
...@@ -238,10 +238,10 @@ public class RTMTestBase { ...@@ -238,10 +238,10 @@ public class RTMTestBase {
String[] filteredVMOpts = Utils.getFilteredTestJavaOpts(filters); String[] filteredVMOpts = Utils.getFilteredTestJavaOpts(filters);
Collections.addAll(finalVMOpts, filteredVMOpts); Collections.addAll(finalVMOpts, filteredVMOpts);
Collections.addAll(finalVMOpts, "-Xcomp", "-server", Collections.addAll(finalVMOpts, "-Xcomp", "-server",
"-XX:-TieredCompilation", "-XX:-TieredCompilation", "-XX:+UseRTMLocking",
CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS,
CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
"-XX:+UseRTMLocking"); "-Xbootclasspath/a:.", "-XX:+WhiteBoxAPI");
if (test != null) { if (test != null) {
for (String method : test.getMethodsToCompileNames()) { for (String method : test.getMethodsToCompileNames()) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册