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