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

Thu, 30 Apr 2015 12:06:39 -0700

author
bmoloden
date
Thu, 30 Apr 2015 12:06:39 -0700
changeset 7798
9041e030d11f
parent 7797
e9a7f132cec3
child 7799
1f0d760ccac1

8050486: compiler/rtm/ tests fail due to monitor deflation at safepoint synchronization
Reviewed-by: kvn, iignatyev

test/compiler/rtm/locking/TestRTMAbortRatio.java file | annotate | diff | comparison | revisions
test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java file | annotate | diff | comparison | revisions
test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java file | annotate | diff | comparison | revisions
test/compiler/rtm/locking/TestRTMLockingThreshold.java file | annotate | diff | comparison | revisions
test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java file | annotate | diff | comparison | revisions
test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java file | annotate | diff | comparison | revisions
test/compiler/testlibrary/rtm/AbortProvoker.java file | annotate | diff | comparison | revisions
test/compiler/testlibrary/rtm/BusyLock.java file | annotate | diff | comparison | revisions
test/compiler/testlibrary/rtm/MemoryConflictProvoker.java file | annotate | diff | comparison | revisions
test/compiler/testlibrary/rtm/RTMTestBase.java file | annotate | diff | comparison | revisions
     1.1 --- a/test/compiler/rtm/locking/TestRTMAbortRatio.java	Thu Apr 30 11:47:53 2015 -0700
     1.2 +++ b/test/compiler/rtm/locking/TestRTMAbortRatio.java	Thu Apr 30 12:06:39 2015 -0700
     1.3 @@ -126,10 +126,7 @@
     1.4  
     1.5          @Override
     1.6          public String[] getMethodsToCompileNames() {
     1.7 -            return new String[] {
     1.8 -                    getMethodWithLockName(),
     1.9 -                    Unsafe.class.getName() + "::addressSize"
    1.10 -            };
    1.11 +            return new String[] { getMethodWithLockName() };
    1.12          }
    1.13  
    1.14          public void lock(boolean abort) {
    1.15 @@ -147,10 +144,12 @@
    1.16          public static void main(String args[]) throws Throwable {
    1.17              Asserts.assertGTE(args.length, 1, "One argument required.");
    1.18              Test t = new Test();
    1.19 -            if (Boolean.valueOf(args[0])) {
    1.20 +            boolean shouldBeInflated = Boolean.valueOf(args[0]);
    1.21 +            if (shouldBeInflated) {
    1.22                  AbortProvoker.inflateMonitor(t.monitor);
    1.23              }
    1.24              for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) {
    1.25 +                AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated);
    1.26                  t.lock(i >= Test.WARMUP_ITERATIONS);
    1.27              }
    1.28          }
     2.1 --- a/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java	Thu Apr 30 11:47:53 2015 -0700
     2.2 +++ b/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java	Thu Apr 30 12:06:39 2015 -0700
     2.3 @@ -156,10 +156,7 @@
     2.4  
     2.5          @Override
     2.6          public String[] getMethodsToCompileNames() {
     2.7 -            return new String[] {
     2.8 -                getMethodWithLockName(),
     2.9 -                sun.misc.Unsafe.class.getName() + "::forceAbort"
    2.10 -            };
    2.11 +            return new String[] { getMethodWithLockName() };
    2.12          }
    2.13  
    2.14          public void forceAbort(int a[], boolean abort) {
    2.15 @@ -182,13 +179,15 @@
    2.16          public static void main(String args[]) throws Throwable {
    2.17              Test t = new Test();
    2.18  
    2.19 -            if (Boolean.valueOf(args[0])) {
    2.20 +            boolean shouldBeInflated = Boolean.valueOf(args[0]);
    2.21 +            if (shouldBeInflated) {
    2.22                  AbortProvoker.inflateMonitor(t.monitor);
    2.23              }
    2.24  
    2.25              int tmp[] = new int[1];
    2.26  
    2.27              for (int i = 0; i < Test.ITERATIONS; i++ ) {
    2.28 +                AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated);
    2.29                  if (i == Test.RANGE_CHECK_AT) {
    2.30                      t.forceAbort(new int[0], false);
    2.31                  } else {
     3.1 --- a/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java	Thu Apr 30 11:47:53 2015 -0700
     3.2 +++ b/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java	Thu Apr 30 12:06:39 2015 -0700
     3.3 @@ -129,10 +129,7 @@
     3.4  
     3.5          @Override
     3.6          public String[] getMethodsToCompileNames() {
     3.7 -            return new String[] {
     3.8 -                getMethodWithLockName(),
     3.9 -                sun.misc.Unsafe.class.getName() + "::addressSize"
    3.10 -            };
    3.11 +            return new String[] { getMethodWithLockName() };
    3.12          }
    3.13  
    3.14          public void forceAbort(boolean abort) {
    3.15 @@ -150,11 +147,12 @@
    3.16          public static void main(String args[]) throws Throwable {
    3.17              Asserts.assertGTE(args.length, 1, "One argument required.");
    3.18              Test t = new Test();
    3.19 -
    3.20 -            if (Boolean.valueOf(args[0])) {
    3.21 +            boolean shouldBeInflated = Boolean.valueOf(args[0]);
    3.22 +            if (shouldBeInflated) {
    3.23                  AbortProvoker.inflateMonitor(t.monitor);
    3.24              }
    3.25              for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) {
    3.26 +                AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated);
    3.27                  t.forceAbort(
    3.28                          i == TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD);
    3.29              }
     4.1 --- a/test/compiler/rtm/locking/TestRTMLockingThreshold.java	Thu Apr 30 11:47:53 2015 -0700
     4.2 +++ b/test/compiler/rtm/locking/TestRTMLockingThreshold.java	Thu Apr 30 12:06:39 2015 -0700
     4.3 @@ -142,10 +142,7 @@
     4.4  
     4.5          @Override
     4.6          public String[] getMethodsToCompileNames() {
     4.7 -            return new String[] {
     4.8 -                getMethodWithLockName(),
     4.9 -                sun.misc.Unsafe.class.getName() + "::addressSize"
    4.10 -            };
    4.11 +            return new String[] { getMethodWithLockName() };
    4.12          }
    4.13  
    4.14          public void lock(boolean abort) {
    4.15 @@ -163,11 +160,12 @@
    4.16          public static void main(String args[]) throws Throwable {
    4.17              Asserts.assertGTE(args.length, 1, "One argument required.");
    4.18              Test t = new Test();
    4.19 -
    4.20 -            if (Boolean.valueOf(args[0])) {
    4.21 +            boolean shouldBeInflated = Boolean.valueOf(args[0]);
    4.22 +            if (shouldBeInflated) {
    4.23                  AbortProvoker.inflateMonitor(t.monitor);
    4.24              }
    4.25              for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) {
    4.26 +                AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated);
    4.27                  t.lock(i % 2 == 1);
    4.28              }
    4.29          }
     5.1 --- a/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java	Thu Apr 30 11:47:53 2015 -0700
     5.2 +++ b/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java	Thu Apr 30 12:06:39 2015 -0700
     5.3 @@ -116,9 +116,7 @@
     5.4  
     5.5          @Override
     5.6          public String[] getMethodsToCompileNames() {
     5.7 -            return new String[] {
     5.8 -                getMethodWithLockName()
     5.9 -            };
    5.10 +            return new String[] { getMethodWithLockName() };
    5.11          }
    5.12  
    5.13          public void lock() {
    5.14 @@ -134,11 +132,13 @@
    5.15          public static void main(String args[]) throws Throwable {
    5.16              Asserts.assertGTE(args.length, 1, "One argument required.");
    5.17              Test test = new Test();
    5.18 -
    5.19 -            if (Boolean.valueOf(args[0])) {
    5.20 +            boolean shouldBeInflated = Boolean.valueOf(args[0]);
    5.21 +            if (shouldBeInflated) {
    5.22                  AbortProvoker.inflateMonitor(test.monitor);
    5.23              }
    5.24              for (long i = 0L; i < Test.TOTAL_ITERATIONS; i++) {
    5.25 +                AbortProvoker.verifyMonitorState(test.monitor,
    5.26 +                        shouldBeInflated);
    5.27                  test.lock();
    5.28              }
    5.29          }
     6.1 --- a/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java	Thu Apr 30 11:47:53 2015 -0700
     6.2 +++ b/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java	Thu Apr 30 12:06:39 2015 -0700
     6.3 @@ -51,7 +51,7 @@
     6.4   * Compiled method invoked {@code AbortProvoker.DEFAULT_ITERATIONS} times before
     6.5   * lock inflation and the same amount of times after inflation.
     6.6   * As a result total locks count should be equal to
     6.7 - * {@code 2*AbortProvoker.DEFAULT_ITERATIONS}.
     6.8 + * {@code 2 * AbortProvoker.DEFAULT_ITERATIONS}.
     6.9   * It is a pretty strict assertion which could fail if some retriable abort
    6.10   * happened: it could be {@code AbortType.RETRIABLE} or
    6.11   * {@code AbortType.MEM_CONFLICT}, but unfortunately abort can has both these
    6.12 @@ -100,7 +100,6 @@
    6.13      }
    6.14  
    6.15      public static class Test {
    6.16 -
    6.17          /**
    6.18           * Usage:
    6.19           * Test &lt;provoker type&gt;
    6.20 @@ -112,10 +111,12 @@
    6.21              AbortProvoker provoker
    6.22                      = AbortType.lookup(Integer.valueOf(args[0])).provoker();
    6.23              for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) {
    6.24 +                AbortProvoker.verifyMonitorState(provoker, false /*deflated*/);
    6.25                  provoker.forceAbort();
    6.26              }
    6.27              provoker.inflateMonitor();
    6.28              for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) {
    6.29 +                AbortProvoker.verifyMonitorState(provoker, true /*inflated*/);
    6.30                  provoker.forceAbort();
    6.31              }
    6.32          }
     7.1 --- a/test/compiler/testlibrary/rtm/AbortProvoker.java	Thu Apr 30 11:47:53 2015 -0700
     7.2 +++ b/test/compiler/testlibrary/rtm/AbortProvoker.java	Thu Apr 30 12:06:39 2015 -0700
     7.3 @@ -29,8 +29,7 @@
     7.4  import java.util.concurrent.CyclicBarrier;
     7.5  
     7.6  import com.oracle.java.testlibrary.Asserts;
     7.7 -import com.oracle.java.testlibrary.Utils;
     7.8 -import sun.misc.Unsafe;
     7.9 +import sun.hotspot.WhiteBox;
    7.10  
    7.11  /**
    7.12   * Base class for different transactional execution abortion
    7.13 @@ -38,6 +37,9 @@
    7.14   */
    7.15  public abstract class AbortProvoker implements CompilableTest {
    7.16      public static final long DEFAULT_ITERATIONS = 10000L;
    7.17 +    private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
    7.18 +    @SuppressWarnings("unused")
    7.19 +    private static int sharedState = 0;
    7.20      /**
    7.21       * Inflates monitor associated with object {@code monitor}.
    7.22       * Inflation is forced by entering the same monitor from
    7.23 @@ -48,36 +50,76 @@
    7.24       * @throws Exception if something went wrong.
    7.25       */
    7.26      public static Object inflateMonitor(Object monitor) throws Exception {
    7.27 -        Unsafe unsafe = Utils.getUnsafe();
    7.28          CyclicBarrier barrier = new CyclicBarrier(2);
    7.29  
    7.30          Runnable inflatingRunnable = () -> {
    7.31 -            unsafe.monitorEnter(monitor);
    7.32 -            try {
    7.33 -                barrier.await();
    7.34 -                barrier.await();
    7.35 -            } catch (InterruptedException | BrokenBarrierException e) {
    7.36 -                throw new RuntimeException(
    7.37 -                        "Synchronization issue occurred.", e);
    7.38 -            } finally {
    7.39 -                unsafe.monitorExit(monitor);
    7.40 +            synchronized (monitor) {
    7.41 +                try {
    7.42 +                    barrier.await();
    7.43 +                } catch (BrokenBarrierException  | InterruptedException e) {
    7.44 +                    throw new RuntimeException(
    7.45 +                            "Synchronization issue occurred.", e);
    7.46 +                }
    7.47 +                try {
    7.48 +                    monitor.wait();
    7.49 +                } catch (InterruptedException e) {
    7.50 +                    throw new AssertionError("The thread waiting on an"
    7.51 +                            + " inflated monitor was interrupted, thus test"
    7.52 +                            + " results may be incorrect.", e);
    7.53 +                }
    7.54              }
    7.55          };
    7.56  
    7.57          Thread t = new Thread(inflatingRunnable);
    7.58 +        t.setDaemon(true);
    7.59          t.start();
    7.60          // Wait until thread t enters the monitor.
    7.61          barrier.await();
    7.62 -        // At this point monitor will be owned by thread t,
    7.63 -        // so our attempt to enter the same monitor will force
    7.64 -        // monitor inflation.
    7.65 -        Asserts.assertFalse(unsafe.tryMonitorEnter(monitor),
    7.66 -                            "Not supposed to enter the monitor first");
    7.67 -        barrier.await();
    7.68 -        t.join();
    7.69 +        synchronized (monitor) {
    7.70 +            // At this point thread t is already waiting on the monitor.
    7.71 +            // Modifying static field just to avoid lock's elimination.
    7.72 +            sharedState++;
    7.73 +        }
    7.74 +        verifyMonitorState(monitor, true /* inflated */);
    7.75          return monitor;
    7.76      }
    7.77  
    7.78 +    /**
    7.79 +     * Verifies that {@code monitor} is a stack-lock or inflated lock depending
    7.80 +     * on {@code shouldBeInflated} value. If {@code monitor} is inflated while
    7.81 +     * it is expected that it should be a stack-lock, then this method attempts
    7.82 +     * to deflate it by forcing a safepoint and then verifies the state once
    7.83 +     * again.
    7.84 +     *
    7.85 +     * @param monitor monitor to be verified.
    7.86 +     * @param shouldBeInflated flag indicating whether or not monitor is
    7.87 +     *                         expected to be inflated.
    7.88 +     * @throws RuntimeException if the {@code monitor} in a wrong state.
    7.89 +     */
    7.90 +    public static void verifyMonitorState(Object monitor,
    7.91 +            boolean shouldBeInflated) {
    7.92 +        if (!shouldBeInflated && WHITE_BOX.isMonitorInflated(monitor)) {
    7.93 +            WHITE_BOX.forceSafepoint();
    7.94 +        }
    7.95 +        Asserts.assertEQ(WHITE_BOX.isMonitorInflated(monitor), shouldBeInflated,
    7.96 +                "Monitor in a wrong state.");
    7.97 +    }
    7.98 +    /**
    7.99 +     * Verifies that monitor used by the {@code provoker} is a stack-lock or
   7.100 +     * inflated lock depending on {@code shouldBeInflated} value. If such
   7.101 +     * monitor is inflated while it is expected that it should be a stack-lock,
   7.102 +     * then this method attempts to deflate it by forcing a safepoint and then
   7.103 +     * verifies the state once again.
   7.104 +     *
   7.105 +     * @param provoker AbortProvoker whose monitor's state should be verified.
   7.106 +     * @param shouldBeInflated flag indicating whether or not monitor is
   7.107 +     *                         expected to be inflated.
   7.108 +     * @throws RuntimeException if the {@code monitor} in a wrong state.
   7.109 +     */
   7.110 +    public static void verifyMonitorState(AbortProvoker provoker,
   7.111 +            boolean shouldBeInflated) {
   7.112 +        verifyMonitorState(provoker.monitor, shouldBeInflated);
   7.113 +    }
   7.114  
   7.115      /**
   7.116       * Get instance of specified AbortProvoker, inflate associated monitor
   7.117 @@ -120,6 +162,7 @@
   7.118          }
   7.119  
   7.120          for (long i = 0; i < iterations; i++) {
   7.121 +            AbortProvoker.verifyMonitorState(provoker, monitorShouldBeInflated);
   7.122              provoker.forceAbort();
   7.123          }
   7.124      }
     8.1 --- a/test/compiler/testlibrary/rtm/BusyLock.java	Thu Apr 30 11:47:53 2015 -0700
     8.2 +++ b/test/compiler/testlibrary/rtm/BusyLock.java	Thu Apr 30 12:06:39 2015 -0700
     8.3 @@ -77,7 +77,7 @@
     8.4          }
     8.5      }
     8.6  
     8.7 -    public void test() {
     8.8 +    public void syncAndTest() {
     8.9          try {
    8.10              barrier.await();
    8.11              // wait until monitor is locked by a ::run method
    8.12 @@ -85,6 +85,10 @@
    8.13          } catch (InterruptedException | BrokenBarrierException e) {
    8.14              throw new RuntimeException("Synchronization error happened.", e);
    8.15          }
    8.16 +        test();
    8.17 +    }
    8.18 +
    8.19 +    public void test() {
    8.20          synchronized(monitor) {
    8.21              BusyLock.field++;
    8.22          }
    8.23 @@ -130,7 +134,7 @@
    8.24  
    8.25          Thread t = new Thread(busyLock);
    8.26          t.start();
    8.27 -        busyLock.test();
    8.28 +        busyLock.syncAndTest();
    8.29          t.join();
    8.30      }
    8.31  }
     9.1 --- a/test/compiler/testlibrary/rtm/MemoryConflictProvoker.java	Thu Apr 30 11:47:53 2015 -0700
     9.2 +++ b/test/compiler/testlibrary/rtm/MemoryConflictProvoker.java	Thu Apr 30 12:06:39 2015 -0700
     9.3 @@ -69,11 +69,6 @@
     9.4       * Accesses and modifies memory region from within the transaction.
     9.5       */
     9.6      public void transactionalRegion() {
     9.7 -        try {
     9.8 -            barrier.await();
     9.9 -        } catch (InterruptedException | BrokenBarrierException e) {
    9.10 -            throw new RuntimeException(e);
    9.11 -        }
    9.12          for (int i = 0; i < MemoryConflictProvoker.INNER_ITERATIONS; i++) {
    9.13              synchronized(monitor) {
    9.14                  MemoryConflictProvoker.field--;
    9.15 @@ -86,6 +81,11 @@
    9.16          try {
    9.17              Thread t = new Thread(conflictingThread);
    9.18              t.start();
    9.19 +            try {
    9.20 +                barrier.await();
    9.21 +            } catch (InterruptedException | BrokenBarrierException e) {
    9.22 +                throw new RuntimeException(e);
    9.23 +            }
    9.24              transactionalRegion();
    9.25              t.join();
    9.26          } catch (Exception e) {
    10.1 --- a/test/compiler/testlibrary/rtm/RTMTestBase.java	Thu Apr 30 11:47:53 2015 -0700
    10.2 +++ b/test/compiler/testlibrary/rtm/RTMTestBase.java	Thu Apr 30 12:06:39 2015 -0700
    10.3 @@ -238,10 +238,10 @@
    10.4          String[] filteredVMOpts = Utils.getFilteredTestJavaOpts(filters);
    10.5          Collections.addAll(finalVMOpts, filteredVMOpts);
    10.6          Collections.addAll(finalVMOpts, "-Xcomp", "-server",
    10.7 -                "-XX:-TieredCompilation",
    10.8 +                "-XX:-TieredCompilation", "-XX:+UseRTMLocking",
    10.9                  CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS,
   10.10                  CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
   10.11 -                "-XX:+UseRTMLocking");
   10.12 +                "-Xbootclasspath/a:.", "-XX:+WhiteBoxAPI");
   10.13  
   10.14          if (test != null) {
   10.15              for (String method : test.getMethodsToCompileNames()) {

mercurial