< prev index next >
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java
Print this page
*** 340,350 ****
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.AddNode;
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.FloatConvertNode;
import org.graalvm.compiler.nodes.calc.IntegerBelowNode;
import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;
import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
import org.graalvm.compiler.nodes.calc.IsNullNode;
--- 340,350 ----
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.AddNode;
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.FloatDivNode;
import org.graalvm.compiler.nodes.calc.FloatConvertNode;
import org.graalvm.compiler.nodes.calc.IntegerBelowNode;
import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;
import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
import org.graalvm.compiler.nodes.calc.IsNullNode;
*** 372,390 ****
import org.graalvm.compiler.nodes.extended.LoadMethodNode;
import org.graalvm.compiler.nodes.extended.MembarNode;
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;
import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo;
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.NodePlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.ProfilingPlugin;
import org.graalvm.compiler.nodes.java.ArrayLengthNode;
import org.graalvm.compiler.nodes.java.ExceptionObjectNode;
import org.graalvm.compiler.nodes.java.FinalFieldBarrierNode;
--- 372,390 ----
import org.graalvm.compiler.nodes.extended.LoadMethodNode;
import org.graalvm.compiler.nodes.extended.MembarNode;
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.GraphBuilderConfiguration;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo;
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;
import org.graalvm.compiler.nodes.java.ExceptionObjectNode;
import org.graalvm.compiler.nodes.java.FinalFieldBarrierNode;
*** 433,442 ****
--- 433,443 ----
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaMethod;
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.
*/
public class BytecodeParser implements GraphBuilderContext {
*** 1034,1044 ****
assert !graphBuilderConfig.unresolvedIsError();
DeoptimizeNode deopt = append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
deopt.updateNodeSourcePosition(() -> createBytecodePosition());
}
! private AbstractBeginNode handleException(ValueNode exceptionObject, int bci) {
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)));
FrameStateBuilder dispatchState = frameState.copy();
dispatchState.clearStack();
--- 1035,1045 ----
assert !graphBuilderConfig.unresolvedIsError();
DeoptimizeNode deopt = append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
deopt.updateNodeSourcePosition(() -> createBytecodePosition());
}
! 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)));
FrameStateBuilder dispatchState = frameState.copy();
dispatchState.clearStack();
*** 1056,1067 ****
dispatchState.setRethrowException(true);
}
this.controlFlowSplit = true;
FixedWithNextNode finishedDispatch = finishInstruction(dispatchBegin, dispatchState);
createHandleExceptionTarget(finishedDispatch, bci, dispatchState);
!
return dispatchBegin;
}
protected void createHandleExceptionTarget(FixedWithNextNode finishedDispatch, int bci, FrameStateBuilder dispatchState) {
BciBlock dispatchBlock = currentBlock.exceptionDispatchBlock();
--- 1057,1072 ----
dispatchState.setRethrowException(true);
}
this.controlFlowSplit = true;
FixedWithNextNode finishedDispatch = finishInstruction(dispatchBegin, 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;
}
protected void createHandleExceptionTarget(FixedWithNextNode finishedDispatch, int bci, FrameStateBuilder dispatchState) {
BciBlock dispatchBlock = currentBlock.exceptionDispatchBlock();
*** 1109,1119 ****
protected ValueNode genFloatMul(ValueNode x, ValueNode y) {
return MulNode.create(x, y);
}
protected ValueNode genFloatDiv(ValueNode x, ValueNode y) {
! return DivNode.create(x, y);
}
protected ValueNode genFloatRem(ValueNode x, ValueNode y) {
return new RemNode(x, y);
}
--- 1114,1124 ----
protected ValueNode genFloatMul(ValueNode x, ValueNode y) {
return MulNode.create(x, y);
}
protected ValueNode genFloatDiv(ValueNode x, ValueNode y) {
! return FloatDivNode.create(x, y);
}
protected ValueNode genFloatRem(ValueNode x, ValueNode y) {
return new RemNode(x, y);
}
*** 1213,1223 ****
genInfoPointNode(InfopointReason.BYTECODE_POSITION, null);
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()));
}
protected LogicNode createInstanceOf(TypeReference type, ValueNode object) {
return InstanceOfNode.create(type, object);
}
--- 1218,1228 ----
genInfoPointNode(InfopointReason.BYTECODE_POSITION, null);
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(), false));
}
protected LogicNode createInstanceOf(TypeReference type, ValueNode object) {
return InstanceOfNode.create(type, object);
}
*** 1273,1288 ****
if (StampTool.isPointerNonNull(receiver.stamp())) {
return receiver;
}
BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, NullPointerException.class));
AbstractBeginNode falseSucc = graph.add(new BeginNode());
! ValueNode nonNullReceiver = graph.addOrUnique(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()));
EXPLICIT_EXCEPTIONS.increment(debug);
return nonNullReceiver;
}
protected void emitExplicitBoundsCheck(ValueNode index, ValueNode length) {
--- 1278,1293 ----
if (StampTool.isPointerNonNull(receiver.stamp())) {
return receiver;
}
BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, NullPointerException.class));
AbstractBeginNode falseSucc = graph.add(new BeginNode());
! 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(), false));
EXPLICIT_EXCEPTIONS.increment(debug);
return nonNullReceiver;
}
protected void emitExplicitBoundsCheck(ValueNode index, ValueNode length) {
*** 1290,1300 ****
BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, ArrayIndexOutOfBoundsException.class, index));
append(new IfNode(genUnique(IntegerBelowNode.create(constantReflection, metaAccess, options, null, index, length)), trueSucc, exception, FAST_PATH_PROBABILITY));
lastInstr = trueSucc;
exception.setStateAfter(createFrameState(bci(), exception));
! exception.setNext(handleException(exception, bci()));
}
protected ValueNode genArrayLength(ValueNode x) {
return ArrayLengthNode.create(x, constantReflection);
}
--- 1295,1305 ----
BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, ArrayIndexOutOfBoundsException.class, index));
append(new IfNode(genUnique(IntegerBelowNode.create(constantReflection, metaAccess, options, null, index, length)), trueSucc, exception, FAST_PATH_PROBABILITY));
lastInstr = trueSucc;
exception.setStateAfter(createFrameState(bci(), exception));
! exception.setNext(handleException(exception, bci(), false));
}
protected ValueNode genArrayLength(ValueNode x) {
return ArrayLengthNode.create(x, constantReflection);
}
*** 1530,1541 ****
}
@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);
}
protected Invoke appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod initialTargetMethod, ValueNode[] args) {
ResolvedJavaMethod targetMethod = initialTargetMethod;
InvokeKind invokeKind = initialInvokeKind;
--- 1535,1546 ----
}
@Override
public void handleReplacedInvoke(CallTargetNode callTarget, JavaKind resultType) {
BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor();
! ExceptionEdgeAction exceptionEdgeAction = intrinsicCallSiteParser == null ? getActionForInvokeExceptionEdge(null) : intrinsicCallSiteParser.getActionForInvokeExceptionEdge(null);
! createNonInlinedInvoke(exceptionEdgeAction, bci(), callTarget, resultType);
}
protected Invoke appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod initialTargetMethod, ValueNode[] args) {
ResolvedJavaMethod targetMethod = initialTargetMethod;
InvokeKind invokeKind = initialInvokeKind;
*** 1601,1632 ****
currentInvoke = null;
}
int invokeBci = bci();
JavaTypeProfile profile = getProfileForInvoke(invokeKind);
! boolean withExceptionEdge = !omitInvokeExceptionEdge(inlineInfo);
boolean partialIntrinsicExit = false;
if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) {
partialIntrinsicExit = true;
ResolvedJavaMethod originalMethod = intrinsicContext.getOriginalMethod();
BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor();
if (intrinsicCallSiteParser != null) {
// When exiting a partial intrinsic, the invoke to the original
// must use the same context as the call to the intrinsic.
invokeBci = intrinsicCallSiteParser.bci();
profile = intrinsicCallSiteParser.getProfileForInvoke(invokeKind);
! withExceptionEdge = !intrinsicCallSiteParser.omitInvokeExceptionEdge(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
// for this callsite. We also have to assume that the call needs an exception
// edge. Finally, we know that this intrinsic is parsed for late inlining,
// so the bci must be set to unknown, so that the inliner patches it later.
assert intrinsicContext.isPostParseInlined();
invokeBci = BytecodeFrame.UNKNOWN_BCI;
profile = null;
! withExceptionEdge = graph.method().getAnnotation(Snippet.class) == null;
}
if (originalMethod.isStatic()) {
invokeKind = InvokeKind.Static;
} else {
--- 1606,1637 ----
currentInvoke = null;
}
int invokeBci = bci();
JavaTypeProfile profile = getProfileForInvoke(invokeKind);
! ExceptionEdgeAction edgeAction = getActionForInvokeExceptionEdge(inlineInfo);
boolean partialIntrinsicExit = false;
if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) {
partialIntrinsicExit = true;
ResolvedJavaMethod originalMethod = intrinsicContext.getOriginalMethod();
BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor();
if (intrinsicCallSiteParser != null) {
// When exiting a partial intrinsic, the invoke to the original
// must use the same context as the call to the intrinsic.
invokeBci = intrinsicCallSiteParser.bci();
profile = intrinsicCallSiteParser.getProfileForInvoke(invokeKind);
! 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
// for this callsite. We also have to assume that the call needs an exception
// edge. Finally, we know that this intrinsic is parsed for late inlining,
// so the bci must be set to unknown, so that the inliner patches it later.
assert intrinsicContext.isPostParseInlined();
invokeBci = BytecodeFrame.UNKNOWN_BCI;
profile = null;
! edgeAction = graph.method().getAnnotation(Snippet.class) == null ? ExceptionEdgeAction.INCLUDE_AND_HANDLE : ExceptionEdgeAction.OMIT;
}
if (originalMethod.isStatic()) {
invokeKind = InvokeKind.Static;
} else {
*** 1635,1648 ****
invokeKind = InvokeKind.Special;
}
Signature sig = originalMethod.getSignature();
returnType = sig.getReturnType(method.getDeclaringClass());
resultType = sig.getReturnKind();
! assert checkPartialIntrinsicExit(intrinsicCallSiteParser == null ? null : intrinsicCallSiteParser.currentInvoke.args, args);
targetMethod = originalMethod;
}
! Invoke invoke = createNonInlinedInvoke(withExceptionEdge, 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
// the intrinsic graph, prevent this invoke from being inlined.
invoke.setUseForInlining(false);
--- 1640,1653 ----
invokeKind = InvokeKind.Special;
}
Signature sig = originalMethod.getSignature();
returnType = sig.getReturnType(method.getDeclaringClass());
resultType = sig.getReturnKind();
! assert intrinsicContext.allowPartialIntrinsicArgumentMismatch() || checkPartialIntrinsicExit(intrinsicCallSiteParser == null ? null : intrinsicCallSiteParser.currentInvoke.args, args);
targetMethod = originalMethod;
}
! 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
// the intrinsic graph, prevent this invoke from being inlined.
invoke.setUseForInlining(false);
*** 1696,1772 ****
assert arg == icArg : String.format("argument %d of call denoting partial intrinsic exit should be %s, not %s", i, icArg, arg);
}
} 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);
}
}
return true;
}
! protected Invoke createNonInlinedInvoke(boolean withExceptionEdge, int invokeBci, ValueNode[] invokeArgs, ResolvedJavaMethod targetMethod,
InvokeKind invokeKind, JavaKind resultType, JavaType returnType, JavaTypeProfile profile) {
StampPair returnStamp = graphBuilderConfig.getPlugins().getOverridingStamp(this, returnType, false);
if (returnStamp == null) {
returnStamp = StampFactory.forDeclaredType(graph.getAssumptions(), returnType, false);
}
MethodCallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, targetMethod, invokeArgs, returnStamp, profile));
! Invoke invoke = createNonInlinedInvoke(withExceptionEdge, invokeBci, callTarget, resultType);
for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) {
plugin.notifyNotInlined(this, targetMethod, invoke);
}
return invoke;
}
! protected Invoke createNonInlinedInvoke(boolean withExceptionEdge, int invokeBci, CallTargetNode callTarget, JavaKind resultType) {
! if (!withExceptionEdge) {
return createInvoke(invokeBci, callTarget, resultType);
} else {
! Invoke invoke = createInvokeWithException(invokeBci, callTarget, resultType);
AbstractBeginNode beginNode = graph.add(KillingBeginNode.create(LocationIdentity.any()));
invoke.setNext(beginNode);
lastInstr = beginNode;
return invoke;
}
}
/**
! * If the method returns true, the invocation of the given {@link MethodCallTargetNode call
! * target} does not need an exception edge.
*/
! protected boolean omitInvokeExceptionEdge(InlineInfo lastInlineInfo) {
if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION) {
! return false;
} else if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_NO_EXCEPTION) {
! return true;
} else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.CheckAll) {
! return false;
} else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.ExplicitOnly) {
! return false;
} else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.OmitAll) {
! return true;
} else {
assert graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.Profile;
// be conservative if information was not recorded (could result in endless
// recompiles otherwise)
if (!StressInvokeWithExceptionNode.getValue(options)) {
if (optimisticOpts.useExceptionProbability(getOptions())) {
if (profilingInfo != null) {
TriState exceptionSeen = profilingInfo.getExceptionSeen(bci());
if (exceptionSeen == TriState.FALSE) {
! return true;
}
}
}
}
! return false;
}
}
/**
* Contains all the assertion checking logic around the application of an
--- 1701,1786 ----
assert arg == icArg : String.format("argument %d of call denoting partial intrinsic exit should be %s, not %s", i, icArg, arg);
}
} 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);
}
}
return true;
}
! 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);
if (returnStamp == null) {
returnStamp = StampFactory.forDeclaredType(graph.getAssumptions(), returnType, false);
}
MethodCallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, targetMethod, invokeArgs, returnStamp, profile));
! Invoke invoke = createNonInlinedInvoke(exceptionEdge, invokeBci, callTarget, resultType);
for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) {
plugin.notifyNotInlined(this, targetMethod, invoke);
}
return invoke;
}
! 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, exceptionEdge);
AbstractBeginNode beginNode = graph.add(KillingBeginNode.create(LocationIdentity.any()));
invoke.setNext(beginNode);
lastInstr = beginNode;
return invoke;
}
}
/**
! * 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 enum ExceptionEdgeAction {
! OMIT,
! INCLUDE_AND_HANDLE,
! INCLUDE_AND_DEOPTIMIZE
! }
!
! protected ExceptionEdgeAction getActionForInvokeExceptionEdge(InlineInfo lastInlineInfo) {
if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION) {
! return ExceptionEdgeAction.INCLUDE_AND_HANDLE;
} else if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_NO_EXCEPTION) {
! 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 ExceptionEdgeAction.INCLUDE_AND_HANDLE;
} else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.ExplicitOnly) {
! return ExceptionEdgeAction.INCLUDE_AND_HANDLE;
} else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.OmitAll) {
! return ExceptionEdgeAction.OMIT;
} else {
assert graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.Profile;
// be conservative if information was not recorded (could result in endless
// recompiles otherwise)
if (!StressInvokeWithExceptionNode.getValue(options)) {
if (optimisticOpts.useExceptionProbability(getOptions())) {
if (profilingInfo != null) {
TriState exceptionSeen = profilingInfo.getExceptionSeen(bci());
if (exceptionSeen == TriState.FALSE) {
! return ExceptionEdgeAction.OMIT;
}
}
}
}
! return ExceptionEdgeAction.INCLUDE_AND_HANDLE;
}
}
/**
* Contains all the assertion checking logic around the application of an
*** 1885,1895 ****
if (profile != null) {
JavaTypeProfile newProfile = adjustProfileForInvocationPlugin(profile, targetMethod);
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.
lastInstr = append(new FixedGuardNode(compare, TypeCheckedInliningViolated, InvalidateReprofile, false));
return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, null, null);
}
} else {
// No profiled types select the intrinsic so emit a virtual call
--- 1899,1909 ----
if (profile != null) {
JavaTypeProfile newProfile = adjustProfileForInvocationPlugin(profile, targetMethod);
if (newProfile != profile) {
if (newProfile.getTypes().length == 0) {
// All profiled types select the intrinsic so
! // 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);
}
} else {
// No profiled types select the intrinsic so emit a virtual call
*** 1964,1974 ****
frameState.pop(resultType);
nonIntrinisicState = frameState;
}
lastInstr = intrinsicGuard.nonIntrinsicBranch;
! createNonInlinedInvoke(omitInvokeExceptionEdge(null), bci(), args, targetMethod, invokeKind, resultType, returnType, intrinsicGuard.profile);
EndNode nonIntrinsicEnd = append(new EndNode());
AbstractMergeNode mergeNode = graph.add(new MergeNode());
mergeNode.addForwardEnd(intrinsicEnd);
--- 1978,1988 ----
frameState.pop(resultType);
nonIntrinisicState = frameState;
}
lastInstr = intrinsicGuard.nonIntrinsicBranch;
! createNonInlinedInvoke(getActionForInvokeExceptionEdge(null), bci(), args, targetMethod, invokeKind, resultType, returnType, intrinsicGuard.profile);
EndNode nonIntrinsicEnd = append(new EndNode());
AbstractMergeNode mergeNode = graph.add(new MergeNode());
mergeNode.addForwardEnd(intrinsicEnd);
*** 2301,2311 ****
FixedWithNextNode calleeBeforeUnwindNode = parser.getBeforeUnwindNode();
if (calleeBeforeUnwindNode != null) {
ValueNode calleeUnwindValue = parser.getUnwindValue();
assert calleeUnwindValue != null;
! calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci()));
}
}
}
public MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, StampPair returnStamp, JavaTypeProfile profile) {
--- 2315,2325 ----
FixedWithNextNode calleeBeforeUnwindNode = parser.getBeforeUnwindNode();
if (calleeBeforeUnwindNode != null) {
ValueNode calleeUnwindValue = parser.getUnwindValue();
assert calleeUnwindValue != null;
! calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci(), false));
}
}
}
public MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, StampPair returnStamp, JavaTypeProfile profile) {
*** 2317,2336 ****
frameState.pushReturn(resultType, invoke);
invoke.setStateAfter(createFrameState(stream.nextBCI(), invoke));
return invoke;
}
! protected InvokeWithExceptionNode createInvokeWithException(int invokeBci, CallTargetNode callTarget, JavaKind resultType) {
if (currentBlock != null && stream.nextBCI() > currentBlock.endBci) {
/*
* Clear non-live locals early so that the exception handler entry gets the cleared
* state.
*/
frameState.clearNonLiveLocals(currentBlock, liveness, false);
}
! AbstractBeginNode exceptionEdge = handleException(null, bci());
InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, invokeBci));
frameState.pushReturn(resultType, invoke);
invoke.setStateAfter(createFrameState(stream.nextBCI(), invoke));
return invoke;
}
--- 2331,2350 ----
frameState.pushReturn(resultType, invoke);
invoke.setStateAfter(createFrameState(stream.nextBCI(), invoke));
return invoke;
}
! 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
* state.
*/
frameState.clearNonLiveLocals(currentBlock, liveness, false);
}
! 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));
return invoke;
}
*** 2357,2380 ****
assert stateAfter == null;
}
}
}
frameState.setRethrowException(false);
frameState.clearStack();
! beforeReturn(returnVal, returnKind);
if (parent == null) {
! append(new ReturnNode(returnVal));
} else {
if (returnDataList == null) {
returnDataList = new ArrayList<>();
}
! returnDataList.add(new ReturnToCallerData(returnVal, lastInstr));
lastInstr = null;
}
}
private void beforeReturn(ValueNode x, JavaKind kind) {
if (graph.method() != null && graph.method().isJavaLangObjectInit()) {
/*
* Get the receiver from the initial state since bytecode rewriting could do arbitrary
* things to the state of the locals.
--- 2371,2417 ----
assert stateAfter == null;
}
}
}
+ ValueNode realReturnVal = processReturnValue(returnVal, returnKind);
+
frameState.setRethrowException(false);
frameState.clearStack();
! beforeReturn(realReturnVal, returnKind);
if (parent == null) {
! append(new ReturnNode(realReturnVal));
} else {
if (returnDataList == null) {
returnDataList = new ArrayList<>();
}
! 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()) {
/*
* Get the receiver from the initial state since bytecode rewriting could do arbitrary
* things to the state of the locals.
*** 2792,2801 ****
--- 2829,2840 ----
throw bailout("unbalanced monitors: too few exits exiting frame");
}
}
private void createExceptionDispatch(ExceptionDispatchBlock block) {
+ lastInstr = finishInstruction(lastInstr, frameState);
+
assert frameState.stackSize() == 1 : frameState;
if (block.handler.isCatchAll()) {
assert block.getSuccessorCount() == 1;
appendGoto(block.getSuccessor(0));
return;
< prev index next >