changeset 13811:641f22b1c6b8

Truffle: further fixes to the new CallNode.
author Christian Humer <christian.humer@gmail.com>
date Wed, 29 Jan 2014 20:49:09 +0100
parents 44bcfc983adb
children f270f09616da
files graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningImpl.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/CallNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java
diffstat 7 files changed, 114 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Wed Jan 29 12:19:03 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Wed Jan 29 20:49:09 2014 +0100
@@ -56,7 +56,6 @@
         super(rootNode);
         this.compiler = compiler;
         this.compilationProfile = new CompilationProfile(compilationThreshold, invokeCounter, rootNode.toString());
-        this.getRootNode().setCallTarget(this);
 
         if (TruffleUseTimeForCompilationDecision.getValue()) {
             compilationPolicy = new TimedCompilationPolicy();
@@ -261,7 +260,7 @@
             }
 
             int notInlinedCallSiteCount = TruffleInliningImpl.getInlinableCallSites(callTarget).size();
-            int nodeCount = NodeUtil.countNodes(callTarget.getRootNode());
+            int nodeCount = NodeUtil.countNodes(callTarget.getRootNode(), null, true);
             int inlinedCallSiteCount = countInlinedNodes(callTarget.getRootNode());
             String comment = callTarget.installedCode == null ? " int" : "";
             comment += callTarget.compilationEnabled ? "" : " fail";
@@ -283,6 +282,7 @@
         for (CallNode callNode : callers) {
             if (callNode.isInlined()) {
                 count++;
+                count += countInlinedNodes(callNode.getInlinedRoot());
             }
         }
         return count;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Wed Jan 29 12:19:03 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Wed Jan 29 20:49:09 2014 +0100
@@ -167,7 +167,7 @@
         }
 
         if (TraceTruffleCompilation.getValue()) {
-            int nodeCountTruffle = NodeUtil.countNodes(compilable.getRootNode());
+            int nodeCountTruffle = NodeUtil.countNodes(compilable.getRootNode(), null, true);
             byte[] code = compiledMethod.getCode();
             OUT.printf("[truffle] optimized %-50s %x |Nodes %7d |Time %5.0f(%4.0f+%-4.0f)ms |Nodes %5d/%5d |CodeSize %d\n", compilable.getRootNode(), compilable.hashCode(), nodeCountTruffle,
                             (timeCompilationFinished - timeCompilationStarted) / 1e6, (timePartialEvaluationFinished - timeCompilationStarted) / 1e6,
@@ -193,6 +193,7 @@
                         OUT.print("   ");
                     }
                     OUT.println(callNode.getCallTarget());
+                    callNode.getInlinedRoot().accept(this);
                 }
             }
             return true;
@@ -200,9 +201,11 @@
 
         private int indent(Node n) {
             if (n instanceof RootNode) {
+                CallNode inlinedParent = ((RootNode) n).getParentInlinedCall();
+                if (inlinedParent != null) {
+                    return indent(inlinedParent) + 1;
+                }
                 return 0;
-            } else if (n instanceof CallNode && ((CallNode) n).isInlined()) {
-                return indent(n.getParent()) + 1;
             } else {
                 return indent(n.getParent());
             }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningImpl.java	Wed Jan 29 12:19:03 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningImpl.java	Wed Jan 29 20:49:09 2014 +0100
@@ -84,9 +84,7 @@
 
         if (inlined) {
             for (InlinableCallSiteInfo callSite : inlinableCallSites) {
-                if (callSite.getCallSite().isInlinable() && !callSite.getCallSite().isInlined()) {
-                    CallNode.internalResetCallCount(callSite.getCallSite());
-                }
+                CallNode.internalResetCallCount(callSite.getCallSite());
             }
         } else {
             if (TraceTruffleInliningDetails.getValue()) {
@@ -116,7 +114,7 @@
         private final int callerInvocationCount;
 
         public InliningPolicy(OptimizedCallTarget caller) {
-            this.callerNodeCount = NodeUtil.countNodes(caller.getRootNode());
+            this.callerNodeCount = NodeUtil.countNodes(caller.getRootNode(), null, true);
             this.callerInvocationCount = caller.getCompilationProfile().getOriginalInvokeCounter();
         }
 
@@ -177,19 +175,18 @@
 
         private int calculateRecursiveDepth() {
             int depth = 0;
-            Node parent = ((Node) callSite).getParent();
-            while (!(parent instanceof RootNode)) {
-                assert parent != null;
-                if (parent instanceof CallNode) {
-                    CallNode parentCall = (CallNode) parent;
-                    if (parentCall.isInlined() && parentCall.getCallTarget() == callSite.getCallTarget()) {
+
+            Node parent = callSite.getParent();
+            while (parent != null) {
+                if (parent instanceof RootNode) {
+                    RootNode root = ((RootNode) parent);
+                    if (root.getCallTarget() == callSite.getCallTarget()) {
                         depth++;
                     }
+                    parent = root.getParentInlinedCall();
+                } else {
+                    parent = parent.getParent();
                 }
-                parent = parent.getParent();
-            }
-            if (((RootNode) parent).getCallTarget() == callSite.getCallTarget()) {
-                depth++;
             }
             return depth;
         }
@@ -215,8 +212,12 @@
             public boolean visit(Node node) {
                 if (node instanceof CallNode) {
                     CallNode callNode = (CallNode) node;
-                    if (callNode.isInlinable() && !callNode.isInlined()) {
-                        inlinableCallSites.add(new InlinableCallSiteInfo(callNode));
+                    if (!callNode.isInlined()) {
+                        if (callNode.isInlinable()) {
+                            inlinableCallSites.add(new InlinableCallSiteInfo(callNode));
+                        }
+                    } else {
+                        callNode.getInlinedRoot().accept(this);
                     }
                 }
                 return true;
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/CallNode.java	Wed Jan 29 12:19:03 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/CallNode.java	Wed Jan 29 20:49:09 2014 +0100
@@ -85,6 +85,16 @@
     public abstract boolean inline();
 
     /**
+     * Returns the inlined root node if the call node was inlined. If the {@link CallNode} was not
+     * inlined <code>null</code> is returned.
+     * 
+     * @return the inlined root node returned by {@link RootNode#inline()}
+     */
+    public RootNode getInlinedRoot() {
+        return null;
+    }
+
+    /**
      * Creates a new {@link CallNode} using a {@link CallTarget}.
      * 
      * @param target the {@link CallTarget} to call
@@ -116,7 +126,6 @@
             ((InlinableCallNode) callNode).resetCallCount();
             return;
         }
-        throw new UnsupportedOperationException();
     }
 
     private static boolean isInlinable(CallTarget callTarget) {
@@ -126,6 +135,11 @@
         return false;
     }
 
+    @Override
+    public String toString() {
+        return getParent() != null ? getParent().toString() : super.toString();
+    }
+
     static final class DefaultCallNode extends CallNode {
 
         public DefaultCallNode(CallTarget target) {
@@ -174,13 +188,14 @@
         public boolean inline() {
             DefaultCallTarget defaultTarget = (DefaultCallTarget) getCallTarget();
             RootNode originalRootNode = defaultTarget.getRootNode();
-            boolean inlined = false;
             if (originalRootNode.isInlinable()) {
                 RootNode inlinedRootNode = defaultTarget.getRootNode().inline();
+                inlinedRootNode.setCallTarget(callTarget);
+                inlinedRootNode.setParentInlinedCall(this);
                 replace(new InlinedCallNode(defaultTarget, inlinedRootNode));
-                inlined = true;
+                return true;
             }
-            return inlined;
+            return false;
         }
 
         @Override
@@ -225,6 +240,11 @@
         }
 
         @Override
+        public RootNode getInlinedRoot() {
+            return inlinedRoot;
+        }
+
+        @Override
         public boolean inline() {
             return false;
         }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Wed Jan 29 12:19:03 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Wed Jan 29 20:49:09 2014 +0100
@@ -246,7 +246,7 @@
     }
 
     private void reportReplace() {
-        RootNode rootNode = getRootNode();
+        RootNode rootNode = NodeUtil.findOutermostRootNode(this);
         if (rootNode != null) {
             if (rootNode.getCallTarget() instanceof ReplaceObserver) {
                 ((ReplaceObserver) rootNode.getCallTarget()).nodeReplaced();
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Wed Jan 29 12:19:03 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Wed Jan 29 20:49:09 2014 +0100
@@ -451,6 +451,31 @@
         return null;
     }
 
+    /**
+     * Returns the outermost not inlined {@link RootNode} which is a parent of this node.
+     * 
+     * @see RootNode#getParentInlinedCall()
+     * @param node to search
+     * @return the outermost {@link RootNode}
+     */
+    public static RootNode findOutermostRootNode(Node node) {
+        Node parent = node;
+        while (parent != null) {
+            if (parent instanceof RootNode) {
+                RootNode root = (RootNode) parent;
+                Node next = root.getParentInlinedCall();
+                if (next != null) {
+                    parent = next;
+                } else {
+                    return root;
+                }
+            } else {
+                parent = parent.getParent();
+            }
+        }
+        return null;
+    }
+
     public static <T> T findParent(Node start, Class<T> clazz) {
         Node parent = start.getParent();
         if (parent == null) {
@@ -571,24 +596,26 @@
     }
 
     public static int countNodes(Node root) {
-        return countNodes(root, null);
+        return countNodes(root, null, false);
     }
 
-    public static int countNodes(Node root, Class<?> clazz) {
-        NodeCountVisitor nodeCount = new NodeCountVisitor(root, clazz);
+    public static int countNodes(Node root, Class<?> clazz, boolean countInlinedCallNodes) {
+        NodeCountVisitor nodeCount = new NodeCountVisitor(root, clazz, countInlinedCallNodes);
         root.accept(nodeCount);
         return nodeCount.nodeCount;
     }
 
     private static final class NodeCountVisitor implements NodeVisitor {
 
+        private Node root;
+        private boolean inspectInlinedCalls;
         int nodeCount;
-        private final Node root;
         private final Class<?> clazz;
 
-        private NodeCountVisitor(Node root, Class<?> clazz) {
+        private NodeCountVisitor(Node root, Class<?> clazz, boolean inspectInlinedCalls) {
             this.root = root;
             this.clazz = clazz;
+            this.inspectInlinedCalls = inspectInlinedCalls;
         }
 
         @Override
@@ -596,9 +623,18 @@
             if (node instanceof RootNode && node != root) {
                 return false;
             }
+
             if (clazz == null || clazz.isInstance(node)) {
                 nodeCount++;
             }
+
+            if (inspectInlinedCalls && node instanceof CallNode) {
+                CallNode call = (CallNode) node;
+                if (call.isInlined()) {
+                    call.getInlinedRoot().getChildren().iterator().next().accept(this);
+                }
+            }
+
             return true;
         }
     }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Wed Jan 29 12:19:03 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Wed Jan 29 20:49:09 2014 +0100
@@ -25,6 +25,7 @@
 package com.oracle.truffle.api.nodes;
 
 import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.*;
 import com.oracle.truffle.api.frame.*;
 
 /**
@@ -37,6 +38,12 @@
     private CallTarget callTarget;
     private final FrameDescriptor frameDescriptor;
 
+    /*
+     * Internal field to keep reference to the inlined call node. The inlined parent should not be
+     * the same as the Node parent to keep the same tree hierarchy if inlined vs not inlined.
+     */
+    @CompilationFinal private CallNode parentInlinedCall;
+
     protected RootNode() {
         this(null, null);
     }
@@ -125,4 +132,20 @@
     public void setCallTarget(CallTarget callTarget) {
         this.callTarget = callTarget;
     }
+
+    /* Internal API. Do not use. */
+    void setParentInlinedCall(CallNode inlinedParent) {
+        this.parentInlinedCall = inlinedParent;
+    }
+
+    /**
+     * Returns the {@link CallNode} that uses this {@link RootNode} for an inlined call. Returns
+     * <code>null</code> if this {@link RootNode} is not inlined into a caller. This method can be
+     * used to also traverse parent {@link CallTarget} that have been inlined into this call.
+     * 
+     * @return the responsible {@link CallNode} for inlining.
+     */
+    public final CallNode getParentInlinedCall() {
+        return parentInlinedCall;
+    }
 }