# HG changeset patch # User Christian Humer # Date 1387146761 -3600 # Node ID 652f24858aad19d70183faac69952c361015aec2 # Parent ecf152c6bd160cad1aaaf28605a8515e392b16f1 SL: simplified call nodes. aligned builtin inlining with user function inlining. diff -r ecf152c6bd16 -r 652f24858aad graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/CallNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/CallNode.java Sun Dec 15 22:43:45 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/CallNode.java Sun Dec 15 23:32:41 2013 +0100 @@ -34,127 +34,126 @@ private static final int INLINE_CACHE_SIZE = 2; @Child protected TypedNode functionNode; - - private CallNode(TypedNode functionNode) { - this.functionNode = adoptChild(functionNode); - } + @Child protected ArgumentsNode argumentsNode; - private CallTarget executeCallTargetNode(VirtualFrame frame) { - try { - return functionNode.executeCallTarget(frame); - } catch (UnexpectedResultException e) { - throw new UnsupportedOperationException("Call to " + e.getMessage() + " not supported."); - } + public CallNode(TypedNode functionNode, ArgumentsNode argumentsNode) { + this.functionNode = adoptChild(functionNode); + this.argumentsNode = adoptChild(argumentsNode); } @Override public final Object executeGeneric(VirtualFrame frame) { - return executeGeneric(frame, executeCallTargetNode(frame)); + CallTarget function; + try { + function = functionNode.executeCallTarget(frame); + } catch (UnexpectedResultException e) { + throw new UnsupportedOperationException("Call to " + e.getMessage() + " not supported."); + } + Object[] arguments = argumentsNode.executeArray(frame); + return executeCall(frame, function, arguments); } - public abstract Object executeGeneric(VirtualFrame frame, CallTarget function); + public abstract Object executeCall(VirtualFrame frame, CallTarget function, Object[] arguments); public static CallNode create(TypedNode function, TypedNode[] arguments) { return new UninitializedCallNode(function, new ArgumentsNode(arguments), 0); } - private static final class CachedCallNode extends CallNode { - - @Child protected CallNode nextNode; - @Child protected TypedNode currentNode; - private final CallTarget cachedFunction; - - public CachedCallNode(TypedNode function, TypedNode current, CallNode next, CallTarget cachedFunction) { - super(function); - this.currentNode = adoptChild(current); - this.nextNode = adoptChild(next); - this.cachedFunction = cachedFunction; - } - - @Override - public Object executeGeneric(VirtualFrame frame, CallTarget function) { - if (this.cachedFunction == function) { - return currentNode.executeGeneric(frame); - } - return nextNode.executeGeneric(frame, function); - } - } - private static final class UninitializedCallNode extends CallNode { - @Child protected ArgumentsNode uninitializedArgs; protected final int depth; UninitializedCallNode(TypedNode function, ArgumentsNode args, int depth) { - super(function); - this.uninitializedArgs = adoptChild(args); + super(function, args); this.depth = depth; } UninitializedCallNode(UninitializedCallNode copy) { - super(null); - this.uninitializedArgs = adoptChild(copy.uninitializedArgs); + super(null, null); this.depth = copy.depth + 1; } @Override - public Object executeGeneric(VirtualFrame frame, CallTarget function) { + public Object executeCall(VirtualFrame frame, CallTarget function, Object[] arguments) { CompilerDirectives.transferToInterpreter(); - return specialize(function).executeGeneric(frame, function); + return specialize(function).executeCall(frame, function, arguments); } private CallNode specialize(CallTarget function) { CompilerAsserts.neverPartOfCompilation(); if (depth < INLINE_CACHE_SIZE) { - TypedNode current = createCacheNode(function); + DefaultCallTarget callTarget = (DefaultCallTarget) function; + FunctionRootNode root = (FunctionRootNode) callTarget.getRootNode(); CallNode next = new UninitializedCallNode(this); - return replace(new CachedCallNode(this.functionNode, current, next, function)); + InlinableDirectCallNode directCall = new InlinableDirectCallNode(functionNode, argumentsNode, next, callTarget); + replace(directCall); + if (root.isInlineImmediatly()) { + return directCall.inlineImpl(); + } else { + return directCall; + } } else { - CallNode topMost = (CallNode) getTopNode(); - return topMost.replace(new GenericCallNode(topMost.functionNode, uninitializedArgs)); + CallNode topMost = (CallNode) NodeUtil.getNthParent(this, depth); + return topMost.replace(new GenericCallNode(topMost.functionNode, topMost.argumentsNode)); } } - protected Node getTopNode() { - Node parentNode = this; - for (int i = 0; i < depth; i++) { - parentNode = parentNode.getParent(); - } - return parentNode; + } + + private abstract static class DirectCallNode extends CallNode { + + protected final DefaultCallTarget cachedFunction; + + @Child protected CallNode nextNode; + + public DirectCallNode(TypedNode function, ArgumentsNode arguments, DefaultCallTarget cachedFunction, CallNode next) { + super(function, arguments); + this.cachedFunction = cachedFunction; + this.nextNode = adoptChild(next); } - protected TypedNode createCacheNode(CallTarget function) { - ArgumentsNode clonedArgs = NodeUtil.cloneNode(uninitializedArgs); + @Override + public Object executeCall(VirtualFrame frame, CallTarget function, Object[] arguments) { + if (this.cachedFunction == function) { + return executeCurrent(frame, arguments); + } + return nextNode.executeCall(frame, function, arguments); + } - if (function instanceof DefaultCallTarget) { - DefaultCallTarget defaultFunction = (DefaultCallTarget) function; - RootNode rootNode = defaultFunction.getRootNode(); - if (rootNode instanceof FunctionRootNode) { - FunctionRootNode root = (FunctionRootNode) rootNode; - if (root.isAlwaysInline()) { - TypedNode inlinedCall = root.inline(clonedArgs); - if (inlinedCall != null) { - return inlinedCall; - } - } - return new InlinableCallNode((DefaultCallTarget) function, clonedArgs); - } - // got a call target that is not inlinable (should not occur for SL) - return new DispatchedCallNode(defaultFunction, clonedArgs); - } else { - throw new AssertionError(); - } + protected abstract Object executeCurrent(VirtualFrame frame, Object[] arguments); - } } - private static final class InlinableCallNode extends DispatchedCallNode implements InlinableCallSite { + private static final class InlinableDirectCallNode extends DirectCallNode implements InlinableCallSite { @CompilationFinal private int callCount; - InlinableCallNode(DefaultCallTarget function, ArgumentsNode arguments) { - super(function, arguments); + InlinableDirectCallNode(TypedNode function, ArgumentsNode arguments, CallNode next, DefaultCallTarget cachedFunction) { + super(function, arguments, cachedFunction, next); + } + + @Override + public Object executeCurrent(VirtualFrame frame, Object[] arguments) { + if (CompilerDirectives.inInterpreter()) { + callCount++; + } + return cachedFunction.call(frame.pack(), new SLArguments(arguments)); + } + + InlinedDirectCallNode inlineImpl() { + CompilerAsserts.neverPartOfCompilation(); + RootNode root = cachedFunction.getRootNode(); + TypedNode inlinedNode = ((FunctionRootNode) root).inline(); + assert inlinedNode != null; + return replace(new InlinedDirectCallNode(this, inlinedNode), "Inlined " + root); + } + + @Override + public boolean inline(FrameFactory factory) { + inlineImpl(); + /* SL is always able to inline if required. */ + return true; } @Override @@ -169,7 +168,7 @@ @Override public Node getInlineTree() { - RootNode root = function.getRootNode(); + RootNode root = cachedFunction.getRootNode(); if (root instanceof FunctionRootNode) { return ((FunctionRootNode) root).getUninitializedBody(); } @@ -177,67 +176,46 @@ } @Override - public boolean inline(FrameFactory factory) { - CompilerAsserts.neverPartOfCompilation(); - TypedNode functionCall = null; - - RootNode root = function.getRootNode(); - if (root instanceof FunctionRootNode) { - functionCall = ((FunctionRootNode) root).inline(NodeUtil.cloneNode(args)); - } - if (functionCall != null) { - this.replace(functionCall); - return true; - } else { - return false; - } - } - - @Override - public Object executeGeneric(VirtualFrame frame) { - if (CompilerDirectives.inInterpreter()) { - callCount++; - } - return super.executeGeneric(frame); - } - - @Override public CallTarget getCallTarget() { - return function; + return cachedFunction; } } - private static class DispatchedCallNode extends TypedNode { + private static class InlinedDirectCallNode extends DirectCallNode implements InlinedCallSite { + + private final FrameDescriptor descriptor; + @Child private TypedNode inlinedBody; - @Child protected ArgumentsNode args; - protected final DefaultCallTarget function; - - DispatchedCallNode(DefaultCallTarget function, ArgumentsNode arguments) { - this.args = adoptChild(arguments); - this.function = function; + InlinedDirectCallNode(InlinableDirectCallNode prev, TypedNode inlinedBody) { + super(prev.functionNode, prev.argumentsNode, prev.cachedFunction, prev.nextNode); + this.descriptor = cachedFunction.getFrameDescriptor(); + this.inlinedBody = adoptChild(inlinedBody); } @Override - public Object executeGeneric(VirtualFrame frame) { - SLArguments argsObject = new SLArguments(args.executeArray(frame)); - return function.call(frame.pack(), argsObject); + public Object executeCurrent(VirtualFrame frame, Object[] arguments) { + SLArguments slArguments = new SLArguments(arguments); + VirtualFrame newFrame = Truffle.getRuntime().createVirtualFrame(frame.pack(), slArguments, descriptor); + return inlinedBody.executeGeneric(newFrame); } + + @Override + public CallTarget getCallTarget() { + return cachedFunction; + } + } private static final class GenericCallNode extends CallNode { - @Child protected ArgumentsNode args; - GenericCallNode(TypedNode functionNode, ArgumentsNode arguments) { - super(functionNode); - this.args = adoptChild(arguments); + super(functionNode, arguments); } @Override - public Object executeGeneric(VirtualFrame frame, CallTarget function) { - SLArguments argsObject = new SLArguments(args.executeArray(frame)); - return function.call(frame.pack(), argsObject); + public Object executeCall(VirtualFrame frame, CallTarget function, Object[] arguments) { + return function.call(frame.pack(), new SLArguments(arguments)); } } diff -r ecf152c6bd16 -r 652f24858aad graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FunctionRootNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FunctionRootNode.java Sun Dec 15 22:43:45 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FunctionRootNode.java Sun Dec 15 23:32:41 2013 +0100 @@ -35,14 +35,14 @@ private final TypedNode uninitializedBody; private final String name; - private final boolean alwaysInline; + private final boolean inlineImmediatly; - private FunctionRootNode(TypedNode body, String name, boolean alwaysInline) { + private FunctionRootNode(TypedNode body, String name, boolean inlineImmediatly) { super(null); this.uninitializedBody = NodeUtil.cloneNode(body); this.body = adoptChild(body); this.name = name; - this.alwaysInline = alwaysInline; + this.inlineImmediatly = inlineImmediatly; } public static CallTarget createBuiltin(SLContext context, NodeFactory factory, String name) { @@ -67,36 +67,12 @@ return body.executeGeneric(frame); } - public boolean isAlwaysInline() { - return alwaysInline; - } - - public TypedNode inline(ArgumentsNode clonedArgs) { - TypedNode clonedBody = NodeUtil.cloneNode(uninitializedBody); - if (clonedBody instanceof BuiltinNode) { - return inlineBuiltin(clonedArgs, (BuiltinNode) clonedBody); - } else if (clonedBody instanceof FunctionBodyNode) { - return inlineFunction(clonedArgs, (FunctionBodyNode) clonedBody); - } else { - throw new UnsupportedOperationException(); - } + public boolean isInlineImmediatly() { + return inlineImmediatly; } - private InlinedFunctionNode inlineFunction(ArgumentsNode clonedArgs, FunctionBodyNode clonedBody) { - return new InlinedFunctionNode(getCallTarget(), clonedBody, clonedArgs); - } - - private static TypedNode inlineBuiltin(ArgumentsNode clonedArgs, BuiltinNode builtin) { - TypedNode[] callerArgs = clonedArgs.getArguments(); - TypedNode[] builtinArgs = builtin.getArguments(); - for (int i = 0; i < builtinArgs.length; i++) { - if (i < callerArgs.length) { - builtinArgs[i].replace(callerArgs[i]); - } else { - builtinArgs[i].replace(new NullLiteralNode()); - } - } - return builtin; + public TypedNode inline() { + return NodeUtil.cloneNode(uninitializedBody); } public Node getUninitializedBody() { @@ -108,34 +84,6 @@ return "function " + name; } - private static final class InlinedFunctionNode extends TypedNode implements InlinedCallSite { - - @Child private FunctionBodyNode body; - @Child private ArgumentsNode arguments; - - private final CallTarget callTarget; - private final FrameDescriptor frameDescriptor; - - public InlinedFunctionNode(CallTarget callTarget, FunctionBodyNode body, ArgumentsNode arguments) { - this.callTarget = callTarget; - this.body = adoptChild(body); - this.frameDescriptor = body.getFrameDescriptor(); - this.arguments = adoptChild(arguments); - } - - @Override - public Object executeGeneric(VirtualFrame frame) { - SLArguments args = new SLArguments(arguments.executeArray(frame)); - VirtualFrame childFrame = Truffle.getRuntime().createVirtualFrame(frame.pack(), args, frameDescriptor); - return body.executeGeneric(childFrame); - } - - public CallTarget getCallTarget() { - return callTarget; - } - - } - public String getName() { return name; }