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