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