Mercurial > hg > truffle
diff graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/CallNode.java @ 13338:652f24858aad
SL: simplified call nodes. aligned builtin inlining with user function inlining.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Sun, 15 Dec 2013 23:32:41 +0100 |
parents | 06afa0db90b3 |
children | c2ed2ce2cfe0 |
line wrap: on
line diff
--- 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)); } }