1 /*
2 * Copyright (c) 2020 SAP SE. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
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 /**
26 * @test
27 * @bug 8227745
28 * @summary Collection of test cases that check if optimizations based on escape analysis are reverted just before non-escaping objects escape through JVMTI.
29 * @author Richard Reingruber richard DOT reingruber AT sap DOT com
30 *
31 * @requires ((vm.compMode == "Xmixed") & vm.compiler2.enabled)
32 * @library /test/lib /test/hotspot/jtreg
33 *
34 * @run build TestScaffold VMConnection TargetListener TargetAdapter jdk.test.whitebox.WhiteBox
35 * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
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
56 * -Xbootclasspath/a:.
57 * -XX:CompileCommand=dontinline,*::dontinline_*
58 * -XX:+WhiteBoxAPI
59 * -Xbatch
60 * -XX:+DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking
61 * @run driver EATests
62 * -XX:+UnlockDiagnosticVMOptions
63 * -Xms256m -Xmx256m
64 * -Xbootclasspath/a:.
65 * -XX:CompileCommand=dontinline,*::dontinline_*
66 * -XX:+WhiteBoxAPI
67 * -Xbatch
68 * -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking
69 * @run driver EATests
70 * -XX:+UnlockDiagnosticVMOptions
71 * -Xms256m -Xmx256m
72 * -Xbootclasspath/a:.
73 * -XX:CompileCommand=dontinline,*::dontinline_*
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
105 *
106 */
107 /**
108 * @test
109 * @bug 8227745
110 *
111 * @summary This is another configuration of EATests.java to test Graal. Some testcases are expected
112 * to fail because Graal does not provide all information about non-escaping objects in
113 * scope. These are skipped.
114 *
115 * @author Richard Reingruber richard DOT reingruber AT sap DOT com
116 *
117 * @requires ((vm.compMode == "Xmixed") & vm.graal.enabled)
118 *
119 * @library /test/lib /test/hotspot/jtreg
120 *
121 * @run build TestScaffold VMConnection TargetListener TargetAdapter jdk.test.whitebox.WhiteBox
122 * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
123 * @run compile -g EATests.java
124 *
125 * @comment Test with Graal. Some testcases are expected to fail because Graal does not provide all information about non-escaping
126 * objects in scope. These are skipped.
127 * @run driver EATests
128 * -XX:+UnlockDiagnosticVMOptions
129 * -Xms256m -Xmx256m
130 * -Xbootclasspath/a:.
131 * -XX:CompileCommand=dontinline,*::dontinline_*
132 * -XX:+WhiteBoxAPI
133 * -Xbatch
134 * -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler
135 */
136
137 import com.sun.jdi.*;
138 import com.sun.jdi.event.*;
139 import compiler.testlibrary.CompilerUtils;
140 import compiler.whitebox.CompilerWhiteBoxTest;
141
142 import java.lang.reflect.Array;
143 import java.util.Arrays;
144 import java.util.List;
145 import java.util.Map;
146 import java.util.function.Function;
147
148 import jdk.test.lib.Asserts;
149 import jdk.test.whitebox.WhiteBox;
150 import jdk.test.whitebox.gc.GC;
151
152
153 //
154 // ANALYZING TEST FAILURES
155 //
156 // - Executing just a single test case with the property EATests.onlytestcase.
157 //
158 // Example: java -DEATests.onlytestcase=<test case name> ... EATests
159 //
160 // - Interactive execution allows for attaching a native debugger, e.g. gdb
161 //
162 // Example: java -DEATests.interactive=true ... EATests
163 //
164 // - Java arguments to the test are passed as vm options to the debuggee:
165 //
166 // Example: java ... EATests -XX:+UseNewCode
167 //
168
169
170
171 /////////////////////////////////////////////////////////////////////////////
172 //
173 // Shared base class for test cases for both, debugger and debuggee.
174 //
175 /////////////////////////////////////////////////////////////////////////////
176
177 class EATestCaseBaseShared {
178 // In interactive mode we wait for a keypress before every test case.
179 public static final boolean INTERACTIVE =
180 System.getProperty("EATests.interactive") != null &&
181 System.getProperty("EATests.interactive").equals("true");
182
183 // If the property is given, then just the test case it refers to is executed.
184 // Use it to diagnose test failures.
185 public static final String RUN_ONLY_TEST_CASE_PROPERTY = "EATests.onlytestcase";
186 public static final String RUN_ONLY_TEST_CASE = System.getProperty(RUN_ONLY_TEST_CASE_PROPERTY);
187
188 public final String testCaseName;
189
190 public EATestCaseBaseShared() {
191 String clName = getClass().getName();
192 int tidx = clName.lastIndexOf("Target");
193 testCaseName = tidx > 0 ? clName.substring(0, tidx) : clName;
194 }
195
196 public boolean shouldSkip() {
197 return EATestCaseBaseShared.RUN_ONLY_TEST_CASE != null &&
198 EATestCaseBaseShared.RUN_ONLY_TEST_CASE.length() > 0 &&
199 !testCaseName.equals(EATestCaseBaseShared.RUN_ONLY_TEST_CASE);
200 }
201 }
202
203 /////////////////////////////////////////////////////////////////////////////
204 //
205 // Target main class, i.e. the program to be debugged.
206 //
207 /////////////////////////////////////////////////////////////////////////////
208
209 class EATestsTarget {
210
211 public static void main(String[] args) {
212 EATestCaseBaseTarget.staticSetUp();
213 EATestCaseBaseTarget.staticSetUpDone();
214
215 // Materializing test cases, i.e. reallocating objects on the heap
216 new EAMaterializeLocalVariableUponGetTarget() .run();
217 new EAGetWithoutMaterializeTarget() .run();
218 new EAMaterializeLocalAtObjectReturnTarget() .run();
219 new EAMaterializeLocalAtObjectPollReturnReturnTarget() .run();
220 new EAMaterializeIntArrayTarget() .run();
221 new EAMaterializeLongArrayTarget() .run();
222 new EAMaterializeFloatArrayTarget() .run();
223 new EAMaterializeDoubleArrayTarget() .run();
224 new EAMaterializeObjectArrayTarget() .run();
225 new EAMaterializeObjectWithConstantAndNotConstantValuesTarget() .run();
226 new EAMaterializeObjReferencedBy2LocalsTarget() .run();
227 new EAMaterializeObjReferencedBy2LocalsAndModifyTarget() .run();
228 new EAMaterializeObjReferencedBy2LocalsInDifferentVirtFramesTarget() .run();
229 new EAMaterializeObjReferencedBy2LocalsInDifferentVirtFramesAndModifyTarget() .run();
230 new EAMaterializeObjReferencedFromOperandStackTarget() .run();
231 new EAMaterializeLocalVariableUponGetAfterSetIntegerTarget() .run();
232
233 // Relocking test cases
234 new EARelockingSimpleTarget() .run();
235 new EARelockingSimple_2Target() .run();
236 new EARelockingRecursiveTarget() .run();
237 new EARelockingNestedInflatedTarget() .run();
238 new EARelockingNestedInflated_02Target() .run();
239 new EARelockingArgEscapeLWLockedInCalleeFrameTarget() .run();
240 new EARelockingArgEscapeLWLockedInCalleeFrame_2Target() .run();
241 new EARelockingArgEscapeLWLockedInCalleeFrame_3Target() .run();
242 new EARelockingArgEscapeLWLockedInCalleeFrame_4Target() .run();
243 new EAGetOwnedMonitorsTarget() .run();
244 new EAEntryCountTarget() .run();
245 new EARelockingObjectCurrentlyWaitingOnTarget() .run();
246
247 // Test cases that require deoptimization even though neither
248 // locks nor allocations are eliminated at the point where
249 // escape state is changed.
250 new EADeoptFrameAfterReadLocalObject_01Target() .run();
251 new EADeoptFrameAfterReadLocalObject_01BTarget() .run();
252 new EADeoptFrameAfterReadLocalObject_02Target() .run();
253 new EADeoptFrameAfterReadLocalObject_02BTarget() .run();
254 new EADeoptFrameAfterReadLocalObject_02CTarget() .run();
255 new EADeoptFrameAfterReadLocalObject_03Target() .run();
256
257 // PopFrame test cases
258 new EAPopFrameNotInlinedTarget() .run();
259 new EAPopFrameNotInlinedReallocFailureTarget() .run();
260 new EAPopInlinedMethodWithScalarReplacedObjectsReallocFailureTarget() .run();
261
262 // ForceEarlyReturn test cases
263 new EAForceEarlyReturnNotInlinedTarget() .run();
264 new EAForceEarlyReturnOfInlinedMethodWithScalarReplacedObjectsTarget() .run();
265 new EAForceEarlyReturnOfInlinedMethodWithScalarReplacedObjectsReallocFailureTarget().run();
266
267 // Instances of ReferenceType
268 new EAGetInstancesOfReferenceTypeTarget() .run();
269 }
270 }
271
272 /////////////////////////////////////////////////////////////////////////////
273 //
274 // Debugger main class
275 //
276 /////////////////////////////////////////////////////////////////////////////
277
278 public class EATests extends TestScaffold {
279
280 public TargetVMOptions targetVMOptions;
281 public ThreadReference targetMainThread;
282
283 EATests(String args[]) {
284 super(args);
285 }
286
287 public static void main(String[] args) throws Exception {
288 if (EATestCaseBaseShared.RUN_ONLY_TEST_CASE != null) {
289 args = Arrays.copyOf(args, args.length + 1);
290 args[args.length - 1] = "-D" + EATestCaseBaseShared.RUN_ONLY_TEST_CASE_PROPERTY + "=" + EATestCaseBaseShared.RUN_ONLY_TEST_CASE;
291 }
292 new EATests(args).startTests();
293 }
294
295 public static class TargetVMOptions {
296
297 public final boolean UseJVMCICompiler;
298 public final boolean EliminateAllocations;
299 public final boolean DeoptimizeObjectsALot;
300 public final boolean DoEscapeAnalysis;
301 public final boolean ZGCIsSelected;
302 public final boolean StressReflectiveCode;
303
304 public TargetVMOptions(EATests env, ClassType testCaseBaseTargetClass) {
305 Value val;
306 val = testCaseBaseTargetClass.getValue(testCaseBaseTargetClass.fieldByName("DoEscapeAnalysis"));
307 DoEscapeAnalysis = ((PrimitiveValue) val).booleanValue();
308 // Escape analysis is a prerequisite for scalar replacement (EliminateAllocations)
309 val = testCaseBaseTargetClass.getValue(testCaseBaseTargetClass.fieldByName("EliminateAllocations"));
310 EliminateAllocations = DoEscapeAnalysis && ((PrimitiveValue) val).booleanValue();
311 val = testCaseBaseTargetClass.getValue(testCaseBaseTargetClass.fieldByName("DeoptimizeObjectsALot"));
312 DeoptimizeObjectsALot = ((PrimitiveValue) val).booleanValue();
313 val = testCaseBaseTargetClass.getValue(testCaseBaseTargetClass.fieldByName("UseJVMCICompiler"));
314 UseJVMCICompiler = ((PrimitiveValue) val).booleanValue();
315 val = testCaseBaseTargetClass.getValue(testCaseBaseTargetClass.fieldByName("ZGCIsSelected"));
316 ZGCIsSelected = ((PrimitiveValue) val).booleanValue();
317 val = testCaseBaseTargetClass.getValue(testCaseBaseTargetClass.fieldByName("StressReflectiveCode"));
318 StressReflectiveCode = ((PrimitiveValue) val).booleanValue();
319 }
320
321 }
322
323 // Execute known test cases
324 protected void runTests() throws Exception {
325 String targetProgName = EATestsTarget.class.getName();
326 msg("starting to main method in class " + targetProgName);
327 startToMain(targetProgName);
328 msg("resuming to EATestCaseBaseTarget.staticSetUpDone()V");
329 targetMainThread = resumeTo("EATestCaseBaseTarget", "staticSetUpDone", "()V").thread();
330 Location loc = targetMainThread.frame(0).location();
331 Asserts.assertEQ("staticSetUpDone", loc.method().name());
332
333 targetVMOptions = new TargetVMOptions(this, (ClassType) loc.declaringType());
334
335 // Materializing test cases, i.e. reallocating objects on the heap
336 new EAMaterializeLocalVariableUponGet() .run(this);
337 new EAGetWithoutMaterialize() .run(this);
338 new EAMaterializeLocalAtObjectReturn() .run(this);
339 new EAMaterializeLocalAtObjectPollReturnReturn() .run(this);
340 new EAMaterializeIntArray() .run(this);
341 new EAMaterializeLongArray() .run(this);
342 new EAMaterializeFloatArray() .run(this);
343 new EAMaterializeDoubleArray() .run(this);
344 new EAMaterializeObjectArray() .run(this);
345 new EAMaterializeObjectWithConstantAndNotConstantValues() .run(this);
346 new EAMaterializeObjReferencedBy2Locals() .run(this);
347 new EAMaterializeObjReferencedBy2LocalsAndModify() .run(this);
348 new EAMaterializeObjReferencedBy2LocalsInDifferentVirtFrames() .run(this);
349 new EAMaterializeObjReferencedBy2LocalsInDifferentVirtFramesAndModify() .run(this);
350 new EAMaterializeObjReferencedFromOperandStack() .run(this);
351 new EAMaterializeLocalVariableUponGetAfterSetInteger() .run(this);
352
353 // Relocking test cases
354 new EARelockingSimple() .run(this);
355 new EARelockingSimple_2() .run(this);
356 new EARelockingRecursive() .run(this);
357 new EARelockingNestedInflated() .run(this);
358 new EARelockingNestedInflated_02() .run(this);
359 new EARelockingArgEscapeLWLockedInCalleeFrame() .run(this);
360 new EARelockingArgEscapeLWLockedInCalleeFrame_2() .run(this);
361 new EARelockingArgEscapeLWLockedInCalleeFrame_3() .run(this);
362 new EARelockingArgEscapeLWLockedInCalleeFrame_4() .run(this);
363 new EAGetOwnedMonitors() .run(this);
364 new EAEntryCount() .run(this);
365 new EARelockingObjectCurrentlyWaitingOn() .run(this);
366
367 // Test cases that require deoptimization even though neither
368 // locks nor allocations are eliminated at the point where
369 // escape state is changed.
370 new EADeoptFrameAfterReadLocalObject_01() .run(this);
371 new EADeoptFrameAfterReadLocalObject_01B() .run(this);
372 new EADeoptFrameAfterReadLocalObject_02() .run(this);
373 new EADeoptFrameAfterReadLocalObject_02B() .run(this);
374 new EADeoptFrameAfterReadLocalObject_02C() .run(this);
375 new EADeoptFrameAfterReadLocalObject_03() .run(this);
376
377 // PopFrame test cases
378 new EAPopFrameNotInlined() .run(this);
379 new EAPopFrameNotInlinedReallocFailure() .run(this);
380 new EAPopInlinedMethodWithScalarReplacedObjectsReallocFailure() .run(this);
381
382 // ForceEarlyReturn test cases
383 new EAForceEarlyReturnNotInlined() .run(this);
384 new EAForceEarlyReturnOfInlinedMethodWithScalarReplacedObjects() .run(this);
385 new EAForceEarlyReturnOfInlinedMethodWithScalarReplacedObjectsReallocFailure().run(this);
386
387 // Instances of ReferenceType
388 new EAGetInstancesOfReferenceType() .run(this);
389
390 // resume the target listening for events
391 listenUntilVMDisconnect();
392 }
393
394 // Print a Message
395 public void msg(String m) {
396 System.out.println();
397 System.out.println("###(Debugger) " + m);
398 System.out.println();
399 }
400
401 // Highlighted message.
402 public void msgHL(String m) {
403 System.out.println();
404 System.out.println();
405 System.out.println("##########################################################");
406 System.out.println("### " + m);
407 System.out.println("### ");
408 System.out.println();
409 System.out.println();
410 }
411 }
412
413 /////////////////////////////////////////////////////////////////////////////
414 //
415 // Base class for debugger side of test cases.
416 //
417 /////////////////////////////////////////////////////////////////////////////
418
419 abstract class EATestCaseBaseDebugger extends EATestCaseBaseShared {
420
421 protected EATests env;
422
423 public ObjectReference testCase;
424
425 public static final String TARGET_TESTCASE_BASE_NAME = EATestCaseBaseTarget.class.getName();
426
427 public static final String XYVAL_NAME = XYVal.class.getName();
428
429 public abstract void runTestCase() throws Exception;
430
431 @Override
432 public boolean shouldSkip() {
433 // Skip if StressReflectiveCode because it effectively disables escape analysis
434 return super.shouldSkip() || env.targetVMOptions.StressReflectiveCode;
435 }
436
437 public void run(EATests env) {
438 this.env = env;
439 if (shouldSkip()) {
440 msg("skipping " + testCaseName);
441 return;
442 }
443 try {
444 msgHL("Executing test case " + getClass().getName());
445 env.testFailed = false;
446
447 if (INTERACTIVE)
448 env.waitForInput();
449
450 resumeToWarmupDone();
451 runTestCase();
452 Asserts.assertTrue(env.targetMainThread.isSuspended(), "must be suspended after the testcase");
453 resumeToTestCaseDone();
454 checkPostConditions();
455 } catch (Exception e) {
456 Asserts.fail("Unexpected exception in test case " + getClass().getName(), e);
457 }
458 }
459
460 /**
461 * Set a breakpoint in the given method and resume all threads. The
462 * breakpoint is configured to suspend just the thread that reaches it
463 * instead of all threads. This is important when running with graal.
464 */
465 public BreakpointEvent resumeTo(String clsName, String methodName, String signature) {
466 boolean suspendThreadOnly = true;
467 return env.resumeTo(clsName, methodName, signature, suspendThreadOnly);
468 }
469
470 public void resumeToWarmupDone() throws Exception {
471 msg("resuming to " + TARGET_TESTCASE_BASE_NAME + ".warmupDone()V");
472 resumeTo(TARGET_TESTCASE_BASE_NAME, "warmupDone", "()V");
473 testCase = env.targetMainThread.frame(0).thisObject();
474 }
475
476 public void resumeToTestCaseDone() {
477 msg("resuming to " + TARGET_TESTCASE_BASE_NAME + ".testCaseDone()V");
478 resumeTo(TARGET_TESTCASE_BASE_NAME, "testCaseDone", "()V");
479 }
480
481 public void checkPostConditions() throws Exception {
482 Asserts.assertFalse(env.getExceptionCaught(), "Uncaught exception in Debuggee");
483
484 String testName = getClass().getName();
485 if (!env.testFailed) {
486 env.println(testName + ": passed");
487 } else {
488 throw new Exception(testName + ": failed");
489 }
490 }
491
492 public void printStack(ThreadReference thread) throws Exception {
493 msg("Debuggee Stack:");
494 List<StackFrame> stack_frames = thread.frames();
495 int i = 0;
496 for (StackFrame ff : stack_frames) {
497 System.out.println("frame[" + i++ +"]: " + ff.location().method() + " (bci:" + ff.location().codeIndex() + ")");
498 }
499 }
500
501 public void msg(String m) {
502 env.msg(m);
503 }
504
505 public void msgHL(String m) {
506 env.msgHL(m);
507 }
508
509 // See Field Descriptors in The Java Virtual Machine Specification
510 // (https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.3.2)
511 enum FD {
512 I, // int
513 J, // long
514 F, // float
515 D, // double
516 }
517
518 // Map field descriptor to jdi type string
519 public static final Map<FD, String> FD2JDIArrType = Map.of(FD.I, "int[]", FD.J, "long[]", FD.F, "float[]", FD.D, "double[]");
520
521 // Map field descriptor to PrimitiveValue getter
522 public static final Function<PrimitiveValue, Integer> v2I = PrimitiveValue::intValue;
523 public static final Function<PrimitiveValue, Long> v2J = PrimitiveValue::longValue;
524 public static final Function<PrimitiveValue, Float> v2F = PrimitiveValue::floatValue;
525 public static final Function<PrimitiveValue, Double> v2D = PrimitiveValue::doubleValue;
526 Map<FD, Function<PrimitiveValue, ?>> FD2getter = Map.of(FD.I, v2I, FD.J, v2J, FD.F, v2F, FD.D, v2D);
527
528 /**
529 * Retrieve array of primitive values referenced by a local variable in target and compare with
530 * an array of expected values.
531 * @param frame Frame in the target holding the local variable
532 * @param lName Name of the local variable referencing the array to be retrieved
533 * @param desc Array element type given as field descriptor.
534 * @param expVals Array of expected values.
535 * @throws Exception
536 */
537 protected void checkLocalPrimitiveArray(StackFrame frame, String lName, FD desc, Object expVals) throws Exception {
538 String lType = FD2JDIArrType.get(desc);
539 Asserts.assertNotNull(lType, "jdi type not found");
540 Asserts.assertEQ(EATestCaseBaseTarget.TESTMETHOD_DEFAULT_NAME, frame .location().method().name());
541 List<LocalVariable> localVars = frame.visibleVariables();
542 msg("Check if the local array variable '" + lName + "' in " + EATestCaseBaseTarget.TESTMETHOD_DEFAULT_NAME + " has the expected elements: ");
543 boolean found = false;
544 for (LocalVariable lv : localVars) {
545 if (lv.name().equals(lName)) {
546 found = true;
547 Value lVal = frame.getValue(lv);
548 Asserts.assertNotNull(lVal);
549 Asserts.assertEQ(lVal.type().name(), lType);
550 ArrayReference aRef = (ArrayReference) lVal;
551 Asserts.assertEQ(3, aRef.length());
552 // now check the elements
553 for (int i = 0; i < aRef.length(); i++) {
554 Object actVal = FD2getter.get(desc).apply((PrimitiveValue)aRef.getValue(i));
555 Object expVal = Array.get(expVals, i);
556 Asserts.assertEQ(expVal, actVal, "checking element at index " + i);
557 }
558 }
559 }
560 Asserts.assertTrue(found);
561 msg("OK.");
562 }
563
564 /**
565 * Retrieve array of objects referenced by a local variable in target and compare with an array
566 * of expected values.
567 * @param frame Frame in the target holding the local variable
568 * @param lName Name of the local variable referencing the array to be retrieved
569 * @param lType Local type, e.g. java.lang.Long[]
570 * @param expVals Array of expected values.
571 * @throws Exception
572 */
573 protected void checkLocalObjectArray(StackFrame frame, String lName, String lType, ObjectReference[] expVals) throws Exception {
574 Asserts.assertEQ(EATestCaseBaseTarget.TESTMETHOD_DEFAULT_NAME, frame .location().method().name());
575 List<LocalVariable> localVars = frame.visibleVariables();
576 msg("Check if the local array variable '" + lName + "' in " + EATestCaseBaseTarget.TESTMETHOD_DEFAULT_NAME + " has the expected elements: ");
577 boolean found = false;
578 for (LocalVariable lv : localVars) {
579 if (lv.name().equals(lName)) {
580 found = true;
581 Value lVal = frame.getValue(lv);
582 Asserts.assertNotNull(lVal);
583 Asserts.assertEQ(lType, lVal.type().name());
584 ArrayReference aRef = (ArrayReference) lVal;
585 Asserts.assertEQ(3, aRef.length());
586 // now check the elements
587 for (int i = 0; i < aRef.length(); i++) {
588 ObjectReference actVal = (ObjectReference)aRef.getValue(i);
589 Asserts.assertSame(expVals[i], actVal, "checking element at index " + i);
590 }
591 }
592 }
593 Asserts.assertTrue(found);
594 msg("OK.");
595 }
596
597 /**
598 * Retrieve a reference held by a local variable in the given frame. Check if the frame's method
599 * is the expected method if the retrieved local value has the expected type and is not null.
600 * @param frame The frame to retrieve the local variable value from.
601 * @param expectedMethodName The name of the frames method should match the expectedMethodName.
602 * @param lName The name of the local variable which is read.
603 * @param expectedType Is the expected type of the object referenced by the local variable.
604 * @return
605 * @throws Exception
606 */
607 protected ObjectReference getLocalRef(StackFrame frame, String expectedMethodName, String lName, String expectedType) throws Exception {
608 Asserts.assertEQ(expectedMethodName, frame.location().method().name());
609 List<LocalVariable> localVars = frame.visibleVariables();
610 msg("Get and check local variable '" + lName + "' in " + expectedMethodName);
611 ObjectReference lRef = null;
612 for (LocalVariable lv : localVars) {
613 if (lv.name().equals(lName)) {
614 Value lVal = frame.getValue(lv);
615 Asserts.assertNotNull(lVal);
616 Asserts.assertEQ(expectedType, lVal.type().name());
617 lRef = (ObjectReference) lVal;
618 break;
619 }
620 }
621 Asserts.assertNotNull(lRef, "Local variable '" + lName + "' not found");
622 msg("OK.");
623 return lRef;
624 }
625
626 /**
627 * Retrieve a reference held by a local variable in the given frame. Check if the frame's method
628 * matches {@link EATestCaseBaseTarget#TESTMETHOD_DEFAULT_NAME} if the retrieved local value has
629 * the expected type and is not null.
630 * @param frame The frame to retrieve the local variable value from.
631 * @param expectedMethodName The name of the frames method should match the expectedMethodName.
632 * @param lName The name of the local variable which is read.
633 * @param expectedType Is the expected type of the object referenced by the local variable.
634 * @return
635 * @throws Exception
636 */
637 protected ObjectReference getLocalRef(StackFrame frame, String lType, String lName) throws Exception {
638 return getLocalRef(frame, EATestCaseBaseTarget.TESTMETHOD_DEFAULT_NAME, lName, lType);
639 }
640
641 /**
642 * Set the value of a local variable in the given frame. Check if the frame's method is the expected method.
643 * @param frame The frame holding the local variable.
644 * @param expectedMethodName The expected name of the frame's method.
645 * @param lName The name of the local variable to change.
646 * @param val The new value of the local variable.
647 * @throws Exception
648 */
649 public void setLocal(StackFrame frame, String expectedMethodName, String lName, Value val) throws Exception {
650 Asserts.assertEQ(expectedMethodName, frame.location().method().name());
651 List<LocalVariable> localVars = frame.visibleVariables();
652 msg("Set local variable '" + lName + "' = " + val + " in " + expectedMethodName);
653 for (LocalVariable lv : localVars) {
654 if (lv.name().equals(lName)) {
655 frame.setValue(lv, val);
656 break;
657 }
658 }
659 msg("OK.");
660 }
661
662 /**
663 * Set the value of a local variable in the given frame. Check if the frame's method matches
664 * {@link EATestCaseBaseTarget#TESTMETHOD_DEFAULT_NAME}.
665 * @param frame The frame holding the local variable.
666 * @param expectedMethodName The expected name of the frame's method.
667 * @param lName The name of the local variable to change.
668 * @param val The new value of the local variable.
669 * @throws Exception
670 */
671 public void setLocal(StackFrame frame, String lName, Value val) throws Exception {
672 setLocal(frame, EATestCaseBaseTarget.TESTMETHOD_DEFAULT_NAME, lName, val);
673 }
674
675 /**
676 * Check if a field has the expected primitive value.
677 * @param o Object holding the field.
678 * @param desc Field descriptor.
679 * @param fName Field name
680 * @param expVal Expected primitive value
681 * @throws Exception
682 */
683 protected void checkPrimitiveField(ObjectReference o, FD desc, String fName, Object expVal) throws Exception {
684 msg("check field " + fName);
685 ReferenceType rt = o.referenceType();
686 Field fld = rt.fieldByName(fName);
687 Value val = o.getValue(fld);
688 Object actVal = FD2getter.get(desc).apply((PrimitiveValue) val);
689 Asserts.assertEQ(expVal, actVal, "field '" + fName + "' has unexpected value.");
690 msg("ok");
691 }
692
693 /**
694 * Check if a field references the expected object.
695 * @param obj Object holding the field.
696 * @param fName Field name
697 * @param expVal Object expected to be referenced by the field
698 * @throws Exception
699 */
700 protected void checkObjField(ObjectReference obj, String fName, ObjectReference expVal) throws Exception {
701 msg("check field " + fName);
702 ReferenceType rt = obj.referenceType();
703 Field fld = rt.fieldByName(fName);
704 Value actVal = obj.getValue(fld);
705 Asserts.assertEQ(expVal, actVal, "field '" + fName + "' has unexpected value.");
706 msg("ok");
707 }
708
709 protected void setField(ObjectReference obj, String fName, Value val) throws Exception {
710 msg("set field " + fName + " = " + val);
711 ReferenceType rt = obj.referenceType();
712 Field fld = rt.fieldByName(fName);
713 obj.setValue(fld, val);
714 msg("ok");
715 }
716
717 protected Value getField(ObjectReference obj, String fName) throws Exception {
718 msg("get field " + fName);
719 ReferenceType rt = obj.referenceType();
720 Field fld = rt.fieldByName(fName);
721 Value val = obj.getValue(fld);
722 msg("result : " + val);
723 return val;
724 }
725
726 /**
727 * Free the memory consumed in the target by {@link EATestCaseBaseTarget#consumedMemory}
728 * @throws Exception
729 */
730 public void freeAllMemory() throws Exception {
731 msg("free consumed memory");
732 setField(testCase, "consumedMemory", null);
733 }
734
735 /**
736 * @return The value of {@link EATestCaseBaseTarget#targetIsInLoop}. The target must set that field to true as soon as it
737 * enters the endless loop.
738 * @throws Exception
739 */
740 public boolean targetHasEnteredEndlessLoop() throws Exception {
741 Value v = getField(testCase, "targetIsInLoop");
742 return ((PrimitiveValue) v).booleanValue();
743 }
744
745 /**
746 * Poll {@link EATestCaseBaseTarget#targetIsInLoop} and return if it is found to be true.
747 * @throws Exception
748 */
749 public void waitUntilTargetHasEnteredEndlessLoop() throws Exception {
750 while(!targetHasEnteredEndlessLoop()) {
751 msg("Target has not yet entered the loop. Sleep 200ms.");
752 try { Thread.sleep(200); } catch (InterruptedException e) { /*ignore */ }
753 }
754 }
755
756 /**
757 * Set {@link EATestCaseBaseTarget#doLoop} to <code>false</code>. This will allow the target to
758 * leave the endless loop.
759 * @throws Exception
760 */
761 public void terminateEndlessLoop() throws Exception {
762 msg("terminate loop");
763 setField(testCase, "doLoop", env.vm().mirrorOf(false));
764 }
765 }
766
767 /////////////////////////////////////////////////////////////////////////////
768 //
769 // Base class for debuggee side of test cases.
770 //
771 /////////////////////////////////////////////////////////////////////////////
772
773 abstract class EATestCaseBaseTarget extends EATestCaseBaseShared implements Runnable {
774
775 /**
776 * The target must set that field to true as soon as it enters the endless loop.
777 */
778 public volatile boolean targetIsInLoop;
779
780 /**
781 * Used for busy loops. See {@link #dontinline_endlessLoop()}.
782 */
783 public volatile long loopCount;
784
785 /**
786 * Used in {@link EATestCaseBaseDebugger#terminateEndlessLoop()} to signal target to leave the endless loop.
787 */
788 public volatile boolean doLoop;
789
790 public long checkSum;
791
792 public static final String TESTMETHOD_DEFAULT_NAME = "dontinline_testMethod";
793
794 public static final WhiteBox WB = WhiteBox.getWhiteBox();
795
796 public static boolean unbox(Boolean value, boolean dflt) {
797 return value == null ? dflt : value;
798 }
799
800 // Some of the fields are only read by the debugger
801 public static final boolean UseJVMCICompiler = unbox(WB.getBooleanVMFlag("UseJVMCICompiler"), false);
802 public static final boolean DoEscapeAnalysis = unbox(WB.getBooleanVMFlag("DoEscapeAnalysis"), UseJVMCICompiler);
803 public static final boolean EliminateAllocations = unbox(WB.getBooleanVMFlag("EliminateAllocations"), UseJVMCICompiler);
804 public static final boolean DeoptimizeObjectsALot = WB.getBooleanVMFlag("DeoptimizeObjectsALot");
805 public static final long BiasedLockingBulkRebiasThreshold = WB.getIntxVMFlag("BiasedLockingBulkRebiasThreshold");
806 public static final long BiasedLockingBulkRevokeThreshold = WB.getIntxVMFlag("BiasedLockingBulkRevokeThreshold");
807 public static final boolean ZGCIsSelected = GC.Z.isSelected();
808 public static final boolean StressReflectiveCode = unbox(WB.getBooleanVMFlag("StressReflectiveCode"), false);
809
810 public String testMethodName;
811 public int testMethodDepth;
812
813 // Results produced by dontinline_testMethod()
814 public int iResult;
815 public long lResult;
816 public float fResult;
817 public double dResult;
818
819
820 public boolean warmupDone;
821
822 public volatile Object biasToBeRevoked;
823
824 // an object with an inflated monitor
825 public static XYVal inflatedLock;
826 public static Thread inflatorThread;
827 public static boolean inflatedLockIsPermanentlyInflated;
828
829 public static int NOT_CONST_1I = 1;
830 public static long NOT_CONST_1L = 1L;
831 public static float NOT_CONST_1F = 1.1F;
832 public static double NOT_CONST_1D = 1.1D;
833
834 public static Long NOT_CONST_1_OBJ = Long.valueOf(1);
835
836
837 public static final Long CONST_2_OBJ = Long.valueOf(2);
838 public static final Long CONST_3_OBJ = Long.valueOf(3);
839
840 @Override
841 public boolean shouldSkip() {
842 // Skip if StressReflectiveCode because it effectively disables escape analysis
843 return super.shouldSkip() || StressReflectiveCode;
844 }
845
846 /**
847 * Main driver of a test case.
848 * <ul>
849 * <li> Skips test case if not selected (see {@link EATestCaseBaseShared#RUN_ONLY_TEST_CASE}
850 * <li> Call {@link #setUp()}
851 * <li> warm-up and compile {@link #dontinline_testMethod()} (see {@link #compileTestMethod()}
852 * <li> calling {@link #dontinline_testMethod()}
853 * <li> checking the result (see {@link #checkResult()}
854 * <ul>
855 */
856 public void run() {
857 try {
858 if (shouldSkip()) {
859 msg("skipping " + testCaseName);
860 return;
861 }
862 setUp();
863 msg(testCaseName + " is up and running.");
864 compileTestMethod();
865 msg(testCaseName + " warmup done.");
866 warmupDone();
867 checkCompLevel();
868 dontinline_testMethod();
869 checkResult();
870 msg(testCaseName + " done.");
871 testCaseDone();
872 } catch (Exception e) {
873 Asserts.fail("Caught unexpected exception", e);
874 }
875 }
876
877 public static void staticSetUp() {
878 inflatedLock = new XYVal(1, 1);
879 synchronized (inflatedLock) {
880 inflatorThread = new Thread("Lock Inflator (test thread)") {
881 @Override
882 public void run() {
883 synchronized (inflatedLock) {
884 inflatedLockIsPermanentlyInflated = true;
885 inflatedLock.notify(); // main thread
886 while (true) {
887 try {
888 // calling wait() on a monitor will cause inflation into a heavy monitor
889 inflatedLock.wait();
890 } catch (InterruptedException e) { /* ignored */ }
891 }
892 }
893 }
894 };
895 inflatorThread.setDaemon(true);
896 inflatorThread.start();
897
898 // wait until the lock is permanently inflated by the inflatorThread
899 while(!inflatedLockIsPermanentlyInflated) {
900 try {
901 inflatedLock.wait(); // until inflated
902 } catch (InterruptedException e1) { /* ignored */ }
903 }
904 }
905 }
906
907 // Debugger will set breakpoint here to sync with target.
908 public static void staticSetUpDone() {
909 }
910
911 public void setUp() {
912 testMethodDepth = 1;
913 testMethodName = TESTMETHOD_DEFAULT_NAME;
914 }
915
916 public abstract void dontinline_testMethod() throws Exception;
917
918 public int dontinline_brkpt_iret() {
919 dontinline_brkpt();
920 return 42;
921 }
922
923 /**
924 * It is a common protocol to have the debugger set a breakpoint in this method and have {@link
925 * #dontinline_testMethod()} call it and then perform some test actions on debugger side.
926 * After that it is checked if a frame of {@link #dontinline_testMethod()} is found at the
927 * expected depth on stack and if it is (not) marked for deoptimization as expected.
928 */
929 public void dontinline_brkpt() {
930 // will set breakpoint here after warmup
931 if (warmupDone) {
932 // check if test method is at expected depth
933 StackTraceElement[] frames = Thread.currentThread().getStackTrace();
934 int stackTraceDepth = testMethodDepth + 1; // ignore java.lang.Thread.getStackTrace()
935 Asserts.assertEQ(testMethodName, frames[stackTraceDepth].getMethodName(),
936 testCaseName + ": test method not found at depth " + testMethodDepth);
937 // check if the frame is (not) deoptimized as expected
938 if (!DeoptimizeObjectsALot) {
939 if (testFrameShouldBeDeoptimized()) {
940 Asserts.assertTrue(WB.isFrameDeoptimized(testMethodDepth+1),
941 testCaseName + ": expected test method frame at depth " + testMethodDepth + " to be deoptimized");
942 } else {
943 Asserts.assertFalse(WB.isFrameDeoptimized(testMethodDepth+1),
944 testCaseName + ": expected test method frame at depth " + testMethodDepth + " not to be deoptimized");
945 }
946 }
947 }
948 }
949
950 /**
951 * Some test cases run busy endless loops by initializing {@link #loopCount}
952 * to {@link Long#MAX_VALUE} after warm-up and then counting down to 0 in their main test method.
953 * During warm-up {@link #loopCount} is initialized to a small value.
954 */
955 public long dontinline_endlessLoop() {
956 long cs = checkSum;
957 doLoop = true;
958 while (loopCount-- > 0 && doLoop) {
959 targetIsInLoop = true;
960 checkSum += checkSum % ++cs;
961 }
962 loopCount = 3;
963 targetIsInLoop = false;
964 return checkSum;
965 }
966
967 public boolean testFrameShouldBeDeoptimized() {
968 return DoEscapeAnalysis;
969 }
970
971 public void warmupDone() {
972 warmupDone = true;
973 }
974
975 // Debugger will set breakpoint here to sync with target.
976 public void testCaseDone() {
977 }
978
979 public void compileTestMethod() throws Exception {
980 int callCount = CompilerWhiteBoxTest.THRESHOLD;
981 while (callCount-- > 0) {
982 dontinline_testMethod();
983 }
984 }
985
986 public void checkCompLevel() {
987 java.lang.reflect.Method m = null;
988 try {
989 m = getClass().getMethod(TESTMETHOD_DEFAULT_NAME);
990 } catch (NoSuchMethodException | SecurityException e) {
991 Asserts.fail("could not check compilation level of", e);
992 }
993 int highestLevel = CompilerUtils.getMaxCompilationLevel();
994 int compLevel = WB.getMethodCompilationLevel(m);
995 if (!UseJVMCICompiler) {
996 Asserts.assertEQ(highestLevel, compLevel,
997 m + " not on expected compilation level");
998 } else {
999 // Background compilation (-Xbatch) will block a thread with timeout
1000 // (see CompileBroker::wait_for_jvmci_completion()). Therefore it is
1001 // possible to reach here before the main test method is compiled.
1002 // In that case we wait for it to be compiled.
1003 while (compLevel != highestLevel) {
1004 msg(TESTMETHOD_DEFAULT_NAME + " is compiled on level " + compLevel +
1005 ". Wait until highes level (" + highestLevel + ") is reached.");
1006 try {
1007 Thread.sleep(200);
1008 } catch (InterruptedException e) { /* ignored */ }
1009 compLevel = WB.getMethodCompilationLevel(m);
1010 }
1011 }
1012 }
1013
1014 // to be overridden as appropriate
1015 public int getExpectedIResult() {
1016 return 0;
1017 }
1018
1019 // to be overridden as appropriate
1020 public long getExpectedLResult() {
1021 return 0;
1022 }
1023
1024 // to be overridden as appropriate
1025 public float getExpectedFResult() {
1026 return 0f;
1027 }
1028
1029 // to be overridden as appropriate
1030 public double getExpectedDResult() {
1031 return 0d;
1032 }
1033
1034 private void checkResult() {
1035 Asserts.assertEQ(getExpectedIResult(), iResult, "checking iResult");
1036 Asserts.assertEQ(getExpectedLResult(), lResult, "checking lResult");
1037 Asserts.assertEQ(getExpectedFResult(), fResult, "checking fResult");
1038 Asserts.assertEQ(getExpectedDResult(), dResult, "checking dResult");
1039 }
1040
1041 public void msg(String m) {
1042 System.out.println();
1043 System.out.println("###(Target) " + m);
1044 System.out.println();
1045 }
1046
1047 // The object passed will be ArgEscape if it was NoEscape before.
1048 public final void dontinline_make_arg_escape(XYVal xy) {
1049 }
1050
1051 /**
1052 * Call a method indirectly using reflection. The indirection is a limit for escape
1053 * analysis in the sense that the VM need not search beyond for frames that might have
1054 * an object being read by an JVMTI agent as ArgEscape.
1055 * @param receiver The receiver object of the call.
1056 * @param methodName The name of the method to be called.
1057 */
1058 public final void dontinline_call_with_entry_frame(Object receiver, String methodName) {
1059 Asserts.assertTrue(warmupDone, "We want to take the slow path through jni, so don't call in warmup");
1060
1061 Class<?> cls = receiver.getClass();
1062 Class<?>[] none = {};
1063
1064 java.lang.reflect.Method m;
1065 try {
1066 m = cls.getDeclaredMethod(methodName, none);
1067 m.invoke(receiver);
1068 } catch (Exception e) {
1069 Asserts.fail("Call through reflection failed", e);
1070 }
1071 }
1072
1073 /**
1074 * Trigger bulk rebiasing for the given class by creating new instances and calling <code> hashCode() </code> on them.
1075 * @param cls The class to bulk rebias
1076 */
1077 public void dontinline_bulkRebiasAfterWarmup(Class<?> cls) {
1078 if (warmupDone) {
1079 try {
1080 for (int i=0; i < BiasedLockingBulkRebiasThreshold+2; i++) {
1081 biasToBeRevoked = cls.getDeclaredConstructor(int.class, int.class).newInstance(1, 1);
1082 synchronized (biasToBeRevoked) { // bias towards current thread
1083 checkSum++;
1084 }
1085 biasToBeRevoked.hashCode(); // calling hashCode triggers revocation
1086 }
1087 } catch (Throwable e) {
1088 Asserts.fail("failed to create new instance of " + cls.getName(), e);
1089 }
1090 }
1091 }
1092
1093 /**
1094 * Trigger bulk revoke of biases for the given class by creating new instances and calling <code> hashCode() </code> on them.
1095 * @param cls The class to bulk rebias
1096 */
1097 public void dontinline_bulkRevokeAfterWarmup(Class<?> cls) {
1098 if (warmupDone) {
1099 try {
1100 for (int i=0; i < BiasedLockingBulkRevokeThreshold+2; i++) {
1101 biasToBeRevoked = cls.getDeclaredConstructor(int.class, int.class).newInstance(1, 1);
1102 synchronized (biasToBeRevoked) { // bias towards current thread
1103 checkSum++;
1104 }
1105 biasToBeRevoked.hashCode(); // calling hashCode triggers revocation
1106 }
1107 } catch (Throwable e) {
1108 Asserts.fail("failed to create new instance of " + cls.getName(), e);
1109 }
1110 }
1111 }
1112
1113 static class LinkedList {
1114 LinkedList l;
1115 public long[] array;
1116 public LinkedList(LinkedList l, int size) {
1117 this.array = size > 0 ? new long[size] : null;
1118 this.l = l;
1119 }
1120 }
1121
1122 public LinkedList consumedMemory;
1123
1124 public void consumeAllMemory() {
1125 msg("consume all memory");
1126 int size = 128 * 1024 * 1024;
1127 while(true) {
1128 try {
1129 while(true) {
1130 consumedMemory = new LinkedList(consumedMemory, size);
1131 }
1132 } catch(OutOfMemoryError oom) {
1133 if (size == 0) break;
1134 }
1135 size = size / 2;
1136 }
1137 }
1138 }
1139
1140 /////////////////////////////////////////////////////////////////////////////
1141 //
1142 // Test Cases
1143 //
1144 /////////////////////////////////////////////////////////////////////////////
1145
1146 // make sure a compiled frame is not deoptimized if an escaping local is accessed
1147 class EAGetWithoutMaterializeTarget extends EATestCaseBaseTarget {
1148
1149 public XYVal getAway;
1150
1151 public void dontinline_testMethod() {
1152 XYVal xy = new XYVal(4, 2);
1153 getAway = xy; // allocated object escapes
1154 dontinline_brkpt();
1155 iResult = xy.x + xy.y;
1156 }
1157
1158 @Override
1159 public int getExpectedIResult() {
1160 return 4 + 2;
1161 }
1162
1163 @Override
1164 public boolean testFrameShouldBeDeoptimized() {
1165 return false;
1166 }
1167 }
1168
1169 class EAGetWithoutMaterialize extends EATestCaseBaseDebugger {
1170
1171 public void runTestCase() throws Exception {
1172 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1173 printStack(bpe.thread());
1174 ObjectReference o = getLocalRef(bpe.thread().frame(1), XYVAL_NAME, "xy");
1175 checkPrimitiveField(o, FD.I, "x", 4);
1176 checkPrimitiveField(o, FD.I, "y", 2);
1177 }
1178 }
1179
1180 /////////////////////////////////////////////////////////////////////////////
1181
1182 //
1183 // Tests the following:
1184 //
1185 // 1. Debugger can obtain a reference to a scalar replaced object R from java thread J.
1186 // See runTestCase.
1187 //
1188 // 2. Subsequent modifications of R by J are noticed by the debugger.
1189 // See checkPostConditions.
1190 //
1191 class EAMaterializeLocalVariableUponGet extends EATestCaseBaseDebugger {
1192
1193 private ObjectReference o;
1194
1195 public void runTestCase() throws Exception {
1196 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1197 printStack(bpe.thread());
1198 // check 1.
1199 o = getLocalRef(bpe.thread().frame(1), XYVAL_NAME, "xy");
1200 // o is referenced in checkPostConditions() and must not be gc'ed.
1201 o.disableCollection();
1202 checkPrimitiveField(o, FD.I, "x", 4);
1203 checkPrimitiveField(o, FD.I, "y", 2);
1204 }
1205
1206 @Override
1207 public void checkPostConditions() throws Exception {
1208 super.checkPostConditions();
1209 // check 2.
1210 checkPrimitiveField(o, FD.I, "x", 5);
1211 }
1212 }
1213
1214 class EAMaterializeLocalVariableUponGetTarget extends EATestCaseBaseTarget {
1215
1216 public void dontinline_testMethod() {
1217 XYVal xy = new XYVal(4, 2);
1218 dontinline_brkpt(); // Debugger obtains scalar replaced object at this point.
1219 xy.x += 1; // Change scalar replaced object after debugger obtained a reference to it.
1220 iResult = xy.x + xy.y;
1221 }
1222
1223 @Override
1224 public int getExpectedIResult() {
1225 return 4 + 2 + 1;
1226 }
1227 }
1228
1229 /////////////////////////////////////////////////////////////////////////////
1230
1231 // Test if an eliminated object can be reallocated in a frame with an active
1232 // call that will return another object
1233 class EAMaterializeLocalAtObjectReturn extends EATestCaseBaseDebugger {
1234 public void runTestCase() throws Exception {
1235 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1236 printStack(bpe.thread());
1237 ObjectReference o = getLocalRef(bpe.thread().frame(2), XYVAL_NAME, "xy");
1238 checkPrimitiveField(o, FD.I, "x", 4);
1239 checkPrimitiveField(o, FD.I, "y", 2);
1240 }
1241 }
1242
1243 class EAMaterializeLocalAtObjectReturnTarget extends EATestCaseBaseTarget {
1244 @Override
1245 public void setUp() {
1246 super.setUp();
1247 testMethodDepth = 2;
1248 }
1249
1250 public void dontinline_testMethod() {
1251 XYVal xy = new XYVal(4, 2);
1252 Integer io = // Read xy here triggers reallocation
1253 dontinline_brkpt_return_Integer();
1254 iResult = xy.x + xy.y + io;
1255 }
1256
1257 public Integer dontinline_brkpt_return_Integer() {
1258 // We can't break directly in this method, as this results in making
1259 // the test method not entrant caused by an existing dependency
1260 dontinline_brkpt();
1261 return Integer.valueOf(23);
1262 }
1263
1264 @Override
1265 public int getExpectedIResult() {
1266 return 4 + 2 + 23;
1267 }
1268 }
1269
1270 /////////////////////////////////////////////////////////////////////////////
1271
1272 // Test if an eliminated object can be reallocated *just* before a call returns an object.
1273 // (See CompiledMethod::is_at_poll_return())
1274 // Details: the callee method has just one safepoint poll at the return. The other safepoint
1275 // is at the end of an iteration of the endless loop. We can detect if we suspended the target
1276 // there because the local xy is out of scope there.
1277 class EAMaterializeLocalAtObjectPollReturnReturn extends EATestCaseBaseDebugger {
1278 public void runTestCase() throws Exception {
1279 msg("Resume " + env.targetMainThread);
1280 env.vm().resume();
1281 waitUntilTargetHasEnteredEndlessLoop();
1282 ObjectReference o = null;
1283 int retryCount = 0;
1284 do {
1285 env.targetMainThread.suspend();
1286 printStack(env.targetMainThread);
1287 try {
1288 o = getLocalRef(env.targetMainThread.frame(0), XYVAL_NAME, "xy");
1289 } catch (Exception e) {
1290 ++retryCount;
1291 msg("The local variable xy is out of scope because we suspended at the wrong bci. Resume and try again! (" + retryCount + ")");
1292 env.targetMainThread.resume();
1293 if ((retryCount % 10) == 0) {
1294 Thread.sleep(200);
1295 }
1296 }
1297 } while (o == null);
1298 checkPrimitiveField(o, FD.I, "x", 4);
1299 checkPrimitiveField(o, FD.I, "y", 2);
1300 terminateEndlessLoop();
1301 }
1302 }
1303
1304 class EAMaterializeLocalAtObjectPollReturnReturnTarget extends EATestCaseBaseTarget {
1305 @Override
1306 public void setUp() {
1307 super.setUp();
1308 loopCount = 3;
1309 doLoop = true;
1310 }
1311
1312 public void warmupDone() {
1313 super.warmupDone();
1314 msg("enter 'endless' loop by setting loopCount = Long.MAX_VALUE");
1315 loopCount = Long.MAX_VALUE; // endless loop
1316 }
1317
1318 public void dontinline_testMethod() {
1319 long result = 0;
1320 while (doLoop && loopCount-- > 0) {
1321 targetIsInLoop = true;
1322 XYVal xy = new XYVal(4, 2);
1323 Integer io = // Read xy here triggers reallocation just before the call returns
1324 dontinline_brkpt_return_Integer();
1325 result += xy.x + xy.y + io;
1326 } // Here is a second safepoint. We were suspended here if xy is not in scope.
1327 targetIsInLoop = false;
1328 lResult = result;
1329 }
1330
1331 public Integer dontinline_brkpt_return_Integer() {
1332 return Integer.valueOf(23);
1333 }
1334
1335 @Override
1336 public long getExpectedLResult() {
1337 return (Long.MAX_VALUE - loopCount) * (4+2+23);
1338 }
1339 }
1340
1341 /////////////////////////////////////////////////////////////////////////////
1342 // Test case collection that tests rematerialization of different
1343 // array types where the first element is always not constant and the
1344 // other elements are constants. Not constant values are stored in
1345 // the stack frame for rematerialization whereas constants are kept
1346 // in the debug info of the nmethod.
1347
1348 class EAMaterializeIntArrayTarget extends EATestCaseBaseTarget {
1349
1350 public void dontinline_testMethod() {
1351 int nums[] = {NOT_CONST_1I , 2, 3};
1352 dontinline_brkpt();
1353 iResult = nums[0] + nums[1] + nums[2];
1354 }
1355
1356 @Override
1357 public int getExpectedIResult() {
1358 return NOT_CONST_1I + 2 + 3;
1359 }
1360 }
1361
1362 class EAMaterializeIntArray extends EATestCaseBaseDebugger {
1363 public void runTestCase() throws Exception {
1364 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1365 printStack(bpe.thread());
1366 int[] expectedVals = {1, 2, 3};
1367 checkLocalPrimitiveArray(bpe.thread().frame(1), "nums", FD.I, expectedVals);
1368 }
1369 }
1370
1371 /////////////////////////////////////////////////////////////////////////////
1372
1373 class EAMaterializeLongArrayTarget extends EATestCaseBaseTarget {
1374
1375 public void dontinline_testMethod() {
1376 long nums[] = {NOT_CONST_1L , 2, 3};
1377 dontinline_brkpt();
1378 lResult = nums[0] + nums[1] + nums[2];
1379 }
1380
1381 @Override
1382 public long getExpectedLResult() {
1383 return NOT_CONST_1L + 2 + 3;
1384 }
1385 }
1386
1387 class EAMaterializeLongArray extends EATestCaseBaseDebugger {
1388 public void runTestCase() throws Exception {
1389 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1390 printStack(bpe.thread());
1391 long[] expectedVals = {1, 2, 3};
1392 checkLocalPrimitiveArray(bpe.thread().frame(1), "nums", FD.J, expectedVals);
1393 }
1394 }
1395
1396 /////////////////////////////////////////////////////////////////////////////
1397
1398 class EAMaterializeFloatArrayTarget extends EATestCaseBaseTarget {
1399
1400 public void dontinline_testMethod() {
1401 float nums[] = {NOT_CONST_1F , 2.2f, 3.3f};
1402 dontinline_brkpt();
1403 fResult = nums[0] + nums[1] + nums[2];
1404 }
1405
1406 @Override
1407 public float getExpectedFResult() {
1408 return NOT_CONST_1F + 2.2f + 3.3f;
1409 }
1410 }
1411
1412 class EAMaterializeFloatArray extends EATestCaseBaseDebugger {
1413 public void runTestCase() throws Exception {
1414 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1415 printStack(bpe.thread());
1416 float[] expectedVals = {1.1f, 2.2f, 3.3f};
1417 checkLocalPrimitiveArray(bpe.thread().frame(1), "nums", FD.F, expectedVals);
1418 }
1419 }
1420
1421 /////////////////////////////////////////////////////////////////////////////
1422
1423 class EAMaterializeDoubleArrayTarget extends EATestCaseBaseTarget {
1424
1425 public void dontinline_testMethod() {
1426 double nums[] = {NOT_CONST_1D , 2.2d, 3.3d};
1427 dontinline_brkpt();
1428 dResult = nums[0] + nums[1] + nums[2];
1429 }
1430
1431 @Override
1432 public double getExpectedDResult() {
1433 return NOT_CONST_1D + 2.2d + 3.3d;
1434 }
1435 }
1436
1437 class EAMaterializeDoubleArray extends EATestCaseBaseDebugger {
1438 public void runTestCase() throws Exception {
1439 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1440 printStack(bpe.thread());
1441 double[] expectedVals = {1.1d, 2.2d, 3.3d};
1442 checkLocalPrimitiveArray(bpe.thread().frame(1), "nums", FD.D, expectedVals);
1443 }
1444 }
1445
1446 /////////////////////////////////////////////////////////////////////////////
1447
1448 class EAMaterializeObjectArrayTarget extends EATestCaseBaseTarget {
1449
1450 public void dontinline_testMethod() {
1451 Long nums[] = {NOT_CONST_1_OBJ , CONST_2_OBJ, CONST_3_OBJ};
1452 dontinline_brkpt();
1453 lResult = nums[0] + nums[1] + nums[2];
1454 }
1455
1456 @Override
1457 public long getExpectedLResult() {
1458 return 1 + 2 + 3;
1459 }
1460 }
1461
1462 class EAMaterializeObjectArray extends EATestCaseBaseDebugger {
1463 public void runTestCase() throws Exception {
1464 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1465 printStack(bpe.thread());
1466 ReferenceType clazz = bpe.thread().frame(0).location().declaringType();
1467 ObjectReference[] expectedVals = {
1468 (ObjectReference) clazz.getValue(clazz.fieldByName("NOT_CONST_1_OBJ")),
1469 (ObjectReference) clazz.getValue(clazz.fieldByName("CONST_2_OBJ")),
1470 (ObjectReference) clazz.getValue(clazz.fieldByName("CONST_3_OBJ"))
1471 };
1472 checkLocalObjectArray(bpe.thread().frame(1), "nums", "java.lang.Long[]", expectedVals);
1473 }
1474 }
1475
1476 /////////////////////////////////////////////////////////////////////////////
1477
1478 // Materialize an object whose fields have constant and not constant values at
1479 // the point where the object is materialized.
1480 class EAMaterializeObjectWithConstantAndNotConstantValuesTarget extends EATestCaseBaseTarget {
1481
1482 public void dontinline_testMethod() {
1483 ILFDO o = new ILFDO(NOT_CONST_1I, 2,
1484 NOT_CONST_1L, 2L,
1485 NOT_CONST_1F, 2.1F,
1486 NOT_CONST_1D, 2.1D,
1487 NOT_CONST_1_OBJ, CONST_2_OBJ
1488 );
1489 dontinline_brkpt();
1490 dResult =
1491 o.i + o.i2 + o.l + o.l2 + o.f + o.f2 + o.d + o.d2 + o.o + o.o2;
1492 }
1493
1494 @Override
1495 public double getExpectedDResult() {
1496 return NOT_CONST_1I + 2 + NOT_CONST_1L + 2L + NOT_CONST_1F + 2.1F + NOT_CONST_1D + 2.1D + NOT_CONST_1_OBJ + CONST_2_OBJ;
1497 }
1498 }
1499
1500 class EAMaterializeObjectWithConstantAndNotConstantValues extends EATestCaseBaseDebugger {
1501 public void runTestCase() throws Exception {
1502 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1503 printStack(bpe.thread());
1504 ObjectReference o = getLocalRef(bpe.thread().frame(1), "ILFDO", "o");
1505 checkPrimitiveField(o, FD.I, "i", 1);
1506 checkPrimitiveField(o, FD.I, "i2", 2);
1507 checkPrimitiveField(o, FD.J, "l", 1L);
1508 checkPrimitiveField(o, FD.J, "l2", 2L);
1509 checkPrimitiveField(o, FD.F, "f", 1.1f);
1510 checkPrimitiveField(o, FD.F, "f2", 2.1f);
1511 checkPrimitiveField(o, FD.D, "d", 1.1d);
1512 checkPrimitiveField(o, FD.D, "d2", 2.1d);
1513 ReferenceType clazz = bpe.thread().frame(1).location().declaringType();
1514 ObjectReference[] expVals = {
1515 (ObjectReference) clazz.getValue(clazz.fieldByName("NOT_CONST_1_OBJ")),
1516 (ObjectReference) clazz.getValue(clazz.fieldByName("CONST_2_OBJ")),
1517 };
1518 checkObjField(o, "o", expVals[0]);
1519 checkObjField(o, "o2", expVals[1]);
1520 }
1521 }
1522
1523 /////////////////////////////////////////////////////////////////////////////
1524
1525 // Two local variables reference the same object.
1526 // Check if the debugger obtains the same object when reading the two variables
1527 class EAMaterializeObjReferencedBy2LocalsTarget extends EATestCaseBaseTarget {
1528
1529 public void dontinline_testMethod() {
1530 XYVal xy = new XYVal(2, 3);
1531 XYVal alias = xy;
1532 dontinline_brkpt();
1533 iResult = xy.x + alias.x;
1534 }
1535
1536 @Override
1537 public int getExpectedIResult() {
1538 return 2 + 2;
1539 }
1540 }
1541
1542 class EAMaterializeObjReferencedBy2Locals extends EATestCaseBaseDebugger {
1543
1544 public void runTestCase() throws Exception {
1545 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1546 printStack(bpe.thread());
1547 ObjectReference xy = getLocalRef(bpe.thread().frame(1), XYVAL_NAME, "xy");
1548 ObjectReference alias = getLocalRef(bpe.thread().frame(1), XYVAL_NAME, "alias");
1549 Asserts.assertSame(xy, alias, "xy and alias are expected to reference the same object");
1550 }
1551
1552 }
1553
1554 /////////////////////////////////////////////////////////////////////////////
1555
1556 // Two local variables reference the same object.
1557 // Check if it has the expected effect in the target if the debugger modifies the object.
1558 class EAMaterializeObjReferencedBy2LocalsAndModifyTarget extends EATestCaseBaseTarget {
1559
1560 public void dontinline_testMethod() {
1561 XYVal xy = new XYVal(2, 3);
1562 XYVal alias = xy;
1563 dontinline_brkpt(); // debugger: alias.x = 42
1564 iResult = xy.x + alias.x;
1565 }
1566
1567 @Override
1568 public int getExpectedIResult() {
1569 return 42 + 42;
1570 }
1571 }
1572
1573 class EAMaterializeObjReferencedBy2LocalsAndModify extends EATestCaseBaseDebugger {
1574
1575 public void runTestCase() throws Exception {
1576 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1577 printStack(bpe.thread());
1578 ObjectReference alias = getLocalRef(bpe.thread().frame(1), XYVAL_NAME, "alias");
1579 setField(alias, "x", env.vm().mirrorOf(42));
1580 }
1581 }
1582
1583 /////////////////////////////////////////////////////////////////////////////
1584
1585 // Two local variables of the same compiled frame but in different virtual frames reference the same
1586 // object.
1587 // Check if the debugger obtains the same object when reading the two variables
1588 class EAMaterializeObjReferencedBy2LocalsInDifferentVirtFramesTarget extends EATestCaseBaseTarget {
1589
1590 @Override
1591 public void setUp() {
1592 super.setUp();
1593 testMethodDepth = 2;
1594 }
1595
1596 public void dontinline_testMethod() {
1597 XYVal xy = new XYVal(2, 3);
1598 testMethod_inlined(xy);
1599 iResult += xy.x;
1600 }
1601
1602 public void testMethod_inlined(XYVal xy) {
1603 XYVal alias = xy;
1604 dontinline_brkpt();
1605 iResult = alias.x;
1606 }
1607
1608 @Override
1609 public int getExpectedIResult() {
1610 return 2 + 2;
1611 }
1612 }
1613
1614 class EAMaterializeObjReferencedBy2LocalsInDifferentVirtFrames extends EATestCaseBaseDebugger {
1615
1616 public void runTestCase() throws Exception {
1617 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1618 printStack(bpe.thread());
1619 ObjectReference xy = getLocalRef(bpe.thread().frame(2), XYVAL_NAME, "xy");
1620 ObjectReference alias = getLocalRef(bpe.thread().frame(1), "testMethod_inlined", "alias", XYVAL_NAME);
1621 Asserts.assertSame(xy, alias, "xy and alias are expected to reference the same object");
1622 }
1623
1624 }
1625
1626 /////////////////////////////////////////////////////////////////////////////
1627
1628 // Two local variables of the same compiled frame but in different virtual frames reference the same
1629 // object.
1630 // Check if it has the expected effect in the target if the debugger modifies the object.
1631 class EAMaterializeObjReferencedBy2LocalsInDifferentVirtFramesAndModifyTarget extends EATestCaseBaseTarget {
1632
1633 @Override
1634 public void setUp() {
1635 super.setUp();
1636 testMethodDepth = 2;
1637 }
1638
1639 public void dontinline_testMethod() {
1640 XYVal xy = new XYVal(2, 3);
1641 testMethod_inlined(xy); // debugger: xy.x = 42
1642 iResult += xy.x;
1643 }
1644
1645 public void testMethod_inlined(XYVal xy) {
1646 XYVal alias = xy;
1647 dontinline_brkpt();
1648 iResult = alias.x;
1649 }
1650
1651 @Override
1652 public int getExpectedIResult() {
1653 return 42 + 42;
1654 }
1655 }
1656
1657 class EAMaterializeObjReferencedBy2LocalsInDifferentVirtFramesAndModify extends EATestCaseBaseDebugger {
1658
1659 public void runTestCase() throws Exception {
1660 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1661 printStack(bpe.thread());
1662 ObjectReference alias = getLocalRef(bpe.thread().frame(1), "testMethod_inlined", "alias", XYVAL_NAME);
1663 setField(alias, "x", env.vm().mirrorOf(42));
1664 }
1665
1666 }
1667
1668 /////////////////////////////////////////////////////////////////////////////
1669
1670 // Test materialization of an object referenced only from expression stack
1671 class EAMaterializeObjReferencedFromOperandStackTarget extends EATestCaseBaseTarget {
1672
1673 @Override
1674 public void setUp() {
1675 super.setUp();
1676 testMethodDepth = 2;
1677 }
1678
1679 public void dontinline_testMethod() {
1680 @SuppressWarnings("unused")
1681 XYVal xy1 = new XYVal(2, 3);
1682 // Debugger breaks in call to dontinline_brkpt_ret_100() and reads
1683 // the value of the local 'xy1'. This triggers materialization
1684 // of the object on the operand stack
1685 iResult = testMethodInlined(new XYVal(4, 2), dontinline_brkpt_ret_100());
1686 }
1687
1688 public int testMethodInlined(XYVal xy2, int dontinline_brkpt_ret_100) {
1689 return xy2.x + dontinline_brkpt_ret_100;
1690 }
1691
1692 public int dontinline_brkpt_ret_100() {
1693 dontinline_brkpt();
1694 return 100;
1695 }
1696
1697 @Override
1698 public int getExpectedIResult() {
1699 return 4 + 100;
1700 }
1701 }
1702
1703 class EAMaterializeObjReferencedFromOperandStack extends EATestCaseBaseDebugger {
1704
1705 public void runTestCase() throws Exception {
1706 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1707 printStack(bpe.thread());
1708 ObjectReference xy1 = getLocalRef(bpe.thread().frame(2), XYVAL_NAME, "xy1");
1709 checkPrimitiveField(xy1, FD.I, "x", 2);
1710 checkPrimitiveField(xy1, FD.I, "y", 3);
1711 }
1712
1713 }
1714
1715 /////////////////////////////////////////////////////////////////////////////
1716
1717 /**
1718 * Tests a regression in the implementation by setting the value of a local int which triggers the
1719 * creation of a deferred update and then getting the reference to a scalar replaced object. The
1720 * issue was that the scalar replaced object was not reallocated. Because of the deferred update it
1721 * was assumed that the reallocation already happened.
1722 */
1723 class EAMaterializeLocalVariableUponGetAfterSetInteger extends EATestCaseBaseDebugger {
1724
1725 public void runTestCase() throws Exception {
1726 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1727 printStack(bpe.thread());
1728 setLocal(bpe.thread().frame(1), "i", env.vm().mirrorOf(43));
1729 ObjectReference o = getLocalRef(bpe.thread().frame(1), XYVAL_NAME, "xy");
1730 checkPrimitiveField(o, FD.I, "x", 4);
1731 checkPrimitiveField(o, FD.I, "y", 2);
1732 }
1733 }
1734
1735 class EAMaterializeLocalVariableUponGetAfterSetIntegerTarget extends EATestCaseBaseTarget {
1736
1737 public void dontinline_testMethod() {
1738 XYVal xy = new XYVal(4, 2);
1739 int i = 42;
1740 dontinline_brkpt();
1741 iResult = xy.x + xy.y + i;
1742 }
1743
1744 @Override
1745 public int getExpectedIResult() {
1746 return 4 + 2 + 43;
1747 }
1748
1749 @Override
1750 public boolean testFrameShouldBeDeoptimized() {
1751 return true; // setting local variable i always triggers deoptimization
1752 }
1753 }
1754
1755 /////////////////////////////////////////////////////////////////////////////
1756 //
1757 // Locking Tests
1758 //
1759 /////////////////////////////////////////////////////////////////////////////
1760
1761 class EARelockingSimple extends EATestCaseBaseDebugger {
1762
1763 public void runTestCase() throws Exception {
1764 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1765 printStack(bpe.thread());
1766 @SuppressWarnings("unused")
1767 ObjectReference o = getLocalRef(bpe.thread().frame(1), XYVAL_NAME, "l1");
1768 }
1769 }
1770
1771 class EARelockingSimpleTarget extends EATestCaseBaseTarget {
1772
1773 public void dontinline_testMethod() {
1774 XYVal l1 = new XYVal(4, 2);
1775 synchronized (l1) {
1776 dontinline_brkpt();
1777 }
1778 }
1779 }
1780
1781 /////////////////////////////////////////////////////////////////////////////
1782
1783 /**
1784 * Test if the bias of an object O that escapes globally is revoked correctly if local objects
1785 * escape through JVMTI. O is referenced by field l0.
1786 * This tests a regression of a previous version of the implementation.
1787 */
1788 class EARelockingSimple_2 extends EATestCaseBaseDebugger {
1789
1790 public void runTestCase() throws Exception {
1791 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1792 printStack(bpe.thread());
1793 @SuppressWarnings("unused")
1794 ObjectReference o = getLocalRef(bpe.thread().frame(1), XYVAL_NAME, "l1");
1795 }
1796 }
1797
1798 class EARelockingSimple_2Target extends EATestCaseBaseTarget {
1799
1800 public XYVal l0;
1801
1802 public void dontinline_testMethod() {
1803 l0 = new XYVal(4, 2); // GobalEscape
1804 XYVal l1 = new XYVal(4, 2);
1805 synchronized (l0) {
1806 synchronized (l1) {
1807 dontinline_brkpt();
1808 }
1809 }
1810 }
1811 }
1812
1813 /////////////////////////////////////////////////////////////////////////////
1814
1815 // Test recursive locking
1816 class EARelockingRecursiveTarget extends EATestCaseBaseTarget {
1817
1818 @Override
1819 public void setUp() {
1820 super.setUp();
1821 testMethodDepth = 2;
1822 }
1823
1824 public void dontinline_testMethod() {
1825 XYVal l1 = new XYVal(4, 2);
1826 synchronized (l1) {
1827 testMethod_inlined(l1);
1828 }
1829 }
1830
1831 public void testMethod_inlined(XYVal l2) {
1832 synchronized (l2) {
1833 dontinline_brkpt();
1834 }
1835 }
1836 }
1837
1838 class EARelockingRecursive extends EATestCaseBaseDebugger {
1839
1840 public void runTestCase() throws Exception {
1841 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1842 printStack(bpe.thread());
1843 @SuppressWarnings("unused")
1844 ObjectReference o = getLocalRef(bpe.thread().frame(2), XYVAL_NAME, "l1");
1845 }
1846 }
1847
1848 /////////////////////////////////////////////////////////////////////////////
1849
1850 // Object ref l1 is retrieved by the debugger at a location where nested locks are omitted. The
1851 // accessed object is globally reachable already before the access, therefore no relocking is done.
1852 class EARelockingNestedInflatedTarget extends EATestCaseBaseTarget {
1853
1854 @Override
1855 public void setUp() {
1856 super.setUp();
1857 testMethodDepth = 2;
1858 }
1859
1860 @Override
1861 public boolean testFrameShouldBeDeoptimized() {
1862 // Access does not trigger deopt., as escape state is already global escape.
1863 return false;
1864 }
1865
1866 public void dontinline_testMethod() {
1867 XYVal l1 = inflatedLock;
1868 synchronized (l1) {
1869 testMethod_inlined(l1);
1870 }
1871 }
1872
1873 public void testMethod_inlined(XYVal l2) {
1874 synchronized (l2) { // eliminated nested locking
1875 dontinline_brkpt();
1876 }
1877 }
1878 }
1879
1880 class EARelockingNestedInflated extends EATestCaseBaseDebugger {
1881
1882 public void runTestCase() throws Exception {
1883 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1884 printStack(bpe.thread());
1885 @SuppressWarnings("unused")
1886 ObjectReference o = getLocalRef(bpe.thread().frame(2), XYVAL_NAME, "l1");
1887 }
1888 }
1889
1890 /////////////////////////////////////////////////////////////////////////////
1891
1892 /**
1893 * Like {@link EARelockingNestedInflated} with the difference that there is
1894 * a scalar replaced object in the scope from which the object with eliminated nested locking
1895 * is read. This triggers materialization and relocking.
1896 */
1897 class EARelockingNestedInflated_02 extends EATestCaseBaseDebugger {
1898
1899 public void runTestCase() throws Exception {
1900 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1901 printStack(bpe.thread());
1902 @SuppressWarnings("unused")
1903 ObjectReference o = getLocalRef(bpe.thread().frame(2), XYVAL_NAME, "l1");
1904 }
1905 }
1906
1907 class EARelockingNestedInflated_02Target extends EATestCaseBaseTarget {
1908
1909 @Override
1910 public void setUp() {
1911 super.setUp();
1912 testMethodDepth = 2;
1913 }
1914
1915 public void dontinline_testMethod() {
1916 @SuppressWarnings("unused")
1917 XYVal xy = new XYVal(1, 1); // scalar replaced
1918 XYVal l1 = inflatedLock; // read by debugger
1919 synchronized (l1) {
1920 testMethod_inlined(l1);
1921 }
1922 }
1923
1924 public void testMethod_inlined(XYVal l2) {
1925 synchronized (l2) { // eliminated nested locking
1926 dontinline_brkpt();
1927 }
1928 }
1929 }
1930
1931 /////////////////////////////////////////////////////////////////////////////
1932
1933 /**
1934 * Checks if an eliminated lock of an ArgEscape object l1 can be relocked if
1935 * l1 is locked in a callee frame.
1936 */
1937 class EARelockingArgEscapeLWLockedInCalleeFrame extends EATestCaseBaseDebugger {
1938
1939 public void runTestCase() throws Exception {
1940 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1941 printStack(bpe.thread());
1942 @SuppressWarnings("unused")
1943 ObjectReference o = getLocalRef(bpe.thread().frame(2), XYVAL_NAME, "l1");
1944 }
1945 }
1946
1947 class EARelockingArgEscapeLWLockedInCalleeFrameTarget extends EATestCaseBaseTarget {
1948
1949 @Override
1950 public void setUp() {
1951 super.setUp();
1952 testMethodDepth = 2;
1953 }
1954
1955 public void dontinline_testMethod() {
1956 XYVal l1 = new XYVal(1, 1); // ArgEscape
1957 synchronized (l1) { // eliminated
1958 l1.dontinline_sync_method(this); // l1 escapes
1959 }
1960 }
1961
1962 @Override
1963 public boolean testFrameShouldBeDeoptimized() {
1964 // Graal does not provide debug info about arg escape objects, therefore the frame is not deoptimized
1965 return !UseJVMCICompiler && super.testFrameShouldBeDeoptimized();
1966 }
1967 }
1968
1969 /////////////////////////////////////////////////////////////////////////////
1970
1971 /**
1972 * Similar to {@link EARelockingArgEscapeLWLockedInCalleeFrame}. In addition
1973 * the test method has got a scalar replaced object with eliminated locking.
1974 * This pattern matches a regression in the implementation.
1975 */
1976 class EARelockingArgEscapeLWLockedInCalleeFrame_2 extends EATestCaseBaseDebugger {
1977
1978 public void runTestCase() throws Exception {
1979 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
1980 printStack(bpe.thread());
1981 @SuppressWarnings("unused")
1982 ObjectReference o = getLocalRef(bpe.thread().frame(2), XYVAL_NAME, "l1");
1983 }
1984 }
1985
1986 class EARelockingArgEscapeLWLockedInCalleeFrame_2Target extends EATestCaseBaseTarget {
1987
1988 @Override
1989 public void setUp() {
1990 super.setUp();
1991 testMethodDepth = 2;
1992 }
1993
1994 public void dontinline_testMethod() {
1995 XYVal l1 = new XYVal(1, 1); // ArgEscape
1996 XYVal l2 = new XYVal(4, 2); // NoEscape, scalar replaced
1997 synchronized (l1) { // eliminated
1998 synchronized (l2) { // eliminated
1999 l1.dontinline_sync_method(this); // l1 escapes
2000 }
2001 }
2002 iResult = l2.x + l2.y;
2003 }
2004
2005 @Override
2006 public int getExpectedIResult() {
2007 return 6;
2008 }
2009 }
2010
2011 /////////////////////////////////////////////////////////////////////////////
2012
2013 /**
2014 * Similar to {@link EARelockingArgEscapeLWLockedInCalleeFrame}.
2015 * A bulk rebias operation is triggered at a position where all locks on the local object referenced
2016 * by l1 are eliminated. This leaves the object with an outdated biased locking epoch which has to be
2017 * considered when relocking.
2018 * This tests a regression in a previous version.
2019 */
2020 class EARelockingArgEscapeLWLockedInCalleeFrame_3 extends EATestCaseBaseDebugger {
2021
2022 public static final String XYVAL_LOCAL_NAME = EARelockingArgEscapeLWLockedInCalleeFrame_3Target.XYValLocal.class.getName();
2023
2024 public void runTestCase() throws Exception {
2025 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
2026 printStack(bpe.thread());
2027 @SuppressWarnings("unused")
2028 ObjectReference o = getLocalRef(bpe.thread().frame(1), XYVAL_LOCAL_NAME, "l1");
2029 }
2030 }
2031
2032 class EARelockingArgEscapeLWLockedInCalleeFrame_3Target extends EATestCaseBaseTarget {
2033
2034 // Using local type to avoid side effects on biased locking heuristics
2035 public static class XYValLocal extends XYVal {
2036 public XYValLocal(int x, int y) {
2037 super(x,y);
2038 }
2039 }
2040
2041 public void dontinline_testMethod() {
2042 XYVal l1 = new XYValLocal(1, 1); // ArgEscape
2043 synchronized (l1) { // eliminated
2044 l1.dontinline_sync_method_no_brkpt(this); // l1 escapes
2045 // trigger bulk rebias
2046 dontinline_bulkRebiasAfterWarmup(l1.getClass());
2047 // Now the epoch of l1 does not match the epoch of its class.
2048 // This has to be considered when relocking because of JVMTI access
2049 dontinline_brkpt();
2050 }
2051 }
2052
2053 @Override
2054 public boolean testFrameShouldBeDeoptimized() {
2055 // Graal does not provide debug info about arg escape objects, therefore the frame is not deoptimized
2056 return !UseJVMCICompiler && super.testFrameShouldBeDeoptimized();
2057 }
2058 }
2059
2060 /////////////////////////////////////////////////////////////////////////////
2061
2062 /**
2063 * Similar to {@link EARelockingArgEscapeLWLockedInCalleeFrame_3}.
2064 * But instead of a bulk rebias a bulk revoke operation is triggered.
2065 * This leaves the object with a stale bias as the prototype header of its calls lost its bias
2066 * pattern in the bulk revoke which has to be considered during relocking.
2067 * This tests a regression in a previous version.
2068 */
2069 class EARelockingArgEscapeLWLockedInCalleeFrame_4 extends EATestCaseBaseDebugger {
2070
2071 public static final String XYVAL_LOCAL_NAME = EARelockingArgEscapeLWLockedInCalleeFrame_4Target.XYValLocal.class.getName();
2072
2073 public void runTestCase() throws Exception {
2074 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
2075 printStack(bpe.thread());
2076 @SuppressWarnings("unused")
2077 ObjectReference o = getLocalRef(bpe.thread().frame(1), XYVAL_LOCAL_NAME, "l1");
2078 }
2079 }
2080
2081 class EARelockingArgEscapeLWLockedInCalleeFrame_4Target extends EATestCaseBaseTarget {
2082
2083 // Using local type to avoid side effects on biased locking heuristics
2084 public static class XYValLocal extends XYVal {
2085 public XYValLocal(int x, int y) {
2086 super(x,y);
2087 }
2088 }
2089
2090 public void dontinline_testMethod() {
2091 XYVal l1 = new XYValLocal(1, 1); // ArgEscape
2092 synchronized (l1) { // eliminated
2093 l1.dontinline_sync_method_no_brkpt(this); // l1 escapes
2094 // trigger bulk rebias
2095 dontinline_bulkRevokeAfterWarmup(l1.getClass());
2096 // Now the epoch of l1 does not match the epoch of its class.
2097 // This has to be considered when relocking because of JVMTI access
2098 dontinline_brkpt();
2099 }
2100 }
2101
2102
2103 @Override
2104 public boolean testFrameShouldBeDeoptimized() {
2105 // Graal does not provide debug info about arg escape objects, therefore the frame is not deoptimized
2106 return !UseJVMCICompiler && super.testFrameShouldBeDeoptimized();
2107 }
2108 }
2109
2110 /////////////////////////////////////////////////////////////////////////////
2111
2112 /**
2113 * Test relocking eliminated (nested) locks of an object on which the
2114 * target thread currently waits.
2115 */
2116 class EARelockingObjectCurrentlyWaitingOn extends EATestCaseBaseDebugger {
2117
2118 public void runTestCase() throws Exception {
2119 env.vm().resume();
2120 boolean inWait = false;
2121 do {
2122 Thread.sleep(100);
2123 env.targetMainThread.suspend();
2124 printStack(env.targetMainThread);
2125 inWait = env.targetMainThread.frame(0).location().method().name().equals("wait");
2126 if (!inWait) {
2127 msg("Target not yet in java.lang.Object.wait(long).");
2128 env.targetMainThread.resume();
2129 }
2130 } while(!inWait);
2131 StackFrame testMethodFrame = env.targetMainThread.frame(4);
2132 // Access triggers relocking of all eliminated locks, including nested locks of l1 which references
2133 // the object on which the target main thread is currently waiting.
2134 ObjectReference l0 = getLocalRef(testMethodFrame, EARelockingObjectCurrentlyWaitingOnTarget.ForLocking.class.getName(), "l0");
2135 Asserts.assertEQ(l0.entryCount(), 1, "wrong entry count");
2136 ObjectReference l1 = getLocalRef(testMethodFrame, EARelockingObjectCurrentlyWaitingOnTarget.ForLocking.class.getName(), "l1");
2137 Asserts.assertEQ(l1.entryCount(), 0, "wrong entry count");
2138 setField(testCase, "objToNotifyOn", l1);
2139 }
2140 }
2141
2142 class EARelockingObjectCurrentlyWaitingOnTarget extends EATestCaseBaseTarget {
2143
2144 public static class ForLocking {
2145 }
2146
2147 public volatile Object objToNotifyOn; // debugger assigns value when notify thread should call objToNotifyOn.notifyAll()
2148
2149 @Override
2150 public void setUp() {
2151 super.setUp();
2152 testMethodDepth = 2;
2153 }
2154
2155 @Override
2156 public void warmupDone() {
2157 super.warmupDone();
2158 Thread t = new Thread(() -> doNotify());
2159 t.start();
2160 }
2161
2162 public void doNotify() {
2163 while (objToNotifyOn == null) {
2164 try {
2165 msg("objToNotifyOn is still null");
2166 Thread.sleep(100);
2167 } catch (InterruptedException e) { /* ignored */ }
2168 }
2169 synchronized (objToNotifyOn) {
2170 // will be received by the target main thread waiting in dontinline_waitWhenWarmupDone
2171 msg("calling objToNotifyOn.notifyAll()");
2172 objToNotifyOn.notifyAll();
2173 }
2174 }
2175
2176 @Override
2177 public boolean testFrameShouldBeDeoptimized() {
2178 return false;
2179 }
2180
2181 @Override
2182 public void dontinline_testMethod() throws Exception {
2183 ForLocking l0 = new ForLocking(); // will be scalar replaced; access triggers realloc/relock
2184 ForLocking l1 = new ForLocking();
2185 synchronized (l0) {
2186 synchronized (l1) {
2187 testMethod_inlined(l1);
2188 }
2189 }
2190 }
2191
2192 public void testMethod_inlined(ForLocking l2) throws Exception {
2193 synchronized (l2) { // eliminated nested locking
2194 dontinline_waitWhenWarmupDone(l2);
2195 }
2196 }
2197
2198 public void dontinline_waitWhenWarmupDone(ForLocking l2) throws Exception {
2199 if (warmupDone) {
2200 l2.wait();
2201 }
2202 }
2203 }
2204
2205 /////////////////////////////////////////////////////////////////////////////
2206 //
2207 // Test cases that require deoptimization even though neither locks
2208 // nor allocations are eliminated at the point where escape state is changed.
2209 //
2210 /////////////////////////////////////////////////////////////////////////////
2211
2212 /**
2213 * Let xy be NoEscape whose allocation cannot be eliminated (simulated by
2214 * -XX:-EliminateAllocations). The holding compiled frame has to be deoptimized when debugger
2215 * accesses xy because afterwards locking on xy is omitted.
2216 * Note: there are no EA based optimizations at the escape point.
2217 */
2218 class EADeoptFrameAfterReadLocalObject_01 extends EATestCaseBaseDebugger {
2219
2220 public void runTestCase() throws Exception {
2221 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
2222 printStack(bpe.thread());
2223 @SuppressWarnings("unused")
2224 ObjectReference xy = getLocalRef(bpe.thread().frame(1), XYVAL_NAME, "xy");
2225 }
2226 }
2227
2228 class EADeoptFrameAfterReadLocalObject_01Target extends EATestCaseBaseTarget {
2229
2230 public void dontinline_testMethod() {
2231 XYVal xy = new XYVal(1, 1);
2232 dontinline_brkpt(); // Debugger reads xy, when there are no virtual objects or eliminated locks in scope
2233 synchronized (xy) { // Locking is eliminated.
2234 xy.x++;
2235 xy.y++;
2236 }
2237 }
2238 }
2239
2240 /////////////////////////////////////////////////////////////////////////////
2241
2242 /**
2243 * Similar to {@link EADeoptFrameAfterReadLocalObject_01} with the difference that the debugger
2244 * reads xy from an inlined callee. So xy is NoEscape instead of ArgEscape.
2245 */
2246 class EADeoptFrameAfterReadLocalObject_01BTarget extends EATestCaseBaseTarget {
2247
2248 @Override
2249 public void setUp() {
2250 super.setUp();
2251 testMethodDepth = 2;
2252 }
2253
2254 public void dontinline_testMethod() {
2255 XYVal xy = new XYVal(1, 1);
2256 callee(xy); // Debugger acquires ref to xy from inlined callee
2257 // xy is NoEscape, nevertheless the object is not replaced
2258 // by scalars if running with -XX:-EliminateAllocations.
2259 // In that case there are no EA based optimizations were
2260 // the debugger reads the NoEscape object.
2261 synchronized (xy) { // Locking is eliminated.
2262 xy.x++;
2263 xy.y++;
2264 }
2265 }
2266
2267 public void callee(XYVal xy) {
2268 dontinline_brkpt(); // Debugger reads xy.
2269 // There are no virtual objects or eliminated locks.
2270 }
2271 }
2272
2273 class EADeoptFrameAfterReadLocalObject_01B extends EATestCaseBaseDebugger {
2274
2275 public void runTestCase() throws Exception {
2276 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
2277 printStack(bpe.thread());
2278 @SuppressWarnings("unused")
2279 ObjectReference xy = getLocalRef(bpe.thread().frame(1), "callee", "xy", XYVAL_NAME);
2280 }
2281 }
2282
2283 /////////////////////////////////////////////////////////////////////////////
2284
2285 /**
2286 * Let xy be ArgEscape. The frame dontinline_testMethod() has to be deoptimized when debugger
2287 * acquires xy from dontinline_callee() because afterwards locking on xy is omitted.
2288 * Note: there are no EA based optimizations at the escape point.
2289 */
2290 class EADeoptFrameAfterReadLocalObject_02 extends EATestCaseBaseDebugger {
2291
2292 public void runTestCase() throws Exception {
2293 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
2294 printStack(bpe.thread());
2295 @SuppressWarnings("unused")
2296 ObjectReference xy = getLocalRef(bpe.thread().frame(1), "dontinline_callee", "xy", XYVAL_NAME);
2297 }
2298 }
2299
2300 class EADeoptFrameAfterReadLocalObject_02Target extends EATestCaseBaseTarget {
2301
2302 public void dontinline_testMethod() {
2303 XYVal xy = new XYVal(1, 1);
2304 dontinline_callee(xy); // xy is ArgEscape, debugger acquires ref to xy from callee
2305 synchronized (xy) { // Locking is eliminated.
2306 xy.x++;
2307 xy.y++;
2308 }
2309 }
2310
2311 public void dontinline_callee(XYVal xy) {
2312 dontinline_brkpt(); // Debugger reads xy.
2313 // There are no virtual objects or eliminated locks.
2314 }
2315
2316 @Override
2317 public void setUp() {
2318 super.setUp();
2319 testMethodDepth = 2;
2320 }
2321
2322 @Override
2323 public boolean testFrameShouldBeDeoptimized() {
2324 // Graal does not provide debug info about arg escape objects, therefore the frame is not deoptimized
2325 return !UseJVMCICompiler && super.testFrameShouldBeDeoptimized();
2326 }
2327 }
2328
2329 /////////////////////////////////////////////////////////////////////////////
2330
2331 /**
2332 * Similar to {@link EADeoptFrameAfterReadLocalObject_02} there is an ArgEscape object xy, but in
2333 * contrast it is not in the parameter list of a call when the debugger reads an object.
2334 * Therefore the frame of the test method should not be deoptimized
2335 */
2336 class EADeoptFrameAfterReadLocalObject_02B extends EATestCaseBaseDebugger {
2337
2338 public void runTestCase() throws Exception {
2339 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
2340 printStack(bpe.thread());
2341 @SuppressWarnings("unused")
2342 ObjectReference xy = getLocalRef(bpe.thread().frame(1), "dontinline_callee", "xy", XYVAL_NAME);
2343 }
2344 }
2345
2346 class EADeoptFrameAfterReadLocalObject_02BTarget extends EATestCaseBaseTarget {
2347
2348 public void dontinline_testMethod() {
2349 XYVal xy = new XYVal(1, 1);
2350 dontinline_make_arg_escape(xy); // because of this call xy is ArgEscape
2351 dontinline_callee(); // xy is ArgEscape, but not a parameter of this call
2352 synchronized (xy) { // Locking is eliminated.
2353 xy.x++;
2354 xy.y++;
2355 }
2356 }
2357
2358 public void dontinline_callee() {
2359 @SuppressWarnings("unused")
2360 XYVal xy = new XYVal(2, 2);
2361 dontinline_brkpt(); // Debugger reads xy.
2362 // No need to deoptimize the caller frame
2363 }
2364
2365 @Override
2366 public void setUp() {
2367 super.setUp();
2368 testMethodDepth = 2;
2369 }
2370
2371 @Override
2372 public boolean testFrameShouldBeDeoptimized() {
2373 return false;
2374 }
2375 }
2376
2377 /////////////////////////////////////////////////////////////////////////////
2378
2379 /**
2380 * Similar to {@link EADeoptFrameAfterReadLocalObject_02} there is an ArgEscape object xy in
2381 * dontinline_testMethod() which is being passed as parameter when the debugger accesses a local object.
2382 * Nevertheless dontinline_testMethod must not be deoptimized because there is an entry frame
2383 * between it and the frame accessed by the debugger.
2384 */
2385 class EADeoptFrameAfterReadLocalObject_02C extends EATestCaseBaseDebugger {
2386
2387 public void runTestCase() throws Exception {
2388 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
2389 printStack(bpe.thread());
2390 @SuppressWarnings("unused")
2391 ObjectReference xy = getLocalRef(bpe.thread().frame(1), "dontinline_callee_accessed_by_debugger", "xy", XYVAL_NAME);
2392 }
2393 }
2394
2395 class EADeoptFrameAfterReadLocalObject_02CTarget extends EATestCaseBaseTarget {
2396
2397 public void dontinline_testMethod() {
2398 XYVal xy = new XYVal(1, 1);
2399 dontinline_callee(xy); // xy is ArgEscape and being passed as parameter
2400 synchronized (xy) { // Locking is eliminated.
2401 xy.x++;
2402 xy.y++;
2403 }
2404 }
2405
2406 public void dontinline_callee(XYVal xy) {
2407 if (warmupDone) {
2408 dontinline_call_with_entry_frame(this, "dontinline_callee_accessed_by_debugger");
2409 }
2410 }
2411
2412 public void dontinline_callee_accessed_by_debugger() {
2413 @SuppressWarnings("unused")
2414 XYVal xy = new XYVal(2, 2);
2415 dontinline_brkpt(); // Debugger reads xy.
2416 // No need to deoptimize the caller frame
2417 }
2418
2419 @Override
2420 public void setUp() {
2421 super.setUp();
2422 testMethodDepth = 8;
2423 }
2424
2425 @Override
2426 public boolean testFrameShouldBeDeoptimized() {
2427 return false;
2428 }
2429 }
2430
2431 /////////////////////////////////////////////////////////////////////////////
2432
2433 /**
2434 * Let xy be NoEscape whose allocation cannot be eliminated (e.g. because of
2435 * -XX:-EliminateAllocations). The holding compiled frame has to be deoptimized when debugger
2436 * accesses xy because the following field accesses get eliminated. Note: there are no EA based
2437 * optimizations at the escape point.
2438 */
2439 class EADeoptFrameAfterReadLocalObject_03 extends EATestCaseBaseDebugger {
2440
2441 public void runTestCase() throws Exception {
2442 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
2443 printStack(bpe.thread());
2444 ObjectReference xy = getLocalRef(bpe.thread().frame(1), XYVAL_NAME, "xy");
2445 setField(xy, "x", env.vm().mirrorOf(1));
2446 }
2447 }
2448
2449 class EADeoptFrameAfterReadLocalObject_03Target extends EATestCaseBaseTarget {
2450
2451 public void dontinline_testMethod() {
2452 XYVal xy = new XYVal(0, 1);
2453 dontinline_brkpt(); // Debugger reads xy, when there are no virtual objects or
2454 // eliminated locks in scope and modifies xy.x
2455 iResult = xy.x + xy.y; // Loads are replaced by constants 0 and 1.
2456 }
2457
2458 @Override
2459 public int getExpectedIResult() {
2460 return 1 + 1;
2461 }
2462 }
2463
2464 /////////////////////////////////////////////////////////////////////////////
2465 //
2466 // Monitor info tests
2467 //
2468 /////////////////////////////////////////////////////////////////////////////
2469
2470 class EAGetOwnedMonitorsTarget extends EATestCaseBaseTarget {
2471
2472 public long checkSum;
2473
2474 public void dontinline_testMethod() {
2475 XYVal l1 = new XYVal(4, 2);
2476 synchronized (l1) {
2477 dontinline_endlessLoop();
2478 }
2479 }
2480
2481 @Override
2482 public void setUp() {
2483 super.setUp();
2484 testMethodDepth = 2;
2485 loopCount = 3;
2486 }
2487
2488 public void warmupDone() {
2489 super.warmupDone();
2490 msg("enter 'endless' loop by setting loopCount = Long.MAX_VALUE");
2491 loopCount = Long.MAX_VALUE; // endless loop
2492 }
2493 }
2494
2495 class EAGetOwnedMonitors extends EATestCaseBaseDebugger {
2496
2497 public void runTestCase() throws Exception {
2498 msg("resume");
2499 env.vm().resume();
2500 waitUntilTargetHasEnteredEndlessLoop();
2501 // In contrast to JVMTI, JDWP requires a target thread to be suspended, before the owned monitors can be queried
2502 msg("suspend target");
2503 env.targetMainThread.suspend();
2504 msg("Get owned monitors");
2505 List<ObjectReference> monitors = env.targetMainThread.ownedMonitors();
2506 Asserts.assertEQ(monitors.size(), 1, "unexpected number of owned monitors");
2507 terminateEndlessLoop();
2508 }
2509 }
2510
2511 /////////////////////////////////////////////////////////////////////////////
2512
2513 class EAEntryCountTarget extends EATestCaseBaseTarget {
2514
2515 public long checkSum;
2516
2517 public void dontinline_testMethod() {
2518 XYVal l1 = new XYVal(4, 2);
2519 synchronized (l1) {
2520 inline_testMethod2(l1);
2521 }
2522 }
2523
2524 public void inline_testMethod2(XYVal l1) {
2525 synchronized (l1) {
2526 dontinline_endlessLoop();
2527 }
2528 }
2529
2530 @Override
2531 public void setUp() {
2532 super.setUp();
2533 testMethodDepth = 2;
2534 loopCount = 3;
2535 }
2536
2537 public void warmupDone() {
2538 super.warmupDone();
2539 msg("enter 'endless' loop by setting loopCount = Long.MAX_VALUE");
2540 loopCount = Long.MAX_VALUE; // endless loop
2541 }
2542 }
2543
2544 class EAEntryCount extends EATestCaseBaseDebugger {
2545
2546 public void runTestCase() throws Exception {
2547 msg("resume");
2548 env.vm().resume();
2549 waitUntilTargetHasEnteredEndlessLoop();
2550 // In contrast to JVMTI, JDWP requires a target thread to be suspended, before the owned monitors can be queried
2551 msg("suspend target");
2552 env.targetMainThread.suspend();
2553 msg("Get owned monitors");
2554 List<ObjectReference> monitors = env.targetMainThread.ownedMonitors();
2555 Asserts.assertEQ(monitors.size(), 1, "unexpected number of owned monitors");
2556 msg("Get entry count");
2557 int entryCount = monitors.get(0).entryCount();
2558 Asserts.assertEQ(entryCount, 2, "wrong entry count");
2559 terminateEndlessLoop();
2560 }
2561 }
2562
2563 /////////////////////////////////////////////////////////////////////////////
2564 //
2565 // PopFrame tests
2566 //
2567 /////////////////////////////////////////////////////////////////////////////
2568
2569 /**
2570 * PopFrame into caller frame with scalar replaced objects.
2571 */
2572 class EAPopFrameNotInlined extends EATestCaseBaseDebugger {
2573
2574 public void runTestCase() throws Exception {
2575 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
2576 printStack(bpe.thread());
2577 msg("PopFrame");
2578 bpe.thread().popFrames(bpe.thread().frame(0));
2579 msg("PopFrame DONE");
2580 }
2581
2582 @Override
2583 public boolean shouldSkip() {
2584 // And Graal currently doesn't support PopFrame
2585 return super.shouldSkip() || env.targetVMOptions.UseJVMCICompiler;
2586 }
2587 }
2588
2589 class EAPopFrameNotInlinedTarget extends EATestCaseBaseTarget {
2590
2591 public void dontinline_testMethod() {
2592 XYVal xy = new XYVal(4, 2);
2593 dontinline_brkpt();
2594 iResult = xy.x + xy.y;
2595 }
2596
2597 @Override
2598 public boolean testFrameShouldBeDeoptimized() {
2599 // Test is only performed after the frame pop.
2600 // Then dontinline_testMethod is interpreted.
2601 return false;
2602 }
2603
2604 @Override
2605 public int getExpectedIResult() {
2606 return 4 + 2;
2607 }
2608
2609 @Override
2610 public boolean shouldSkip() {
2611 // And Graal currently doesn't support PopFrame
2612 return super.shouldSkip() || UseJVMCICompiler;
2613 }
2614 }
2615
2616 /////////////////////////////////////////////////////////////////////////////
2617
2618 /**
2619 * Pop frames into {@link EAPopFrameNotInlinedReallocFailureTarget#dontinline_testMethod()} which
2620 * holds scalar replaced objects. In preparation of the pop frame operations the vm eagerly
2621 * reallocates scalar replaced objects to avoid failures when actually popping the frames. We provoke
2622 * a reallocation failures and expect {@link VMOutOfMemoryException}.
2623 */
2624 class EAPopFrameNotInlinedReallocFailure extends EATestCaseBaseDebugger {
2625
2626 public void runTestCase() throws Exception {
2627 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
2628 ThreadReference thread = bpe.thread();
2629 printStack(thread);
2630 // frame[0]: EATestCaseBaseTarget.dontinline_brkpt()
2631 // frame[1]: EAPopFrameNotInlinedReallocFailureTarget.dontinline_consume_all_memory_brkpt()
2632 // frame[2]: EAPopFrameNotInlinedReallocFailureTarget.dontinline_testMethod()
2633 // frame[3]: EATestCaseBaseTarget.run()
2634 // frame[4]: EATestsTarget.main(java.lang.String[])
2635 msg("PopFrame");
2636 boolean coughtOom = false;
2637 try {
2638 // try to pop dontinline_consume_all_memory_brkpt
2639 thread.popFrames(thread.frame(1));
2640 } catch (VMOutOfMemoryException oom) {
2641 // as expected
2642 msg("cought OOM");
2643 coughtOom = true;
2644 }
2645 freeAllMemory();
2646 // We succeeded to pop just one frame. When we continue, we will call dontinline_brkpt() again.
2647 Asserts.assertTrue(coughtOom, "PopFrame should have triggered an OOM exception in target");
2648 String expectedTopFrame = "dontinline_consume_all_memory_brkpt";
2649 Asserts.assertEQ(expectedTopFrame, thread.frame(0).location().method().name());
2650 printStack(thread);
2651 }
2652
2653 @Override
2654 public boolean shouldSkip() {
2655 // OOMEs because of realloc failures with DeoptimizeObjectsALot are too random.
2656 // And Graal currently doesn't provide all information about non-escaping objects in debug info
2657 return super.shouldSkip() ||
2658 !env.targetVMOptions.EliminateAllocations ||
2659 // With ZGC the OOME is not always thrown as expected
2660 env.targetVMOptions.ZGCIsSelected ||
2661 env.targetVMOptions.DeoptimizeObjectsALot ||
2662 env.targetVMOptions.UseJVMCICompiler;
2663 }
2664 }
2665
2666 class EAPopFrameNotInlinedReallocFailureTarget extends EATestCaseBaseTarget {
2667
2668 public boolean doneAlready;
2669
2670 public void dontinline_testMethod() {
2671 long a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // scalar replaced
2672 Vector10 v = new Vector10(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // scalar replaced
2673 dontinline_consume_all_memory_brkpt();
2674 lResult = a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9]
2675 + v.i0 + v.i1 + v.i2 + v.i3 + v.i4 + v.i5 + v.i6 + v.i7 + v.i8 + v.i9;
2676 }
2677
2678 public void dontinline_consume_all_memory_brkpt() {
2679 if (warmupDone && !doneAlready) {
2680 doneAlready = true;
2681 consumeAllMemory(); // provoke reallocation failure
2682 dontinline_brkpt();
2683 }
2684 }
2685
2686 @Override
2687 public void setUp() {
2688 super.setUp();
2689 testMethodDepth = 2;
2690 }
2691
2692 @Override
2693 public long getExpectedLResult() {
2694 long n = 10;
2695 return 2*n*(n+1)/2;
2696 }
2697
2698 @Override
2699 public boolean shouldSkip() {
2700 // OOMEs because of realloc failures with DeoptimizeObjectsALot are too random.
2701 // And Graal currently doesn't provide all information about non-escaping objects in debug info
2702 return super.shouldSkip() ||
2703 !EliminateAllocations ||
2704 // With ZGC the OOME is not always thrown as expected
2705 ZGCIsSelected ||
2706 DeoptimizeObjectsALot ||
2707 UseJVMCICompiler;
2708 }
2709 }
2710
2711 /////////////////////////////////////////////////////////////////////////////
2712
2713 /**
2714 * Pop inlined top frame dropping into method with scalar replaced opjects.
2715 */
2716 class EAPopInlinedMethodWithScalarReplacedObjectsReallocFailure extends EATestCaseBaseDebugger {
2717
2718 public void runTestCase() throws Exception {
2719 ThreadReference thread = env.targetMainThread;
2720 env.vm().resume();
2721 waitUntilTargetHasEnteredEndlessLoop();
2722
2723 thread.suspend();
2724 printStack(thread);
2725 // frame[0]: EAPopInlinedMethodWithScalarReplacedObjectsReallocFailureTarget.inlinedCallForcedToReturn()
2726 // frame[1]: EAPopInlinedMethodWithScalarReplacedObjectsReallocFailureTarget.dontinline_testMethod()
2727 // frame[2]: EATestCaseBaseTarget.run()
2728
2729 msg("Pop Frames");
2730 boolean coughtOom = false;
2731 try {
2732 thread.popFrames(thread.frame(0)); // Request pop frame of inlinedCallForcedToReturn()
2733 // reallocation is triggered here
2734 } catch (VMOutOfMemoryException oom) {
2735 // as expected
2736 msg("cought OOM");
2737 coughtOom = true;
2738 }
2739 printStack(thread);
2740 // frame[0]: EAPopInlinedMethodWithScalarReplacedObjectsReallocFailureTarget.inlinedCallForcedToReturn()
2741 // frame[1]: EAPopInlinedMethodWithScalarReplacedObjectsReallocFailureTarget.dontinline_testMethod()
2742 // frame[2]: EATestCaseBaseTarget.run()
2743
2744 freeAllMemory();
2745 setField(testCase, "loopCount", env.vm().mirrorOf(0)); // terminate loop
2746 Asserts.assertTrue(coughtOom, "PopFrame should have triggered an OOM exception in target");
2747 String expectedTopFrame = "inlinedCallForcedToReturn";
2748 Asserts.assertEQ(expectedTopFrame, thread.frame(0).location().method().name());
2749 }
2750
2751 @Override
2752 public boolean shouldSkip() {
2753 // OOMEs because of realloc failures with DeoptimizeObjectsALot are too random.
2754 // And Graal currently doesn't provide all information about non-escaping objects in debug info
2755 return super.shouldSkip() ||
2756 !env.targetVMOptions.EliminateAllocations ||
2757 // With ZGC the OOME is not always thrown as expected
2758 env.targetVMOptions.ZGCIsSelected ||
2759 env.targetVMOptions.DeoptimizeObjectsALot ||
2760 env.targetVMOptions.UseJVMCICompiler;
2761 }
2762 }
2763
2764 class EAPopInlinedMethodWithScalarReplacedObjectsReallocFailureTarget extends EATestCaseBaseTarget {
2765
2766 public long checkSum;
2767
2768 public void dontinline_testMethod() {
2769 long a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // scalar replaced
2770 Vector10 v = new Vector10(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // scalar replaced
2771 long l = inlinedCallForcedToReturn();
2772 lResult = a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9]
2773 + v.i0 + v.i1 + v.i2 + v.i3 + v.i4 + v.i5 + v.i6 + v.i7 + v.i8 + v.i9;
2774 }
2775
2776 public long inlinedCallForcedToReturn() {
2777 long cs = checkSum;
2778 dontinline_consumeAllMemory();
2779 while (loopCount-- > 0) {
2780 targetIsInLoop = true;
2781 checkSum += checkSum % ++cs;
2782 }
2783 loopCount = 3;
2784 targetIsInLoop = false;
2785 return checkSum;
2786 }
2787
2788 public void dontinline_consumeAllMemory() {
2789 if (warmupDone && (loopCount > 3)) {
2790 consumeAllMemory();
2791 }
2792 }
2793
2794 @Override
2795 public long getExpectedLResult() {
2796 long n = 10;
2797 return 2*n*(n+1)/2;
2798 }
2799
2800 @Override
2801 public void setUp() {
2802 super.setUp();
2803 loopCount = 3;
2804 }
2805
2806 public void warmupDone() {
2807 super.warmupDone();
2808 msg("enter 'endless' loop by setting loopCount = Long.MAX_VALUE");
2809 loopCount = Long.MAX_VALUE; // endless loop
2810 }
2811
2812 @Override
2813 public boolean shouldSkip() {
2814 // OOMEs because of realloc failures with DeoptimizeObjectsALot are too random.
2815 // And Graal currently doesn't provide all information about non-escaping objects in debug info
2816 return super.shouldSkip() ||
2817 !EliminateAllocations ||
2818 // With ZGC the OOME is not always thrown as expected
2819 ZGCIsSelected ||
2820 DeoptimizeObjectsALot ||
2821 UseJVMCICompiler;
2822 }
2823 }
2824
2825 /////////////////////////////////////////////////////////////////////////////
2826 //
2827 // ForceEarlyReturn tests
2828 //
2829 /////////////////////////////////////////////////////////////////////////////
2830
2831 /**
2832 * ForceEarlyReturn into caller frame with scalar replaced objects.
2833 */
2834 class EAForceEarlyReturnNotInlined extends EATestCaseBaseDebugger {
2835
2836 public void runTestCase() throws Exception {
2837 BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
2838 ThreadReference thread = bpe.thread();
2839 printStack(thread);
2840 // frame[0]: EATestCaseBaseTarget.dontinline_brkpt()
2841 // frame[1]: EATestCaseBaseTarget.dontinline_brkpt_iret()
2842 // frame[2]: EAForceEarlyReturnNotInlinedTarget.dontinline_testMethod()
2843 // frame[3]: EATestCaseBaseTarget.run()
2844 // frame[4]: EATestsTarget.main(java.lang.String[])
2845
2846 msg("Step out");
2847 env.stepOut(thread); // return from dontinline_brkpt
2848 printStack(thread);
2849 msg("ForceEarlyReturn");
2850 thread.forceEarlyReturn(env.vm().mirrorOf(43)); // return from dontinline_brkpt_iret,
2851 // does not trigger reallocation in contrast to PopFrame
2852 msg("Step over line");
2853 env.stepOverLine(thread); // reallocation is triggered here
2854 printStack(thread);
2855 msg("ForceEarlyReturn DONE");
2856 }
2857
2858 @Override
2859 public boolean shouldSkip() {
2860 // Graal currently doesn't support Force Early Return
2861 return super.shouldSkip() || env.targetVMOptions.UseJVMCICompiler;
2862 }
2863 }
2864
2865 class EAForceEarlyReturnNotInlinedTarget extends EATestCaseBaseTarget {
2866
2867 public void dontinline_testMethod() {
2868 XYVal xy = new XYVal(4, 2);
2869 int i = dontinline_brkpt_iret();
2870 iResult = xy.x + xy.y + i;
2871 }
2872
2873 @Override
2874 public int getExpectedIResult() {
2875 return 4 + 2 + 43;
2876 }
2877
2878 @Override
2879 public void setUp() {
2880 super.setUp();
2881 testMethodDepth = 2;
2882 }
2883
2884 public boolean testFrameShouldBeDeoptimized() {
2885 return true; // because of stepping
2886 }
2887
2888 @Override
2889 public boolean shouldSkip() {
2890 // Graal currently doesn't support Force Early Return
2891 return super.shouldSkip() || UseJVMCICompiler;
2892 }
2893 }
2894
2895 /////////////////////////////////////////////////////////////////////////////
2896
2897 /**
2898 * ForceEarlyReturn at safepoint in frame with scalar replaced objects.
2899 */
2900 class EAForceEarlyReturnOfInlinedMethodWithScalarReplacedObjects extends EATestCaseBaseDebugger {
2901
2902 public void runTestCase() throws Exception {
2903 ThreadReference thread = env.targetMainThread;
2904 env.vm().resume();
2905 waitUntilTargetHasEnteredEndlessLoop();
2906
2907 thread.suspend();
2908 printStack(thread);
2909 // frame[0]: EAForceEarlyReturnOfInlinedMethodWithScalarReplacedObjectsTarget.inlinedCallForcedToReturn()
2910 // frame[1]: EAForceEarlyReturnOfInlinedMethodWithScalarReplacedObjectsTarget.dontinline_testMethod()
2911 // frame[2]: EATestCaseBaseTarget.run()
2912
2913 msg("ForceEarlyReturn");
2914 thread.forceEarlyReturn(env.vm().mirrorOf(43)); // Request force return 43 from inlinedCallForcedToReturn()
2915 // reallocation is triggered here
2916 msg("Step over instruction to do the forced return");
2917 env.stepOverInstruction(thread);
2918 printStack(thread);
2919 msg("ForceEarlyReturn DONE");
2920 }
2921
2922 @Override
2923 public boolean shouldSkip() {
2924 // Graal currently doesn't support Force Early Return
2925 return super.shouldSkip() || env.targetVMOptions.UseJVMCICompiler;
2926 }
2927 }
2928
2929 class EAForceEarlyReturnOfInlinedMethodWithScalarReplacedObjectsTarget extends EATestCaseBaseTarget {
2930
2931 public int checkSum;
2932
2933 public void dontinline_testMethod() {
2934 XYVal xy = new XYVal(4, 2);
2935 int i = inlinedCallForcedToReturn();
2936 iResult = xy.x + xy.y + i;
2937 }
2938
2939 public int inlinedCallForcedToReturn() { // forced to return 43
2940 int i = checkSum;
2941 while (loopCount-- > 0) {
2942 targetIsInLoop = true;
2943 checkSum += checkSum % ++i;
2944 }
2945 loopCount = 3;
2946 targetIsInLoop = false;
2947 return checkSum;
2948 }
2949
2950 @Override
2951 public int getExpectedIResult() {
2952 return 4 + 2 + 43;
2953 }
2954
2955 @Override
2956 public void setUp() {
2957 super.setUp();
2958 testMethodDepth = 2;
2959 loopCount = 3;
2960 }
2961
2962 public void warmupDone() {
2963 super.warmupDone();
2964 msg("enter 'endless' loop by setting loopCount = Long.MAX_VALUE");
2965 loopCount = Long.MAX_VALUE; // endless loop
2966 }
2967
2968 public boolean testFrameShouldBeDeoptimized() {
2969 return true; // because of stepping
2970 }
2971
2972 @Override
2973 public boolean shouldSkip() {
2974 // Graal currently doesn't support Force Early Return
2975 return super.shouldSkip() || UseJVMCICompiler;
2976 }
2977 }
2978
2979 /////////////////////////////////////////////////////////////////////////////
2980
2981 /**
2982 * ForceEarlyReturn with reallocation failure.
2983 */
2984 class EAForceEarlyReturnOfInlinedMethodWithScalarReplacedObjectsReallocFailure extends EATestCaseBaseDebugger {
2985
2986 public void runTestCase() throws Exception {
2987 ThreadReference thread = env.targetMainThread;
2988 env.vm().resume();
2989 waitUntilTargetHasEnteredEndlessLoop();
2990
2991 thread.suspend();
2992 printStack(thread);
2993 // frame[0]: EAForceEarlyReturnOfInlinedMethodWithScalarReplacedObjectsReallocFailureTarget.inlinedCallForcedToReturn()
2994 // frame[1]: EAForceEarlyReturnOfInlinedMethodWithScalarReplacedObjectsReallocFailureTarget.dontinline_testMethod()
2995 // frame[2]: EATestCaseBaseTarget.run()
2996
2997 msg("ForceEarlyReturn");
2998 boolean coughtOom = false;
2999 try {
3000 thread.forceEarlyReturn(env.vm().mirrorOf(43)); // Request force return 43 from inlinedCallForcedToReturn()
3001 // reallocation is triggered here
3002 } catch (VMOutOfMemoryException oom) {
3003 // as expected
3004 msg("cought OOM");
3005 coughtOom = true;
3006 }
3007 freeAllMemory();
3008 Asserts.assertTrue(coughtOom, "ForceEarlyReturn should have triggered an OOM exception in target");
3009 printStack(thread);
3010 msg("ForceEarlyReturn(2)");
3011 thread.forceEarlyReturn(env.vm().mirrorOf(43));
3012 msg("Step over instruction to do the forced return");
3013 env.stepOverInstruction(thread);
3014 printStack(thread);
3015 msg("ForceEarlyReturn DONE");
3016 }
3017
3018 @Override
3019 public boolean shouldSkip() {
3020 // OOMEs because of realloc failures with DeoptimizeObjectsALot are too random.
3021 // And Graal currently doesn't support Force Early Return
3022 return super.shouldSkip() ||
3023 !env.targetVMOptions.EliminateAllocations ||
3024 // With ZGC the OOME is not always thrown as expected
3025 env.targetVMOptions.ZGCIsSelected ||
3026 env.targetVMOptions.DeoptimizeObjectsALot ||
3027 env.targetVMOptions.UseJVMCICompiler;
3028 }
3029 }
3030
3031 class EAForceEarlyReturnOfInlinedMethodWithScalarReplacedObjectsReallocFailureTarget extends EATestCaseBaseTarget {
3032
3033 public int checkSum;
3034
3035 public void dontinline_testMethod() {
3036 long a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // scalar replaced
3037 Vector10 v = new Vector10(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // scalar replaced
3038 long l = inlinedCallForcedToReturn();
3039 lResult = a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9]
3040 + v.i0 + v.i1 + v.i2 + v.i3 + v.i4 + v.i5 + v.i6 + v.i7 + v.i8 + v.i9 + l;
3041 }
3042
3043 public long inlinedCallForcedToReturn() { // forced to return 43
3044 long cs = checkSum;
3045 dontinline_consumeAllMemory();
3046 while (loopCount-- > 0) {
3047 targetIsInLoop = true;
3048 checkSum += checkSum % ++cs;
3049 }
3050 loopCount = 3;
3051 targetIsInLoop = false;
3052 return checkSum;
3053 }
3054
3055 public void dontinline_consumeAllMemory() {
3056 if (warmupDone) {
3057 consumeAllMemory();
3058 }
3059 }
3060
3061 @Override
3062 public long getExpectedLResult() {
3063 long n = 10;
3064 return 2*n*(n+1)/2 + 43;
3065 }
3066
3067 @Override
3068 public void setUp() {
3069 super.setUp();
3070 testMethodDepth = 2;
3071 loopCount = 3;
3072 }
3073
3074 public void warmupDone() {
3075 super.warmupDone();
3076 msg("enter 'endless' loop by setting loopCount = Long.MAX_VALUE");
3077 loopCount = Long.MAX_VALUE; // endless loop
3078 }
3079
3080 @Override
3081 public boolean shouldSkip() {
3082 // OOMEs because of realloc failures with DeoptimizeObjectsALot are too random.
3083 // And Graal currently doesn't support Force Early Return
3084 return super.shouldSkip() ||
3085 !EliminateAllocations ||
3086 // With ZGC the OOME is not always thrown as expected
3087 ZGCIsSelected ||
3088 DeoptimizeObjectsALot ||
3089 UseJVMCICompiler;
3090 }
3091 }
3092
3093 /////////////////////////////////////////////////////////////////////////////
3094 //
3095 // Get Instances of ReferenceType
3096 //
3097 /////////////////////////////////////////////////////////////////////////////
3098
3099 /**
3100 * Check if instances of a type are found even if they are scalar replaced. To stress the
3101 * implementation a little more, the instances should be retrieved while the target is running.
3102 */
3103 class EAGetInstancesOfReferenceType extends EATestCaseBaseDebugger {
3104
3105 public void runTestCase() throws Exception {
3106 printStack(env.targetMainThread);
3107 ReferenceType cls = ((ClassObjectReference)getField(testCase, "cls")).reflectedType();
3108 msg("reflected type is " + cls);
3109 msg("resume");
3110 env.vm().resume();
3111 waitUntilTargetHasEnteredEndlessLoop();
3112 // do this while thread is running!
3113 msg("Retrieve instances of " + cls.name());
3114 List<ObjectReference> instances = cls.instances(10);
3115 Asserts.assertEQ(instances.size(), 3, "unexpected number of instances of " + cls.name());
3116 // invariant: main thread is suspended at the end of the test case
3117 msg("suspend");
3118 env.targetMainThread.suspend();
3119 terminateEndlessLoop();
3120 }
3121 }
3122
3123 class EAGetInstancesOfReferenceTypeTarget extends EATestCaseBaseTarget {
3124
3125 public long checkSum;
3126
3127 public static Class<LocalXYVal> cls = LocalXYVal.class;
3128
3129 public static class LocalXYVal {
3130 public int x, y;
3131
3132 public LocalXYVal(int x, int y) {
3133 this.x = x; this.y = y;
3134 }
3135 }
3136
3137 @Override
3138 public void dontinline_testMethod() {
3139 LocalXYVal p1 = new LocalXYVal(4, 2);
3140 LocalXYVal p2 = new LocalXYVal(5, 3);
3141 LocalXYVal p3 = new LocalXYVal(6, 4);
3142 dontinline_endlessLoop();
3143 iResult = p1.x+p1.y + p2.x+p2.y + p3.x+p3.y;
3144 }
3145
3146 @Override
3147 public int getExpectedIResult() {
3148 return 6+8+10;
3149 }
3150
3151 @Override
3152 public void setUp() {
3153 super.setUp();
3154 testMethodDepth = 2;
3155 loopCount = 3;
3156 }
3157
3158 public void warmupDone() {
3159 super.warmupDone();
3160 msg("enter 'endless' loop by setting loopCount = Long.MAX_VALUE");
3161 loopCount = Long.MAX_VALUE; // endless loop
3162 }
3163 }
3164
3165
3166 // End of test case collection
3167 /////////////////////////////////////////////////////////////////////////////
3168
3169 /////////////////////////////////////////////////////////////////////////////
3170 // Helper classes
3171 class XYVal {
3172
3173 public int x, y;
3174
3175 public XYVal(int x, int y) {
3176 this.x = x;
3177 this.y = y;
3178 }
3179
3180 /**
3181 * Note that we don't use a sync block here because javac would generate an synthetic exception
3182 * handler for the synchronized block that catches Throwable E, unlocks and throws E
3183 * again. The throw bytecode causes the BCEscapeAnalyzer to set the escape state to GlobalEscape
3184 * (see comment on exception handlers in BCEscapeAnalyzer::iterate_blocks())
3185 */
3186 public synchronized void dontinline_sync_method(EATestCaseBaseTarget target) {
3187 target.dontinline_brkpt();
3188 }
3189
3190 /**
3191 * Just like {@link #dontinline_sync_method(EATestCaseBaseTarget)} but without the call to
3192 * {@link EATestCaseBaseTarget#dontinline_brkpt()}.
3193 */
3194 public synchronized void dontinline_sync_method_no_brkpt(EATestCaseBaseTarget target) {
3195 }
3196 }
3197
3198 class Vector10 {
3199 int i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
3200 public Vector10(int j0, int j1, int j2, int j3, int j4, int j5, int j6, int j7, int j8, int j9) {
3201 i0=j0; i1=j1; i2=j2; i3=j3; i4=j4; i5=j5; i6=j6; i7=j7; i8=j8; i9=j9;
3202 }
3203 }
3204
3205 class ILFDO {
3206
3207 public int i;
3208 public int i2;
3209 public long l;
3210 public long l2;
3211 public float f;
3212 public float f2;
3213 public double d;
3214 public double d2;
3215 public Long o;
3216 public Long o2;
3217
3218 public ILFDO(int i,
3219 int i2,
3220 long l,
3221 long l2,
3222 float f,
3223 float f2,
3224 double d,
3225 double d2,
3226 Long o,
3227 Long o2) {
3228 this.i = i;
3229 this.i2 = i2;
3230 this.l = l;
3231 this.l2 = l2;
3232 this.f = f;
3233 this.f2 = f2;
3234 this.d = d;
3235 this.d2 = d2;
3236 this.o = o;
3237 this.o2 = o2;
3238 }
3239
3240 }