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