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