changeset 13598:82fc603fcc05

refactored ForeignCallStub.GraphBuilder into top level GraphKit class
author Doug Simon <doug.simon@oracle.com>
date Sun, 12 Jan 2014 22:20:27 +0100
parents 565bf188d39b
children 29b1b216d20a 8c019a9beb16
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/GraphKit.java
diffstat 2 files changed, 186 insertions(+), 102 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Sun Jan 12 20:25:33 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Sun Jan 12 22:20:27 2014 +0100
@@ -26,10 +26,6 @@
 import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*;
 
-import java.lang.reflect.*;
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.hotspot.*;
@@ -38,15 +34,9 @@
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.phases.common.*;
-import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
-import com.oracle.graal.word.phases.*;
 
 /**
  * A {@linkplain #getGraph() generated} stub for a {@link Transition non-leaf} foreign call from
@@ -146,35 +136,6 @@
         };
     }
 
-    static class GraphBuilder {
-
-        public GraphBuilder(Stub stub) {
-            this.graph = new StructuredGraph(stub.toString(), null);
-            graph.replaceFixed(graph.start(), graph.add(new StubStartNode(stub)));
-            this.lastFixedNode = graph.start();
-        }
-
-        final StructuredGraph graph;
-        private FixedWithNextNode lastFixedNode;
-
-        <T extends FloatingNode> T add(T node) {
-            return graph.unique(node);
-        }
-
-        <T extends FixedNode> T append(T node) {
-            T result = graph.add(node);
-            assert lastFixedNode != null;
-            assert result.predecessor() == null;
-            graph.addAfterFixed(lastFixedNode, result);
-            if (result instanceof FixedWithNextNode) {
-                lastFixedNode = (FixedWithNextNode) result;
-            } else {
-                lastFixedNode = null;
-            }
-            return result;
-        }
-    }
-
     /**
      * Creates a graph for this stub.
      * <p>
@@ -222,43 +183,37 @@
     protected StructuredGraph getGraph() {
         Class<?>[] args = linkage.getDescriptor().getArgumentTypes();
         boolean isObjectResult = linkage.getOutgoingCallingConvention().getReturn().getKind() == Kind.Object;
-        GraphBuilder builder = new GraphBuilder(this);
-        LocalNode[] locals = createLocals(builder, args);
-        List<InvokeNode> invokes = new ArrayList<>(3);
+
+        StructuredGraph graph = new StructuredGraph(toString(), null);
+        graph.replaceFixed(graph.start(), graph.add(new StubStartNode(this)));
+
+        GraphKit kit = new GraphKit(graph, providers);
+        LocalNode[] locals = createLocals(kit, args);
 
-        ReadRegisterNode thread = builder.append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), true, false));
-        ValueNode result = createTargetCall(builder, locals, thread);
-        invokes.add(createInvoke(builder, StubUtil.class, "handlePendingException", thread, ConstantNode.forBoolean(isObjectResult, builder.graph)));
+        ReadRegisterNode thread = kit.append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), true, false));
+        ValueNode result = createTargetCall(kit, locals, thread);
+        kit.createInvoke(StubUtil.class, "handlePendingException", thread, ConstantNode.forBoolean(isObjectResult, graph));
         if (isObjectResult) {
-            InvokeNode object = createInvoke(builder, HotSpotReplacementsUtil.class, "getAndClearObjectResult", thread);
-            result = createInvoke(builder, StubUtil.class, "verifyObject", object);
-            invokes.add(object);
-            invokes.add((InvokeNode) result);
+            InvokeNode object = kit.createInvoke(HotSpotReplacementsUtil.class, "getAndClearObjectResult", thread);
+            result = kit.createInvoke(StubUtil.class, "verifyObject", object);
         }
-        builder.append(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result));
+        kit.append(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result));
 
         if (Debug.isDumpEnabled()) {
-            Debug.dump(builder.graph, "Initial stub graph");
+            Debug.dump(graph, "Initial stub graph");
         }
 
-        /* Rewrite all word types that can come in from the method argument types. */
-        new WordTypeRewriterPhase(providers.getMetaAccess(), providers.getCodeCache().getTarget().wordKind).apply(builder.graph);
-        /* Inline all method calls that are create above. */
-        for (InvokeNode invoke : invokes) {
-            inline(invoke);
-        }
-        /* Clean up all code that is now dead after inlining. */
-        new DeadCodeEliminationPhase().apply(builder.graph);
-        assert builder.graph.getNodes().filter(InvokeNode.class).isEmpty();
+        kit.rewriteWordTypes();
+        kit.inlineInvokes();
 
         if (Debug.isDumpEnabled()) {
-            Debug.dump(builder.graph, "Stub graph before compilation");
+            Debug.dump(graph, "Stub graph before compilation");
         }
 
-        return builder.graph;
+        return graph;
     }
 
-    private LocalNode[] createLocals(GraphBuilder builder, Class<?>[] args) {
+    private LocalNode[] createLocals(GraphKit kit, Class<?>[] args) {
         LocalNode[] locals = new LocalNode[args.length];
         ResolvedJavaType accessingClass = providers.getMetaAccess().lookupJavaType(getClass());
         for (int i = 0; i < args.length; i++) {
@@ -270,55 +225,20 @@
             } else {
                 stamp = StampFactory.forKind(type.getKind());
             }
-            LocalNode local = builder.add(new LocalNode(i, stamp));
+            LocalNode local = kit.unique(new LocalNode(i, stamp));
             locals[i] = local;
         }
         return locals;
     }
 
-    private InvokeNode createInvoke(GraphBuilder builder, Class<?> declaringClass, String name, ValueNode... args) {
-        ResolvedJavaMethod method = null;
-        for (Method m : declaringClass.getDeclaredMethods()) {
-            if (Modifier.isStatic(m.getModifiers()) && m.getName().equals(name)) {
-                assert method == null : "found more than one method in " + declaringClass + " named " + name;
-                method = providers.getMetaAccess().lookupJavaMethod(m);
-            }
-        }
-        assert method != null : "did not find method in " + declaringClass + " named " + name;
-        Signature signature = method.getSignature();
-        JavaType returnType = signature.getReturnType(null);
-        assert checkArgs(method, args);
-        MethodCallTargetNode callTarget = builder.graph.add(new MethodCallTargetNode(InvokeKind.Static, method, args, returnType));
-        InvokeNode invoke = builder.append(new InvokeNode(callTarget, FrameState.UNKNOWN_BCI));
-        return invoke;
-    }
-
-    private boolean checkArgs(ResolvedJavaMethod method, ValueNode... args) {
-        Signature signature = method.getSignature();
-        assert signature.getParameterCount(false) == args.length : target + ": wrong number of arguments to " + method;
-        for (int i = 0; i != args.length; i++) {
-            Kind expected = signature.getParameterKind(i).getStackKind();
-            Kind actual = args[i].stamp().kind();
-            assert expected == actual : target + ": wrong kind of value for argument " + i + " of calls to " + method + " [" + actual + " != " + expected + "]";
-        }
-        return true;
-    }
-
-    private StubForeignCallNode createTargetCall(GraphBuilder builder, LocalNode[] locals, ReadRegisterNode thread) {
+    private StubForeignCallNode createTargetCall(GraphKit kit, LocalNode[] locals, ReadRegisterNode thread) {
         if (prependThread) {
             ValueNode[] targetArguments = new ValueNode[1 + locals.length];
             targetArguments[0] = thread;
             System.arraycopy(locals, 0, targetArguments, 1, locals.length);
-            return builder.append(new StubForeignCallNode(providers.getForeignCalls(), target.getDescriptor(), targetArguments));
+            return kit.append(new StubForeignCallNode(providers.getForeignCalls(), target.getDescriptor(), targetArguments));
         } else {
-            return builder.append(new StubForeignCallNode(providers.getForeignCalls(), target.getDescriptor(), locals));
+            return kit.append(new StubForeignCallNode(providers.getForeignCalls(), target.getDescriptor(), locals));
         }
     }
-
-    private void inline(InvokeNode invoke) {
-        ResolvedJavaMethod method = ((MethodCallTargetNode) invoke.callTarget()).targetMethod();
-        ReplacementsImpl repl = new ReplacementsImpl(providers, new Assumptions(false), providers.getCodeCache().getTarget());
-        StructuredGraph calleeGraph = repl.makeGraph(method, null, null, false);
-        InliningUtil.inline(invoke, calleeGraph, false);
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/GraphKit.java	Sun Jan 12 22:20:27 2014 +0100
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2014, 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.hotspot.stubs;
+
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.util.*;
+import com.oracle.graal.replacements.*;
+import com.oracle.graal.word.phases.*;
+
+/**
+ * A utility for manually creating a graph. This will be expanded as necessary to support all
+ * subsystems that employ manual graph creation (as opposed to {@linkplain GraphBuilderPhase
+ * bytecode parsing} based graph creation).
+ */
+public class GraphKit {
+
+    private final Providers providers;
+    private final StructuredGraph graph;
+    private FixedWithNextNode lastFixedNode;
+
+    public GraphKit(StructuredGraph graph, Providers providers) {
+        this.providers = providers;
+        this.graph = graph;
+        this.lastFixedNode = graph.start();
+    }
+
+    public StructuredGraph getGraph() {
+        return graph;
+    }
+
+    /**
+     * Ensures a floating node is added to or already present in the graph via {@link Graph#unique}.
+     * 
+     * @return a node similar to {@code node} if one exists, otherwise {@code node}
+     */
+    <T extends FloatingNode> T unique(T node) {
+        return graph.unique(node);
+    }
+
+    /**
+     * Appends a fixed node to the graph.
+     */
+    <T extends FixedNode> T append(T node) {
+        T result = graph.add(node);
+        assert lastFixedNode != null;
+        assert result.predecessor() == null;
+        graph.addAfterFixed(lastFixedNode, result);
+        if (result instanceof FixedWithNextNode) {
+            lastFixedNode = (FixedWithNextNode) result;
+        } else {
+            lastFixedNode = null;
+        }
+        return result;
+    }
+
+    /**
+     * Creates and appends an {@link InvokeNode} for a call to a given method with a given set of
+     * arguments.
+     * 
+     * @param declaringClass the class declaring the invoked method
+     * @param name the name of the invoked method
+     * @param args the arguments to the invocation
+     */
+    public InvokeNode createInvoke(Class<?> declaringClass, String name, ValueNode... args) {
+        ResolvedJavaMethod method = null;
+        for (Method m : declaringClass.getDeclaredMethods()) {
+            if (Modifier.isStatic(m.getModifiers()) && m.getName().equals(name)) {
+                assert method == null : "found more than one method in " + declaringClass + " named " + name;
+                method = providers.getMetaAccess().lookupJavaMethod(m);
+            }
+        }
+        assert method != null : "did not find method in " + declaringClass + " named " + name;
+        Signature signature = method.getSignature();
+        JavaType returnType = signature.getReturnType(null);
+        assert checkArgs(method, args);
+        MethodCallTargetNode callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, method, args, returnType));
+        InvokeNode invoke = append(new InvokeNode(callTarget, FrameState.UNKNOWN_BCI));
+        return invoke;
+    }
+
+    /**
+     * Determines if a given set of arguments is compatible with the signature of a given method.
+     * 
+     * @return true if {@code args} are compatible with the signature if {@code method}
+     * @throws AssertionError if {@code args} are not compatible with the signature if
+     *             {@code method}
+     */
+    public boolean checkArgs(ResolvedJavaMethod method, ValueNode... args) {
+        Signature signature = method.getSignature();
+        if (signature.getParameterCount(false) != args.length) {
+            throw new AssertionError(graph + ": wrong number of arguments to " + method);
+        }
+        for (int i = 0; i != args.length; i++) {
+            Kind expected = signature.getParameterKind(i).getStackKind();
+            Kind actual = args[i].stamp().kind();
+            if (expected != actual) {
+                throw new AssertionError(graph + ": wrong kind of value for argument " + i + " of calls to " + method + " [" + actual + " != " + expected + "]");
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Rewrite all word types in the graph.
+     */
+    public void rewriteWordTypes() {
+        new WordTypeRewriterPhase(providers.getMetaAccess(), providers.getCodeCache().getTarget().wordKind).apply(graph);
+    }
+
+    /**
+     * {@linkplain #inline(InvokeNode) Inlines} all invocations currently in the graph.
+     */
+    public void inlineInvokes() {
+        for (InvokeNode invoke : graph.getNodes().filter(InvokeNode.class).snapshot()) {
+            inline(invoke);
+        }
+
+        // Clean up all code that is now dead after inlining.
+        new DeadCodeEliminationPhase().apply(graph);
+        assert graph.getNodes().filter(InvokeNode.class).isEmpty();
+    }
+
+    /**
+     * Inlines a given invocation to a method. The graph of the inlined method is
+     * {@linkplain ReplacementsImpl#makeGraph processed} in the same manner as for snippets and
+     * method substitutions.
+     */
+    public void inline(InvokeNode invoke) {
+        ResolvedJavaMethod method = ((MethodCallTargetNode) invoke.callTarget()).targetMethod();
+        ReplacementsImpl repl = new ReplacementsImpl(providers, new Assumptions(false), providers.getCodeCache().getTarget());
+        StructuredGraph calleeGraph = repl.makeGraph(method, null, null, false);
+        InliningUtil.inline(invoke, calleeGraph, false);
+    }
+}