changeset 14567:b1dded9c748a

Merge.
author Christian Humer <christian.humer@gmail.com>
date Mon, 17 Mar 2014 14:30:59 +0100
parents 6681b9eb3f4c (diff) 82e4fe6fa525 (current diff)
children 2e90d9a9a677
files agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaslineCompiler.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/Test.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraphCache.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java src/os/bsd/dtrace/hotspot.d src/os/bsd/dtrace/hotspot_jni.d src/os/bsd/dtrace/hs_private.d src/os/solaris/dtrace/hotspot.d src/os/solaris/dtrace/hotspot_jni.d src/os/solaris/dtrace/hs_private.d src/share/vm/utilities/dtrace_usdt2_disabled.hpp
diffstat 15 files changed, 302 insertions(+), 264 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNode.java	Mon Mar 17 13:08:32 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNode.java	Mon Mar 17 14:30:59 2014 +0100
@@ -28,7 +28,7 @@
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.impl.*;
 import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeInfo.Kind;
+import com.oracle.truffle.api.nodes.NodeUtil.NodeFilter;
 
 /**
  * Call target that is optimized by Graal upon surpassing a specific invocation threshold.
@@ -85,6 +85,11 @@
         return new DefaultOptimizedCallNode(target);
     }
 
+    @Override
+    public boolean isInlinable() {
+        return true;
+    }
+
     private static final class DefaultOptimizedCallNode extends OptimizedCallNode {
 
         private boolean trySplit = true;
@@ -135,7 +140,7 @@
             if (isMaxSingleCall()) {
                 return true;
             }
-            return countPolymorphic() >= 1 || countGeneric() > 0;
+            return countPolymorphic() >= 1;
         }
 
         @Override
@@ -143,11 +148,6 @@
             trySplit = true;
         }
 
-        @Override
-        protected void notifyCallNodeAdded() {
-            trySplit = true;
-        }
-
         private boolean isMaxSingleCall() {
             final AtomicInteger count = new AtomicInteger(0);
             getCurrentCallTarget().getRootNode().accept(new NodeVisitor() {
@@ -163,11 +163,12 @@
         }
 
         private int countPolymorphic() {
-            return NodeUtil.countNodes(getCallTarget().getRootNode(), null, Kind.POLYMORPHIC, false);
-        }
-
-        private int countGeneric() {
-            return NodeUtil.countNodes(getCallTarget().getRootNode(), null, Kind.GENERIC, false);
+            return NodeUtil.countNodes(getCallTarget().getRootNode(), new NodeFilter() {
+                public boolean isFiltered(Node node) {
+                    NodeCost cost = node.getCost();
+                    return cost == NodeCost.POLYMORPHIC || cost == NodeCost.MEGAMORPHIC;
+                }
+            });
         }
 
         @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Mon Mar 17 13:08:32 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Mon Mar 17 14:30:59 2014 +0100
@@ -34,7 +34,7 @@
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.impl.*;
 import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeInfo.Kind;
+import com.oracle.truffle.api.nodes.NodeUtil.NodeFilter;
 
 /**
  * Call target that is optimized by Graal upon surpassing a specific invocation threshold.
@@ -428,11 +428,11 @@
 
             target.getRootNode().accept(new NodeVisitor() {
                 public boolean visit(Node node) {
-                    Kind kind = node.getKind();
-                    if (kind == Kind.POLYMORPHIC || kind == Kind.GENERIC) {
+                    NodeCost kind = node.getCost();
+                    if (kind == NodeCost.POLYMORPHIC || kind == NodeCost.MEGAMORPHIC) {
                         Map<String, Object> props = new LinkedHashMap<>();
                         props.put("simpleName", node.getClass().getSimpleName());
-                        String msg = kind == Kind.GENERIC ? "generic" : "polymorphic";
+                        String msg = kind == NodeCost.MEGAMORPHIC ? "megamorphic" : "polymorphic";
                         log(0, msg, node.toString(), props);
                     }
                     if (node instanceof CallNode) {
@@ -461,8 +461,20 @@
     }
 
     static void addASTSizeProperty(RootNode target, Map<String, Object> properties) {
+        int polymorphicCount = NodeUtil.countNodes(target.getRootNode(), new NodeFilter() {
+            public boolean isFiltered(Node node) {
+                return node.getCost() == NodeCost.POLYMORPHIC;
+            }
+        }, true);
+
+        int megamorphicCount = NodeUtil.countNodes(target.getRootNode(), new NodeFilter() {
+            public boolean isFiltered(Node node) {
+                return node.getCost() == NodeCost.MEGAMORPHIC;
+            }
+        }, true);
+
         String value = String.format("%4d (%d/%d)", NodeUtil.countNodes(target.getRootNode(), null, true), //
-                        NodeUtil.countNodes(target.getRootNode(), null, Kind.POLYMORPHIC, true), NodeUtil.countNodes(target.getRootNode(), null, Kind.GENERIC, true)); //
+                        polymorphicCount, megamorphicCount); //
 
         properties.put("ASTSize", value);
     }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java	Mon Mar 17 13:08:32 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java	Mon Mar 17 14:30:59 2014 +0100
@@ -33,7 +33,6 @@
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
 import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeInfo.Kind;
 
 public class PolymorphicTest {
 
@@ -55,7 +54,7 @@
         assertEquals("(boolean,boolean)", executeWith(node, false, false));
         assertEquals("(int,boolean)", executeWith(node, 42, false));
         assertEquals("(boolean,int)", executeWith(node, false, 42));
-        assertEquals(Kind.SPECIALIZED, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+        assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost());
         assertParent(node.getNode(), node.getNode().getLeft());
         assertParent(node.getNode(), node.getNode().getRight());
     }
@@ -65,7 +64,7 @@
         TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
         assertEquals("(int,boolean)", executeWith(node, 42, false));
         assertEquals("(int,int)", executeWith(node, 42, 42));
-        assertEquals(Kind.POLYMORPHIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+        assertEquals(NodeCost.NONE, node.getNode().getCost());
         assertParent(node.getNode(), node.getNode().getLeft());
         assertParent(node.getNode(), node.getNode().getRight());
     }
@@ -76,7 +75,7 @@
         assertEquals("(int,boolean)", executeWith(node, 42, false));
         assertEquals("(boolean,boolean)", executeWith(node, true, false));
         assertEquals("(int,int)", executeWith(node, 42, 42));
-        assertEquals(Kind.POLYMORPHIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+        assertEquals(NodeCost.NONE, node.getNode().getCost());
         assertParent(node.getNode(), node.getNode().getLeft());
         assertParent(node.getNode(), node.getNode().getRight());
     }
@@ -88,7 +87,7 @@
         assertEquals("(int,boolean)", executeWith(node, 42, false));
         assertEquals("(boolean,boolean)", executeWith(node, true, false));
         assertEquals("(int,int)", executeWith(node, 42, 42));
-        assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+        assertEquals(NodeCost.MEGAMORPHIC, node.getNode().getCost());
         assertParent(node.getNode(), node.getNode().getLeft());
         assertParent(node.getNode(), node.getNode().getRight());
     }
@@ -97,7 +96,7 @@
     public void testGenericInitial() {
         TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
         assertEquals("(generic,generic)", executeWith(node, "1", "1"));
-        assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+        assertEquals(NodeCost.MEGAMORPHIC, node.getNode().getCost());
         assertParent(node.getNode(), node.getNode().getLeft());
         assertParent(node.getNode(), node.getNode().getRight());
     }
@@ -108,7 +107,7 @@
         assertEquals("(boolean,int)", executeWith(node, false, 42));
         assertEquals("(boolean,boolean)", executeWith(node, false, false));
         assertEquals("(generic,generic)", executeWith(node, "", ""));
-        assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+        assertEquals(NodeCost.MEGAMORPHIC, node.getNode().getCost());
         /* Assertions for bug GRAAL-425 */
         assertParent(node.getNode(), node.getNode().getLeft());
         assertParent(node.getNode(), node.getNode().getRight());
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java	Mon Mar 17 13:08:32 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java	Mon Mar 17 14:30:59 2014 +0100
@@ -32,7 +32,6 @@
 import com.oracle.truffle.api.dsl.test.PolymorphicTest2Factory.Node1Factory;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
 import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeInfo.Kind;
 
 public class PolymorphicTest2 {
 
@@ -43,7 +42,7 @@
         assertEquals(21, executeWith(node, false, false));
         assertEquals(42, executeWith(node, 21, 21));
         assertEquals("(boolean,int)", executeWith(node, false, 42));
-        assertEquals(Kind.POLYMORPHIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+        assertEquals(NodeCost.NONE, node.getNode().getCost());
     }
 
     @SuppressWarnings("unused")
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java	Mon Mar 17 13:08:32 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java	Mon Mar 17 14:30:59 2014 +0100
@@ -25,7 +25,6 @@
 package com.oracle.truffle.api;
 
 import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeInfo.Kind;
 
 /**
  * Class containing general Truffle options.
@@ -56,29 +55,29 @@
     public static String TraceRewritesFilterClass = System.getProperty("truffle.TraceRewritesFilterClass");
 
     /**
-     * Filters rewrites which does not contain the {@link Kind} in its source {@link NodeInfo}. If
-     * no {@link NodeInfo} is defined the element is filtered if the filter value is set.
+     * Filters rewrites which does not contain the {@link NodeCost} in its source {@link NodeInfo}.
+     * If no {@link NodeInfo} is defined the element is filtered if the filter value is set.
      * <p>
      * Can be set with
-     * {@code -Dtruffle.TraceRewritesFilterFromKind=UNINITIALIZED|SPECIALIZED|POLYMORPHIC|GENERIC}.
+     * {@code -Dtruffle.TraceRewritesFilterFromCost=NONE|MONOMORPHIC|POLYMORPHIC|MEGAMORPHIC}.
      */
-    public static NodeInfo.Kind TraceRewritesFilterFromKind = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterFromKind"));
+    public static NodeCost TraceRewritesFilterFromCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterFromCost"));
 
     /**
-     * Filters rewrites which does not contain the {@link Kind} in its target {@link NodeInfo}. If
-     * no {@link NodeInfo} is defined the element is filtered if the filter value is set.
+     * Filters rewrites which does not contain the {@link NodeCost} in its target {@link NodeInfo}.
+     * If no {@link NodeInfo} is defined the element is filtered if the filter value is set.
      * <p>
      * Can be set with
      * {@code -Dtruffle.TraceRewritesFilterToKind=UNINITIALIZED|SPECIALIZED|POLYMORPHIC|GENERIC}.
      */
-    public static NodeInfo.Kind TraceRewritesFilterToKind = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterToKind"));
+    public static NodeCost TraceRewritesFilterToCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterToCost"));
 
-    private static NodeInfo.Kind parseNodeInfoKind(String kind) {
+    private static NodeCost parseNodeInfoKind(String kind) {
         if (kind == null) {
             return null;
         }
 
-        return NodeInfo.Kind.valueOf(kind);
+        return NodeCost.valueOf(kind);
     }
 
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallNode.java	Mon Mar 17 13:08:32 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallNode.java	Mon Mar 17 14:30:59 2014 +0100
@@ -64,6 +64,11 @@
     }
 
     @Override
+    public boolean isInlinable() {
+        return false;
+    }
+
+    @Override
     public String toString() {
         return getParent() != null ? getParent().toString() : super.toString();
     }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/CallNode.java	Mon Mar 17 13:08:32 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/CallNode.java	Mon Mar 17 14:30:59 2014 +0100
@@ -28,13 +28,18 @@
 import com.oracle.truffle.api.frame.*;
 
 /**
- * This node represents a call to a static {@link CallTarget}. This node should be used whenever a
- * {@link CallTarget} is considered constant at a certain location in the tree. This enables the
- * Truffle runtime to perform inlining or other optimizations for this call-site. This class is
- * intended to be implemented by truffle runtime implementors and not by guest language
- * implementors.
+ * Represents a call to a {@link CallTarget} in the Truffle AST. Addtionally to calling the
+ * {@link CallTarget} this {@link Node} enables the runtime system to implement further
+ * optimizations. Optimizations that can possibly applied to a {@link CallNode} are inlining and
+ * splitting. Inlining inlines this call site into the call graph of the parent {@link CallTarget}.
+ * Splitting duplicates the {@link CallTarget} using {@link RootNode#split()} to collect call site
+ * sensitive profiling information.
  * 
- * @see #create(CallTarget) to create a CallNode instance.
+ * Please note: This class is not intended to be subclassed by guest language implementations.
+ * 
+ * @see TruffleRuntime#createCallNode(CallTarget)
+ * @see #inline()
+ * @see #split()
  */
 public abstract class CallNode extends Node {
 
@@ -45,7 +50,7 @@
     }
 
     /**
-     * Calls this constant target passing a caller frame and arguments.
+     * Calls the inner {@link CallTarget} returned by {@link #getCurrentCallTarget()}.
      * 
      * @param caller the caller frame
      * @param arguments the arguments that should be passed to the callee
@@ -65,27 +70,63 @@
     }
 
     /**
-     * @return true if this {@link CallNode} was already inlined.
+     * Returns <code>true</code> if the underlying runtime system supports inlining for the
+     * {@link CallTarget} in this {@link CallNode}.
+     * 
+     * @return true if inlining is supported.
+     */
+    public abstract boolean isInlinable();
+
+    /**
+     * Returns <code>true</code> if the {@link CallTarget} in this {@link CallNode} is inlined. A
+     * {@link CallNode} can either be inlined manually by invoking {@link #inline()} or by the
+     * runtime system which may at any point decide to inline.
+     * 
+     * @return true if this method was inlined else false.
      */
     public abstract boolean isInlined();
 
+    /**
+     * Enforces the runtime system to inline the {@link CallTarget} at this call site. If the
+     * runtime system does not support inlining or it is already inlined this method has no effect.
+     */
     public abstract void inline();
 
+    /**
+     * Returns <code>true</code> if this {@link CallNode} can be split. A {@link CallNode} can only
+     * be split if the runtime system supports splitting and if the {@link RootNode} contained the
+     * {@link CallTarget} returns <code>true</code> for {@link RootNode#isSplittable()}.
+     * 
+     * @return <code>true</code> if the target can be split
+     */
     public abstract boolean isSplittable();
 
+    /**
+     * Enforces the runtime system to split the {@link CallTarget}. If the {@link CallNode} is not
+     * splittable this methods has no effect.
+     */
     public abstract boolean split();
 
+    /**
+     * Returns <code>true</code> if the target of the {@link CallNode} was split.
+     * 
+     * @return if the target was split
+     */
     public final boolean isSplit() {
         return getSplitCallTarget() != null;
     }
 
+    /**
+     * Returns the splitted {@link CallTarget} if this method is split.
+     * 
+     * @return the split {@link CallTarget}
+     */
     public abstract CallTarget getSplitCallTarget();
 
     /**
      * Returns the used call target when {@link #call(PackedFrame, Arguments)} is invoked. If the
-     * {@link CallNode} was split this method returns the {@link CallTarget} returned by
-     * {@link #getSplitCallTarget()}. If not split this method returns the original supplied
-     * {@link CallTarget}.
+     * {@link CallTarget} was split this method returns the {@link CallTarget} returned by
+     * {@link #getSplitCallTarget()}.
      * 
      * @return the used {@link CallTarget} when node is called
      */
@@ -98,6 +139,22 @@
         }
     }
 
+    /**
+     * Returns the {@link RootNode} associated with {@link CallTarget} returned by
+     * {@link #getCurrentCallTarget()}. If the stored {@link CallTarget} does not contain a
+     * {@link RootNode} this method returns <code>null</code>.
+     * 
+     * @see #getCurrentCallTarget()
+     * @return the root node of the used call target
+     */
+    public final RootNode getCurrentRootNode() {
+        CallTarget target = getCurrentCallTarget();
+        if (target instanceof RootCallTarget) {
+            return ((RootCallTarget) target).getRootNode();
+        }
+        return null;
+    }
+
     @Override
     protected void onReplace(Node newNode, String reason) {
         super.onReplace(newNode, reason);
@@ -114,6 +171,9 @@
         registerCallTarget((CallNode) newNode);
     }
 
+    /**
+     * Internal API for the runtime system.
+     */
     protected static final void registerCallTarget(CallNode newNode) {
         RootNode newRoot = newNode.getCurrentRootNode();
         if (newRoot != null) {
@@ -121,51 +181,4 @@
         }
     }
 
-    protected void notifyCallNodeAdded() {
-
-    }
-
-    /**
-     * Returns the {@link RootNode} associated with {@link CallTarget} returned by
-     * {@link #getCurrentCallTarget()}.
-     * 
-     * @see #getCurrentCallTarget()
-     * @return the root node of the used call target
-     */
-    public final RootNode getCurrentRootNode() {
-        CallTarget target = getCurrentCallTarget();
-        if (target instanceof RootCallTarget) {
-            return ((RootCallTarget) target).getRootNode();
-        }
-        return null;
-    }
-
-    /**
-     * @deprecated always returns <code>true</code> now.
-     */
-    @Deprecated
-    public boolean isInlinable() {
-        return true;
-    }
-
-    /**
-     * @deprecated instead use {@link #getCurrentRootNode()} and check for {@link #isInlined()} for
-     *             true.
-     */
-    @Deprecated
-    public RootNode getInlinedRoot() {
-        if (!isInlined()) {
-            return null;
-        }
-        return getCurrentRootNode();
-    }
-
-    /**
-     * @deprecated use {@link TruffleRuntime#createCallNode(CallTarget)} instead
-     */
-    @Deprecated
-    public static CallNode create(CallTarget target) {
-        return Truffle.getRuntime().createCallNode(target);
-    }
-
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java	Mon Mar 17 13:08:32 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java	Mon Mar 17 14:30:59 2014 +0100
@@ -214,7 +214,7 @@
             setNodeProperty(node, "name", node.getClass().getSimpleName().replaceFirst("Node$", ""));
             NodeInfo nodeInfo = node.getClass().getAnnotation(NodeInfo.class);
             if (nodeInfo != null) {
-                setNodeProperty(node, "kind", nodeInfo.kind());
+                setNodeProperty(node, "cost", nodeInfo.cost());
                 if (!nodeInfo.shortName().isEmpty()) {
                     setNodeProperty(node, "shortName", nodeInfo.shortName());
                 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Mon Mar 17 13:08:32 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Mon Mar 17 14:30:59 2014 +0100
@@ -29,7 +29,6 @@
 import java.util.*;
 
 import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.nodes.NodeInfo.Kind;
 
 /**
  * Abstract base class for all Truffle nodes.
@@ -82,12 +81,20 @@
         this.sourceSection = section;
     }
 
-    public Kind getKind() {
+    /**
+     * Returns a rough estimate for the cost of this {@link Node}. This estimate can be used by
+     * runtime systems or guest languages to implement heuristics based on Truffle ASTs. This method
+     * is intended to be overridden by subclasses. The default implementation returns the value of
+     * {@link NodeInfo#cost()} of the {@link NodeInfo} annotation declared at the subclass. If no
+     * {@link NodeInfo} annotation is declared the method returns {@link NodeCost#MONOMORPHIC} as a
+     * default value.
+     */
+    public NodeCost getCost() {
         NodeInfo info = getClass().getAnnotation(NodeInfo.class);
         if (info != null) {
-            return info.kind();
+            return info.cost();
         }
-        return Kind.SPECIALIZED;
+        return NodeCost.MONOMORPHIC;
     }
 
     /**
@@ -277,61 +284,54 @@
     }
 
     private void traceRewrite(Node newNode, String reason) {
-        Class<? extends Node> from = getClass();
-        Class<? extends Node> to = newNode.getClass();
 
-        if (TruffleOptions.TraceRewritesFilterFromKind != null) {
-            if (filterByKind(from, TruffleOptions.TraceRewritesFilterFromKind)) {
+        if (TruffleOptions.TraceRewritesFilterFromCost != null) {
+            if (filterByKind(this, TruffleOptions.TraceRewritesFilterFromCost)) {
                 return;
             }
         }
 
-        if (TruffleOptions.TraceRewritesFilterToKind != null) {
-            if (filterByKind(to, TruffleOptions.TraceRewritesFilterToKind)) {
+        if (TruffleOptions.TraceRewritesFilterToCost != null) {
+            if (filterByKind(newNode, TruffleOptions.TraceRewritesFilterToCost)) {
                 return;
             }
         }
 
         String filter = TruffleOptions.TraceRewritesFilterClass;
+        Class<? extends Node> from = getClass();
+        Class<? extends Node> to = newNode.getClass();
         if (filter != null && (filterByContainsClassName(from, filter) || filterByContainsClassName(to, filter))) {
             return;
         }
 
         PrintStream out = System.out;
-        out.printf("[truffle]   rewrite %-50s |From %-40s |To %-40s |Reason %s.%n", this.toString(), formatNodeInfo(from), formatNodeInfo(to), reason);
+        out.printf("[truffle]   rewrite %-50s |From %-40s |To %-40s |Reason %s.%n", this.toString(), formatNodeInfo(this), formatNodeInfo(newNode), reason);
     }
 
-    private static String formatNodeInfo(Class<? extends Node> clazz) {
-        NodeInfo nodeInfo = clazz.getAnnotation(NodeInfo.class);
-        String kind = "?";
-        if (nodeInfo != null) {
-            switch (nodeInfo.kind()) {
-                case GENERIC:
-                    kind = "G";
-                    break;
-                case SPECIALIZED:
-                    kind = "S";
-                    break;
-                case UNINITIALIZED:
-                    kind = "U";
-                    break;
-                case POLYMORPHIC:
-                    kind = "P";
-                    break;
-                default:
-                    kind = "?";
-                    break;
-            }
+    private static String formatNodeInfo(Node node) {
+        String cost = "?";
+        switch (node.getCost()) {
+            case NONE:
+                cost = "G";
+                break;
+            case MONOMORPHIC:
+                cost = "M";
+                break;
+            case POLYMORPHIC:
+                cost = "P";
+                break;
+            case MEGAMORPHIC:
+                cost = "G";
+                break;
+            default:
+                cost = "?";
+                break;
         }
-        return kind + " " + clazz.getSimpleName();
+        return cost + " " + node.getClass().getSimpleName();
     }
 
-    private static boolean filterByKind(Class<?> clazz, Kind kind) {
-        NodeInfo info = clazz.getAnnotation(NodeInfo.class);
-        if (info != null) {
-            return info.kind() != kind;
-        }
-        return true;
+    private static boolean filterByKind(Node node, NodeCost cost) {
+        return node.getCost() == cost;
     }
 
     private static boolean filterByContainsClassName(Class<? extends Node> from, String filter) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeCost.java	Mon Mar 17 14:30:59 2014 +0100
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2012, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.nodes;
+
+import com.oracle.truffle.api.*;
+
+/**
+ * Represents a rough estimate for the cost of a {@link Node}. This estimate can be used by runtime
+ * systems or guest languages to implement heuristics based on Truffle ASTs.
+ * 
+ * @see Node#getCost()
+ */
+public enum NodeCost {
+
+    /**
+     * This node has literally no costs and should be ignored for heuristics. This is particularly
+     * useful for wrapper and profiling nodes which should not influence the heuristics.
+     */
+    NONE,
+
+    /**
+     * This node has a {@link CompilerDirectives#transferToInterpreter()} or
+     * {@link CompilerDirectives#transferToInterpreterAndInvalidate()} as its first unconditional
+     * statement.
+     */
+    UNINITIALIZED,
+
+    /**
+     * This node represents a specialized monomorphic version of an operation.
+     */
+    MONOMORPHIC,
+
+    /**
+     * This node represents a polymorphic version of an operation. For multiple chained polymorphic
+     * nodes the first may return {@link #MONOMORPHIC} and all addtional nodes should return
+     * {@link #POLYMORPHIC}.
+     */
+    POLYMORPHIC,
+
+    /**
+     * This node represents a megamorphic version of an operation. This value should only be used if
+     * the operation implementation supports monomorphism and polymorphism otherwise
+     * {@link #MONOMORPHIC} should be used instead.
+     */
+    MEGAMORPHIC;
+
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInfo.java	Mon Mar 17 13:08:32 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInfo.java	Mon Mar 17 14:30:59 2014 +0100
@@ -40,10 +40,13 @@
      */
     String shortName() default "";
 
-    Kind kind() default Kind.SPECIALIZED;
-
-    public enum Kind {
-        UNINITIALIZED, SPECIALIZED, POLYMORPHIC, GENERIC
-    }
+    /**
+     * Provides a rough estimate for the cost of the annotated {@link Node}. This estimate can be
+     * used by runtime systems or guest languages to implement heuristics based on Truffle ASTs.
+     * 
+     * @see Node#getCost()
+     * @see NodeCost
+     */
+    NodeCost cost() default NodeCost.MONOMORPHIC;
 
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Mon Mar 17 13:08:32 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Mon Mar 17 14:30:59 2014 +0100
@@ -34,7 +34,6 @@
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.nodes.Node.Child;
 import com.oracle.truffle.api.nodes.Node.Children;
-import com.oracle.truffle.api.nodes.NodeInfo.Kind;
 
 /**
  * Utility class that manages the special access methods for node instances.
@@ -452,48 +451,6 @@
         return null;
     }
 
-    /**
-     * @deprecated will be removed, exposed Truffle runtime specific functionality.
-     */
-    @Deprecated
-    public static List<CallTarget> findOutermostCallTargets(Node node) {
-        RootNode root = node.getRootNode();
-        if (root == null) {
-            return Collections.emptyList();
-        }
-        List<CallTarget> roots = new ArrayList<>();
-        roots.add(root.getCallTarget());
-        for (CallNode callNode : root.getCachedCallNodes()) {
-            if (callNode.isInlined()) {
-                roots.addAll(findOutermostCallTargets(callNode));
-            }
-        }
-        return roots;
-    }
-
-    /**
-     * @deprecated will be removed, exposed Truffle runtime specific functionality.
-     */
-    @Deprecated
-    public static RootNode findOutermostRootNode(Node node) {
-        Node parent = node;
-        while (parent != null) {
-            if (parent instanceof RootNode) {
-                RootNode root = (RootNode) parent;
-                @SuppressWarnings("deprecation")
-                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) {
@@ -614,39 +571,43 @@
     }
 
     public static int countNodes(Node root) {
-        return countNodes(root, null, null, false);
+        return countNodes(root, null, false);
     }
 
-    public static int countNodes(Node root, Class<?> clazz, Kind nodeKind, boolean countInlinedCallNodes) {
-        NodeCountVisitor nodeCount = new NodeCountVisitor(clazz, nodeKind, countInlinedCallNodes);
+    public static int countNodes(Node root, NodeFilter filter) {
+        return countNodes(root, filter, false);
+    }
+
+    public static int countNodes(Node root, NodeFilter filter, boolean visitInlinedCallNodes) {
+        NodeCountVisitor nodeCount = new NodeCountVisitor(filter, visitInlinedCallNodes);
         root.accept(nodeCount);
         return nodeCount.nodeCount;
     }
 
-    public static int countNodes(Node root, Class<?> clazz, boolean countInlinedCallNodes) {
-        return countNodes(root, clazz, null, countInlinedCallNodes);
+    public interface NodeFilter {
+
+        boolean isFiltered(Node node);
+
     }
 
     private static final class NodeCountVisitor implements NodeVisitor {
 
-        private final boolean inspectInlinedCalls;
+        private final boolean visitInlinedCallNodes;
         int nodeCount;
-        private final Kind kind;
-        private final Class<?> clazz;
+        private final NodeFilter filter;
 
-        private NodeCountVisitor(Class<?> clazz, Kind kind, boolean inspectInlinedCalls) {
-            this.clazz = clazz;
-            this.kind = kind;
-            this.inspectInlinedCalls = inspectInlinedCalls;
+        private NodeCountVisitor(NodeFilter filter, boolean visitInlinedCallNodes) {
+            this.filter = filter;
+            this.visitInlinedCallNodes = visitInlinedCallNodes;
         }
 
         @Override
         public boolean visit(Node node) {
-            if ((clazz == null || clazz.isInstance(node)) && (kind == null || isKind(node))) {
+            if (filter == null || !filter.isFiltered(node)) {
                 nodeCount++;
             }
 
-            if (inspectInlinedCalls && node instanceof CallNode) {
+            if (visitInlinedCallNodes && node instanceof CallNode) {
                 CallNode call = (CallNode) node;
                 if (call.isInlined()) {
                     Node target = ((RootCallTarget) call.getCurrentCallTarget()).getRootNode();
@@ -659,9 +620,6 @@
             return true;
         }
 
-        private boolean isKind(Node n) {
-            return kind == n.getKind();
-        }
     }
 
     public static void printInliningTree(final PrintStream stream, RootNode root) {
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Mon Mar 17 13:08:32 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Mon Mar 17 14:30:59 2014 +0100
@@ -36,7 +36,7 @@
  */
 public abstract class RootNode extends Node {
 
-    private CallTarget callTarget;
+    private RootCallTarget callTarget;
     private final FrameDescriptor frameDescriptor;
 
     /*
@@ -62,36 +62,24 @@
     }
 
     /**
-     * @deprecated Not required anymore. Do not use.
+     * Creates a split {@link RootNode} based on the current {@link RootNode}. This method should
+     * return an AST that was never executed and must not be shared with other {@link RootNode} or
+     * {@link CallTarget} instances. This method is intended to be overridden by a subclass.
+     * 
+     * @return the split {@link RootNode}
      */
-    @Deprecated
-    public RootNode inline() {
-        if (!isInlinable()) {
-            throw new UnsupportedOperationException("Inlining is not enabled.");
-        }
-        return split();
+    public RootNode split() {
+        throw new UnsupportedOperationException();
     }
 
     /**
-     * @deprecated Not required anymore. Do not use.
-     */
-    @Deprecated
-    public int getInlineNodeCount() {
-        return 0;
-    }
-
-    /**
-     * @deprecated Not required anymore. Do not use.
+     * Returns <code>true</code> if this {@link RootNode} can be split. A {@link RootNode} can be
+     * split inside of a {@link CallTarget} that is invoked using a {@link CallNode}. If this method
+     * returns <code>true</code> a proper implementation of {@link #split()} must also be provided.
+     * This method is intended to be overridden by a subclass.
+     * 
+     * @return <code>true</code> if splittable else <code>false</code>.
      */
-    @Deprecated
-    public boolean isInlinable() {
-        return true;
-    }
-
-    public RootNode split() {
-        return NodeUtil.cloneNode(this);
-    }
-
     public boolean isSplittable() {
         return false;
     }
@@ -100,7 +88,7 @@
      * Reports the execution count of a loop that is a child of this node. The optimization
      * heuristics can use the loop count to guide compilation and inlining.
      */
-    public void reportLoopCount(int count) {
+    public final void reportLoopCount(int count) {
         if (getCallTarget() instanceof LoopCountReceiver) {
             ((LoopCountReceiver) getCallTarget()).reportLoopCount(count);
         }
@@ -114,7 +102,7 @@
      */
     public abstract Object execute(VirtualFrame frame);
 
-    public CallTarget getCallTarget() {
+    public final RootCallTarget getCallTarget() {
         return callTarget;
     }
 
@@ -122,17 +110,17 @@
         return frameDescriptor;
     }
 
-    public final void setCallTarget(CallTarget callTarget) {
+    public final void setCallTarget(RootCallTarget callTarget) {
         this.callTarget = callTarget;
     }
 
     /* Internal API. Do not use. */
-    void addCachedCallNode(CallNode callSite) {
+    final void addCachedCallNode(CallNode callSite) {
         this.cachedCallNodes.add(callSite);
     }
 
     /* Internal API. Do not use. */
-    void removeCachedCallNode(CallNode callSite) {
+    final void removeCachedCallNode(CallNode callSite) {
         this.cachedCallNodes.remove(callSite);
     }
 
@@ -148,11 +136,4 @@
         return Collections.unmodifiableSet(cachedCallNodes);
     }
 
-    /**
-     * @deprecated use {@link #getCachedCallNodes()} instead.
-     */
-    @Deprecated
-    public final CallNode getParentInlinedCall() {
-        return cachedCallNodes.isEmpty() ? null : cachedCallNodes.iterator().next();
-    }
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java	Mon Mar 17 13:08:32 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java	Mon Mar 17 14:30:59 2014 +0100
@@ -52,7 +52,7 @@
     private final DeclaredType childAnnotation;
     private final DeclaredType childrenAnnotation;
     private final DeclaredType nodeInfoAnnotation;
-    private final DeclaredType nodeInfoKind;
+    private final DeclaredType nodeCost;
     private final TypeMirror compilerDirectives;
     private final TypeMirror compilerAsserts;
     private final DeclaredType slowPath;
@@ -75,7 +75,7 @@
         assumption = getRequired(context, Assumption.class);
         invalidAssumption = getRequired(context, InvalidAssumptionException.class);
         nodeInfoAnnotation = getRequired(context, NodeInfo.class);
-        nodeInfoKind = getRequired(context, NodeInfo.Kind.class);
+        nodeCost = getRequired(context, NodeCost.class);
         slowPath = getRequired(context, SlowPath.class);
         sourceSection = getRequired(context, SourceSection.class);
         truffleOptions = getRequired(context, TruffleOptions.class);
@@ -107,8 +107,8 @@
         return false;
     }
 
-    public DeclaredType getNodeInfoKind() {
-        return nodeInfoKind;
+    public DeclaredType getNodeCost() {
+        return nodeCost;
     }
 
     private DeclaredType getRequired(ProcessorContext context, Class clazz) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Mon Mar 17 13:08:32 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Mon Mar 17 14:30:59 2014 +0100
@@ -32,7 +32,6 @@
 import javax.lang.model.util.*;
 
 import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.nodes.NodeInfo.Kind;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.ast.*;
@@ -953,28 +952,28 @@
                 clazz.add(createGenericExecute(node, rootGroup));
             }
 
-            clazz.add(createGetKind(node, null, Kind.SPECIALIZED));
+            clazz.add(createGetCost(node, null, NodeCost.MONOMORPHIC));
         }
 
         protected boolean needsInvokeCopyConstructorMethod() {
             return getModel().getNode().isPolymorphic();
         }
 
-        protected CodeExecutableElement createGetKind(NodeData node, SpecializationData specialization, Kind kind) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getTruffleTypes().getNodeInfoKind(), "getKind");
-
-            TypeMirror nodeInfoKind = context.getTruffleTypes().getNodeInfoKind();
+        protected CodeExecutableElement createGetCost(NodeData node, SpecializationData specialization, NodeCost cost) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getTruffleTypes().getNodeCost(), "getCost");
+
+            TypeMirror nodeInfoKind = context.getTruffleTypes().getNodeCost();
 
             CodeTreeBuilder builder = method.createBuilder();
             if (node.isPolymorphic() && specialization == null) {
                 // assume next0 exists
-                builder.startIf().string("next0 != null && next0.getKind() == ").staticReference(nodeInfoKind, "SPECIALIZED").end();
+                builder.startIf().string("next0 != null && next0.getCost() == ").staticReference(nodeInfoKind, "MONOMORPHIC").end();
                 builder.startBlock();
                 builder.startReturn().staticReference(nodeInfoKind, "POLYMORPHIC").end();
                 builder.end();
             }
 
-            builder.startReturn().staticReference(nodeInfoKind, kind.name()).end();
+            builder.startReturn().staticReference(nodeInfoKind, cost.name()).end();
             return method;
         }
 
@@ -2475,7 +2474,7 @@
             }
             CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node), baseType, false);
 
-            clazz.getAnnotationMirrors().add(createNodeInfo(node, Kind.POLYMORPHIC));
+            clazz.getAnnotationMirrors().add(createNodeInfo(node, NodeCost.NONE));
 
             for (ActualParameter polymorphParameter : polymorph.getSignatureParameters()) {
                 if (!polymorphParameter.getTypeSystemType().isGeneric()) {
@@ -2522,7 +2521,7 @@
             }
 
             createCachedExecuteMethods(specialization);
-            clazz.add(createGetKind(specialization.getNode(), specialization, Kind.SPECIALIZED));
+            clazz.add(createGetCost(specialization.getNode(), specialization, NodeCost.NONE));
         }
 
         private ExecutableElement createUpdateType(ActualParameter parameter) {
@@ -2562,34 +2561,34 @@
             }
             CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false);
 
-            Kind kind;
+            NodeCost cost;
             if (specialization.isGeneric()) {
-                kind = Kind.GENERIC;
+                cost = NodeCost.MEGAMORPHIC;
             } else if (specialization.isUninitialized()) {
-                kind = Kind.UNINITIALIZED;
+                cost = NodeCost.UNINITIALIZED;
             } else if (specialization.isPolymorphic()) {
-                kind = Kind.POLYMORPHIC;
+                cost = NodeCost.NONE;
             } else if (specialization.isSpecialized()) {
-                kind = Kind.SPECIALIZED;
+                cost = NodeCost.MONOMORPHIC;
             } else {
                 throw new AssertionError();
             }
-            clazz.getAnnotationMirrors().add(createNodeInfo(node, kind));
+            clazz.getAnnotationMirrors().add(createNodeInfo(node, cost));
 
             return clazz;
         }
 
-        protected CodeAnnotationMirror createNodeInfo(NodeData node, Kind kind) {
+        protected CodeAnnotationMirror createNodeInfo(NodeData node, NodeCost cost) {
             String shortName = node.getShortName();
             CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation());
             if (shortName != null) {
                 nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("shortName"), new CodeAnnotationValue(shortName));
             }
 
-            DeclaredType nodeinfoKind = getContext().getTruffleTypes().getNodeInfoKind();
-            VariableElement varKind = Utils.findVariableElement(nodeinfoKind, kind.name());
-
-            nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("kind"), new CodeAnnotationValue(varKind));
+            DeclaredType nodeinfoCost = getContext().getTruffleTypes().getNodeCost();
+            VariableElement varKind = Utils.findVariableElement(nodeinfoCost, cost.name());
+
+            nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("cost"), new CodeAnnotationValue(varKind));
             return nodeInfoMirror;
         }
 
@@ -2608,9 +2607,9 @@
             }
 
             if (specialization.isGeneric()) {
-                clazz.add(createGetKind(specialization.getNode(), specialization, Kind.GENERIC));
+                clazz.add(createGetCost(specialization.getNode(), specialization, NodeCost.MEGAMORPHIC));
             } else if (specialization.isUninitialized()) {
-                clazz.add(createGetKind(specialization.getNode(), specialization, Kind.UNINITIALIZED));
+                clazz.add(createGetCost(specialization.getNode(), specialization, NodeCost.UNINITIALIZED));
             }
         }