15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /**
25 * @test
26 * @bug 8227745
27 * @summary Collection of test cases that check if optimizations based on escape analysis are reverted just before non-escaping objects escape through JVMTI.
28 * @author Richard Reingruber richard DOT reingruber AT sap DOT com
29 *
30 * @requires ((vm.compMode == "Xmixed") & vm.compiler2.enabled)
31 * @library /test/lib /test/hotspot/jtreg
32 *
33 * @run build TestScaffold VMConnection TargetListener TargetAdapter sun.hotspot.WhiteBox
34 * @run driver ClassFileInstaller sun.hotspot.WhiteBox
35 * sun.hotspot.WhiteBox$WhiteBoxPermission
36 * @run compile -g EATests.java
37 * @run driver EATests
38 * -XX:+UnlockDiagnosticVMOptions
39 * -Xms256m -Xmx256m
40 * -Xbootclasspath/a:.
41 * -XX:CompileCommand=dontinline,*::dontinline_*
42 * -XX:+WhiteBoxAPI
43 * -Xbatch
44 * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking
45 * @run driver EATests
46 * -XX:+UnlockDiagnosticVMOptions
47 * -Xms256m -Xmx256m
48 * -Xbootclasspath/a:.
49 * -XX:CompileCommand=dontinline,*::dontinline_*
50 * -XX:+WhiteBoxAPI
51 * -Xbatch
52 * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:-EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking -XX:-UseOptoBiasInlining
53 * @run driver EATests
54 * -XX:+UnlockDiagnosticVMOptions
55 * -Xms256m -Xmx256m
74 * -XX:+WhiteBoxAPI
75 * -Xbatch
76 * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:-UseBiasedLocking
77 * @run driver EATests
78 * -XX:+UnlockDiagnosticVMOptions
79 * -Xms256m -Xmx256m
80 * -Xbootclasspath/a:.
81 * -XX:CompileCommand=dontinline,*::dontinline_*
82 * -XX:+WhiteBoxAPI
83 * -Xbatch
84 * -XX:+DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:-UseBiasedLocking
85 * @run driver EATests
86 * -XX:+UnlockDiagnosticVMOptions
87 * -Xms256m -Xmx256m
88 * -Xbootclasspath/a:.
89 * -XX:CompileCommand=dontinline,*::dontinline_*
90 * -XX:+WhiteBoxAPI
91 * -Xbatch
92 * -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:-UseBiasedLocking
93 *
94 * @comment Excercise -XX:DeoptimizeObjectsALot. Mostly to prevent bit-rot, because the option is meant to stress object deoptimization
95 * with non-synthetic workloads.
96 * @run driver EATests
97 * -XX:+UnlockDiagnosticVMOptions
98 * -Xms256m -Xmx256m
99 * -Xbootclasspath/a:.
100 * -XX:CompileCommand=dontinline,*::dontinline_*
101 * -XX:+WhiteBoxAPI
102 * -Xbatch
103 * -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:-UseBiasedLocking
104 * -XX:+IgnoreUnrecognizedVMOptions -XX:DeoptimizeObjectsALot=2 -XX:DeoptimizeObjectsALotThreadCount=2
105 */
106
107 import java.lang.reflect.Array;
108 import java.util.Arrays;
109 import java.util.List;
110 import java.util.Map;
111 import java.util.function.Function;
112
113 import com.sun.jdi.*;
114 import com.sun.jdi.event.*;
115
116 import compiler.testlibrary.CompilerUtils;
117 import compiler.whitebox.CompilerWhiteBoxTest;
118 import jdk.test.lib.Asserts;
119 import sun.hotspot.WhiteBox;
120
121
122 /////////////////////////////////////////////////////////////////////////////
123 //
124 // Shared base class for test cases for both, debugger and debuggee.
125 //
126 /////////////////////////////////////////////////////////////////////////////
127
128 class EATestCaseBaseShared {
129 // In interactive mode we wait for a keypress before every test case.
130 public static final boolean INTERACTIVE =
131 System.getProperty("EATests.interactive") != null &&
132 System.getProperty("EATests.interactive").equals("true");
133
134 // If the property is given, then just the test case it refers to is executed.
135 // Use it to diagnose test failures.
136 public static final String RUN_ONLY_TEST_CASE_PROPERTY = "EATests.onlytestcase";
137 public static final String RUN_ONLY_TEST_CASE = System.getProperty(RUN_ONLY_TEST_CASE_PROPERTY);
230
231 public TargetVMOptions targetVMOptions;
232 public ThreadReference targetMainThread;
233
234 EATests(String args[]) {
235 super(args);
236 }
237
238 public static void main(String[] args) throws Exception {
239 if (EATestCaseBaseShared.RUN_ONLY_TEST_CASE != null) {
240 args = Arrays.copyOf(args, args.length + 1);
241 args[args.length - 1] = "-D" + EATestCaseBaseShared.RUN_ONLY_TEST_CASE_PROPERTY + "=" + EATestCaseBaseShared.RUN_ONLY_TEST_CASE;
242 }
243 new EATests(args).startTests();
244 }
245
246 public static class TargetVMOptions {
247
248 public final boolean UseJVMCICompiler;
249 public final boolean EliminateAllocations;
250 public final int DeoptimizeObjectsALot;
251
252 public TargetVMOptions(EATests env, ClassType testCaseBaseTargetClass) {
253 Value val = testCaseBaseTargetClass.getValue(testCaseBaseTargetClass.fieldByName("EliminateAllocations"));
254 EliminateAllocations = ((PrimitiveValue) val).booleanValue();
255 val = testCaseBaseTargetClass.getValue(testCaseBaseTargetClass.fieldByName("DeoptimizeObjectsALot"));
256 DeoptimizeObjectsALot = ((PrimitiveValue) val).intValue();
257 val = testCaseBaseTargetClass.getValue(testCaseBaseTargetClass.fieldByName("UseJVMCICompiler"));
258 UseJVMCICompiler = ((PrimitiveValue) val).booleanValue();
259 }
260
261 }
262
263 // Execute known test cases
264 protected void runTests() throws Exception {
265 String targetProgName = EATestsTarget.class.getName();
266 msg("starting to main method in class " + targetProgName);
267 startToMain(targetProgName);
268 msg("resuming to EATestCaseBaseTarget.staticSetUpDone()V");
269 targetMainThread = resumeTo("EATestCaseBaseTarget", "staticSetUpDone", "()V").thread();
270 Location loc = targetMainThread.frame(0).location();
271 Asserts.assertEQ("staticSetUpDone", loc.method().name());
272
273 targetVMOptions = new TargetVMOptions(this, (ClassType) loc.declaringType());
274
275 // Materializing test cases, i.e. reallocating objects on the heap
276 new EAMaterializeLocalVariableUponGet() .run(this);
707 public volatile long loopCount;
708
709 /**
710 * Used in {@link EATestCaseBaseDebugger#terminateEndlessLoop()} to signal target to leave the endless loop.
711 */
712 public volatile boolean doLoop;
713
714 public long checkSum;
715
716 public static final String TESTMETHOD_DEFAULT_NAME = "dontinline_testMethod";
717
718 public static final WhiteBox WB = WhiteBox.getWhiteBox();
719
720 public static boolean unbox(Boolean value, boolean dflt) {
721 return value == null ? dflt : value;
722 }
723
724 public static final boolean UseJVMCICompiler = unbox(WB.getBooleanVMFlag("UseJVMCICompiler"), false); // read by debugger
725 public static final boolean DoEscapeAnalysis = unbox(WB.getBooleanVMFlag("DoEscapeAnalysis"), UseJVMCICompiler);
726 public static final boolean EliminateAllocations = unbox(WB.getBooleanVMFlag("EliminateAllocations"), UseJVMCICompiler); // read by debugger
727 public static final long DeoptimizeObjectsALot = WB.getIntVMFlag("DeoptimizeObjectsALot"); // read by debugger
728 public static final long BiasedLockingBulkRebiasThreshold = WB.getIntxVMFlag("BiasedLockingBulkRebiasThreshold");
729 public static final long BiasedLockingBulkRevokeThreshold = WB.getIntxVMFlag("BiasedLockingBulkRevokeThreshold");
730
731 public String testMethodName;
732 public int testMethodDepth;
733
734 // Results produced by dontinline_testMethod()
735 public int iResult;
736 public long lResult;
737 public float fResult;
738 public double dResult;
739
740
741 public boolean warmupDone;
742
743 public volatile Object biasToBeRevoked;
744
745 // an object with an inflated monitor
746 public static XYVal inflatedLock;
747 public static Thread inflatorThread;
833 public int dontinline_brkpt_iret() {
834 dontinline_brkpt();
835 return 42;
836 }
837
838 /**
839 * It is a common protocol to have the debugger set a breakpoint in this method and have {@link
840 * #dontinline_testMethod()} call it and then perform some test actions on debugger side.
841 * After that it is checked if a frame of {@link #dontinline_testMethod()} is found at the
842 * expected depth on stack and if it is (not) marked for deoptimization as expected.
843 */
844 public void dontinline_brkpt() {
845 // will set breakpoint here after warmup
846 if (warmupDone) {
847 // check if test method is at expected depth
848 StackTraceElement[] frames = Thread.currentThread().getStackTrace();
849 int stackTraceDepth = testMethodDepth + 1; // ignore java.lang.Thread.getStackTrace()
850 Asserts.assertEQ(testMethodName, frames[stackTraceDepth].getMethodName(),
851 testCaseName + ": test method not found at depth " + testMethodDepth);
852 // check if the frame is (not) deoptimized as expected
853 if (DeoptimizeObjectsALot == 0) {
854 if (testFrameShouldBeDeoptimized()) {
855 Asserts.assertTrue(WB.isFrameDeoptimized(testMethodDepth+1),
856 testCaseName + ": expected test method frame at depth " + testMethodDepth + " to be deoptimized");
857 } else {
858 Asserts.assertFalse(WB.isFrameDeoptimized(testMethodDepth+1),
859 testCaseName + ": expected test method frame at depth " + testMethodDepth + " not to be deoptimized");
860 }
861 }
862 }
863 }
864
865 /**
866 * Some test cases run busy endless loops by initializing {@link #loopCount}
867 * to {@link Long#MAX_VALUE} after warm-up and then counting down to 0 in their main test method.
868 * During warm-up {@link #loopCount} is initialized to a small value.
869 */
870 public long dontinline_endlessLoop() {
871 long cs = checkSum;
872 doLoop = true;
873 while (loopCount-- > 0 && doLoop) {
1721
1722 public void testMethod_inlined(XYVal l2) {
1723 synchronized (l2) {
1724 dontinline_brkpt();
1725 }
1726 }
1727 }
1728
1729 class EARelockingRecursive extends EATestCaseBaseDebugger {
1730
1731 public void runTestCase() throws Exception {
1732 BreakpointEvent bpe = env.resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1733 printStack(bpe.thread());
1734 @SuppressWarnings("unused")
1735 ObjectReference o = getLocalRef(bpe.thread().frame(2), XYVAL_NAME, "l1");
1736 }
1737 }
1738
1739 /////////////////////////////////////////////////////////////////////////////
1740
1741 // Object ref l1 is retrieved by the debugger at a location where nested lockes are ommitted. The
1742 // accessed object is globally reachable already before the access, therefore no relocking is done.
1743 class EARelockingNestedInflatedTarget extends EATestCaseBaseTarget {
1744
1745 @Override
1746 public void setUp() {
1747 super.setUp();
1748 testMethodDepth = 2;
1749 }
1750
1751 @Override
1752 public boolean testFrameShouldBeDeoptimized() {
1753 // Access does not trigger deopt., as escape state is already global escape.
1754 return false;
1755 }
1756
1757 public void dontinline_testMethod() {
1758 XYVal l1 = inflatedLock;
1759 synchronized (l1) {
1760 testMethod_inlined(l1);
1761 }
2527 boolean coughtOom = false;
2528 try {
2529 // try to pop dontinline_consume_all_memory_brkpt
2530 thread.popFrames(thread.frame(1));
2531 } catch (VMOutOfMemoryException oom) {
2532 // as expected
2533 msg("cought OOM");
2534 coughtOom = true;
2535 }
2536 freeAllMemory();
2537 // We succeeded to pop just one frame. When we continue, we will call dontinline_brkpt() again.
2538 Asserts.assertTrue(coughtOom || !env.targetVMOptions.EliminateAllocations, "PopFrame should have triggered an OOM exception in target");
2539 String expectedTopFrame =
2540 env.targetVMOptions.EliminateAllocations ? "dontinline_consume_all_memory_brkpt" : "dontinline_testMethod";
2541 Asserts.assertEQ(expectedTopFrame, thread.frame(0).location().method().name());
2542 printStack(thread);
2543 }
2544
2545 @Override
2546 public boolean shouldSkip() {
2547 // OOMEs because of realloc failures with DeoptimizeObjectsALot > 0 are too random.
2548 // And graal currently doesn't provide all information about non-escaping objects in debug info
2549 return super.shouldSkip() || (env.targetVMOptions.DeoptimizeObjectsALot > 0) || env.targetVMOptions.UseJVMCICompiler;
2550 }
2551 }
2552
2553 class EAPopFrameNotInlinedReallocFailureTarget extends EATestCaseBaseTarget {
2554
2555 public boolean doneAlready;
2556
2557 public void dontinline_testMethod() {
2558 long a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // scalar replaced
2559 Vector10 v = new Vector10(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // scalar replaced
2560 dontinline_consume_all_memory_brkpt();
2561 lResult = a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9]
2562 + v.i0 + v.i1 + v.i2 + v.i3 + v.i4 + v.i5 + v.i6 + v.i7 + v.i8 + v.i9;
2563 }
2564
2565 public void dontinline_consume_all_memory_brkpt() {
2566 if (warmupDone && !doneAlready) {
2567 doneAlready = true;
2568 consumeAllMemory(); // provoke reallocation failure
2569 dontinline_brkpt();
2570 }
2571 }
2572
2573 @Override
2574 public void setUp() {
2575 super.setUp();
2576 testMethodDepth = 2;
2577 }
2578
2579 @Override
2580 public long getExpectedLResult() {
2581 long n = 10;
2582 return 2*n*(n+1)/2;
2583 }
2584
2585 @Override
2586 public boolean shouldSkip() {
2587 // OOMEs because of realloc failures with DeoptimizeObjectsALot > 0 are too random.
2588 // And graal currently doesn't provide all information about non-escaping objects in debug info
2589 return super.shouldSkip() || (DeoptimizeObjectsALot > 0) || UseJVMCICompiler;
2590 }
2591 }
2592
2593 /////////////////////////////////////////////////////////////////////////////
2594
2595 /**
2596 * Pop inlined top frame dropping into method with scalar replaced opjects.
2597 */
2598 class EAPopInlinedMethodWithScalarReplacedObjectsReallocFailure extends EATestCaseBaseDebugger {
2599
2600 public void runTestCase() throws Exception {
2601 ThreadReference thread = env.targetMainThread;
2602 thread.resume();
2603 waitUntilTargetHasEnteredEndlessLoop();
2604
2605 thread.suspend();
2606 printStack(thread);
2607 // frame[0]: EAPopInlinedMethodWithScalarReplacedObjectsReallocFailureTarget.inlinedCallForcedToReturn()
2608 // frame[1]: EAPopInlinedMethodWithScalarReplacedObjectsReallocFailureTarget.dontinline_testMethod()
2609 // frame[2]: EATestCaseBaseTarget.run()
2616 } catch (VMOutOfMemoryException oom) {
2617 // as expected
2618 msg("cought OOM");
2619 coughtOom = true;
2620 }
2621 printStack(thread);
2622 // frame[0]: EAPopInlinedMethodWithScalarReplacedObjectsReallocFailureTarget.inlinedCallForcedToReturn()
2623 // frame[1]: EAPopInlinedMethodWithScalarReplacedObjectsReallocFailureTarget.dontinline_testMethod()
2624 // frame[2]: EATestCaseBaseTarget.run()
2625
2626 freeAllMemory();
2627 setField(testCase, "loopCount", env.vm().mirrorOf(0)); // terminate loop
2628 Asserts.assertTrue(coughtOom || !env.targetVMOptions.EliminateAllocations, "PopFrame should have triggered an OOM exception in target");
2629 String expectedTopFrame =
2630 env.targetVMOptions.EliminateAllocations ? "inlinedCallForcedToReturn" : "dontinline_testMethod";
2631 Asserts.assertEQ(expectedTopFrame, thread.frame(0).location().method().name());
2632 }
2633
2634 @Override
2635 public boolean shouldSkip() {
2636 // OOMEs because of realloc failures with DeoptimizeObjectsALot > 0 are too random.
2637 // And graal currently doesn't provide all information about non-escaping objects in debug info
2638 return super.shouldSkip() || (env.targetVMOptions.DeoptimizeObjectsALot > 0) || env.targetVMOptions.UseJVMCICompiler;
2639 }
2640 }
2641
2642 class EAPopInlinedMethodWithScalarReplacedObjectsReallocFailureTarget extends EATestCaseBaseTarget {
2643
2644 public long checkSum;
2645
2646 public void dontinline_testMethod() {
2647 long a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // scalar replaced
2648 Vector10 v = new Vector10(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // scalar replaced
2649 long l = inlinedCallForcedToReturn();
2650 lResult = a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9]
2651 + v.i0 + v.i1 + v.i2 + v.i3 + v.i4 + v.i5 + v.i6 + v.i7 + v.i8 + v.i9;
2652 }
2653
2654 public long inlinedCallForcedToReturn() {
2655 long cs = checkSum;
2656 dontinline_consumeAllMemory();
2657 while (loopCount-- > 0) {
2658 targetIsInLoop = true;
2672 @Override
2673 public long getExpectedLResult() {
2674 long n = 10;
2675 return 2*n*(n+1)/2;
2676 }
2677
2678 @Override
2679 public void setUp() {
2680 super.setUp();
2681 loopCount = 3;
2682 }
2683
2684 public void warmupDone() {
2685 super.warmupDone();
2686 msg("enter 'endless' loop by setting loopCount = Long.MAX_VALUE");
2687 loopCount = Long.MAX_VALUE; // endless loop
2688 }
2689
2690 @Override
2691 public boolean shouldSkip() {
2692 // OOMEs because of realloc failures with DeoptimizeObjectsALot > 0 are too random.
2693 // And graal currently doesn't provide all information about non-escaping objects in debug info
2694 return super.shouldSkip() || (DeoptimizeObjectsALot > 0) || UseJVMCICompiler;
2695 }
2696 }
2697
2698 /////////////////////////////////////////////////////////////////////////////
2699 //
2700 // ForceEarlyReturn tests
2701 //
2702 /////////////////////////////////////////////////////////////////////////////
2703
2704 /**
2705 * ForceEarlyReturn into caller frame with scalar replaced objects.
2706 */
2707 class EAForceEarlyReturnNotInlined extends EATestCaseBaseDebugger {
2708
2709 public void runTestCase() throws Exception {
2710 BreakpointEvent bpe = env.resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
2711 ThreadReference thread = bpe.thread();
2712 printStack(thread);
2713 // frame[0]: EATestCaseBaseTarget.dontinline_brkpt()
2714 // frame[1]: EATestCaseBaseTarget.dontinline_brkpt_iret()
2873 thread.forceEarlyReturn(env.vm().mirrorOf(43)); // Request force return 43 from inlinedCallForcedToReturn()
2874 // reallocation is triggered here
2875 } catch (VMOutOfMemoryException oom) {
2876 // as expected
2877 msg("cought OOM");
2878 coughtOom = true;
2879 }
2880 freeAllMemory();
2881 if (env.targetVMOptions.EliminateAllocations) {
2882 Asserts.assertTrue(coughtOom, "PopFrame should have triggered an OOM exception in target");
2883 thread.forceEarlyReturn(env.vm().mirrorOf(43));
2884 }
2885 msg("Step over instruction to do the forced return");
2886 env.stepOverInstruction(thread);
2887 printStack(thread);
2888 msg("ForceEarlyReturn DONE");
2889 }
2890
2891 @Override
2892 public boolean shouldSkip() {
2893 // OOMEs because of realloc failures with DeoptimizeObjectsALot > 0 are too random.
2894 // And Graal currently doesn't support Force Early Return
2895 return super.shouldSkip() || (env.targetVMOptions.DeoptimizeObjectsALot > 0) || env.targetVMOptions.UseJVMCICompiler;
2896 }
2897 }
2898
2899 class EAForceEarlyReturnOfInlinedMethodWithScalarReplacedObjectsReallocFailureTarget extends EATestCaseBaseTarget {
2900
2901 public int checkSum;
2902
2903 public void dontinline_testMethod() {
2904 long a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // scalar replaced
2905 Vector10 v = new Vector10(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // scalar replaced
2906 long l = inlinedCallForcedToReturn();
2907 lResult = a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9]
2908 + v.i0 + v.i1 + v.i2 + v.i3 + v.i4 + v.i5 + v.i6 + v.i7 + v.i8 + v.i9 + l;
2909 }
2910
2911 public long inlinedCallForcedToReturn() { // forced to return 43
2912 long cs = checkSum;
2913 dontinline_consumeAllMemory();
2914 while (loopCount-- > 0) {
2915 targetIsInLoop = true;
2930 public long getExpectedLResult() {
2931 long n = 10;
2932 return 2*n*(n+1)/2 + 43;
2933 }
2934
2935 @Override
2936 public void setUp() {
2937 super.setUp();
2938 testMethodDepth = 2;
2939 loopCount = 3;
2940 }
2941
2942 public void warmupDone() {
2943 super.warmupDone();
2944 msg("enter 'endless' loop by setting loopCount = Long.MAX_VALUE");
2945 loopCount = Long.MAX_VALUE; // endless loop
2946 }
2947
2948 @Override
2949 public boolean shouldSkip() {
2950 // OOMEs because of realloc failures with DeoptimizeObjectsALot > 0 are too random.
2951 // And Graal currently doesn't support Force Early Return
2952 return super.shouldSkip() || (DeoptimizeObjectsALot > 0) || UseJVMCICompiler;
2953 }
2954 }
2955
2956 /////////////////////////////////////////////////////////////////////////////
2957 //
2958 // Get Instances of ReferenceType
2959 //
2960 /////////////////////////////////////////////////////////////////////////////
2961
2962 /**
2963 * Check if instances of a type are found even if they are scalar replaced. To stress the
2964 * implementation a little more, the instances should be retrieved while the target is running.
2965 */
2966 class EAGetInstancesOfReferenceType extends EATestCaseBaseDebugger {
2967
2968 public void runTestCase() throws Exception {
2969 printStack(env.targetMainThread);
2970 ReferenceType cls = ((ClassObjectReference)getField(testCase, "cls")).reflectedType();
2971 msg("reflected type is " + cls);
2972 msg("resume");
|
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /**
25 * @test
26 * @bug 8227745
27 * @summary Collection of test cases that check if optimizations based on escape analysis are reverted just before non-escaping objects escape through JVMTI.
28 * @author Richard Reingruber richard DOT reingruber AT sap DOT com
29 *
30 * @requires ((vm.compMode == "Xmixed") & vm.compiler2.enabled)
31 * @library /test/lib /test/hotspot/jtreg
32 *
33 * @run build TestScaffold VMConnection TargetListener TargetAdapter sun.hotspot.WhiteBox
34 * @run driver ClassFileInstaller sun.hotspot.WhiteBox
35 * @run compile -g EATests.java
36 * @run driver EATests
37 * -XX:+UnlockDiagnosticVMOptions
38 * -Xms256m -Xmx256m
39 * -Xbootclasspath/a:.
40 * -XX:CompileCommand=dontinline,*::dontinline_*
41 * -XX:+WhiteBoxAPI
42 * -Xbatch
43 * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking
44 * @run driver EATests
45 * -XX:+UnlockDiagnosticVMOptions
46 * -Xms256m -Xmx256m
47 * -Xbootclasspath/a:.
48 * -XX:CompileCommand=dontinline,*::dontinline_*
49 * -XX:+WhiteBoxAPI
50 * -Xbatch
51 * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:-EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking -XX:-UseOptoBiasInlining
52 * @run driver EATests
53 * -XX:+UnlockDiagnosticVMOptions
54 * -Xms256m -Xmx256m
73 * -XX:+WhiteBoxAPI
74 * -Xbatch
75 * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:-UseBiasedLocking
76 * @run driver EATests
77 * -XX:+UnlockDiagnosticVMOptions
78 * -Xms256m -Xmx256m
79 * -Xbootclasspath/a:.
80 * -XX:CompileCommand=dontinline,*::dontinline_*
81 * -XX:+WhiteBoxAPI
82 * -Xbatch
83 * -XX:+DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:-UseBiasedLocking
84 * @run driver EATests
85 * -XX:+UnlockDiagnosticVMOptions
86 * -Xms256m -Xmx256m
87 * -Xbootclasspath/a:.
88 * -XX:CompileCommand=dontinline,*::dontinline_*
89 * -XX:+WhiteBoxAPI
90 * -Xbatch
91 * -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:-UseBiasedLocking
92 *
93 * @comment Excercise -XX:+DeoptimizeObjectsALot. Mostly to prevent bit-rot, because the option is meant to stress object deoptimization
94 * with non-synthetic workloads.
95 * @run driver EATests
96 * -XX:+UnlockDiagnosticVMOptions
97 * -Xms256m -Xmx256m
98 * -Xbootclasspath/a:.
99 * -XX:CompileCommand=dontinline,*::dontinline_*
100 * -XX:+WhiteBoxAPI
101 * -Xbatch
102 * -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:-UseBiasedLocking
103 * -XX:+IgnoreUnrecognizedVMOptions -XX:+DeoptimizeObjectsALot
104 */
105
106 import com.sun.jdi.*;
107 import com.sun.jdi.event.*;
108 import compiler.testlibrary.CompilerUtils;
109 import compiler.whitebox.CompilerWhiteBoxTest;
110
111 import java.lang.reflect.Array;
112 import java.util.Arrays;
113 import java.util.List;
114 import java.util.Map;
115 import java.util.function.Function;
116
117 import jdk.test.lib.Asserts;
118 import sun.hotspot.WhiteBox;
119
120
121 /////////////////////////////////////////////////////////////////////////////
122 //
123 // Shared base class for test cases for both, debugger and debuggee.
124 //
125 /////////////////////////////////////////////////////////////////////////////
126
127 class EATestCaseBaseShared {
128 // In interactive mode we wait for a keypress before every test case.
129 public static final boolean INTERACTIVE =
130 System.getProperty("EATests.interactive") != null &&
131 System.getProperty("EATests.interactive").equals("true");
132
133 // If the property is given, then just the test case it refers to is executed.
134 // Use it to diagnose test failures.
135 public static final String RUN_ONLY_TEST_CASE_PROPERTY = "EATests.onlytestcase";
136 public static final String RUN_ONLY_TEST_CASE = System.getProperty(RUN_ONLY_TEST_CASE_PROPERTY);
229
230 public TargetVMOptions targetVMOptions;
231 public ThreadReference targetMainThread;
232
233 EATests(String args[]) {
234 super(args);
235 }
236
237 public static void main(String[] args) throws Exception {
238 if (EATestCaseBaseShared.RUN_ONLY_TEST_CASE != null) {
239 args = Arrays.copyOf(args, args.length + 1);
240 args[args.length - 1] = "-D" + EATestCaseBaseShared.RUN_ONLY_TEST_CASE_PROPERTY + "=" + EATestCaseBaseShared.RUN_ONLY_TEST_CASE;
241 }
242 new EATests(args).startTests();
243 }
244
245 public static class TargetVMOptions {
246
247 public final boolean UseJVMCICompiler;
248 public final boolean EliminateAllocations;
249 public final boolean DeoptimizeObjectsALot;
250
251 public TargetVMOptions(EATests env, ClassType testCaseBaseTargetClass) {
252 Value val = testCaseBaseTargetClass.getValue(testCaseBaseTargetClass.fieldByName("EliminateAllocations"));
253 EliminateAllocations = ((PrimitiveValue) val).booleanValue();
254 val = testCaseBaseTargetClass.getValue(testCaseBaseTargetClass.fieldByName("DeoptimizeObjectsALot"));
255 DeoptimizeObjectsALot = ((PrimitiveValue) val).booleanValue();
256 val = testCaseBaseTargetClass.getValue(testCaseBaseTargetClass.fieldByName("UseJVMCICompiler"));
257 UseJVMCICompiler = ((PrimitiveValue) val).booleanValue();
258 }
259
260 }
261
262 // Execute known test cases
263 protected void runTests() throws Exception {
264 String targetProgName = EATestsTarget.class.getName();
265 msg("starting to main method in class " + targetProgName);
266 startToMain(targetProgName);
267 msg("resuming to EATestCaseBaseTarget.staticSetUpDone()V");
268 targetMainThread = resumeTo("EATestCaseBaseTarget", "staticSetUpDone", "()V").thread();
269 Location loc = targetMainThread.frame(0).location();
270 Asserts.assertEQ("staticSetUpDone", loc.method().name());
271
272 targetVMOptions = new TargetVMOptions(this, (ClassType) loc.declaringType());
273
274 // Materializing test cases, i.e. reallocating objects on the heap
275 new EAMaterializeLocalVariableUponGet() .run(this);
706 public volatile long loopCount;
707
708 /**
709 * Used in {@link EATestCaseBaseDebugger#terminateEndlessLoop()} to signal target to leave the endless loop.
710 */
711 public volatile boolean doLoop;
712
713 public long checkSum;
714
715 public static final String TESTMETHOD_DEFAULT_NAME = "dontinline_testMethod";
716
717 public static final WhiteBox WB = WhiteBox.getWhiteBox();
718
719 public static boolean unbox(Boolean value, boolean dflt) {
720 return value == null ? dflt : value;
721 }
722
723 public static final boolean UseJVMCICompiler = unbox(WB.getBooleanVMFlag("UseJVMCICompiler"), false); // read by debugger
724 public static final boolean DoEscapeAnalysis = unbox(WB.getBooleanVMFlag("DoEscapeAnalysis"), UseJVMCICompiler);
725 public static final boolean EliminateAllocations = unbox(WB.getBooleanVMFlag("EliminateAllocations"), UseJVMCICompiler); // read by debugger
726 public static final boolean DeoptimizeObjectsALot = WB.getBooleanVMFlag("DeoptimizeObjectsALot"); // read by debugger
727 public static final long BiasedLockingBulkRebiasThreshold = WB.getIntxVMFlag("BiasedLockingBulkRebiasThreshold");
728 public static final long BiasedLockingBulkRevokeThreshold = WB.getIntxVMFlag("BiasedLockingBulkRevokeThreshold");
729
730 public String testMethodName;
731 public int testMethodDepth;
732
733 // Results produced by dontinline_testMethod()
734 public int iResult;
735 public long lResult;
736 public float fResult;
737 public double dResult;
738
739
740 public boolean warmupDone;
741
742 public volatile Object biasToBeRevoked;
743
744 // an object with an inflated monitor
745 public static XYVal inflatedLock;
746 public static Thread inflatorThread;
832 public int dontinline_brkpt_iret() {
833 dontinline_brkpt();
834 return 42;
835 }
836
837 /**
838 * It is a common protocol to have the debugger set a breakpoint in this method and have {@link
839 * #dontinline_testMethod()} call it and then perform some test actions on debugger side.
840 * After that it is checked if a frame of {@link #dontinline_testMethod()} is found at the
841 * expected depth on stack and if it is (not) marked for deoptimization as expected.
842 */
843 public void dontinline_brkpt() {
844 // will set breakpoint here after warmup
845 if (warmupDone) {
846 // check if test method is at expected depth
847 StackTraceElement[] frames = Thread.currentThread().getStackTrace();
848 int stackTraceDepth = testMethodDepth + 1; // ignore java.lang.Thread.getStackTrace()
849 Asserts.assertEQ(testMethodName, frames[stackTraceDepth].getMethodName(),
850 testCaseName + ": test method not found at depth " + testMethodDepth);
851 // check if the frame is (not) deoptimized as expected
852 if (!DeoptimizeObjectsALot) {
853 if (testFrameShouldBeDeoptimized()) {
854 Asserts.assertTrue(WB.isFrameDeoptimized(testMethodDepth+1),
855 testCaseName + ": expected test method frame at depth " + testMethodDepth + " to be deoptimized");
856 } else {
857 Asserts.assertFalse(WB.isFrameDeoptimized(testMethodDepth+1),
858 testCaseName + ": expected test method frame at depth " + testMethodDepth + " not to be deoptimized");
859 }
860 }
861 }
862 }
863
864 /**
865 * Some test cases run busy endless loops by initializing {@link #loopCount}
866 * to {@link Long#MAX_VALUE} after warm-up and then counting down to 0 in their main test method.
867 * During warm-up {@link #loopCount} is initialized to a small value.
868 */
869 public long dontinline_endlessLoop() {
870 long cs = checkSum;
871 doLoop = true;
872 while (loopCount-- > 0 && doLoop) {
1720
1721 public void testMethod_inlined(XYVal l2) {
1722 synchronized (l2) {
1723 dontinline_brkpt();
1724 }
1725 }
1726 }
1727
1728 class EARelockingRecursive extends EATestCaseBaseDebugger {
1729
1730 public void runTestCase() throws Exception {
1731 BreakpointEvent bpe = env.resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1732 printStack(bpe.thread());
1733 @SuppressWarnings("unused")
1734 ObjectReference o = getLocalRef(bpe.thread().frame(2), XYVAL_NAME, "l1");
1735 }
1736 }
1737
1738 /////////////////////////////////////////////////////////////////////////////
1739
1740 // Object ref l1 is retrieved by the debugger at a location where nested locks are omitted. The
1741 // accessed object is globally reachable already before the access, therefore no relocking is done.
1742 class EARelockingNestedInflatedTarget extends EATestCaseBaseTarget {
1743
1744 @Override
1745 public void setUp() {
1746 super.setUp();
1747 testMethodDepth = 2;
1748 }
1749
1750 @Override
1751 public boolean testFrameShouldBeDeoptimized() {
1752 // Access does not trigger deopt., as escape state is already global escape.
1753 return false;
1754 }
1755
1756 public void dontinline_testMethod() {
1757 XYVal l1 = inflatedLock;
1758 synchronized (l1) {
1759 testMethod_inlined(l1);
1760 }
2526 boolean coughtOom = false;
2527 try {
2528 // try to pop dontinline_consume_all_memory_brkpt
2529 thread.popFrames(thread.frame(1));
2530 } catch (VMOutOfMemoryException oom) {
2531 // as expected
2532 msg("cought OOM");
2533 coughtOom = true;
2534 }
2535 freeAllMemory();
2536 // We succeeded to pop just one frame. When we continue, we will call dontinline_brkpt() again.
2537 Asserts.assertTrue(coughtOom || !env.targetVMOptions.EliminateAllocations, "PopFrame should have triggered an OOM exception in target");
2538 String expectedTopFrame =
2539 env.targetVMOptions.EliminateAllocations ? "dontinline_consume_all_memory_brkpt" : "dontinline_testMethod";
2540 Asserts.assertEQ(expectedTopFrame, thread.frame(0).location().method().name());
2541 printStack(thread);
2542 }
2543
2544 @Override
2545 public boolean shouldSkip() {
2546 // OOMEs because of realloc failures with DeoptimizeObjectsALot are too random.
2547 // And Graal currently doesn't provide all information about non-escaping objects in debug info
2548 return super.shouldSkip() || env.targetVMOptions.DeoptimizeObjectsALot || env.targetVMOptions.UseJVMCICompiler;
2549 }
2550 }
2551
2552 class EAPopFrameNotInlinedReallocFailureTarget extends EATestCaseBaseTarget {
2553
2554 public boolean doneAlready;
2555
2556 public void dontinline_testMethod() {
2557 long a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // scalar replaced
2558 Vector10 v = new Vector10(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // scalar replaced
2559 dontinline_consume_all_memory_brkpt();
2560 lResult = a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9]
2561 + v.i0 + v.i1 + v.i2 + v.i3 + v.i4 + v.i5 + v.i6 + v.i7 + v.i8 + v.i9;
2562 }
2563
2564 public void dontinline_consume_all_memory_brkpt() {
2565 if (warmupDone && !doneAlready) {
2566 doneAlready = true;
2567 consumeAllMemory(); // provoke reallocation failure
2568 dontinline_brkpt();
2569 }
2570 }
2571
2572 @Override
2573 public void setUp() {
2574 super.setUp();
2575 testMethodDepth = 2;
2576 }
2577
2578 @Override
2579 public long getExpectedLResult() {
2580 long n = 10;
2581 return 2*n*(n+1)/2;
2582 }
2583
2584 @Override
2585 public boolean shouldSkip() {
2586 // OOMEs because of realloc failures with DeoptimizeObjectsALot are too random.
2587 // And Graal currently doesn't provide all information about non-escaping objects in debug info
2588 return super.shouldSkip() || DeoptimizeObjectsALot || UseJVMCICompiler;
2589 }
2590 }
2591
2592 /////////////////////////////////////////////////////////////////////////////
2593
2594 /**
2595 * Pop inlined top frame dropping into method with scalar replaced opjects.
2596 */
2597 class EAPopInlinedMethodWithScalarReplacedObjectsReallocFailure extends EATestCaseBaseDebugger {
2598
2599 public void runTestCase() throws Exception {
2600 ThreadReference thread = env.targetMainThread;
2601 thread.resume();
2602 waitUntilTargetHasEnteredEndlessLoop();
2603
2604 thread.suspend();
2605 printStack(thread);
2606 // frame[0]: EAPopInlinedMethodWithScalarReplacedObjectsReallocFailureTarget.inlinedCallForcedToReturn()
2607 // frame[1]: EAPopInlinedMethodWithScalarReplacedObjectsReallocFailureTarget.dontinline_testMethod()
2608 // frame[2]: EATestCaseBaseTarget.run()
2615 } catch (VMOutOfMemoryException oom) {
2616 // as expected
2617 msg("cought OOM");
2618 coughtOom = true;
2619 }
2620 printStack(thread);
2621 // frame[0]: EAPopInlinedMethodWithScalarReplacedObjectsReallocFailureTarget.inlinedCallForcedToReturn()
2622 // frame[1]: EAPopInlinedMethodWithScalarReplacedObjectsReallocFailureTarget.dontinline_testMethod()
2623 // frame[2]: EATestCaseBaseTarget.run()
2624
2625 freeAllMemory();
2626 setField(testCase, "loopCount", env.vm().mirrorOf(0)); // terminate loop
2627 Asserts.assertTrue(coughtOom || !env.targetVMOptions.EliminateAllocations, "PopFrame should have triggered an OOM exception in target");
2628 String expectedTopFrame =
2629 env.targetVMOptions.EliminateAllocations ? "inlinedCallForcedToReturn" : "dontinline_testMethod";
2630 Asserts.assertEQ(expectedTopFrame, thread.frame(0).location().method().name());
2631 }
2632
2633 @Override
2634 public boolean shouldSkip() {
2635 // OOMEs because of realloc failures with DeoptimizeObjectsALot are too random.
2636 // And Graal currently doesn't provide all information about non-escaping objects in debug info
2637 return super.shouldSkip() || env.targetVMOptions.DeoptimizeObjectsALot || env.targetVMOptions.UseJVMCICompiler;
2638 }
2639 }
2640
2641 class EAPopInlinedMethodWithScalarReplacedObjectsReallocFailureTarget extends EATestCaseBaseTarget {
2642
2643 public long checkSum;
2644
2645 public void dontinline_testMethod() {
2646 long a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // scalar replaced
2647 Vector10 v = new Vector10(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // scalar replaced
2648 long l = inlinedCallForcedToReturn();
2649 lResult = a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9]
2650 + v.i0 + v.i1 + v.i2 + v.i3 + v.i4 + v.i5 + v.i6 + v.i7 + v.i8 + v.i9;
2651 }
2652
2653 public long inlinedCallForcedToReturn() {
2654 long cs = checkSum;
2655 dontinline_consumeAllMemory();
2656 while (loopCount-- > 0) {
2657 targetIsInLoop = true;
2671 @Override
2672 public long getExpectedLResult() {
2673 long n = 10;
2674 return 2*n*(n+1)/2;
2675 }
2676
2677 @Override
2678 public void setUp() {
2679 super.setUp();
2680 loopCount = 3;
2681 }
2682
2683 public void warmupDone() {
2684 super.warmupDone();
2685 msg("enter 'endless' loop by setting loopCount = Long.MAX_VALUE");
2686 loopCount = Long.MAX_VALUE; // endless loop
2687 }
2688
2689 @Override
2690 public boolean shouldSkip() {
2691 // OOMEs because of realloc failures with DeoptimizeObjectsALot are too random.
2692 // And Graal currently doesn't provide all information about non-escaping objects in debug info
2693 return super.shouldSkip() || DeoptimizeObjectsALot || UseJVMCICompiler;
2694 }
2695 }
2696
2697 /////////////////////////////////////////////////////////////////////////////
2698 //
2699 // ForceEarlyReturn tests
2700 //
2701 /////////////////////////////////////////////////////////////////////////////
2702
2703 /**
2704 * ForceEarlyReturn into caller frame with scalar replaced objects.
2705 */
2706 class EAForceEarlyReturnNotInlined extends EATestCaseBaseDebugger {
2707
2708 public void runTestCase() throws Exception {
2709 BreakpointEvent bpe = env.resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
2710 ThreadReference thread = bpe.thread();
2711 printStack(thread);
2712 // frame[0]: EATestCaseBaseTarget.dontinline_brkpt()
2713 // frame[1]: EATestCaseBaseTarget.dontinline_brkpt_iret()
2872 thread.forceEarlyReturn(env.vm().mirrorOf(43)); // Request force return 43 from inlinedCallForcedToReturn()
2873 // reallocation is triggered here
2874 } catch (VMOutOfMemoryException oom) {
2875 // as expected
2876 msg("cought OOM");
2877 coughtOom = true;
2878 }
2879 freeAllMemory();
2880 if (env.targetVMOptions.EliminateAllocations) {
2881 Asserts.assertTrue(coughtOom, "PopFrame should have triggered an OOM exception in target");
2882 thread.forceEarlyReturn(env.vm().mirrorOf(43));
2883 }
2884 msg("Step over instruction to do the forced return");
2885 env.stepOverInstruction(thread);
2886 printStack(thread);
2887 msg("ForceEarlyReturn DONE");
2888 }
2889
2890 @Override
2891 public boolean shouldSkip() {
2892 // OOMEs because of realloc failures with DeoptimizeObjectsALot are too random.
2893 // And Graal currently doesn't support Force Early Return
2894 return super.shouldSkip() || env.targetVMOptions.DeoptimizeObjectsALot || env.targetVMOptions.UseJVMCICompiler;
2895 }
2896 }
2897
2898 class EAForceEarlyReturnOfInlinedMethodWithScalarReplacedObjectsReallocFailureTarget extends EATestCaseBaseTarget {
2899
2900 public int checkSum;
2901
2902 public void dontinline_testMethod() {
2903 long a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // scalar replaced
2904 Vector10 v = new Vector10(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // scalar replaced
2905 long l = inlinedCallForcedToReturn();
2906 lResult = a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9]
2907 + v.i0 + v.i1 + v.i2 + v.i3 + v.i4 + v.i5 + v.i6 + v.i7 + v.i8 + v.i9 + l;
2908 }
2909
2910 public long inlinedCallForcedToReturn() { // forced to return 43
2911 long cs = checkSum;
2912 dontinline_consumeAllMemory();
2913 while (loopCount-- > 0) {
2914 targetIsInLoop = true;
2929 public long getExpectedLResult() {
2930 long n = 10;
2931 return 2*n*(n+1)/2 + 43;
2932 }
2933
2934 @Override
2935 public void setUp() {
2936 super.setUp();
2937 testMethodDepth = 2;
2938 loopCount = 3;
2939 }
2940
2941 public void warmupDone() {
2942 super.warmupDone();
2943 msg("enter 'endless' loop by setting loopCount = Long.MAX_VALUE");
2944 loopCount = Long.MAX_VALUE; // endless loop
2945 }
2946
2947 @Override
2948 public boolean shouldSkip() {
2949 // OOMEs because of realloc failures with DeoptimizeObjectsALot are too random.
2950 // And Graal currently doesn't support Force Early Return
2951 return super.shouldSkip() || DeoptimizeObjectsALot || UseJVMCICompiler;
2952 }
2953 }
2954
2955 /////////////////////////////////////////////////////////////////////////////
2956 //
2957 // Get Instances of ReferenceType
2958 //
2959 /////////////////////////////////////////////////////////////////////////////
2960
2961 /**
2962 * Check if instances of a type are found even if they are scalar replaced. To stress the
2963 * implementation a little more, the instances should be retrieved while the target is running.
2964 */
2965 class EAGetInstancesOfReferenceType extends EATestCaseBaseDebugger {
2966
2967 public void runTestCase() throws Exception {
2968 printStack(env.targetMainThread);
2969 ReferenceType cls = ((ClassObjectReference)getField(testCase, "cls")).reflectedType();
2970 msg("reflected type is " + cls);
2971 msg("resume");
|