Search in sources :

Example 16 with Invoke

use of org.graalvm.compiler.nodes.Invoke in project graal by oracle.

the class InliningData method doInline.

@SuppressWarnings("try")
private void doInline(CallsiteHolderExplorable callerCallsiteHolder, MethodInvocation calleeInvocation) {
    StructuredGraph callerGraph = callerCallsiteHolder.graph();
    InlineInfo calleeInfo = calleeInvocation.callee();
    try {
        try (DebugContext.Scope scope = debug.scope("doInline", callerGraph)) {
            EconomicSet<Node> canonicalizedNodes = EconomicSet.create(Equivalence.IDENTITY);
            canonicalizedNodes.addAll(calleeInfo.invoke().asNode().usages());
            EconomicSet<Node> parameterUsages = calleeInfo.inline(new Providers(context));
            canonicalizedNodes.addAll(parameterUsages);
            counterInliningRuns.increment(debug);
            debug.dump(DebugContext.DETAILED_LEVEL, callerGraph, "after %s", calleeInfo);
            Graph.Mark markBeforeCanonicalization = callerGraph.getMark();
            canonicalizer.applyIncremental(callerGraph, context, canonicalizedNodes);
            // process invokes that are possibly created during canonicalization
            for (Node newNode : callerGraph.getNewNodes(markBeforeCanonicalization)) {
                if (newNode instanceof Invoke) {
                    callerCallsiteHolder.pushInvoke((Invoke) newNode);
                }
            }
            callerCallsiteHolder.computeProbabilities();
            counterInliningPerformed.increment(debug);
        }
    } catch (BailoutException bailout) {
        throw bailout;
    } catch (AssertionError | RuntimeException e) {
        throw new GraalError(e).addContext(calleeInfo.toString());
    } catch (GraalError e) {
        throw e.addContext(calleeInfo.toString());
    } catch (Throwable e) {
        throw debug.handle(e);
    }
}
Also used : AllocatedObjectNode(org.graalvm.compiler.nodes.virtual.AllocatedObjectNode) ParameterNode(org.graalvm.compiler.nodes.ParameterNode) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) AbstractNewObjectNode(org.graalvm.compiler.nodes.java.AbstractNewObjectNode) CallTargetNode(org.graalvm.compiler.nodes.CallTargetNode) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Node(org.graalvm.compiler.graph.Node) TypeGuardInlineInfo(org.graalvm.compiler.phases.common.inlining.info.TypeGuardInlineInfo) AssumptionInlineInfo(org.graalvm.compiler.phases.common.inlining.info.AssumptionInlineInfo) InlineInfo(org.graalvm.compiler.phases.common.inlining.info.InlineInfo) ExactInlineInfo(org.graalvm.compiler.phases.common.inlining.info.ExactInlineInfo) MultiTypeGuardInlineInfo(org.graalvm.compiler.phases.common.inlining.info.MultiTypeGuardInlineInfo) DebugContext(org.graalvm.compiler.debug.DebugContext) Providers(org.graalvm.compiler.phases.util.Providers) Invoke(org.graalvm.compiler.nodes.Invoke) BailoutException(jdk.vm.ci.code.BailoutException) InlineableGraph(org.graalvm.compiler.phases.common.inlining.info.elem.InlineableGraph) Graph(org.graalvm.compiler.graph.Graph) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) GraalError(org.graalvm.compiler.debug.GraalError)

Example 17 with Invoke

use of org.graalvm.compiler.nodes.Invoke in project graal by oracle.

the class InliningData method processNextInvoke.

/**
 * This method picks one of the callsites belonging to the current
 * {@link CallsiteHolderExplorable}. Provided the callsite qualifies to be analyzed for
 * inlining, this method prepares a new stack top in {@link InliningData} for such callsite,
 * which comprises:
 * <ul>
 * <li>preparing a summary of feasible targets, ie preparing an {@link InlineInfo}</li>
 * <li>based on it, preparing the stack top proper which consists of:</li>
 * <ul>
 * <li>one {@link MethodInvocation}</li>
 * <li>a {@link CallsiteHolder} for each feasible target</li>
 * </ul>
 * </ul>
 *
 * <p>
 * The thus prepared "stack top" is needed by {@link #moveForward()} to explore the space of
 * inlining decisions (each decision one of: backtracking, delving, inlining).
 * </p>
 *
 * <p>
 * The {@link InlineInfo} used to get things rolling is kept around in the
 * {@link MethodInvocation}, it will be needed in case of inlining, see
 * {@link InlineInfo#inline(Providers)}
 * </p>
 */
private void processNextInvoke() {
    CallsiteHolderExplorable callsiteHolder = (CallsiteHolderExplorable) currentGraph();
    Invoke invoke = callsiteHolder.popInvoke();
    InlineInfo info = getInlineInfo(invoke);
    if (info != null) {
        info.populateInlinableElements(context, currentGraph().graph(), canonicalizer, rootGraph.getOptions());
        double invokeProbability = callsiteHolder.invokeProbability(invoke);
        double invokeRelevance = callsiteHolder.invokeRelevance(invoke);
        MethodInvocation methodInvocation = new MethodInvocation(info, invokeProbability, invokeRelevance, freshlyInstantiatedArguments(invoke, callsiteHolder.getFixedParams()));
        pushInvocationAndGraphs(methodInvocation);
    }
}
Also used : TypeGuardInlineInfo(org.graalvm.compiler.phases.common.inlining.info.TypeGuardInlineInfo) AssumptionInlineInfo(org.graalvm.compiler.phases.common.inlining.info.AssumptionInlineInfo) InlineInfo(org.graalvm.compiler.phases.common.inlining.info.InlineInfo) ExactInlineInfo(org.graalvm.compiler.phases.common.inlining.info.ExactInlineInfo) MultiTypeGuardInlineInfo(org.graalvm.compiler.phases.common.inlining.info.MultiTypeGuardInlineInfo) Invoke(org.graalvm.compiler.nodes.Invoke)

Example 18 with Invoke

use of org.graalvm.compiler.nodes.Invoke in project graal by oracle.

the class ArrayCopyIntrinsificationTest method getCode.

@Override
protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph g, boolean forceCompile, boolean installAsDefault, OptionValues options) {
    StructuredGraph graph = g == null ? parseForCompile(method) : g;
    int nodeCount = graph.getNodeCount();
    InstalledCode result = super.getCode(method, graph, forceCompile, installAsDefault, options);
    boolean graphWasProcessed = nodeCount != graph.getNodeCount();
    if (graphWasProcessed) {
        if (mustIntrinsify) {
            for (Node node : graph.getNodes()) {
                if (node instanceof Invoke) {
                    Invoke invoke = (Invoke) node;
                    Assert.assertTrue(invoke.callTarget() instanceof DirectCallTargetNode);
                    LoweredCallTargetNode directCall = (LoweredCallTargetNode) invoke.callTarget();
                    JavaMethod callee = directCall.targetMethod();
                    if (callee.getDeclaringClass().equals(getMetaAccess().lookupJavaType(System.class)) && callee.getName().equals("arraycopy")) {
                    // A partial snippet (e.g., ArrayCopySnippets.checkcastArraycopy) may
                    // call the original arraycopy method
                    } else {
                        Assert.assertTrue(callee.toString(), callee.getName().equals("<init>"));
                        Assert.assertTrue(getMetaAccess().lookupJavaType(ArrayIndexOutOfBoundsException.class).equals(callee.getDeclaringClass()) || getMetaAccess().lookupJavaType(NullPointerException.class).equals(callee.getDeclaringClass()));
                    }
                }
            }
        } else {
            boolean found = false;
            for (Node node : graph.getNodes()) {
                if (node instanceof Invoke) {
                    Invoke invoke = (Invoke) node;
                    LoweredCallTargetNode directCall = (LoweredCallTargetNode) invoke.callTarget();
                    JavaMethod callee = directCall.targetMethod();
                    if (callee.getDeclaringClass().equals(getMetaAccess().lookupJavaType(System.class)) && callee.getName().equals("arraycopy")) {
                        found = true;
                    } else {
                        fail("found invoke to some method other than arraycopy: " + callee);
                    }
                }
            }
            Assert.assertTrue("did not find invoke to arraycopy", found);
        }
    }
    return result;
}
Also used : StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) DirectCallTargetNode(org.graalvm.compiler.nodes.DirectCallTargetNode) LoweredCallTargetNode(org.graalvm.compiler.nodes.LoweredCallTargetNode) Node(org.graalvm.compiler.graph.Node) DirectCallTargetNode(org.graalvm.compiler.nodes.DirectCallTargetNode) InstalledCode(jdk.vm.ci.code.InstalledCode) JavaMethod(jdk.vm.ci.meta.JavaMethod) ResolvedJavaMethod(jdk.vm.ci.meta.ResolvedJavaMethod) LoweredCallTargetNode(org.graalvm.compiler.nodes.LoweredCallTargetNode) Invoke(org.graalvm.compiler.nodes.Invoke)

Example 19 with Invoke

use of org.graalvm.compiler.nodes.Invoke in project graal by oracle.

the class IntrinsifyMethodHandlesInvocationPlugin method processInvokeWithMethodHandle.

@SuppressWarnings("try")
private void processInvokeWithMethodHandle(GraphBuilderContext b, BytecodeProvider bytecodeProvider, ResolvedJavaMethod methodHandleMethod, ValueNode[] methodHandleArguments) {
    Plugins graphBuilderPlugins = new Plugins(((ReplacementsImpl) originalProviders.getReplacements()).getGraphBuilderPlugins());
    registerInvocationPlugins(graphBuilderPlugins.getInvocationPlugins(), bytecodeProvider);
    graphBuilderPlugins.prependParameterPlugin(new MethodHandlesParameterPlugin(methodHandleArguments));
    graphBuilderPlugins.clearInlineInvokePlugins();
    graphBuilderPlugins.prependInlineInvokePlugin(new MethodHandlesInlineInvokePlugin());
    graphBuilderPlugins.prependNodePlugin(new MethodHandlePlugin(originalProviders.getConstantReflection().getMethodHandleAccess(), false));
    /* We do all the word type rewriting because parameters to the lambda can be word types. */
    SnippetReflectionProvider originalSnippetReflection = GraalAccess.getOriginalSnippetReflection();
    WordOperationPlugin wordOperationPlugin = new WordOperationPlugin(originalSnippetReflection, new WordTypes(originalProviders.getMetaAccess(), FrameAccess.getWordKind()));
    graphBuilderPlugins.appendInlineInvokePlugin(wordOperationPlugin);
    graphBuilderPlugins.appendTypePlugin(wordOperationPlugin);
    graphBuilderPlugins.appendTypePlugin(new TrustedInterfaceTypePlugin());
    graphBuilderPlugins.appendNodePlugin(wordOperationPlugin);
    GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getSnippetDefault(graphBuilderPlugins);
    GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(originalProviders.getMetaAccess(), originalProviders.getStampProvider(), originalProviders.getConstantReflection(), originalProviders.getConstantFieldProvider(), graphBuilderConfig, OptimisticOptimizations.NONE, null);
    DebugContext debug = b.getDebug();
    StructuredGraph graph = new StructuredGraph.Builder(b.getOptions(), debug).method(toOriginal(methodHandleMethod)).build();
    try (DebugContext.Scope s = debug.scope("IntrinsifyMethodHandles", graph)) {
        graphBuilder.apply(graph);
        /*
             * We do not care about the improved type information from Pi nodes, so we just delete
             * them to simplify our graph.
             */
        for (PiNode pi : graph.getNodes(PiNode.TYPE)) {
            pi.replaceAndDelete(pi.object());
        }
        /*
             * Support for MethodHandle that adapt the input type to a more generic type, i.e., a
             * MethodHandle that does a dynamic type check on a parameter.
             */
        for (UnaryOpLogicNode node : graph.getNodes().filter(UnaryOpLogicNode.class).filter(v -> v instanceof IsNullNode || v instanceof InstanceOfNode)) {
            ValueNode value = node.getValue();
            if (value instanceof ParameterNode) {
                /*
                     * We just assume that the InstanceOfNode or IsNullNode are used in an If and
                     * the true-successor is actually the branch we want. If that assumption is
                     * wrong, nothing bad happens - we will just continue to report the invocation
                     * as unsupported because the updated stamp for the parameter will not simplify
                     * the graph.
                     */
                if (node instanceof InstanceOfNode) {
                    InstanceOfNode inst = (InstanceOfNode) node;
                    TypeReference typeRef = inst.type();
                    value.setStamp(new ObjectStamp(typeRef.getType(), typeRef.isExact(), !inst.allowsNull(), false));
                } else {
                    assert node instanceof IsNullNode;
                    ResolvedJavaType type = value.stamp(NodeView.DEFAULT).javaType(originalProviders.getMetaAccess());
                    value.setStamp(new ObjectStamp(type, false, /* non-null */
                    true, false));
                }
            }
        }
        /*
             * The canonicalizer converts unsafe field accesses for get/set method handles back to
             * high-level field load and store nodes.
             */
        new CanonicalizerPhase().apply(graph, new PhaseContext(originalProviders));
        for (FixedGuardNode guard : graph.getNodes(FixedGuardNode.TYPE)) {
            if (guard.next() instanceof AccessFieldNode && guard.condition() instanceof IsNullNode && guard.isNegated() && ((IsNullNode) guard.condition()).getValue() == ((AccessFieldNode) guard.next()).object()) {
                /*
                     * Method handles to load and stores fields have null checks. Remove them, since
                     * the null check is implicitly done by the field access.
                     */
                GraphUtil.removeFixedWithUnusedInputs(guard);
            }
        }
        debug.dump(DebugContext.VERY_DETAILED_LEVEL, graph, "Final intrinisfication graph");
        /*
             * After parsing (and recursive inlining during parsing), the graph must contain only
             * one invocation (and therefore only one MethodCallTargetNode), plus the parameters,
             * constants, start, and return nodes.
             */
        Node singleFunctionality = null;
        ReturnNode singleReturn = null;
        for (Node node : graph.getNodes()) {
            if (node == graph.start() || node instanceof ParameterNode || node instanceof ConstantNode || node instanceof FrameState) {
                /* Ignore the allowed framework around the nodes we care about. */
                continue;
            } else if (node instanceof Invoke) {
                /* We check the MethodCallTargetNode, so we can ignore the invoke. */
                continue;
            } else if ((node instanceof MethodCallTargetNode || node instanceof LoadFieldNode || node instanceof StoreFieldNode) && singleFunctionality == null) {
                singleFunctionality = node;
                continue;
            } else if (node instanceof ReturnNode && singleReturn == null) {
                singleReturn = (ReturnNode) node;
                continue;
            }
            throw new UnsupportedFeatureException("Invoke with MethodHandle argument could not be reduced to at most a single call: " + methodHandleMethod.format("%H.%n(%p)"));
        }
        if (singleFunctionality instanceof MethodCallTargetNode) {
            MethodCallTargetNode singleCallTarget = (MethodCallTargetNode) singleFunctionality;
            assert singleReturn.result() == null || singleReturn.result() == singleCallTarget.invoke();
            /*
                 * Replace the originalTarget with the replacementTarget. Note that the
                 * replacementTarget node belongs to a different graph than originalTarget, so we
                 * need to match parameter back to the original graph and allocate a new
                 * MethodCallTargetNode for the original graph.
                 */
            ValueNode[] replacedArguments = new ValueNode[singleCallTarget.arguments().size()];
            for (int i = 0; i < replacedArguments.length; i++) {
                replacedArguments[i] = lookup(b, methodHandleArguments, singleCallTarget.arguments().get(i));
            }
            b.handleReplacedInvoke(singleCallTarget.invokeKind(), lookup(singleCallTarget.targetMethod()), replacedArguments, false);
        } else if (singleFunctionality instanceof LoadFieldNode) {
            LoadFieldNode fieldLoad = (LoadFieldNode) singleFunctionality;
            b.addPush(b.getInvokeReturnType().getJavaKind(), LoadFieldNode.create(null, lookup(b, methodHandleArguments, fieldLoad.object()), lookup(fieldLoad.field())));
        } else if (singleFunctionality instanceof StoreFieldNode) {
            StoreFieldNode fieldStore = (StoreFieldNode) singleFunctionality;
            b.add(new StoreFieldNode(lookup(b, methodHandleArguments, fieldStore.object()), lookup(fieldStore.field()), lookup(b, methodHandleArguments, fieldStore.value())));
        } else if (singleReturn.result() != null) {
            /* Replace the invocation with he constant result. */
            JavaConstant constantResult = singleReturn.result().asJavaConstant();
            assert b.getInvokeReturnType().getJavaKind() == constantResult.getJavaKind();
            b.addPush(constantResult.getJavaKind(), ConstantNode.forConstant(lookup(constantResult), universeProviders.getMetaAccess()));
        } else {
            /* No invoke and no return value, so nothing to do. */
            assert b.getInvokeReturnType().getJavaKind() == JavaKind.Void;
        }
    } catch (Throwable ex) {
        throw debug.handle(ex);
    }
}
Also used : ObjectStamp(org.graalvm.compiler.core.common.type.ObjectStamp) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) AccessFieldNode(org.graalvm.compiler.nodes.java.AccessFieldNode) ReturnNode(org.graalvm.compiler.nodes.ReturnNode) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) PiNode(org.graalvm.compiler.nodes.PiNode) UnaryOpLogicNode(org.graalvm.compiler.nodes.UnaryOpLogicNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) IsNullNode(org.graalvm.compiler.nodes.calc.IsNullNode) FloatingNode(org.graalvm.compiler.nodes.calc.FloatingNode) LoadFieldNode(org.graalvm.compiler.nodes.java.LoadFieldNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) InstanceOfNode(org.graalvm.compiler.nodes.java.InstanceOfNode) ParameterNode(org.graalvm.compiler.nodes.ParameterNode) StoreFieldNode(org.graalvm.compiler.nodes.java.StoreFieldNode) Node(org.graalvm.compiler.graph.Node) WordTypes(org.graalvm.compiler.word.WordTypes) JavaConstant(jdk.vm.ci.meta.JavaConstant) PiNode(org.graalvm.compiler.nodes.PiNode) FrameState(org.graalvm.compiler.nodes.FrameState) UnaryOpLogicNode(org.graalvm.compiler.nodes.UnaryOpLogicNode) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) Invoke(org.graalvm.compiler.nodes.Invoke) PhaseContext(org.graalvm.compiler.phases.tiers.PhaseContext) SnippetReflectionProvider(org.graalvm.compiler.api.replacements.SnippetReflectionProvider) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) ParameterNode(org.graalvm.compiler.nodes.ParameterNode) TypeReference(org.graalvm.compiler.core.common.type.TypeReference) GraphBuilderPhase(org.graalvm.compiler.java.GraphBuilderPhase) InvocationPlugins(org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins) Plugins(org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins) StoreFieldNode(org.graalvm.compiler.nodes.java.StoreFieldNode) UnsupportedFeatureException(com.oracle.graal.pointsto.constraints.UnsupportedFeatureException) GraphBuilderConfiguration(org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration) DebugContext(org.graalvm.compiler.debug.DebugContext) LoadFieldNode(org.graalvm.compiler.nodes.java.LoadFieldNode) TrustedInterfaceTypePlugin(com.oracle.svm.core.graal.phases.TrustedInterfaceTypePlugin) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) ReturnNode(org.graalvm.compiler.nodes.ReturnNode) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) IsNullNode(org.graalvm.compiler.nodes.calc.IsNullNode) AccessFieldNode(org.graalvm.compiler.nodes.java.AccessFieldNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) CanonicalizerPhase(org.graalvm.compiler.phases.common.CanonicalizerPhase) InstanceOfNode(org.graalvm.compiler.nodes.java.InstanceOfNode) MethodHandlePlugin(org.graalvm.compiler.replacements.MethodHandlePlugin) WordOperationPlugin(org.graalvm.compiler.word.WordOperationPlugin)

Example 20 with Invoke

use of org.graalvm.compiler.nodes.Invoke in project graal by oracle.

the class DevirtualizeCallsPhase method run.

@Override
protected void run(StructuredGraph graph) {
    for (Invoke invoke : graph.getInvokes()) {
        if (invoke.callTarget() instanceof SubstrateMethodCallTargetNode) {
            SubstrateMethodCallTargetNode callTarget = (SubstrateMethodCallTargetNode) invoke.callTarget();
            JavaMethodProfile methodProfile = callTarget.getMethodProfile();
            if (methodProfile != null) {
                if (methodProfile.getMethods().length == 0) {
                    unreachableInvoke(graph, invoke, callTarget);
                } else if (methodProfile.getMethods().length == 1) {
                    if (callTarget.invokeKind().isIndirect()) {
                        singleCallee((HostedMethod) methodProfile.getMethods()[0].getMethod(), graph, invoke, callTarget);
                    }
                }
            }
        }
    }
}
Also used : HostedMethod(com.oracle.svm.hosted.meta.HostedMethod) SubstrateMethodCallTargetNode(com.oracle.svm.hosted.nodes.SubstrateMethodCallTargetNode) JavaMethodProfile(jdk.vm.ci.meta.JavaMethodProfile) Invoke(org.graalvm.compiler.nodes.Invoke)

Aggregations

Invoke (org.graalvm.compiler.nodes.Invoke)49 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)19 Node (org.graalvm.compiler.graph.Node)17 MethodCallTargetNode (org.graalvm.compiler.nodes.java.MethodCallTargetNode)17 ValueNode (org.graalvm.compiler.nodes.ValueNode)16 FixedNode (org.graalvm.compiler.nodes.FixedNode)13 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)12 ResolvedJavaMethod (jdk.vm.ci.meta.ResolvedJavaMethod)10 FrameState (org.graalvm.compiler.nodes.FrameState)10 DebugContext (org.graalvm.compiler.debug.DebugContext)9 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)9 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)9 CanonicalizerPhase (org.graalvm.compiler.phases.common.CanonicalizerPhase)8 DeoptimizeNode (org.graalvm.compiler.nodes.DeoptimizeNode)7 EndNode (org.graalvm.compiler.nodes.EndNode)7 GraalError (org.graalvm.compiler.debug.GraalError)6 ParameterNode (org.graalvm.compiler.nodes.ParameterNode)6 ArrayList (java.util.ArrayList)5 ResolvedJavaField (jdk.vm.ci.meta.ResolvedJavaField)5 ResolvedJavaType (jdk.vm.ci.meta.ResolvedJavaType)5