view graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java @ 11700:528ab536b403

changed iteration over InvokeNodes in a graph to avoid Graph.getNodes() (GRAAL-471)
author Doug Simon <doug.simon@oracle.com>
date Wed, 18 Sep 2013 10:31:34 +0200
parents 0d3b767e5356
children 03c781923573
line wrap: on
line source

/*
 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.oracle.graal.replacements.nodes;

import java.lang.reflect.*;

import com.oracle.graal.api.meta.*;
import com.oracle.graal.graph.*;
import com.oracle.graal.nodes.*;
import com.oracle.graal.nodes.extended.*;
import com.oracle.graal.nodes.java.*;
import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
import com.oracle.graal.nodes.spi.*;
import com.oracle.graal.phases.common.*;

public class MacroNode extends AbstractStateSplit implements Lowerable, MemoryCheckpoint.Single {

    @Input protected final NodeInputList<ValueNode> arguments;

    private final int bci;
    private final ResolvedJavaMethod targetMethod;
    private final JavaType returnType;

    protected MacroNode(Invoke invoke) {
        super(invoke.asNode().stamp(), invoke.stateAfter());
        MethodCallTargetNode methodCallTarget = (MethodCallTargetNode) invoke.callTarget();
        this.arguments = new NodeInputList<>(this, methodCallTarget.arguments());
        this.bci = invoke.bci();
        this.targetMethod = methodCallTarget.targetMethod();
        this.returnType = methodCallTarget.returnType();
    }

    public int getBci() {
        return bci;
    }

    public ResolvedJavaMethod getTargetMethod() {
        return targetMethod;
    }

    public JavaType getReturnType() {
        return returnType;
    }

    /**
     * Gets a snippet to be used for lowering this macro node.
     */
    @SuppressWarnings("unused")
    protected StructuredGraph getSnippetGraph(LoweringTool tool) {
        return null;
    }

    /**
     * Gets a normal method substitution to be used for lowering this macro node. This is only
     * called if {@link #getSnippetGraph(LoweringTool)} return nulls.
     */
    protected StructuredGraph getSubstitutionGraph(LoweringTool tool) {
        return tool.getReplacements().getMethodSubstitution(getTargetMethod());
    }

    @Override
    public void lower(LoweringTool tool) {
        boolean nullCheck = false;
        StructuredGraph replacementGraph = getSnippetGraph(tool);
        if (replacementGraph == null) {
            replacementGraph = getSubstitutionGraph(tool);
            nullCheck = true;
        }

        InvokeNode invoke = replaceWithInvoke();
        assert invoke.verify();

        if (replacementGraph != null) {
            InliningUtil.inline(invoke, replacementGraph, nullCheck);
        }
    }

    private InvokeNode replaceWithInvoke() {
        InvokeNode invoke = createInvoke();
        graph().replaceFixedWithFixed(this, invoke);
        return invoke;
    }

    protected InvokeNode createInvoke() {
        InvokeKind invokeKind = Modifier.isStatic(targetMethod.getModifiers()) ? InvokeKind.Static : InvokeKind.Special;
        MethodCallTargetNode callTarget = graph().add(new MethodCallTargetNode(invokeKind, targetMethod, arguments.toArray(new ValueNode[arguments.size()]), returnType));
        InvokeNode invoke = graph().add(new InvokeNode(callTarget, bci));
        invoke.setStateAfter(stateAfter());
        return invoke;
    }

    protected void replaceSnippetInvokes(StructuredGraph snippetGraph) {
        for (MethodCallTargetNode call : snippetGraph.getNodes(MethodCallTargetNode.class)) {
            Invoke invoke = call.invoke();
            if (call.targetMethod() != getTargetMethod()) {
                throw new GraalInternalError("unexpected invoke %s in snippet", getClass().getSimpleName());
            }
            if (invoke.stateAfter().bci == FrameState.INVALID_FRAMESTATE_BCI) {
                InvokeNode newInvoke = snippetGraph.add(new InvokeNode(invoke.callTarget(), getBci()));
                newInvoke.setStateAfter(snippetGraph.add(new FrameState(FrameState.AFTER_BCI)));
                snippetGraph.replaceFixedWithFixed((InvokeNode) invoke.asNode(), newInvoke);
            } else {
                assert invoke.stateAfter().bci == FrameState.AFTER_BCI : invoke;
            }
        }
    }

    @Override
    public LocationIdentity getLocationIdentity() {
        return LocationIdentity.ANY_LOCATION;
    }
}