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