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