changeset 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 ecf152c6bd16
children f17969ae4a35 136df94b5aa8
files graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/CallNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FunctionRootNode.java
diffstat 2 files changed, 104 insertions(+), 178 deletions(-) [+]
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));
         }
     }
 
--- 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<? extends BuiltinNode> 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;
     }