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