Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/LibreOffice/external/graphite/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 1 kB image not shown  

Quelle  EATests.java   Sprache: unbekannt

 
/*
 * Copyright (c) 2020 SAP SE. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */


/**
 * @test
 * @bug 8227745
 * @summary Collection of test cases that check if optimizations based on escape analysis are reverted just before non-escaping objects escape through JVMTI.
 * @author Richard Reingruber richard DOT reingruber AT sap DOT com
 *
 * @requires ((vm.compMode == "Xmixed") & vm.compiler2.enabled)
 * @library /test/lib /test/hotspot/jtreg
 *
 * @run build TestScaffold VMConnection TargetListener TargetAdapter jdk.test.whitebox.WhiteBox
 * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
 * @run compile -g EATests.java
 * @run driver EATests
 *                 -XX:+UnlockDiagnosticVMOptions
 *                 -Xms256m -Xmx256m
 *                 -Xbootclasspath/a:.
 *                 -XX:CompileCommand=dontinline,*::dontinline_*
 *                 -XX:+WhiteBoxAPI
 *                 -Xbatch
 *                 -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks
 * @run driver EATests
 *                 -XX:+UnlockDiagnosticVMOptions
 *                 -Xms256m -Xmx256m
 *                 -Xbootclasspath/a:.
 *                 -XX:CompileCommand=dontinline,*::dontinline_*
 *                 -XX:+WhiteBoxAPI
 *                 -Xbatch
 *                 -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:-EliminateLocks -XX:+EliminateNestedLocks
 * @run driver EATests
 *                 -XX:+UnlockDiagnosticVMOptions
 *                 -Xms256m -Xmx256m
 *                 -Xbootclasspath/a:.
 *                 -XX:CompileCommand=dontinline,*::dontinline_*
 *                 -XX:+WhiteBoxAPI
 *                 -Xbatch
 *                 -XX:+DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks
 * @run driver EATests
 *                 -XX:+UnlockDiagnosticVMOptions
 *                 -Xms256m -Xmx256m
 *                 -Xbootclasspath/a:.
 *                 -XX:CompileCommand=dontinline,*::dontinline_*
 *                 -XX:+WhiteBoxAPI
 *                 -Xbatch
 *                 -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks
 *
 * @comment Excercise -XX:+DeoptimizeObjectsALot. Mostly to prevent bit-rot because the option is meant to stress object deoptimization
 *          with non-synthetic workloads.
 * @run driver EATests
 *                 -XX:+UnlockDiagnosticVMOptions
 *                 -Xms256m -Xmx256m
 *                 -Xbootclasspath/a:.
 *                 -XX:CompileCommand=dontinline,*::dontinline_*
 *                 -XX:+WhiteBoxAPI
 *                 -Xbatch
 *                 -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks
 *                 -XX:+IgnoreUnrecognizedVMOptions -XX:+DeoptimizeObjectsALot
 *
 */

/**
 * @test
 * @bug 8227745
 *
 * @summary This is another configuration of EATests.java to test Graal. Some testcases are expected
 *          to fail because Graal does not provide all information about non-escaping objects in
 *          scope. These are skipped.
 *
 * @author Richard Reingruber richard DOT reingruber AT sap DOT com
 *
 * @requires ((vm.compMode == "Xmixed") & vm.graal.enabled)
 *
 * @library /test/lib /test/hotspot/jtreg
 *
 * @run build TestScaffold VMConnection TargetListener TargetAdapter jdk.test.whitebox.WhiteBox
 * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
 * @run compile -g EATests.java
 *
 * @comment Test with Graal. Some testcases are expected to fail because Graal does not provide all information about non-escaping
 *          objects in scope. These are skipped.
 * @run driver EATests
 *                 -XX:+UnlockDiagnosticVMOptions
 *                 -Xms256m -Xmx256m
 *                 -Xbootclasspath/a:.
 *                 -XX:CompileCommand=dontinline,*::dontinline_*
 *                 -XX:+WhiteBoxAPI
 *                 -Xbatch
 *                 -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler
 */


import com.sun.jdi.*;
import com.sun.jdi.event.*;
import compiler.testlibrary.CompilerUtils;
import compiler.whitebox.CompilerWhiteBoxTest;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

import jdk.test.lib.Asserts;
import jdk.test.whitebox.WhiteBox;
import jdk.test.whitebox.gc.GC;


//
// ANALYZING TEST FAILURES
//
// - Executing just a single test case with the property EATests.onlytestcase.
//
//      Example: java -DEATests.onlytestcase=<test case name> ... EATests
//
// - Interactive execution allows for attaching a native debugger, e.g. gdb
//
//      Example: java -DEATests.interactive=true ... EATests
//
// - Java arguments to the test are passed as vm options to the debuggee:
//
//      Example: java ... EATests -XX:+UseNewCode
//



/////////////////////////////////////////////////////////////////////////////
//
// Shared base class for test cases for both, debugger and debuggee.
//
/////////////////////////////////////////////////////////////////////////////

class EATestCaseBaseShared {
    // In interactive mode we wait for a keypress before every test case.
    public static final boolean INTERACTIVE =
            System.getProperty("EATests.interactive") != null &&
            System.getProperty("EATests.interactive").equals("true");

    // If the property is given, then just the test case it refers to is executed.
    // Use it to diagnose test failures.
    public static final String RUN_ONLY_TEST_CASE_PROPERTY = "EATests.onlytestcase";
    public static final String RUN_ONLY_TEST_CASE = System.getProperty(RUN_ONLY_TEST_CASE_PROPERTY);

    public final String testCaseName;

    public EATestCaseBaseShared() {
        String clName = getClass().getName();
        int tidx = clName.lastIndexOf("Target");
        testCaseName = tidx > 0 ? clName.substring(0, tidx) : clName;
    }

    public boolean shouldSkip() {
        return EATestCaseBaseShared.RUN_ONLY_TEST_CASE != null &&
               EATestCaseBaseShared.RUN_ONLY_TEST_CASE.length() > 0 &&
               !testCaseName.equals(EATestCaseBaseShared.RUN_ONLY_TEST_CASE);
    }
}

/////////////////////////////////////////////////////////////////////////////
//
// Target main class, i.e. the program to be debugged.
//
/////////////////////////////////////////////////////////////////////////////

class EATestsTarget {

    public static void main(String[] args) {
        EATestCaseBaseTarget.staticSetUp();
        EATestCaseBaseTarget.staticSetUpDone();

        // Materializing test cases, i.e. reallocating objects on the heap
        new EAMaterializeLocalVariableUponGetTarget()                                       .run();
        new EAGetWithoutMaterializeTarget()                                                 .run();
        new EAMaterializeLocalAtObjectReturnTarget()                                        .run();
        new EAMaterializeLocalAtObjectPollReturnReturnTarget()                              .run();
        new EAMaterializeIntArrayTarget()                                                   .run();
        new EAMaterializeLongArrayTarget()                                                  .run();
        new EAMaterializeFloatArrayTarget()                                                 .run();
        new EAMaterializeDoubleArrayTarget()                                                .run();
        new EAMaterializeObjectArrayTarget()                                                .run();
        new EAMaterializeObjectWithConstantAndNotConstantValuesTarget()                     .run();
        new EAMaterializeObjReferencedBy2LocalsTarget()                                     .run();
        new EAMaterializeObjReferencedBy2LocalsAndModifyTarget()                            .run();
        new EAMaterializeObjReferencedBy2LocalsInDifferentVirtFramesTarget()                .run();
        new EAMaterializeObjReferencedBy2LocalsInDifferentVirtFramesAndModifyTarget()       .run();
        new EAMaterializeObjReferencedFromOperandStackTarget()                              .run();
        new EAMaterializeLocalVariableUponGetAfterSetIntegerTarget()                        .run();

        // Relocking test cases
        new EARelockingSimpleTarget()                                                       .run();
        new EARelockingRecursiveTarget()                                                    .run();
        new EARelockingNestedInflatedTarget()                                               .run();
        new EARelockingNestedInflated_02Target()                                            .run();
        new EARelockingArgEscapeLWLockedInCalleeFrameTarget()                               .run();
        new EARelockingArgEscapeLWLockedInCalleeFrame_2Target()                             .run();
        new EAGetOwnedMonitorsTarget()                                                      .run();
        new EAEntryCountTarget()                                                            .run();
        new EARelockingObjectCurrentlyWaitingOnTarget()                                     .run();

        // Test cases that require deoptimization even though neither
        // locks nor allocations are eliminated at the point where
        // escape state is changed.
        new EADeoptFrameAfterReadLocalObject_01Target()                                     .run();
        new EADeoptFrameAfterReadLocalObject_01BTarget()                                    .run();
        new EADeoptFrameAfterReadLocalObject_02Target()                                     .run();
        new EADeoptFrameAfterReadLocalObject_02BTarget()                                    .run();
        new EADeoptFrameAfterReadLocalObject_02CTarget()                                    .run();
        new EADeoptFrameAfterReadLocalObject_03Target()                                     .run();

        // PopFrame test cases
        new EAPopFrameNotInlinedTarget()                                                    .run();
        new EAPopFrameNotInlinedReallocFailureTarget()                                      .run();
        new EAPopInlinedMethodWithScalarReplacedObjectsReallocFailureTarget()               .run();

        // ForceEarlyReturn test cases
        new EAForceEarlyReturnNotInlinedTarget()                                            .run();
        new EAForceEarlyReturnOfInlinedMethodWithScalarReplacedObjectsTarget()              .run();
        new EAForceEarlyReturnOfInlinedMethodWithScalarReplacedObjectsReallocFailureTarget().run();

        // Instances of ReferenceType
        new EAGetInstancesOfReferenceTypeTarget()                                           .run();
    }
}

/////////////////////////////////////////////////////////////////////////////
//
// Debugger main class
//
/////////////////////////////////////////////////////////////////////////////

public class EATests extends TestScaffold {

    public TargetVMOptions targetVMOptions;
    public ThreadReference targetMainThread;

    EATests(String args[]) {
        super(args);
    }

    public static void main(String[] args) throws Exception {
        if (EATestCaseBaseShared.RUN_ONLY_TEST_CASE != null) {
            args = Arrays.copyOf(args, args.length + 1);
            args[args.length - 1] = "-D" + EATestCaseBaseShared.RUN_ONLY_TEST_CASE_PROPERTY + "=" + EATestCaseBaseShared.RUN_ONLY_TEST_CASE;
        }
        new EATests(args).startTests();
    }

    public static class TargetVMOptions {

        public final boolean UseJVMCICompiler;
        public final boolean EliminateAllocations;
        public final boolean DeoptimizeObjectsALot;
        public final boolean DoEscapeAnalysis;
        public final boolean ZGCIsSelected;
        public final boolean StressReflectiveCode;

        public TargetVMOptions(EATests env, ClassType testCaseBaseTargetClass) {
            Value val;
            val = testCaseBaseTargetClass.getValue(testCaseBaseTargetClass.fieldByName("DoEscapeAnalysis"));
            DoEscapeAnalysis = ((PrimitiveValue) val).booleanValue();
            // Escape analysis is a prerequisite for scalar replacement (EliminateAllocations)
            val = testCaseBaseTargetClass.getValue(testCaseBaseTargetClass.fieldByName("EliminateAllocations"));
            EliminateAllocations = DoEscapeAnalysis && ((PrimitiveValue) val).booleanValue();
            val = testCaseBaseTargetClass.getValue(testCaseBaseTargetClass.fieldByName("DeoptimizeObjectsALot"));
            DeoptimizeObjectsALot = ((PrimitiveValue) val).booleanValue();
            val = testCaseBaseTargetClass.getValue(testCaseBaseTargetClass.fieldByName("UseJVMCICompiler"));
            UseJVMCICompiler = ((PrimitiveValue) val).booleanValue();
            val = testCaseBaseTargetClass.getValue(testCaseBaseTargetClass.fieldByName("ZGCIsSelected"));
            ZGCIsSelected = ((PrimitiveValue) val).booleanValue();
            val = testCaseBaseTargetClass.getValue(testCaseBaseTargetClass.fieldByName("StressReflectiveCode"));
            StressReflectiveCode = ((PrimitiveValue) val).booleanValue();
        }

    }

    // Execute known test cases
    protected void runTests() throws Exception {
        String targetProgName = EATestsTarget.class.getName();
        msg("starting to main method in class " +  targetProgName);
        startToMain(targetProgName);
        msg("resuming to EATestCaseBaseTarget.staticSetUpDone()V");
        targetMainThread = resumeTo("EATestCaseBaseTarget""staticSetUpDone""()V").thread();
        Location loc = targetMainThread.frame(0).location();
        Asserts.assertEQ("staticSetUpDone", loc.method().name());

        targetVMOptions = new TargetVMOptions(this, (ClassType) loc.declaringType());

        // Materializing test cases, i.e. reallocating objects on the heap
        new EAMaterializeLocalVariableUponGet()                                       .run(this);
        new EAGetWithoutMaterialize()                                                 .run(this);
        new EAMaterializeLocalAtObjectReturn()                                        .run(this);
        new EAMaterializeLocalAtObjectPollReturnReturn()                              .run(this);
        new EAMaterializeIntArray()                                                   .run(this);
        new EAMaterializeLongArray()                                                  .run(this);
        new EAMaterializeFloatArray()                                                 .run(this);
        new EAMaterializeDoubleArray()                                                .run(this);
        new EAMaterializeObjectArray()                                                .run(this);
        new EAMaterializeObjectWithConstantAndNotConstantValues()                     .run(this);
        new EAMaterializeObjReferencedBy2Locals()                                     .run(this);
        new EAMaterializeObjReferencedBy2LocalsAndModify()                            .run(this);
        new EAMaterializeObjReferencedBy2LocalsInDifferentVirtFrames()                .run(this);
        new EAMaterializeObjReferencedBy2LocalsInDifferentVirtFramesAndModify()       .run(this);
        new EAMaterializeObjReferencedFromOperandStack()                              .run(this);
        new EAMaterializeLocalVariableUponGetAfterSetInteger()                        .run(this);

        // Relocking test cases
        new EARelockingSimple()                                                       .run(this);
        new EARelockingRecursive()                                                    .run(this);
        new EARelockingNestedInflated()                                               .run(this);
        new EARelockingNestedInflated_02()                                            .run(this);
        new EARelockingArgEscapeLWLockedInCalleeFrame()                               .run(this);
        new EARelockingArgEscapeLWLockedInCalleeFrame_2()                             .run(this);
        new EAGetOwnedMonitors()                                                      .run(this);
        new EAEntryCount()                                                            .run(this);
        new EARelockingObjectCurrentlyWaitingOn()                                     .run(this);

        // Test cases that require deoptimization even though neither
        // locks nor allocations are eliminated at the point where
        // escape state is changed.
        new EADeoptFrameAfterReadLocalObject_01()                                     .run(this);
        new EADeoptFrameAfterReadLocalObject_01B()                                    .run(this);
        new EADeoptFrameAfterReadLocalObject_02()                                     .run(this);
        new EADeoptFrameAfterReadLocalObject_02B()                                    .run(this);
        new EADeoptFrameAfterReadLocalObject_02C()                                    .run(this);
        new EADeoptFrameAfterReadLocalObject_03()                                     .run(this);

        // PopFrame test cases
        new EAPopFrameNotInlined()                                                    .run(this);
        new EAPopFrameNotInlinedReallocFailure()                                      .run(this);
        new EAPopInlinedMethodWithScalarReplacedObjectsReallocFailure()               .run(this);

        // ForceEarlyReturn test cases
        new EAForceEarlyReturnNotInlined()                                            .run(this);
        new EAForceEarlyReturnOfInlinedMethodWithScalarReplacedObjects()              .run(this);
        new EAForceEarlyReturnOfInlinedMethodWithScalarReplacedObjectsReallocFailure().run(this);

        // Instances of ReferenceType
        new EAGetInstancesOfReferenceType()                                           .run(this);

        // resume the target listening for events
        listenUntilVMDisconnect();
    }

    // Print a Message
    public void msg(String m) {
        System.out.println();
        System.out.println("###(Debugger) " + m);
        System.out.println();
    }

    // Highlighted message.
    public void msgHL(String m) {
        System.out.println();
        System.out.println();
        System.out.println("##########################################################");
        System.out.println("### " + m);
        System.out.println("### ");
        System.out.println();
        System.out.println();
    }
}

/////////////////////////////////////////////////////////////////////////////
//
// Base class for debugger side of test cases.
//
/////////////////////////////////////////////////////////////////////////////

abstract class EATestCaseBaseDebugger  extends EATestCaseBaseShared {

    protected EATests env;

    public ObjectReference testCase;

    public static final String TARGET_TESTCASE_BASE_NAME = EATestCaseBaseTarget.class.getName();

    public static final String XYVAL_NAME = XYVal.class.getName();

    public abstract void runTestCase() throws Exception;

    @Override
    public boolean shouldSkip() {
        // Skip if StressReflectiveCode because it effectively disables escape analysis
        return super.shouldSkip() || env.targetVMOptions.StressReflectiveCode;
    }

    public void run(EATests env) {
        this.env = env;
        if (shouldSkip()) {
            msg("skipping " + testCaseName);
            return;
        }
        try {
            msgHL("Executing test case " + getClass().getName());
            env.testFailed = false;

            if (INTERACTIVE)
                env.waitForInput();

            resumeToWarmupDone();
            runTestCase();
            Asserts.assertTrue(env.targetMainThread.isSuspended(), "must be suspended after the testcase");
            resumeToTestCaseDone();
            checkPostConditions();
        } catch (Exception e) {
            Asserts.fail("Unexpected exception in test case " + getClass().getName(), e);
        }
    }

    /**
     * Set a breakpoint in the given method and resume all threads. The
     * breakpoint is configured to suspend just the thread that reaches it
     * instead of all threads. This is important when running with graal.
     */

    public BreakpointEvent resumeTo(String clsName, String methodName, String signature) {
        boolean suspendThreadOnly = true;
        return env.resumeTo(clsName, methodName, signature, suspendThreadOnly);
    }

    public void resumeToWarmupDone() throws Exception {
        msg("resuming to " + TARGET_TESTCASE_BASE_NAME + ".warmupDone()V");
        resumeTo(TARGET_TESTCASE_BASE_NAME, "warmupDone""()V");
        testCase = env.targetMainThread.frame(0).thisObject();
    }

    public void resumeToTestCaseDone() {
        msg("resuming to " + TARGET_TESTCASE_BASE_NAME + ".testCaseDone()V");
        resumeTo(TARGET_TESTCASE_BASE_NAME, "testCaseDone""()V");
    }

    public void checkPostConditions() throws Exception {
        Asserts.assertFalse(env.getExceptionCaught(), "Uncaught exception in Debuggee");

        String testName = getClass().getName();
        if (!env.testFailed) {
            env.println(testName  + ": passed");
        } else {
            throw new Exception(testName + ": failed");
        }
    }

    public void printStack(ThreadReference threadthrows Exception {
        msg("Debuggee Stack:");
        List<StackFrame> stack_frames = thread.frames();
        int i = 0;
        for (StackFrame ff : stack_frames) {
            System.out.println("frame[" + i++ +"]: " + ff.location().method() + " (bci:" + ff.location().codeIndex() + ")");
        }
    }

    public void msg(String m) {
        env.msg(m);
    }

    public void msgHL(String m) {
        env.msgHL(m);
    }

    // See Field Descriptors in The Java Virtual Machine Specification
    // (https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.3.2)
    enum FD {
        I, // int
        J, // long
        F, // float
        D, // double
    }

    // Map field descriptor to jdi type string
    public static final Map<FD, String> FD2JDIArrType = Map.of(FD.I, "int[]", FD.J, "long[]", FD.F, "float[]", FD.D, "double[]");

    // Map field descriptor to PrimitiveValue getter
    public static final Function<PrimitiveValue, Integer> v2I = PrimitiveValue::intValue;
    public static final Function<PrimitiveValue, Long>    v2J = PrimitiveValue::longValue;
    public static final Function<PrimitiveValue, Float>   v2F = PrimitiveValue::floatValue;
    public static final Function<PrimitiveValue, Double>  v2D = PrimitiveValue::doubleValue;
    Map<FD, Function<PrimitiveValue, ?>> FD2getter = Map.of(FD.I, v2I, FD.J, v2J, FD.F, v2F, FD.D, v2D);

    /**
     * Retrieve array of primitive values referenced by a local variable in target and compare with
     * an array of expected values.
     * @param frame Frame in the target holding the local variable
     * @param lName Name of the local variable referencing the array to be retrieved
     * @param desc Array element type given as field descriptor.
     * @param expVals Array of expected values.
     * @throws Exception
     */

    protected void checkLocalPrimitiveArray(StackFrame frame, String lName, FD desc, Object expVals) throws Exception {
        String lType = FD2JDIArrType.get(desc);
        Asserts.assertNotNull(lType, "jdi type not found");
        Asserts.assertEQ(EATestCaseBaseTarget.TESTMETHOD_DEFAULT_NAME, frame .location().method().name());
        List<LocalVariable> localVars = frame.visibleVariables();
        msg("Check if the local array variable '" + lName  + "' in " + EATestCaseBaseTarget.TESTMETHOD_DEFAULT_NAME + " has the expected elements: ");
        boolean found = false;
        for (LocalVariable lv : localVars) {
            if (lv.name().equals(lName)) {
                found  = true;
                Value lVal = frame.getValue(lv);
                Asserts.assertNotNull(lVal);
                Asserts.assertEQ(lVal.type().name(), lType);
                ArrayReference aRef = (ArrayReference) lVal;
                Asserts.assertEQ(3, aRef.length());
                // now check the elements
                for (int i = 0; i < aRef.length(); i++) {
                    Object actVal = FD2getter.get(desc).apply((PrimitiveValue)aRef.getValue(i));
                    Object expVal = Array.get(expVals, i);
                    Asserts.assertEQ(expVal, actVal, "checking element at index " + i);
                }
            }
        }
        Asserts.assertTrue(found);
        msg("OK.");
    }

    /**
     * Retrieve array of objects referenced by a local variable in target and compare with an array
     * of expected values.
     * @param frame Frame in the target holding the local variable
     * @param lName Name of the local variable referencing the array to be retrieved
     * @param lType Local type, e.g. java.lang.Long[]
     * @param expVals Array of expected values.
     * @throws Exception
     */

    protected void checkLocalObjectArray(StackFrame frame, String lName, String lType, ObjectReference[] expVals) throws Exception {
        Asserts.assertEQ(EATestCaseBaseTarget.TESTMETHOD_DEFAULT_NAME, frame .location().method().name());
        List<LocalVariable> localVars = frame.visibleVariables();
        msg("Check if the local array variable '" + lName  + "' in " + EATestCaseBaseTarget.TESTMETHOD_DEFAULT_NAME + " has the expected elements: ");
        boolean found = false;
        for (LocalVariable lv : localVars) {
            if (lv.name().equals(lName)) {
                found  = true;
                Value lVal = frame.getValue(lv);
                Asserts.assertNotNull(lVal);
                Asserts.assertEQ(lType, lVal.type().name());
                ArrayReference aRef = (ArrayReference) lVal;
                Asserts.assertEQ(3, aRef.length());
                // now check the elements
                for (int i = 0; i < aRef.length(); i++) {
                    ObjectReference actVal = (ObjectReference)aRef.getValue(i);
                    Asserts.assertSame(expVals[i], actVal, "checking element at index " + i);
                }
            }
        }
        Asserts.assertTrue(found);
        msg("OK.");
    }

    /**
     * Retrieve a reference held by a local variable in the given frame. Check if the frame's method
     * is the expected method if the retrieved local value has the expected type and is not null.
     * @param frame The frame to retrieve the local variable value from.
     * @param expectedMethodName The name of the frames method should match the expectedMethodName.
     * @param lName The name of the local variable which is read.
     * @param expectedType Is the expected type of the object referenced by the local variable.
     * @return
     * @throws Exception
     */

    protected ObjectReference getLocalRef(StackFrame frame, String expectedMethodName, String lName, String expectedType) throws Exception {
        Asserts.assertEQ(expectedMethodName, frame.location().method().name());
        List<LocalVariable> localVars = frame.visibleVariables();
        msg("Get and check local variable '" + lName + "' in " + expectedMethodName);
        ObjectReference lRef = null;
        for (LocalVariable lv : localVars) {
            if (lv.name().equals(lName)) {
                Value lVal = frame.getValue(lv);
                Asserts.assertNotNull(lVal);
                Asserts.assertEQ(expectedType, lVal.type().name());
                lRef = (ObjectReference) lVal;
                break;
            }
        }
        Asserts.assertNotNull(lRef, "Local variable '" + lName + "' not found");
        msg("OK.");
        return lRef;
    }

    /**
     * Retrieve a reference held by a local variable in the given frame. Check if the frame's method
     * matches {@link EATestCaseBaseTarget#TESTMETHOD_DEFAULT_NAME} if the retrieved local value has
     * the expected type and is not null.
     * @param frame The frame to retrieve the local variable value from.
     * @param expectedMethodName The name of the frames method should match the expectedMethodName.
     * @param lName The name of the local variable which is read.
     * @param expectedType Is the expected type of the object referenced by the local variable.
     * @return
     * @throws Exception
     */

    protected ObjectReference getLocalRef(StackFrame frame, String lType, String lName) throws Exception {
        return getLocalRef(frame, EATestCaseBaseTarget.TESTMETHOD_DEFAULT_NAME, lName, lType);
    }

    /**
     * Set the value of a local variable in the given frame. Check if the frame's method is the expected method.
     * @param frame The frame holding the local variable.
     * @param expectedMethodName The expected name of the frame's method.
     * @param lName The name of the local variable to change.
     * @param val The new value of the local variable.
     * @throws Exception
     */

    public void setLocal(StackFrame frame, String expectedMethodName, String lName, Value valthrows Exception {
        Asserts.assertEQ(expectedMethodName, frame.location().method().name());
        List<LocalVariable> localVars = frame.visibleVariables();
        msg("Set local variable '" + lName + "' = " + val + " in " + expectedMethodName);
        for (LocalVariable lv : localVars) {
            if (lv.name().equals(lName)) {
                frame.setValue(lv, val);
                break;
            }
        }
        msg("OK.");
    }

    /**
     * Set the value of a local variable in the given frame. Check if the frame's method matches
     * {@link EATestCaseBaseTarget#TESTMETHOD_DEFAULT_NAME}.
     * @param frame The frame holding the local variable.
     * @param expectedMethodName The expected name of the frame's method.
     * @param lName The name of the local variable to change.
     * @param val The new value of the local variable.
     * @throws Exception
     */

    public void setLocal(StackFrame frame, String lName, Value val) throws Exception {
        setLocal(frame, EATestCaseBaseTarget.TESTMETHOD_DEFAULT_NAME, lName, val);
    }

    /**
     * Check if a field has the expected primitive value.
     * @param o Object holding the field.
     * @param desc Field descriptor.
     * @param fName Field name
     * @param expVal Expected primitive value
     * @throws Exception
     */

    protected void checkPrimitiveField(ObjectReference o, FD desc, String fName, Object expVal) throws Exception {
        msg("check field " + fName);
        ReferenceType rt = o.referenceType();
        Field fld = rt.fieldByName(fName);
        Value val = o.getValue(fld);
        Object actVal = FD2getter.get(desc).apply((PrimitiveValue) val);
        Asserts.assertEQ(expVal, actVal, "field '" + fName + "' has unexpected value.");
        msg("ok");
    }

    /**
     * Check if a field references the expected object.
     * @param obj Object holding the field.
     * @param fName Field name
     * @param expVal Object expected to be referenced by the field
     * @throws Exception
     */

    protected void checkObjField(ObjectReference obj, String fName, ObjectReference expVal) throws Exception {
        msg("check field " + fName);
        ReferenceType rt = obj.referenceType();
        Field fld = rt.fieldByName(fName);
        Value actVal = obj.getValue(fld);
        Asserts.assertEQ(expVal, actVal, "field '" + fName + "' has unexpected value.");
        msg("ok");
    }

    protected void setField(ObjectReference obj, String fName, Value val) throws Exception {
        msg("set field " + fName + " = " + val);
        ReferenceType rt = obj.referenceType();
        Field fld = rt.fieldByName(fName);
        obj.setValue(fld, val);
        msg("ok");
    }

    protected Value getField(ObjectReference obj, String fName) throws Exception {
        msg("get field " + fName);
        ReferenceType rt = obj.referenceType();
        Field fld = rt.fieldByName(fName);
        Value val = obj.getValue(fld);
        msg("result : " + val);
        return val;
    }

    /**
     * Free the memory consumed in the target by {@link EATestCaseBaseTarget#consumedMemory}
     * @throws Exception
     */

    public void freeAllMemory() throws Exception {
        msg("free consumed memory");
        setField(testCase, "consumedMemory"null);
    }

    /**
     * @return The value of {@link EATestCaseBaseTarget#targetIsInLoop}. The target must set that field to true as soon as it
     *         enters the endless loop.
     * @throws Exception
     */

    public boolean targetHasEnteredEndlessLoop() throws Exception {
        Value v = getField(testCase, "targetIsInLoop");
        return ((PrimitiveValue) v).booleanValue();
    }

    /**
     * Poll {@link EATestCaseBaseTarget#targetIsInLoop} and return if it is found to be true.
     * @throws Exception
     */

    public void waitUntilTargetHasEnteredEndlessLoop() throws Exception {
        while(!targetHasEnteredEndlessLoop()) {
            msg("Target has not yet entered the loop. Sleep 200ms.");
            try { Thread.sleep(200); } catch (InterruptedException e) { /*ignore */ }
        }
    }

    /**
     * Set {@link EATestCaseBaseTarget#doLoop} to <code>false</code>. This will allow the target to
     * leave the endless loop.
     * @throws Exception
     */

    public void terminateEndlessLoop() throws Exception {
        msg("terminate loop");
        setField(testCase, "doLoop", env.vm().mirrorOf(false));
    }
}

/////////////////////////////////////////////////////////////////////////////
//
// Base class for debuggee side of test cases.
//
/////////////////////////////////////////////////////////////////////////////

abstract class EATestCaseBaseTarget extends EATestCaseBaseShared implements Runnable {

    /**
     * The target must set that field to true as soon as it enters the endless loop.
     */

    public volatile boolean targetIsInLoop;

    /**
     * Used for busy loops. See {@link #dontinline_endlessLoop()}.
     */

    public volatile long loopCount;

    /**
     * Used in {@link EATestCaseBaseDebugger#terminateEndlessLoop()} to signal target to leave the endless loop.
     */

    public volatile boolean doLoop;

    public long checkSum;

    public static final String TESTMETHOD_DEFAULT_NAME = "dontinline_testMethod";

    public static final WhiteBox WB = WhiteBox.getWhiteBox();

    public static boolean unbox(Boolean value, boolean dflt) {
        return value == null ? dflt : value;
    }

    // Some of the fields are only read by the debugger
    public static final boolean UseJVMCICompiler = unbox(WB.getBooleanVMFlag("UseJVMCICompiler"), false);
    public static final boolean DoEscapeAnalysis = unbox(WB.getBooleanVMFlag("DoEscapeAnalysis"), UseJVMCICompiler);
    public static final boolean EliminateAllocations = unbox(WB.getBooleanVMFlag("EliminateAllocations"), UseJVMCICompiler);
    public static final boolean DeoptimizeObjectsALot = WB.getBooleanVMFlag("DeoptimizeObjectsALot");
    public static final boolean ZGCIsSelected = GC.Z.isSelected();
    public static final boolean StressReflectiveCode = unbox(WB.getBooleanVMFlag("StressReflectiveCode"), false);

    public String testMethodName;
    public int testMethodDepth;

    // Results produced by dontinline_testMethod()
    public int  iResult;
    public long lResult;
    public float  fResult;
    public double dResult;


    public boolean warmupDone;

    // an object with an inflated monitor
    public static XYVal inflatedLock;
    public static Thread  inflatorThread;
    public static boolean inflatedLockIsPermanentlyInflated;

    public static int    NOT_CONST_1I = 1;
    public static long   NOT_CONST_1L = 1L;
    public static float  NOT_CONST_1F = 1.1F;
    public static double NOT_CONST_1D = 1.1D;

    public static          Long NOT_CONST_1_OBJ = Long.valueOf(1);


    public static final    Long CONST_2_OBJ     = Long.valueOf(2);
    public static final    Long CONST_3_OBJ     = Long.valueOf(3);

    @Override
    public boolean shouldSkip() {
        // Skip if StressReflectiveCode because it effectively disables escape analysis
        return super.shouldSkip() || StressReflectiveCode;
    }

    /**
     * Main driver of a test case.
     * <ul>
     * <li> Skips test case if not selected (see {@link EATestCaseBaseShared#RUN_ONLY_TEST_CASE}
     * <li> Call {@link #setUp()}
     * <li> warm-up and compile {@link #dontinline_testMethod()} (see {@link #compileTestMethod()}
     * <li> calling {@link #dontinline_testMethod()}
     * <li> checking the result (see {@link #checkResult()}
     * <ul>
     */

    public void run() {
        try {
            if (shouldSkip()) {
                msg("skipping " + testCaseName);
                return;
            }
            setUp();
            msg(testCaseName + " is up and running.");
            compileTestMethod();
            msg(testCaseName + " warmup done.");
            warmupDone();
            checkCompLevel();
            dontinline_testMethod();
            checkResult();
            msg(testCaseName + " done.");
            testCaseDone();
        } catch (Exception e) {
            Asserts.fail("Caught unexpected exception", e);
        }
    }

    public static void staticSetUp() {
        inflatedLock = new XYVal(1, 1);
        synchronized (inflatedLock) {
            inflatorThread = new Thread("Lock Inflator (test thread)") {
                @Override
                public void run() {
                    synchronized (inflatedLock) {
                        inflatedLockIsPermanentlyInflated = true;
                        inflatedLock.notify(); // main thread
                        while (true) {
                            try {
                                // calling wait() on a monitor will cause inflation into a heavy monitor
                                inflatedLock.wait();
                            } catch (InterruptedException e) { /* ignored */ }
                        }
                    }
                }
            };
            inflatorThread.setDaemon(true);
            inflatorThread.start();

            // wait until the lock is permanently inflated by the inflatorThread
            while(!inflatedLockIsPermanentlyInflated) {
                try {
                    inflatedLock.wait(); // until inflated
                } catch (InterruptedException e1) { /* ignored */ }
            }
        }
    }

    // Debugger will set breakpoint here to sync with target.
    public static void staticSetUpDone() {
    }

    public void setUp() {
        testMethodDepth = 1;
        testMethodName = TESTMETHOD_DEFAULT_NAME;
    }

    public abstract void dontinline_testMethod() throws Exception;

    public int dontinline_brkpt_iret() {
        dontinline_brkpt();
        return 42;
    }

    /**
     * It is a common protocol to have the debugger set a breakpoint in this method and have {@link
     * #dontinline_testMethod()} call it and then perform some test actions on debugger side.
     * After that it is checked if a frame of {@link #dontinline_testMethod()} is found at the
     * expected depth on stack and if it is (not) marked for deoptimization as expected.
     */

    public void dontinline_brkpt() {
        // will set breakpoint here after warmup
        if (warmupDone) {
            // check if test method is at expected depth
            StackTraceElement[] frames = Thread.currentThread().getStackTrace();
            int stackTraceDepth = testMethodDepth + 1; // ignore java.lang.Thread.getStackTrace()
            Asserts.assertEQ(testMethodName, frames[stackTraceDepth].getMethodName(),
                    testCaseName + ": test method not found at depth " + testMethodDepth);
            // check if the frame is (not) deoptimized as expected
            if (!DeoptimizeObjectsALot) {
                if (testFrameShouldBeDeoptimized()) {
                    Asserts.assertTrue(WB.isFrameDeoptimized(testMethodDepth+1),
                            testCaseName + ": expected test method frame at depth " + testMethodDepth + " to be deoptimized");
                } else {
                    Asserts.assertFalse(WB.isFrameDeoptimized(testMethodDepth+1),
                            testCaseName + ": expected test method frame at depth " + testMethodDepth + " not to be deoptimized");
                }
            }
        }
    }

    /**
     * Some test cases run busy endless loops by initializing {@link #loopCount}
     * to {@link Long#MAX_VALUE} after warm-up and then counting down to 0 in their main test method.
     * During warm-up {@link #loopCount} is initialized to a small value.
     */

    public long dontinline_endlessLoop() {
        long cs = checkSum;
        doLoop = true;
        while (loopCount-- > 0 && doLoop) {
            targetIsInLoop = true;
            checkSum += checkSum % ++cs;
        }
        loopCount = 3;
        targetIsInLoop = false;
        return checkSum;
    }

    public boolean testFrameShouldBeDeoptimized() {
        return DoEscapeAnalysis;
    }

    public void warmupDone() {
        warmupDone = true;
    }

    // Debugger will set breakpoint here to sync with target.
    public void testCaseDone() {
    }

    public void compileTestMethod() throws Exception {
        int callCount = CompilerWhiteBoxTest.THRESHOLD;
        while (callCount-- > 0) {
            dontinline_testMethod();
        }
    }

    public void checkCompLevel() {
        java.lang.reflect.Method m = null;
        try {
            m = getClass().getMethod(TESTMETHOD_DEFAULT_NAME);
        } catch (NoSuchMethodException | SecurityException e) {
            Asserts.fail("could not check compilation level of", e);
        }
        int highestLevel = CompilerUtils.getMaxCompilationLevel();
        int compLevel = WB.getMethodCompilationLevel(m);
        if (!UseJVMCICompiler) {
            Asserts.assertEQ(highestLevel, compLevel,
                             m + " not on expected compilation level");
        } else {
            // Background compilation (-Xbatch) will block a thread with timeout
            // (see CompileBroker::wait_for_jvmci_completion()). Therefore it is
            // possible to reach here before the main test method is compiled.
            // In that case we wait for it to be compiled.
            while (compLevel != highestLevel) {
                msg(TESTMETHOD_DEFAULT_NAME + " is compiled on level " + compLevel +
                    ". Wait until highes level (" + highestLevel + ") is reached.");
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) { /* ignored */ }
                compLevel = WB.getMethodCompilationLevel(m);
            }
        }
    }

    // to be overridden as appropriate
    public int getExpectedIResult() {
        return 0;
    }

    // to be overridden as appropriate
    public long getExpectedLResult() {
        return 0;
    }

    // to be overridden as appropriate
    public float getExpectedFResult() {
        return 0f;
    }

    // to be overridden as appropriate
    public double getExpectedDResult() {
        return 0d;
    }

    private void checkResult() {
        Asserts.assertEQ(getExpectedIResult(), iResult, "checking iResult");
        Asserts.assertEQ(getExpectedLResult(), lResult, "checking lResult");
        Asserts.assertEQ(getExpectedFResult(), fResult, "checking fResult");
        Asserts.assertEQ(getExpectedDResult(), dResult, "checking dResult");
    }

    public void msg(String m) {
        System.out.println();
        System.out.println("###(Target) " + m);
        System.out.println();
    }

    // The object passed will be ArgEscape if it was NoEscape before.
    public final void dontinline_make_arg_escape(XYVal xy) {
    }

    /**
     * Call a method indirectly using reflection. The indirection is a limit for escape
     * analysis in the sense that the VM need not search beyond for frames that might have
     * an object being read by an JVMTI agent as ArgEscape.
     * @param receiver The receiver object of the call.
     * @param methodName The name of the method to be called.
     */

    public final void dontinline_call_with_entry_frame(Object receiver, String methodName) {
        Asserts.assertTrue(warmupDone, "We want to take the slow path through jni, so don't call in warmup");

        Class<?> cls = receiver.getClass();
        Class<?>[] none = {};

        java.lang.reflect.Method m;
        try {
            m = cls.getDeclaredMethod(methodName, none);
            m.invoke(receiver);
        } catch (Exception e) {
            Asserts.fail("Call through reflection failed", e);
        }
    }

    static class LinkedList {
        LinkedList l;
        public long[] array;
        public LinkedList(LinkedList l, int size) {
            this.array = size > 0 ? new long[size] : null;
            this.l = l;
        }
    }

    public LinkedList consumedMemory;

    public void consumeAllMemory() {
        msg("consume all memory");
        int size = 128 * 1024 * 1024;
        while(true) {
            try {
                while(true) {
                    consumedMemory = new LinkedList(consumedMemory, size);
                }
            } catch(OutOfMemoryError oom) {
                if (size == 0) break;
            }
            size = size / 2;
        }
    }
}

/////////////////////////////////////////////////////////////////////////////
//
// Test Cases
//
/////////////////////////////////////////////////////////////////////////////

// make sure a compiled frame is not deoptimized if an escaping local is accessed
class EAGetWithoutMaterializeTarget extends EATestCaseBaseTarget {

    public XYVal getAway;

    public void dontinline_testMethod() {
        XYVal xy = new XYVal(4, 2);
        getAway = xy;  // allocated object escapes
        dontinline_brkpt();
        iResult = xy.x + xy.y;
    }

    @Override
    public int getExpectedIResult() {
        return 4 + 2;
    }

    @Override
    public boolean testFrameShouldBeDeoptimized() {
        return false;
    }
}

class EAGetWithoutMaterialize extends EATestCaseBaseDebugger {

    public void runTestCase() throws Exception {
        BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt""()V");
        printStack(bpe.thread());
        ObjectReference o = getLocalRef(bpe.thread().frame(1), XYVAL_NAME, "xy");
        checkPrimitiveField(o, FD.I, "x", 4);
        checkPrimitiveField(o, FD.I, "y", 2);
    }
}

/////////////////////////////////////////////////////////////////////////////

//
// Tests the following:
//
// 1. Debugger can obtain a reference to a scalar replaced object R from java thread J.
//    See runTestCase.
//
// 2. Subsequent modifications of R by J are noticed by the debugger.
//    See checkPostConditions.
//
class EAMaterializeLocalVariableUponGet extends EATestCaseBaseDebugger {

    private ObjectReference o;

    public void runTestCase() throws Exception {
        BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt""()V");
        printStack(bpe.thread());
        // check 1.
        o = getLocalRef(bpe.thread().frame(1), XYVAL_NAME, "xy");
        // o is referenced in checkPostConditions() and must not be gc'ed.
        o.disableCollection();
        checkPrimitiveField(o, FD.I, "x", 4);
        checkPrimitiveField(o, FD.I, "y", 2);
    }

    @Override
    public void checkPostConditions() throws Exception {
        super.checkPostConditions();
        // check 2.
        checkPrimitiveField(o, FD.I, "x", 5);
    }
}

class EAMaterializeLocalVariableUponGetTarget extends EATestCaseBaseTarget {

    public void dontinline_testMethod() {
        XYVal xy = new XYVal(4, 2);
        dontinline_brkpt();       // Debugger obtains scalar replaced object at this point.
        xy.x += 1;                // Change scalar replaced object after debugger obtained a reference to it.
        iResult = xy.x + xy.y;
    }

    @Override
    public int getExpectedIResult() {
        return 4 + 2 + 1;
    }
}

/////////////////////////////////////////////////////////////////////////////

// Test if an eliminated object can be reallocated in a frame with an active
// call that will return another object
class EAMaterializeLocalAtObjectReturn extends EATestCaseBaseDebugger {
    public void runTestCase() throws Exception {
        BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt""()V");
        printStack(bpe.thread());
        ObjectReference o = getLocalRef(bpe.thread().frame(2), XYVAL_NAME, "xy");
        checkPrimitiveField(o, FD.I, "x", 4);
        checkPrimitiveField(o, FD.I, "y", 2);
    }
}

class EAMaterializeLocalAtObjectReturnTarget extends EATestCaseBaseTarget {
    @Override
    public void setUp() {
        super.setUp();
        testMethodDepth = 2;
    }

    public void dontinline_testMethod() {
        XYVal xy = new XYVal(4, 2);
        Integer io =                 // Read xy here triggers reallocation
                dontinline_brkpt_return_Integer();
        iResult = xy.x + xy.y + io;
    }

    public Integer dontinline_brkpt_return_Integer() {
        // We can't break directly in this method, as this results in making
        // the test method not entrant caused by an existing dependency
        dontinline_brkpt();
        return Integer.valueOf(23);
    }

    @Override
    public int getExpectedIResult() {
        return 4 + 2 + 23;
    }
}

/////////////////////////////////////////////////////////////////////////////

// Test if an eliminated object can be reallocated *just* before a call returns an object.
// (See CompiledMethod::is_at_poll_return())
// Details: the callee method has just one safepoint poll at the return. The other safepoint
// is at the end of an iteration of the endless loop. We can detect if we suspended the target
// there because the local xy is out of scope there.
class EAMaterializeLocalAtObjectPollReturnReturn extends EATestCaseBaseDebugger {
    public void runTestCase() throws Exception {
        msg("Resume " + env.targetMainThread);
        env.vm().resume();
        waitUntilTargetHasEnteredEndlessLoop();
        ObjectReference o = null;
        int retryCount = 0;
        do {
            env.targetMainThread.suspend();
            printStack(env.targetMainThread);
            try {
                o = getLocalRef(env.targetMainThread.frame(0), XYVAL_NAME, "xy");
            } catch (Exception e) {
                ++retryCount;
                msg("The local variable xy is out of scope because we suspended at the wrong bci. Resume and try again! (" + retryCount + ")");
                env.targetMainThread.resume();
                if ((retryCount % 10) == 0) {
                    Thread.sleep(200);
                }
            }
        } while (o == null);
        checkPrimitiveField(o, FD.I, "x", 4);
        checkPrimitiveField(o, FD.I, "y", 2);
        terminateEndlessLoop();
    }
}

class EAMaterializeLocalAtObjectPollReturnReturnTarget extends EATestCaseBaseTarget {
    @Override
    public void setUp() {
        super.setUp();
        loopCount = 3;
        doLoop = true;
    }

    public void warmupDone() {
        super.warmupDone();
        msg("enter 'endless' loop by setting loopCount = Long.MAX_VALUE");
        loopCount = Long.MAX_VALUE; // endless loop
    }

    public void dontinline_testMethod() {
        long result = 0;
        while (doLoop && loopCount-- > 0) {
            targetIsInLoop = true;
            XYVal xy = new XYVal(4, 2);
            Integer io =           // Read xy here triggers reallocation just before the call returns
                    dontinline_brkpt_return_Integer();
            result += xy.x + xy.y + io;
        }  // Here is a second safepoint. We were suspended here if xy is not in scope.
        targetIsInLoop = false;
        lResult = result;
    }

    public Integer dontinline_brkpt_return_Integer() {
        return Integer.valueOf(23);
    }

    @Override
    public long getExpectedLResult() {
        return (Long.MAX_VALUE - loopCount) * (4+2+23);
    }
}

/////////////////////////////////////////////////////////////////////////////
// Test case collection that tests rematerialization of different
// array types where the first element is always not constant and the
// other elements are constants. Not constant values are stored in
// the stack frame for rematerialization whereas constants are kept
// in the debug info of the nmethod.

class EAMaterializeIntArrayTarget extends EATestCaseBaseTarget {

    public void dontinline_testMethod() {
        int nums[] = {NOT_CONST_1I , 2, 3};
        dontinline_brkpt();
        iResult = nums[0] + nums[1] + nums[2];
    }

    @Override
    public int getExpectedIResult() {
        return NOT_CONST_1I + 2 + 3;
    }
}

class EAMaterializeIntArray extends EATestCaseBaseDebugger {
    public void runTestCase() throws Exception {
        BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt""()V");
        printStack(bpe.thread());
        int[] expectedVals = {1, 2, 3};
        checkLocalPrimitiveArray(bpe.thread().frame(1), "nums", FD.I, expectedVals);
    }
}

/////////////////////////////////////////////////////////////////////////////

class EAMaterializeLongArrayTarget extends EATestCaseBaseTarget {

    public void dontinline_testMethod() {
        long nums[] = {NOT_CONST_1L , 2, 3};
        dontinline_brkpt();
        lResult = nums[0] + nums[1] + nums[2];
    }

    @Override
    public long getExpectedLResult() {
        return NOT_CONST_1L + 2 + 3;
    }
}

class EAMaterializeLongArray extends EATestCaseBaseDebugger {
    public void runTestCase() throws Exception {
        BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt""()V");
        printStack(bpe.thread());
        long[] expectedVals = {1, 2, 3};
        checkLocalPrimitiveArray(bpe.thread().frame(1), "nums", FD.J, expectedVals);
    }
}

/////////////////////////////////////////////////////////////////////////////

class EAMaterializeFloatArrayTarget extends EATestCaseBaseTarget {

    public void dontinline_testMethod() {
        float nums[] = {NOT_CONST_1F , 2.2f, 3.3f};
        dontinline_brkpt();
        fResult = nums[0] + nums[1] + nums[2];
    }

    @Override
    public float getExpectedFResult() {
        return NOT_CONST_1F + 2.2f + 3.3f;
    }
}

class EAMaterializeFloatArray extends EATestCaseBaseDebugger {
    public void runTestCase() throws Exception {
        BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt""()V");
        printStack(bpe.thread());
        float[] expectedVals = {1.1f, 2.2f, 3.3f};
        checkLocalPrimitiveArray(bpe.thread().frame(1), "nums", FD.F, expectedVals);
    }
}

/////////////////////////////////////////////////////////////////////////////

class EAMaterializeDoubleArrayTarget extends EATestCaseBaseTarget {

    public void dontinline_testMethod() {
        double nums[] = {NOT_CONST_1D , 2.2d, 3.3d};
        dontinline_brkpt();
        dResult = nums[0] + nums[1] + nums[2];
    }

    @Override
    public double getExpectedDResult() {
        return NOT_CONST_1D + 2.2d + 3.3d;
    }
}

class EAMaterializeDoubleArray extends EATestCaseBaseDebugger {
    public void runTestCase() throws Exception {
        BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt""()V");
        printStack(bpe.thread());
        double[] expectedVals = {1.1d, 2.2d, 3.3d};
        checkLocalPrimitiveArray(bpe.thread().frame(1), "nums", FD.D, expectedVals);
    }
}

/////////////////////////////////////////////////////////////////////////////

class EAMaterializeObjectArrayTarget extends EATestCaseBaseTarget {

    public void dontinline_testMethod() {
        Long nums[] = {NOT_CONST_1_OBJ , CONST_2_OBJ, CONST_3_OBJ};
        dontinline_brkpt();
        lResult = nums[0] + nums[1] + nums[2];
    }

    @Override
    public long getExpectedLResult() {
        return 1 + 2 + 3;
    }
}

class EAMaterializeObjectArray extends EATestCaseBaseDebugger {
    public void runTestCase() throws Exception {
        BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt""()V");
        printStack(bpe.thread());
        ReferenceType clazz = bpe.thread().frame(0).location().declaringType();
        ObjectReference[] expectedVals = {
                (ObjectReference) clazz.getValue(clazz.fieldByName("NOT_CONST_1_OBJ")),
                (ObjectReference) clazz.getValue(clazz.fieldByName("CONST_2_OBJ")),
                (ObjectReference) clazz.getValue(clazz.fieldByName("CONST_3_OBJ"))
        };
        checkLocalObjectArray(bpe.thread().frame(1), "nums""java.lang.Long[]", expectedVals);
    }
}

/////////////////////////////////////////////////////////////////////////////

// Materialize an object whose fields have constant and not constant values at
// the point where the object is materialized.
class EAMaterializeObjectWithConstantAndNotConstantValuesTarget extends EATestCaseBaseTarget {

    public void dontinline_testMethod() {
        ILFDO o = new ILFDO(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
                            );
        dontinline_brkpt();
        dResult =
            o.i + o.i2 + o.l + o.l2 + o.f + o.f2 + o.d + o.d2 + o.o + o.o2;
    }

    @Override
    public double getExpectedDResult() {
        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;
    }
}

class EAMaterializeObjectWithConstantAndNotConstantValues extends EATestCaseBaseDebugger {
    public void runTestCase() throws Exception {
        BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt""()V");
        printStack(bpe.thread());
        ObjectReference o = getLocalRef(bpe.thread().frame(1), "ILFDO""o");
        checkPrimitiveField(o, FD.I, "i", 1);
        checkPrimitiveField(o, FD.I, "i2", 2);
        checkPrimitiveField(o, FD.J, "l", 1L);
        checkPrimitiveField(o, FD.J, "l2", 2L);
        checkPrimitiveField(o, FD.F, "f", 1.1f);
        checkPrimitiveField(o, FD.F, "f2", 2.1f);
        checkPrimitiveField(o, FD.D, "d", 1.1d);
        checkPrimitiveField(o, FD.D, "d2", 2.1d);
        ReferenceType clazz = bpe.thread().frame(1).location().declaringType();
        ObjectReference[] expVals = {
                (ObjectReference) clazz.getValue(clazz.fieldByName("NOT_CONST_1_OBJ")),
                (ObjectReference) clazz.getValue(clazz.fieldByName("CONST_2_OBJ")),
        };
        checkObjField(o, "o", expVals[0]);
        checkObjField(o, "o2", expVals[1]);
    }
}

/////////////////////////////////////////////////////////////////////////////

// Two local variables reference the same object.
// Check if the debugger obtains the same object when reading the two variables
class EAMaterializeObjReferencedBy2LocalsTarget extends EATestCaseBaseTarget {

    public void dontinline_testMethod() {
        XYVal xy = new XYVal(2, 3);
        XYVal alias = xy;
        dontinline_brkpt();
        iResult = xy.x + alias.x;
    }

    @Override
    public int getExpectedIResult() {
        return 2 + 2;
    }
}

class EAMaterializeObjReferencedBy2Locals extends EATestCaseBaseDebugger {

    public void runTestCase() throws Exception {
        BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt""()V");
        printStack(bpe.thread());
        ObjectReference xy = getLocalRef(bpe.thread().frame(1), XYVAL_NAME, "xy");
        ObjectReference alias = getLocalRef(bpe.thread().frame(1), XYVAL_NAME, "alias");
        Asserts.assertSame(xy, alias, "xy and alias are expected to reference the same object");
    }

}

/////////////////////////////////////////////////////////////////////////////

// Two local variables reference the same object.
// Check if it has the expected effect in the target if the debugger modifies the object.
class EAMaterializeObjReferencedBy2LocalsAndModifyTarget extends EATestCaseBaseTarget {

    public void dontinline_testMethod() {
        XYVal xy = new XYVal(2, 3);
        XYVal alias = xy;
        dontinline_brkpt(); // debugger: alias.x = 42
        iResult = xy.x + alias.x;
    }

    @Override
    public int getExpectedIResult() {
        return 42 + 42;
    }
}

class EAMaterializeObjReferencedBy2LocalsAndModify extends EATestCaseBaseDebugger {

    public void runTestCase() throws Exception {
        BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt""()V");
        printStack(bpe.thread());
        ObjectReference alias = getLocalRef(bpe.thread().frame(1), XYVAL_NAME, "alias");
        setField(alias, "x", env.vm().mirrorOf(42));
    }
}

/////////////////////////////////////////////////////////////////////////////

// Two local variables of the same compiled frame but in different virtual frames reference the same
// object.
// Check if the debugger obtains the same object when reading the two variables
class EAMaterializeObjReferencedBy2LocalsInDifferentVirtFramesTarget extends EATestCaseBaseTarget {

    @Override
    public void setUp() {
        super.setUp();
        testMethodDepth = 2;
    }

    public void dontinline_testMethod() {
        XYVal xy = new XYVal(2, 3);
        testMethod_inlined(xy);
        iResult += xy.x;
    }

    public void testMethod_inlined(XYVal xy) {
        XYVal alias = xy;
        dontinline_brkpt();
        iResult = alias.x;
    }

    @Override
    public int getExpectedIResult() {
        return 2 + 2;
    }
}

class EAMaterializeObjReferencedBy2LocalsInDifferentVirtFrames extends EATestCaseBaseDebugger {

    public void runTestCase() throws Exception {
        BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt""()V");
        printStack(bpe.thread());
        ObjectReference xy = getLocalRef(bpe.thread().frame(2), XYVAL_NAME, "xy");
        ObjectReference alias = getLocalRef(bpe.thread().frame(1), "testMethod_inlined""alias", XYVAL_NAME);
        Asserts.assertSame(xy, alias, "xy and alias are expected to reference the same object");
    }

}

/////////////////////////////////////////////////////////////////////////////

// Two local variables of the same compiled frame but in different virtual frames reference the same
// object.
// Check if it has the expected effect in the target if the debugger modifies the object.
class EAMaterializeObjReferencedBy2LocalsInDifferentVirtFramesAndModifyTarget extends EATestCaseBaseTarget {

    @Override
    public void setUp() {
        super.setUp();
        testMethodDepth = 2;
    }

    public void dontinline_testMethod() {
        XYVal xy = new XYVal(2, 3);
        testMethod_inlined(xy);   // debugger: xy.x = 42
        iResult += xy.x;
    }

    public void testMethod_inlined(XYVal xy) {
        XYVal alias = xy;
        dontinline_brkpt();
        iResult = alias.x;
    }

    @Override
    public int getExpectedIResult() {
        return 42 + 42;
    }
}

class EAMaterializeObjReferencedBy2LocalsInDifferentVirtFramesAndModify extends EATestCaseBaseDebugger {

    public void runTestCase() throws Exception {
        BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt""()V");
        printStack(bpe.thread());
        ObjectReference alias = getLocalRef(bpe.thread().frame(1), "testMethod_inlined""alias", XYVAL_NAME);
        setField(alias, "x", env.vm().mirrorOf(42));
    }

}

/////////////////////////////////////////////////////////////////////////////

// Test materialization of an object referenced only from expression stack
class EAMaterializeObjReferencedFromOperandStackTarget extends EATestCaseBaseTarget {

    @Override
    public void setUp() {
        super.setUp();
        testMethodDepth = 2;
    }

    public void dontinline_testMethod() {
        @SuppressWarnings("unused")
        XYVal xy1 = new XYVal(2, 3);
        // Debugger breaks in call to dontinline_brkpt_ret_100() and reads
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=92 H=91 G=91

[ Verzeichnis aufwärts0.25unsichere Verbindung  Übersetzung europäischer Sprachen durch Browser  ]