/* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ /** * @test * @bug 8031320 * @summary Verify that rtm locking is used for stack locks before * inflation and after it used for inflated locks. * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestUseRTMAfterLockInflation * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestUseRTMAfterLockInflation */ import java.util.List; import com.oracle.java.testlibrary.*; import com.oracle.java.testlibrary.cli.CommandLineOptionTest; import com.oracle.java.testlibrary.cli.predicate.AndPredicate; import rtm.*; import rtm.predicate.SupportedCPU; import rtm.predicate.SupportedVM; /** * Test verifies that RTM is used after lock inflation by executing compiled * method with RTM-based lock elision using stack lock first, then that lock * is inflated and the same compiled method invoked again. * * 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}. * 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 * reasons simultaneously. In order to avoid false negative failures related * to incorrect aborts counting, -XX:RTMRetryCount=0 is used. */ public class TestUseRTMAfterLockInflation extends CommandLineOptionTest { private static final long EXPECTED_LOCKS = 2L * AbortProvoker.DEFAULT_ITERATIONS; private TestUseRTMAfterLockInflation() { super(new AndPredicate(new SupportedVM(), new SupportedCPU())); } @Override protected void runTestCases() throws Throwable { AbortProvoker provoker = AbortType.XABORT.provoker(); long totalLocksCount = 0; OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest( provoker, "-XX:+UseRTMForStackLocks", "-XX:RTMTotalCountIncrRate=1", "-XX:RTMRetryCount=0", "-XX:+PrintPreciseRTMLockingStatistics", Test.class.getName(), AbortType.XABORT.toString()); outputAnalyzer.shouldHaveExitValue(0); List statistics = RTMLockingStatistics.fromString( provoker.getMethodWithLockName(), outputAnalyzer.getOutput()); Asserts.assertEQ(statistics.size(), 2, "VM output should contain two rtm locking statistics entries " + "for method " + provoker.getMethodWithLockName()); for (RTMLockingStatistics s : statistics) { totalLocksCount += s.getTotalLocks(); } Asserts.assertEQ(totalLocksCount, TestUseRTMAfterLockInflation.EXPECTED_LOCKS, "Total lock count should be greater or equal to " + TestUseRTMAfterLockInflation.EXPECTED_LOCKS); } public static class Test { /** * Usage: * Test <provoker type> */ public static void main(String args[]) throws Throwable { Asserts.assertGT(args.length, 0, "AbortType name is expected as first argument."); 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(); } } } public static void main(String args[]) throws Throwable { new TestUseRTMAfterLockInflation().test(); } }