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