--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Mon Nov 06 14:12:37 2017 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Mon Nov 06 20:29:49 2017 -0800
@@ -342,7 +342,7 @@
import org.graalvm.compiler.nodes.calc.AndNode;
import org.graalvm.compiler.nodes.calc.CompareNode;
import org.graalvm.compiler.nodes.calc.ConditionalNode;
-import org.graalvm.compiler.nodes.calc.DivNode;
+import org.graalvm.compiler.nodes.calc.FloatDivNode;
import org.graalvm.compiler.nodes.calc.FloatConvertNode;
import org.graalvm.compiler.nodes.calc.IntegerBelowNode;
import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;
@@ -374,7 +374,6 @@
import org.graalvm.compiler.nodes.extended.StateSplitProxyNode;
import org.graalvm.compiler.nodes.extended.ValueAnchorNode;
import org.graalvm.compiler.nodes.graphbuilderconf.ClassInitializationPlugin;
-import org.graalvm.compiler.nodes.graphbuilderconf.InvokeDynamicPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
@@ -383,6 +382,7 @@
import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.InvocationPluginReceiver;
+import org.graalvm.compiler.nodes.graphbuilderconf.InvokeDynamicPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.ProfilingPlugin;
import org.graalvm.compiler.nodes.java.ArrayLengthNode;
@@ -435,6 +435,7 @@
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.meta.Signature;
import jdk.vm.ci.meta.TriState;
+import org.graalvm.compiler.core.common.type.IntegerStamp;
/**
* The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph.
@@ -1036,7 +1037,7 @@
deopt.updateNodeSourcePosition(() -> createBytecodePosition());
}
- private AbstractBeginNode handleException(ValueNode exceptionObject, int bci) {
+ private AbstractBeginNode handleException(ValueNode exceptionObject, int bci, boolean deoptimizeOnly) {
assert bci == BytecodeFrame.BEFORE_BCI || bci == bci() : "invalid bci";
debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, (profilingInfo == null ? "" : profilingInfo.getExceptionSeen(bci)));
@@ -1058,8 +1059,12 @@
this.controlFlowSplit = true;
FixedWithNextNode finishedDispatch = finishInstruction(dispatchBegin, dispatchState);
- createHandleExceptionTarget(finishedDispatch, bci, dispatchState);
-
+ if (deoptimizeOnly) {
+ DeoptimizeNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter));
+ dispatchBegin.setNext(BeginNode.begin(deoptimizeNode));
+ } else {
+ createHandleExceptionTarget(finishedDispatch, bci, dispatchState);
+ }
return dispatchBegin;
}
@@ -1111,7 +1116,7 @@
}
protected ValueNode genFloatDiv(ValueNode x, ValueNode y) {
- return DivNode.create(x, y);
+ return FloatDivNode.create(x, y);
}
protected ValueNode genFloatRem(ValueNode x, ValueNode y) {
@@ -1215,7 +1220,7 @@
ValueNode exception = frameState.pop(JavaKind.Object);
FixedGuardNode nullCheck = append(new FixedGuardNode(graph.addOrUniqueWithInputs(IsNullNode.create(exception)), NullCheckException, InvalidateReprofile, true));
ValueNode nonNullException = graph.maybeAddOrUnique(PiNode.create(exception, exception.stamp().join(objectNonNull()), nullCheck));
- lastInstr.setNext(handleException(nonNullException, bci()));
+ lastInstr.setNext(handleException(nonNullException, bci(), false));
}
protected LogicNode createInstanceOf(TypeReference type, ValueNode object) {
@@ -1275,12 +1280,12 @@
}
BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, NullPointerException.class));
AbstractBeginNode falseSucc = graph.add(new BeginNode());
- ValueNode nonNullReceiver = graph.addOrUnique(PiNode.create(receiver, objectNonNull(), falseSucc));
+ ValueNode nonNullReceiver = graph.addOrUniqueWithInputs(PiNode.create(receiver, objectNonNull(), falseSucc));
append(new IfNode(graph.addOrUniqueWithInputs(IsNullNode.create(receiver)), exception, falseSucc, SLOW_PATH_PROBABILITY));
lastInstr = falseSucc;
exception.setStateAfter(createFrameState(bci(), exception));
- exception.setNext(handleException(exception, bci()));
+ exception.setNext(handleException(exception, bci(), false));
EXPLICIT_EXCEPTIONS.increment(debug);
return nonNullReceiver;
}
@@ -1292,7 +1297,7 @@
lastInstr = trueSucc;
exception.setStateAfter(createFrameState(bci(), exception));
- exception.setNext(handleException(exception, bci()));
+ exception.setNext(handleException(exception, bci(), false));
}
protected ValueNode genArrayLength(ValueNode x) {
@@ -1532,8 +1537,8 @@
@Override
public void handleReplacedInvoke(CallTargetNode callTarget, JavaKind resultType) {
BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor();
- boolean withExceptionEdge = intrinsicCallSiteParser == null ? !omitInvokeExceptionEdge(null) : !intrinsicCallSiteParser.omitInvokeExceptionEdge(null);
- createNonInlinedInvoke(withExceptionEdge, bci(), callTarget, resultType);
+ ExceptionEdgeAction exceptionEdgeAction = intrinsicCallSiteParser == null ? getActionForInvokeExceptionEdge(null) : intrinsicCallSiteParser.getActionForInvokeExceptionEdge(null);
+ createNonInlinedInvoke(exceptionEdgeAction, bci(), callTarget, resultType);
}
protected Invoke appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod initialTargetMethod, ValueNode[] args) {
@@ -1603,7 +1608,7 @@
int invokeBci = bci();
JavaTypeProfile profile = getProfileForInvoke(invokeKind);
- boolean withExceptionEdge = !omitInvokeExceptionEdge(inlineInfo);
+ ExceptionEdgeAction edgeAction = getActionForInvokeExceptionEdge(inlineInfo);
boolean partialIntrinsicExit = false;
if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) {
partialIntrinsicExit = true;
@@ -1614,7 +1619,7 @@
// must use the same context as the call to the intrinsic.
invokeBci = intrinsicCallSiteParser.bci();
profile = intrinsicCallSiteParser.getProfileForInvoke(invokeKind);
- withExceptionEdge = !intrinsicCallSiteParser.omitInvokeExceptionEdge(inlineInfo);
+ edgeAction = intrinsicCallSiteParser.getActionForInvokeExceptionEdge(inlineInfo);
} else {
// We are parsing the intrinsic for the root compilation or for inlining,
// This call is a partial intrinsic exit, and we do not have profile information
@@ -1624,7 +1629,7 @@
assert intrinsicContext.isPostParseInlined();
invokeBci = BytecodeFrame.UNKNOWN_BCI;
profile = null;
- withExceptionEdge = graph.method().getAnnotation(Snippet.class) == null;
+ edgeAction = graph.method().getAnnotation(Snippet.class) == null ? ExceptionEdgeAction.INCLUDE_AND_HANDLE : ExceptionEdgeAction.OMIT;
}
if (originalMethod.isStatic()) {
@@ -1637,10 +1642,10 @@
Signature sig = originalMethod.getSignature();
returnType = sig.getReturnType(method.getDeclaringClass());
resultType = sig.getReturnKind();
- assert checkPartialIntrinsicExit(intrinsicCallSiteParser == null ? null : intrinsicCallSiteParser.currentInvoke.args, args);
+ assert intrinsicContext.allowPartialIntrinsicArgumentMismatch() || checkPartialIntrinsicExit(intrinsicCallSiteParser == null ? null : intrinsicCallSiteParser.currentInvoke.args, args);
targetMethod = originalMethod;
}
- Invoke invoke = createNonInlinedInvoke(withExceptionEdge, invokeBci, args, targetMethod, invokeKind, resultType, returnType, profile);
+ Invoke invoke = createNonInlinedInvoke(edgeAction, invokeBci, args, targetMethod, invokeKind, resultType, returnType, profile);
if (partialIntrinsicExit) {
// This invoke must never be later inlined as it might select the intrinsic graph.
// Until there is a mechanism to guarantee that any late inlining will not select
@@ -1698,14 +1703,14 @@
} else {
for (int i = 0; i < recursiveArgs.length; i++) {
ValueNode arg = GraphUtil.unproxify(recursiveArgs[i]);
- assert arg instanceof ParameterNode && ((ParameterNode) arg).index() == i : String.format("argument %d of call denoting partial intrinsic exit should be a %s with index %d, not %s", i,
- ParameterNode.class.getSimpleName(), i, arg);
+ assert arg instanceof ParameterNode && ((ParameterNode) arg).index() == i : String.format("argument %d of call denoting partial intrinsic exit should be a %s with index %d, not %s",
+ i, ParameterNode.class.getSimpleName(), i, arg);
}
}
return true;
}
- protected Invoke createNonInlinedInvoke(boolean withExceptionEdge, int invokeBci, ValueNode[] invokeArgs, ResolvedJavaMethod targetMethod,
+ protected Invoke createNonInlinedInvoke(ExceptionEdgeAction exceptionEdge, int invokeBci, ValueNode[] invokeArgs, ResolvedJavaMethod targetMethod,
InvokeKind invokeKind, JavaKind resultType, JavaType returnType, JavaTypeProfile profile) {
StampPair returnStamp = graphBuilderConfig.getPlugins().getOverridingStamp(this, returnType, false);
@@ -1714,7 +1719,7 @@
}
MethodCallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, targetMethod, invokeArgs, returnStamp, profile));
- Invoke invoke = createNonInlinedInvoke(withExceptionEdge, invokeBci, callTarget, resultType);
+ Invoke invoke = createNonInlinedInvoke(exceptionEdge, invokeBci, callTarget, resultType);
for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) {
plugin.notifyNotInlined(this, targetMethod, invoke);
@@ -1723,11 +1728,11 @@
return invoke;
}
- protected Invoke createNonInlinedInvoke(boolean withExceptionEdge, int invokeBci, CallTargetNode callTarget, JavaKind resultType) {
- if (!withExceptionEdge) {
+ protected Invoke createNonInlinedInvoke(ExceptionEdgeAction exceptionEdge, int invokeBci, CallTargetNode callTarget, JavaKind resultType) {
+ if (exceptionEdge == ExceptionEdgeAction.OMIT) {
return createInvoke(invokeBci, callTarget, resultType);
} else {
- Invoke invoke = createInvokeWithException(invokeBci, callTarget, resultType);
+ Invoke invoke = createInvokeWithException(invokeBci, callTarget, resultType, exceptionEdge);
AbstractBeginNode beginNode = graph.add(KillingBeginNode.create(LocationIdentity.any()));
invoke.setNext(beginNode);
lastInstr = beginNode;
@@ -1736,20 +1741,29 @@
}
/**
- * If the method returns true, the invocation of the given {@link MethodCallTargetNode call
- * target} does not need an exception edge.
+ * Describes what should be done with the exception edge of an invocation. The edge can be
+ * omitted or included. An included edge can handle the exception or transfer execution to the
+ * interpreter for handling (deoptimize).
*/
- protected boolean omitInvokeExceptionEdge(InlineInfo lastInlineInfo) {
+ protected enum ExceptionEdgeAction {
+ OMIT,
+ INCLUDE_AND_HANDLE,
+ INCLUDE_AND_DEOPTIMIZE
+ }
+
+ protected ExceptionEdgeAction getActionForInvokeExceptionEdge(InlineInfo lastInlineInfo) {
if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION) {
- return false;
+ return ExceptionEdgeAction.INCLUDE_AND_HANDLE;
} else if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_NO_EXCEPTION) {
- return true;
+ return ExceptionEdgeAction.OMIT;
+ } else if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_DEOPTIMIZE_ON_EXCEPTION) {
+ return ExceptionEdgeAction.INCLUDE_AND_DEOPTIMIZE;
} else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.CheckAll) {
- return false;
+ return ExceptionEdgeAction.INCLUDE_AND_HANDLE;
} else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.ExplicitOnly) {
- return false;
+ return ExceptionEdgeAction.INCLUDE_AND_HANDLE;
} else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.OmitAll) {
- return true;
+ return ExceptionEdgeAction.OMIT;
} else {
assert graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.Profile;
// be conservative if information was not recorded (could result in endless
@@ -1759,12 +1773,12 @@
if (profilingInfo != null) {
TriState exceptionSeen = profilingInfo.getExceptionSeen(bci());
if (exceptionSeen == TriState.FALSE) {
- return true;
+ return ExceptionEdgeAction.OMIT;
}
}
}
}
- return false;
+ return ExceptionEdgeAction.INCLUDE_AND_HANDLE;
}
}
@@ -1887,7 +1901,7 @@
if (newProfile != profile) {
if (newProfile.getTypes().length == 0) {
// All profiled types select the intrinsic so
- // emit a fixed guard instead of a if-then-else.
+ // emit a fixed guard instead of an if-then-else.
lastInstr = append(new FixedGuardNode(compare, TypeCheckedInliningViolated, InvalidateReprofile, false));
return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, null, null);
}
@@ -1966,7 +1980,7 @@
}
lastInstr = intrinsicGuard.nonIntrinsicBranch;
- createNonInlinedInvoke(omitInvokeExceptionEdge(null), bci(), args, targetMethod, invokeKind, resultType, returnType, intrinsicGuard.profile);
+ createNonInlinedInvoke(getActionForInvokeExceptionEdge(null), bci(), args, targetMethod, invokeKind, resultType, returnType, intrinsicGuard.profile);
EndNode nonIntrinsicEnd = append(new EndNode());
AbstractMergeNode mergeNode = graph.add(new MergeNode());
@@ -2303,7 +2317,7 @@
if (calleeBeforeUnwindNode != null) {
ValueNode calleeUnwindValue = parser.getUnwindValue();
assert calleeUnwindValue != null;
- calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci()));
+ calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci(), false));
}
}
}
@@ -2319,7 +2333,7 @@
return invoke;
}
- protected InvokeWithExceptionNode createInvokeWithException(int invokeBci, CallTargetNode callTarget, JavaKind resultType) {
+ protected InvokeWithExceptionNode createInvokeWithException(int invokeBci, CallTargetNode callTarget, JavaKind resultType, ExceptionEdgeAction exceptionEdgeAction) {
if (currentBlock != null && stream.nextBCI() > currentBlock.endBci) {
/*
* Clear non-live locals early so that the exception handler entry gets the cleared
@@ -2328,7 +2342,7 @@
frameState.clearNonLiveLocals(currentBlock, liveness, false);
}
- AbstractBeginNode exceptionEdge = handleException(null, bci());
+ AbstractBeginNode exceptionEdge = handleException(null, bci(), exceptionEdgeAction == ExceptionEdgeAction.INCLUDE_AND_DEOPTIMIZE);
InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, invokeBci));
frameState.pushReturn(resultType, invoke);
invoke.setStateAfter(createFrameState(stream.nextBCI(), invoke));
@@ -2359,20 +2373,43 @@
}
}
+ ValueNode realReturnVal = processReturnValue(returnVal, returnKind);
+
frameState.setRethrowException(false);
frameState.clearStack();
- beforeReturn(returnVal, returnKind);
+ beforeReturn(realReturnVal, returnKind);
if (parent == null) {
- append(new ReturnNode(returnVal));
+ append(new ReturnNode(realReturnVal));
} else {
if (returnDataList == null) {
returnDataList = new ArrayList<>();
}
- returnDataList.add(new ReturnToCallerData(returnVal, lastInstr));
+ returnDataList.add(new ReturnToCallerData(realReturnVal, lastInstr));
lastInstr = null;
}
}
+ private ValueNode processReturnValue(ValueNode value, JavaKind kind) {
+ JavaKind returnKind = method.getSignature().getReturnKind();
+ if (kind != returnKind) {
+ // sub-word integer
+ assert returnKind.isNumericInteger() && returnKind.getStackKind() == JavaKind.Int;
+ IntegerStamp stamp = (IntegerStamp) value.stamp();
+
+ // the bytecode verifier doesn't check that the value is in the correct range
+ if (stamp.lowerBound() < returnKind.getMinValue() || returnKind.getMaxValue() < stamp.upperBound()) {
+ ValueNode narrow = append(genNarrow(value, returnKind.getBitCount()));
+ if (returnKind.isUnsigned()) {
+ return append(genZeroExtend(narrow, 32));
+ } else {
+ return append(genSignExtend(narrow, 32));
+ }
+ }
+ }
+
+ return value;
+ }
+
private void beforeReturn(ValueNode x, JavaKind kind) {
if (graph.method() != null && graph.method().isJavaLangObjectInit()) {
/*
@@ -2794,6 +2831,8 @@
}
private void createExceptionDispatch(ExceptionDispatchBlock block) {
+ lastInstr = finishInstruction(lastInstr, frameState);
+
assert frameState.stackSize() == 1 : frameState;
if (block.handler.isCatchAll()) {
assert block.getSuccessorCount() == 1;