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