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