/* * 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
*/
// // 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. publicstaticfinalboolean 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. publicstaticfinal String RUN_ONLY_TEST_CASE_PROPERTY = "EATests.onlytestcase"; publicstaticfinal String RUN_ONLY_TEST_CASE = System.getProperty(RUN_ONLY_TEST_CASE_PROPERTY);
///////////////////////////////////////////////////////////////////////////// // // Target main class, i.e. the program to be debugged. // /////////////////////////////////////////////////////////////////////////////
// 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 // /////////////////////////////////////////////////////////////////////////////
publicclass EATests extends TestScaffold {
public TargetVMOptions targetVMOptions; public ThreadReference targetMainThread;
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 protectedvoid 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 publicvoid msg(String m) {
System.out.println();
System.out.println("###(Debugger) " + m);
System.out.println();
}
///////////////////////////////////////////////////////////////////////////// // // Base class for debugger side of test cases. // /////////////////////////////////////////////////////////////////////////////
@Override publicboolean shouldSkip() { // Skip if StressReflectiveCode because it effectively disables escape analysis returnsuper.shouldSkip() || env.targetVMOptions.StressReflectiveCode;
}
publicvoid 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);
}
/** * 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
*/ protectedvoid 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
*/ protectedvoid 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
*/ publicvoid setLocal(StackFrame frame, String expectedMethodName, String lName, Value val) throws 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
*/ publicvoid 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
*/ protectedvoid 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
*/ protectedvoid 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 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
*/ publicvoid 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
*/ publicboolean 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
*/ publicvoid 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
*/ publicvoid terminateEndlessLoop() throws Exception {
msg("terminate loop");
setField(testCase, "doLoop", env.vm().mirrorOf(false));
}
}
///////////////////////////////////////////////////////////////////////////// // // Base class for debuggee side of test cases. // /////////////////////////////////////////////////////////////////////////////
// Some of the fields are only read by the debugger publicstaticfinalboolean UseJVMCICompiler = unbox(WB.getBooleanVMFlag("UseJVMCICompiler"), false); publicstaticfinalboolean DoEscapeAnalysis = unbox(WB.getBooleanVMFlag("DoEscapeAnalysis"), UseJVMCICompiler); publicstaticfinalboolean EliminateAllocations = unbox(WB.getBooleanVMFlag("EliminateAllocations"), UseJVMCICompiler); publicstaticfinalboolean DeoptimizeObjectsALot = WB.getBooleanVMFlag("DeoptimizeObjectsALot"); publicstaticfinalboolean ZGCIsSelected = GC.Z.isSelected(); publicstaticfinalboolean StressReflectiveCode = unbox(WB.getBooleanVMFlag("StressReflectiveCode"), false);
public String testMethodName; publicint testMethodDepth;
// Results produced by dontinline_testMethod() publicint iResult; publiclong lResult; publicfloat fResult; publicdouble dResult;
publicboolean warmupDone;
// an object with an inflated monitor publicstatic XYVal inflatedLock; publicstaticThread inflatorThread; publicstaticboolean inflatedLockIsPermanentlyInflated;
/** * 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.
*/ publicvoid 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.
*/ publiclong dontinline_endlessLoop() { long cs = checkSum;
doLoop = true; while (loopCount-- > 0 && doLoop) {
targetIsInLoop = true;
checkSum += checkSum % ++cs;
}
loopCount = 3;
targetIsInLoop = false; return checkSum;
}
// Debugger will set breakpoint here to sync with target. publicvoid testCaseDone() {
}
publicvoid compileTestMethod() throws Exception { int callCount = CompilerWhiteBoxTest.THRESHOLD; while (callCount-- > 0) {
dontinline_testMethod();
}
}
publicvoid 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 publicint getExpectedIResult() { return 0;
}
// to be overridden as appropriate publiclong getExpectedLResult() { return 0;
}
// to be overridden as appropriate publicfloat getExpectedFResult() { return 0f;
}
// to be overridden as appropriate publicdouble getExpectedDResult() { return 0d;
}
// The object passed will be ArgEscape if it was NoEscape before. publicfinalvoid 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.
*/ publicfinalvoid 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");
// // 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;
publicvoid 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);
}
// Test if an eliminated object can be reallocated in a frame with an active // call that will return another object class EAMaterializeLocalAtObjectReturn extends EATestCaseBaseDebugger { publicvoid 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);
}
}
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);
}
// 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 { publicvoid 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();
}
}
publicvoid 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);
}
///////////////////////////////////////////////////////////////////////////// // 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 {
// Materialize an object whose fields have constant and not constant values at // the point where the object is materialized. class EAMaterializeObjectWithConstantAndNotConstantValuesTarget extends EATestCaseBaseTarget {
// Two local variables reference the same object. // Check if the debugger obtains the same object when reading the two variables class EAMaterializeObjReferencedBy2LocalsTarget extends EATestCaseBaseTarget {
publicvoid dontinline_testMethod() {
XYVal xy = new XYVal(2, 3);
XYVal alias = xy;
dontinline_brkpt();
iResult = xy.x + alias.x;
}
// 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 {
// 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 {
// 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 {
// Test materialization of an object referenced only from expression stack class EAMaterializeObjReferencedFromOperandStackTarget extends EATestCaseBaseTarget {
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.