// // 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);
}
}
///////////////////////////////////////////////////////////////////////////// // // 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;
/** *Itisacommonprotocoltohavethedebuggersetabreakpointinthismethodandhave{@link *#dontinline_testMethod()}callitandthenperformsometestactionsondebuggerside. *Afterthatitischeckedifaframeof{@link#dontinline_testMethod()}isfoundatthe *expecteddepthonstackandifitis(not)markedfordeoptimizationasexpected.
*/ 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");
}
}
}
}
// 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() { return0;
}
// to be overridden as appropriate publiclong getExpectedLResult() { return0;
}
// to be overridden as appropriate publicfloat getExpectedFResult() { return0f;
}
// to be overridden as appropriate publicdouble getExpectedDResult() { return0d;
}
// The object passed will be ArgEscape if it was NoEscape before. publicfinalvoid dontinline_make_arg_escape(XYVal xy) {
}
/** *Callamethodindirectlyusingreflection.Theindirectionisalimitforescape *analysisinthesensethattheVMneednotsearchbeyondforframesthatmighthave *anobjectbeingreadbyanJVMTIagentasArgEscape. *@paramreceiverThereceiverobjectofthecall. *@parammethodNameThenameofthemethodtobecalled.
*/ 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 {
publicvoid dontinline_testMethod() {
@SuppressWarnings("unused")
XYVal xy1 = new XYVal(2, 3); // Debugger breaks in call to dontinline_brkpt_ret_100() and reads // the value of the local 'xy1'. This triggers materialization // of the object on the operand stack
iResult = testMethodInlined(new XYVal(4, 2), dontinline_brkpt_ret_100());
}
// Object ref l1 is retrieved by the debugger at a location where nested locks are omitted. The // accessed object is globally reachable already before the access, therefore no relocking is done. class EARelockingNestedInflatedTarget extends EATestCaseBaseTarget {
@Override publicboolean testFrameShouldBeDeoptimized() { // Graal does not provide debug info about arg escape objects, therefore the frame is not deoptimized return !UseJVMCICompiler && super.testFrameShouldBeDeoptimized();
}
}
publicvoid doNotify() { while (objToNotifyOn == null) { try {
msg("objToNotifyOn is still null"); Thread.sleep(100);
} catch (InterruptedException e) { /* ignored */ }
} synchronized (objToNotifyOn) { // will be received by the target main thread waiting in dontinline_waitWhenWarmupDone
msg("calling objToNotifyOn.notifyAll()");
objToNotifyOn.notifyAll();
}
}
///////////////////////////////////////////////////////////////////////////// // // Test cases that require deoptimization even though neither locks // nor allocations are eliminated at the point where escape state is changed. // /////////////////////////////////////////////////////////////////////////////
class EADeoptFrameAfterReadLocalObject_01Target extends EATestCaseBaseTarget {
publicvoid dontinline_testMethod() {
XYVal xy = new XYVal(1, 1);
dontinline_brkpt(); // Debugger reads xy, when there are no virtual objects or eliminated locks in scope synchronized (xy) { // Locking is eliminated.
xy.x++;
xy.y++;
}
}
}
publicvoid dontinline_testMethod() {
XYVal xy = new XYVal(1, 1);
callee(xy); // Debugger acquires ref to xy from inlined callee // xy is NoEscape, nevertheless the object is not replaced // by scalars if running with -XX:-EliminateAllocations. // In that case there are no EA based optimizations were // the debugger reads the NoEscape object. synchronized (xy) { // Locking is eliminated.
xy.x++;
xy.y++;
}
}
publicvoid callee(XYVal xy) {
dontinline_brkpt(); // Debugger reads xy. // There are no virtual objects or eliminated locks.
}
}
class EADeoptFrameAfterReadLocalObject_01B extends EATestCaseBaseDebugger {
@Override publicboolean testFrameShouldBeDeoptimized() { // Graal does not provide debug info about arg escape objects, therefore the frame is not deoptimized return !UseJVMCICompiler && super.testFrameShouldBeDeoptimized();
}
}
class EADeoptFrameAfterReadLocalObject_02BTarget extends EATestCaseBaseTarget {
publicvoid dontinline_testMethod() {
XYVal xy = new XYVal(1, 1);
dontinline_make_arg_escape(xy); // because of this call xy is ArgEscape
dontinline_callee(); // xy is ArgEscape, but not a parameter of this call synchronized (xy) { // Locking is eliminated.
xy.x++;
xy.y++;
}
}
publicvoid dontinline_callee() {
@SuppressWarnings("unused")
XYVal xy = new XYVal(2, 2);
dontinline_brkpt(); // Debugger reads xy. // No need to deoptimize the caller frame
}
class EADeoptFrameAfterReadLocalObject_02CTarget extends EATestCaseBaseTarget {
publicvoid dontinline_testMethod() {
XYVal xy = new XYVal(1, 1);
dontinline_callee(xy); // xy is ArgEscape and being passed as parameter synchronized (xy) { // Locking is eliminated.
xy.x++;
xy.y++;
}
}
publicvoid dontinline_callee_accessed_by_debugger() {
@SuppressWarnings("unused")
XYVal xy = new XYVal(2, 2);
dontinline_brkpt(); // Debugger reads xy. // No need to deoptimize the caller frame
}
@Override publicvoid setUp() { super.setUp(); // the method depth in debuggee is 11 as it includes all hidden frames // the expected method depth is 6 excluding 5 hidden frames
testMethodDepth = 11-5;
}
class EADeoptFrameAfterReadLocalObject_03Target extends EATestCaseBaseTarget {
publicvoid dontinline_testMethod() {
XYVal xy = new XYVal(0, 1);
dontinline_brkpt(); // Debugger reads xy, when there are no virtual objects or // eliminated locks in scope and modifies xy.x
iResult = xy.x + xy.y; // Loads are replaced by constants 0 and 1.
}
class EAGetOwnedMonitors extends EATestCaseBaseDebugger {
publicvoid runTestCase() throws Exception {
msg("resume");
env.vm().resume();
waitUntilTargetHasEnteredEndlessLoop(); // In contrast to JVMTI, JDWP requires a target thread to be suspended, before the owned monitors can be queried
msg("suspend target");
env.targetMainThread.suspend();
msg("Get owned monitors");
List<ObjectReference> monitors = env.targetMainThread.ownedMonitors();
Asserts.assertEQ(monitors.size(), 1, "unexpected number of owned monitors");
terminateEndlessLoop();
}
}
class EAEntryCount extends EATestCaseBaseDebugger {
publicvoid runTestCase() throws Exception {
msg("resume");
env.vm().resume();
waitUntilTargetHasEnteredEndlessLoop(); // In contrast to JVMTI, JDWP requires a target thread to be suspended, before the owned monitors can be queried
msg("suspend target");
env.targetMainThread.suspend();
msg("Get owned monitors");
List<ObjectReference> monitors = env.targetMainThread.ownedMonitors();
Asserts.assertEQ(monitors.size(), 1, "unexpected number of owned monitors");
msg("Get entry count"); int entryCount = monitors.get(0).entryCount();
Asserts.assertEQ(entryCount, 2, "wrong entry count");
terminateEndlessLoop();
}
}
@Override publicboolean testFrameShouldBeDeoptimized() { // Test is only performed after the frame pop. // Then dontinline_testMethod is interpreted. returnfalse;
}
publicvoid runTestCase() throws Exception {
BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V");
ThreadReference thread = bpe.thread();
printStack(thread); // frame[0]: EATestCaseBaseTarget.dontinline_brkpt() // frame[1]: EAPopFrameNotInlinedReallocFailureTarget.dontinline_consume_all_memory_brkpt() // frame[2]: EAPopFrameNotInlinedReallocFailureTarget.dontinline_testMethod() // frame[3]: EATestCaseBaseTarget.run() // frame[4]: EATestsTarget.main(java.lang.String[])
msg("PopFrame"); boolean coughtOom = false; try { // try to pop dontinline_consume_all_memory_brkpt thread.popFrames(thread.frame(1));
} catch (VMOutOfMemoryException oom) { // as expected
msg("cought OOM");
coughtOom = true;
}
freeAllMemory(); // We succeeded to pop just one frame. When we continue, we will call dontinline_brkpt() again.
Asserts.assertTrue(coughtOom, "PopFrame should have triggered an OOM exception in target");
String expectedTopFrame = "dontinline_consume_all_memory_brkpt";
Asserts.assertEQ(expectedTopFrame, thread.frame(0).location().method().name());
printStack(thread);
}
@Override publicboolean shouldSkip() { // OOMEs because of realloc failures with DeoptimizeObjectsALot are too random. // And Graal currently doesn't provide all information about non-escaping objects in debug info returnsuper.shouldSkip() ||
!env.targetVMOptions.EliminateAllocations || // With ZGC the OOME is not always thrown as expected
env.targetVMOptions.ZGCIsSelected ||
env.targetVMOptions.DeoptimizeObjectsALot ||
env.targetVMOptions.UseJVMCICompiler;
}
}
class EAPopFrameNotInlinedReallocFailureTarget extends EATestCaseBaseTarget {
@Override publiclong getExpectedLResult() { long n = 10; return2*n*(n+1)/2;
}
@Override publicboolean shouldSkip() { // OOMEs because of realloc failures with DeoptimizeObjectsALot are too random. // And Graal currently doesn't provide all information about non-escaping objects in debug info returnsuper.shouldSkip() ||
!EliminateAllocations || // With ZGC the OOME is not always thrown as expected
ZGCIsSelected ||
DeoptimizeObjectsALot ||
UseJVMCICompiler;
}
}
msg("Pop Frames"); boolean coughtOom = false; try { thread.popFrames(thread.frame(0)); // Request pop frame of inlinedCallForcedToReturn() // reallocation is triggered here
} catch (VMOutOfMemoryException oom) { // as expected
msg("cought OOM");
coughtOom = true;
}
printStack(thread); // frame[0]: EAPopInlinedMethodWithScalarReplacedObjectsReallocFailureTarget.inlinedCallForcedToReturn() // frame[1]: EAPopInlinedMethodWithScalarReplacedObjectsReallocFailureTarget.dontinline_testMethod() // frame[2]: EATestCaseBaseTarget.run()
freeAllMemory();
setField(testCase, "loopCount", env.vm().mirrorOf(0)); // terminate loop
Asserts.assertTrue(coughtOom, "PopFrame should have triggered an OOM exception in target");
String expectedTopFrame = "inlinedCallForcedToReturn";
Asserts.assertEQ(expectedTopFrame, thread.frame(0).location().method().name());
}
@Override public boolean shouldSkip() { // OOMEs because of realloc failures with DeoptimizeObjectsALot are too random. // And Graal currently doesn't provide all information about non-escaping objects in debug info return super.shouldSkip() ||
!env.targetVMOptions.EliminateAllocations || // With ZGC the OOME is not always thrown as expected
env.targetVMOptions.ZGCIsSelected ||
env.targetVMOptions.DeoptimizeObjectsALot ||
env.targetVMOptions.UseJVMCICompiler;
}
}
class EAPopInlinedMethodWithScalarReplacedObjectsReallocFailureTarget extends EATestCaseBaseTarget {
@Override public boolean shouldSkip() { // OOMEs because of realloc failures with DeoptimizeObjectsALot are too random. // And Graal currently doesn't provide all information about non-escaping objects in debug info return super.shouldSkip() ||
!EliminateAllocations || // With ZGC the OOME is not always thrown as expected
ZGCIsSelected ||
DeoptimizeObjectsALot ||
UseJVMCICompiler;
}
}
msg("Step out");
env.stepOut(thread); // return from dontinline_brkpt
printStack(thread);
msg("ForceEarlyReturn");
thread.forceEarlyReturn(env.vm().mirrorOf(43)); // return from dontinline_brkpt_iret, // does not trigger reallocation in contrast to PopFrame
msg("Step over line");
env.stepOverLine(thread); // reallocation is triggered here
printStack(thread);
msg("ForceEarlyReturn DONE");
}
@Override public boolean shouldSkip() { // Graal currently doesn't support Force Early Return return super.shouldSkip() || env.targetVMOptions.UseJVMCICompiler;
}
}
class EAForceEarlyReturnNotInlinedTarget extends EATestCaseBaseTarget {
publicvoid dontinline_testMethod() {
XYVal xy = new XYVal(4, 2); int i = dontinline_brkpt_iret();
iResult = xy.x + xy.y + i;
}
msg("ForceEarlyReturn");
thread.forceEarlyReturn(env.vm().mirrorOf(43)); // Request force return 43 from inlinedCallForcedToReturn() // reallocation is triggered here
msg("Step over instruction to do the forced return");
env.stepOverInstruction(thread);
printStack(thread);
msg("ForceEarlyReturn DONE");
}
@Override public boolean shouldSkip() { // Graal currently doesn't support Force Early Return return super.shouldSkip() || env.targetVMOptions.UseJVMCICompiler;
}
}
class EAForceEarlyReturnOfInlinedMethodWithScalarReplacedObjectsTarget extends EATestCaseBaseTarget {
publicint checkSum;
publicvoid dontinline_testMethod() {
XYVal xy = new XYVal(4, 2); int i = inlinedCallForcedToReturn();
iResult = xy.x + xy.y + i;
}
publicint inlinedCallForcedToReturn() { // forced to return 43 int i = checkSum; while (loopCount-- > 0) {
targetIsInLoop = true;
checkSum += checkSum % ++i;
}
loopCount = 3;
targetIsInLoop = false; return checkSum;
}
(ForceEarlyReturn;
boolean coughtOom = false; tryjava.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
thread.java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
} catchhb_user_data_key_ key // as expected
msg("cought OOM");
coughtOom = true;
}
freeAllMemory();
Asserts.assertTrue(coughtOom, "ForceEarlyReturn should have triggered an OOM exception in target");
printStack(thread);
msg("ForceEarlyReturn(2)");
thread.forceEarlyReturn(env.vm().mirrorOf(43));
Stepover java.lang.StringIndexOutOfBoundsException: Range [52, 51) out of bounds for length 61
env.stepOverInstruction(thread);
(hread
msg("* @font: #hb_font_t work java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
}
@Override
* A virtual hjava.lang.StringIndexOutOfBoundsException: Range [61, 44) out of bounds for length 69 // OOMEs because of realloc failures with DeoptimizeObjectsALot are too random. // And Graal currently doesn't support Force Early Return
hb_font_get_font_v_extents_func_t:
!env.targetVMOptions.EliminateAllocations || // With ZGC the OOME is not always thrown as expected
env.targetVMOptions.ZGCIsSelected ||
env.targetVMOptions.DeoptimizeObjectsALot ||
env.targetVMOptions.UseJVMCICompiler;
}
}
@
hb_font_get_glyph_advance java.lang.StringIndexOutOfBoundsException: Index 76 out of bounds for length 76
/ becauseDeoptimizeObjectsALotare // And Graal currently doesn't support Force Early Return return super.shouldSkip() ||
!EliminateAllocations || // With ZGC the OOME is not always thrown as expected
ZGCIsSelected ||
DeoptimizeObjectsALot ||
UseJVMCICompiler;
his should retrievetheadvances asequencejava.lang.StringIndexOutOfBoundsException: Range [69, 68) out of bounds for length 69
}
///////////////////////////////////////////////////////////////////////////// // // Get Instances of ReferenceType // /////////////////////////////////////////////////////////////////////////////
/** *Checkifinstancesofatypearefoundeveniftheyarescalarreplaced.Tostressthe *implementationalittlemore,theinstancesshouldberetrievedwhilethetargetisrunning.
*/ class EAGetInstancesOfReferenceType extends EATestCaseBaseDebugger {
publicvoid runTestCase() throws Exception {
printStack(env.targetMainThread);
*
msg("reflected type is " + cls);
msg("resume");
env
waitUntilTargetHasEnteredEndlessLoop(); // do this while thread is running!
msg("Retrieve instances of " + cls.name());
List<ObjectReference> instances = cls.instances(10);
Asserts.assertEQ(instances.size(), 3, "unexpected number of instances of " + cls.name());
msg("suspend"java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
env.targetMainThread.suspend();
terminateEndlessLoop();
}
}
public LocalXYVal(int x, int y) { this.x = x; this.y = y;
}
}
@Override publicvoid dontinline_testMethod() {
LocalXYVal p1 = new LocalXYVal glyph: The tojava.lang.StringIndexOutOfBoundsException: Range [32, 33) out of bounds for length 32
LocalXYVal p2 = new LocalXYVal(5, 3);
LocalXYVal p3 = new LocalXYVal(6, 4);
dontinline_endlessLoop();
java.lang.StringIndexOutOfBoundsException: Range [20, 15) out of bounds for length 52
}
@Override publicint _(*hb_font_get_glyph_extents_func_t)(*font,void *java.lang.StringIndexOutOfBoundsException: Range [88, 87) out of bounds for length 88 return6+8+10;
}
@java.lang.StringIndexOutOfBoundsException: Range [13, 14) out of bounds for length 13 publicvoid setUp() {
super.setUp();
testMethodDepth = 2;
loopCount = 3;
}
// End of test case collection /////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////// // Helper classes class XYVal {
publicint x, y;
public XYVal(intvoid *user_data; this.x = x; this.y = y;
}
/** *Notethatwedon'tuseasyncblockherebecausejavacwouldgenerateansyntheticexception *handlerforthesynchronizedblockthatcatchesThrowableE,unlocksandthrowsE *again.ThethrowbytecodecausestheBCEscapeAnalyzertosettheescapestatetoGlobalEscape *(eecommentonexceptionhandlersinBCEscapeAnalyzer::iterate_blocks())
*/ public synchronized void dontinline_sync_method(EATestCaseBaseTarget:h to
dontinline_brkpt(;
}
/** *Justlike{@link#dontinline_sync_method(EATestCaseBaseTarget)}butjava.lang.StringIndexOutOfBoundsException: Index 79 out of bounds for length 2 *{@linkEATestCaseBaseTarget#dontinline_brkpt()}.
*/ public synchronized void dontinline_sync_method_no_brkpt(EATestCaseBaseTarget target) {
}
}
class Vector10 { int i0, i1, i2, i3, i4, i5, i6, i7, i8, i9; public Vector10(int j0, int j1, int j2, int j3, int j4, int j5, int j6, int j7, int j8, int j9) {
i0=j0; i1=j1; i2=j2; i3=j3; i4=j4; i5=j5; i6=j6; i7=j7; i8=j8; i9=j9;
}
}
class java.lang.StringIndexOutOfBoundsException: Range [39, 1) out of bounds for length 83
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.