# HG changeset patch # User Doug Simon # Date 1389561627 -3600 # Node ID 82fc603fcc05873ff8aae7f543c5e2119f2e4f88 # Parent 565bf188d39b5afeea1128b27d5487c2c75112f9 refactored ForeignCallStub.GraphBuilder into top level GraphKit class diff -r 565bf188d39b -r 82fc603fcc05 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java --- 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 add(T node) { - return graph.unique(node); - } - - 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. *

@@ -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 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); - } } diff -r 565bf188d39b -r 82fc603fcc05 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/GraphKit.java --- /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 unique(T node) { + return graph.unique(node); + } + + /** + * Appends a fixed node to the graph. + */ + 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); + } +}