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