< 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 >