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