diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoQueryResult.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoQueryResult.java index d5b55f03bd83..55e828785053 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoQueryResult.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoQueryResult.java @@ -264,24 +264,24 @@ public boolean isDeoptEntry() { } /** - * Returns the number of locals variables. It can be larger than the length of - * {@link #getValueInfos()} because trailing illegal values are truncated there. It can be - * smaller than the length of {@link #getValueInfos()} when expression stack values and locked - * values are present. + * Returns the number of locals variables. See {@link #getValueInfos()} for description of array + * layout. */ public int getNumLocals() { return numLocals; } /** - * Returns the number of locked values. + * Returns the number of locked values. See {@link #getValueInfos()} for description of array + * layout. */ public int getNumLocks() { return numLocks; } /** - * Returns the number of stack values. + * Returns the number of stack values. See {@link #getValueInfos()} for description of array + * layout. */ public int getNumStack() { return numStack; @@ -295,7 +295,10 @@ public boolean hasLocalValueInfo() { } /** - * Returns the local variables and expression stack values. + * Returns array containing information about the local, stack, and lock values. The values are + * arranged in the order {locals, stack values, locks} and matches the order of + * {@code BytecodeFrame#values}. Trailing illegal values can be pruned, so the array size may + * not be equal to (numLocals + numStack + numLocks). */ public ValueInfo[] getValueInfos() { return valueInfos; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompilationInfoSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompilationInfoSupport.java index f4e2ebcce8ec..b0590b040c40 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompilationInfoSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompilationInfoSupport.java @@ -28,7 +28,6 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import org.graalvm.compiler.nodeinfo.Verbosity; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.nativeimage.ImageSingletons; @@ -37,7 +36,6 @@ import com.oracle.svm.core.code.FrameInfoEncoder; import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; import com.oracle.svm.core.util.VMError; -import com.oracle.svm.hosted.image.NativeImageCodeCache; import com.oracle.svm.hosted.meta.HostedMethod; import jdk.vm.ci.meta.JavaKind; @@ -57,6 +55,8 @@ public static final class DeoptSourceFrameInfo { public final int numStack; public final int numLocks; + public static final DeoptSourceFrameInfo INVALID_DEOPT_SOURCE_FRAME = new DeoptSourceFrameInfo(null, 0, 0, 0); + private DeoptSourceFrameInfo(JavaKind[] expectedKinds, int numLocals, int numStack, int numLocks) { this.expectedKinds = expectedKinds; this.numLocals = numLocals; @@ -71,14 +71,14 @@ public static DeoptSourceFrameInfo create(FrameState state) { private static JavaKind[] getKinds(FrameState state) { JavaKind[] kinds = new JavaKind[state.locksSize() + state.stackSize() + state.localsSize()]; int index = 0; - for (int i = 0; i < state.locksSize(); i++) { - kinds[index++] = getKind(state.lockAt(i)); + for (int i = 0; i < state.localsSize(); i++) { + kinds[index++] = getKind(state.localAt(i)); } for (int i = 0; i < state.stackSize(); i++) { kinds[index++] = getKind(state.stackAt(i)); } - for (int i = 0; i < state.localsSize(); i++) { - kinds[index++] = getKind(state.localAt(i)); + for (int i = 0; i < state.locksSize(); i++) { + kinds[index++] = getKind(state.lockAt(i)); } return kinds; } @@ -97,6 +97,11 @@ private static JavaKind getKind(ValueNode value) { * the intersection of all potential deoptimization points. */ public DeoptSourceFrameInfo mergeStateInfo(FrameState state) { + if (this == INVALID_DEOPT_SOURCE_FRAME) { + // nothing do to + return this; + } + JavaKind[] otherKinds = getKinds(state); boolean matchingSizes = numLocals == state.localsSize() && @@ -104,23 +109,7 @@ public DeoptSourceFrameInfo mergeStateInfo(FrameState state) { numLocks == state.locksSize() && expectedKinds.length == otherKinds.length; if (!matchingSizes) { - if (!NativeImageCodeCache.Options.VerifyDeoptimizationEntryPoints.getValue()) { - /* - * If VerifyDeoptimizationEntryPoints is not enabled, then this information does - * not need to be accurate. - */ - return this; - } - - StringBuilder errorMessage = new StringBuilder(); - errorMessage.append( - "Unexpected number of values in state to merge. Please report this problem and try building again with -H:-VerifyDeoptimizationEntryPoints " + - "to check if you are calling methods on the blocklist without a @TruffleBoundary.\n"); - errorMessage.append(String.format("****Merge FrameState****\n%s************************\n", state.toString(Verbosity.Debugger))); - errorMessage.append(String.format("bci: %d, duringCall: %b, rethrowException: %b\n", state.bci, state.duringCall(), state.rethrowException())); - errorMessage.append(String.format("DeoptSourceFrameInfo: locals-%d, stack-%d, locks-%d.\n", numLocals, numStack, numLocks)); - errorMessage.append(String.format("Merge FrameState: locals-%d, stack-%d, locks-%d.\n", state.localsSize(), state.stackSize(), state.locksSize())); - throw VMError.shouldNotReachHere(errorMessage.toString()); + return INVALID_DEOPT_SOURCE_FRAME; } for (int i = 0; i < expectedKinds.length; i++) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java index fb0a0f1fefdf..35d87ed4612f 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java @@ -411,6 +411,11 @@ private void verifyDeoptEntries(CodeInfo codeInfo) { private static boolean verifyDeoptEntry(CodeInfo codeInfo, HostedMethod method, Entry sourceFrameInfo) { int deoptOffsetInImage = method.getDeoptOffsetInImage(); long encodedBci = sourceFrameInfo.getKey(); + + if (sourceFrameInfo.getValue() == DeoptSourceFrameInfo.INVALID_DEOPT_SOURCE_FRAME) { + return error(method, encodedBci, "Incompatible source frames; multiple frames with different sizes of locals, locks, and/or stack values exist"); + } + if (deoptOffsetInImage <= 0) { return error(method, encodedBci, "entry point method not compiled"); }