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