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