changeset 9290:17b598df8da9

Merge.
author Doug Simon <doug.simon@oracle.com>
date Thu, 25 Apr 2013 16:53:29 +0200
parents 261a43921c5e (current diff) cadb3702cb8f (diff)
children 90ee20fd2c05
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/DefaultTypeConversion.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotTypeListener.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameVersion.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/TypeConversion.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/intrinsics/ExactMath.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/intrinsics/TruffleIntrinsics.java
diffstat 195 files changed, 3697 insertions(+), 2084 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java	Thu Apr 25 16:53:29 2013 +0200
@@ -26,6 +26,7 @@
 import java.util.*;
 
 import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.util.*;
 
 /**
  * Computes an ordering of the block that can be used by the linear scan register allocator and the
@@ -66,11 +67,11 @@
      * 
      * @return sorted list of blocks
      */
-    public static List<Block> computeLinearScanOrder(int blockCount, Block startBlock) {
+    public static List<Block> computeLinearScanOrder(int blockCount, Block startBlock, NodesToDoubles nodeProbabilities) {
         List<Block> order = new ArrayList<>();
         BitSet visitedBlocks = new BitSet(blockCount);
-        PriorityQueue<Block> worklist = initializeWorklist(startBlock, visitedBlocks);
-        computeLinearScanOrder(order, worklist, visitedBlocks);
+        PriorityQueue<Block> worklist = initializeWorklist(startBlock, visitedBlocks, nodeProbabilities);
+        computeLinearScanOrder(order, worklist, visitedBlocks, nodeProbabilities);
         assert checkOrder(order, blockCount);
         return order;
     }
@@ -80,11 +81,11 @@
      * 
      * @return sorted list of blocks
      */
-    public static List<Block> computeCodeEmittingOrder(int blockCount, Block startBlock) {
+    public static List<Block> computeCodeEmittingOrder(int blockCount, Block startBlock, NodesToDoubles nodeProbabilities) {
         List<Block> order = new ArrayList<>();
         BitSet visitedBlocks = new BitSet(blockCount);
-        PriorityQueue<Block> worklist = initializeWorklist(startBlock, visitedBlocks);
-        computeCodeEmittingOrder(order, worklist, visitedBlocks);
+        PriorityQueue<Block> worklist = initializeWorklist(startBlock, visitedBlocks, nodeProbabilities);
+        computeCodeEmittingOrder(order, worklist, visitedBlocks, nodeProbabilities);
         assert checkOrder(order, blockCount);
         return order;
     }
@@ -92,28 +93,28 @@
     /**
      * Iteratively adds paths to the code emission block order.
      */
-    private static void computeCodeEmittingOrder(List<Block> order, PriorityQueue<Block> worklist, BitSet visitedBlocks) {
+    private static void computeCodeEmittingOrder(List<Block> order, PriorityQueue<Block> worklist, BitSet visitedBlocks, NodesToDoubles nodeProbabilities) {
         while (!worklist.isEmpty()) {
             Block nextImportantPath = worklist.poll();
-            addPathToCodeEmittingOrder(nextImportantPath, order, worklist, visitedBlocks);
+            addPathToCodeEmittingOrder(nextImportantPath, order, worklist, visitedBlocks, nodeProbabilities);
         }
     }
 
     /**
      * Iteratively adds paths to the linear scan block order.
      */
-    private static void computeLinearScanOrder(List<Block> order, PriorityQueue<Block> worklist, BitSet visitedBlocks) {
+    private static void computeLinearScanOrder(List<Block> order, PriorityQueue<Block> worklist, BitSet visitedBlocks, NodesToDoubles nodeProbabilities) {
         while (!worklist.isEmpty()) {
             Block nextImportantPath = worklist.poll();
-            addPathToLinearScanOrder(nextImportantPath, order, worklist, visitedBlocks);
+            addPathToLinearScanOrder(nextImportantPath, order, worklist, visitedBlocks, nodeProbabilities);
         }
     }
 
     /**
      * Initializes the priority queue used for the work list of blocks and adds the start block.
      */
-    private static PriorityQueue<Block> initializeWorklist(Block startBlock, BitSet visitedBlocks) {
-        PriorityQueue<Block> result = new PriorityQueue<>(INITIAL_WORKLIST_CAPACITY, blockComparator);
+    private static PriorityQueue<Block> initializeWorklist(Block startBlock, BitSet visitedBlocks, NodesToDoubles nodeProbabilities) {
+        PriorityQueue<Block> result = new PriorityQueue<>(INITIAL_WORKLIST_CAPACITY, new BlockOrderComparator(nodeProbabilities));
         result.add(startBlock);
         visitedBlocks.set(startBlock.getId());
         return result;
@@ -122,10 +123,10 @@
     /**
      * Add a linear path to the linear scan order greedily following the most likely successor.
      */
-    private static void addPathToLinearScanOrder(Block block, List<Block> order, PriorityQueue<Block> worklist, BitSet visitedBlocks) {
+    private static void addPathToLinearScanOrder(Block block, List<Block> order, PriorityQueue<Block> worklist, BitSet visitedBlocks, NodesToDoubles nodeProbabilities) {
         block.setLinearScanNumber(order.size());
         order.add(block);
-        Block mostLikelySuccessor = findAndMarkMostLikelySuccessor(block, visitedBlocks);
+        Block mostLikelySuccessor = findAndMarkMostLikelySuccessor(block, visitedBlocks, nodeProbabilities);
         enqueueSuccessors(block, worklist, visitedBlocks);
         if (mostLikelySuccessor != null) {
             if (!mostLikelySuccessor.isLoopHeader() && mostLikelySuccessor.getPredecessorCount() > 1) {
@@ -134,24 +135,24 @@
                 double unscheduledSum = 0.0;
                 for (Block pred : mostLikelySuccessor.getPredecessors()) {
                     if (pred.getLinearScanNumber() == -1) {
-                        unscheduledSum += pred.getBeginNode().probability();
+                        unscheduledSum += nodeProbabilities.get(pred.getBeginNode());
                     }
                 }
 
-                if (unscheduledSum > block.getProbability() / PENALTY_VERSUS_UNSCHEDULED) {
+                if (unscheduledSum > nodeProbabilities.get(block.getBeginNode()) / PENALTY_VERSUS_UNSCHEDULED) {
                     // Add this merge only after at least one additional predecessor gets scheduled.
                     visitedBlocks.clear(mostLikelySuccessor.getId());
                     return;
                 }
             }
-            addPathToLinearScanOrder(mostLikelySuccessor, order, worklist, visitedBlocks);
+            addPathToLinearScanOrder(mostLikelySuccessor, order, worklist, visitedBlocks, nodeProbabilities);
         }
     }
 
     /**
      * Add a linear path to the code emission order greedily following the most likely successor.
      */
-    private static void addPathToCodeEmittingOrder(Block block, List<Block> order, PriorityQueue<Block> worklist, BitSet visitedBlocks) {
+    private static void addPathToCodeEmittingOrder(Block block, List<Block> order, PriorityQueue<Block> worklist, BitSet visitedBlocks, NodesToDoubles nodeProbabilities) {
 
         // Skip loop headers if there is only a single loop end block to make the backward jump be a
         // conditional jump.
@@ -180,10 +181,10 @@
             }
         }
 
-        Block mostLikelySuccessor = findAndMarkMostLikelySuccessor(block, visitedBlocks);
+        Block mostLikelySuccessor = findAndMarkMostLikelySuccessor(block, visitedBlocks, nodeProbabilities);
         enqueueSuccessors(block, worklist, visitedBlocks);
         if (mostLikelySuccessor != null) {
-            addPathToCodeEmittingOrder(mostLikelySuccessor, order, worklist, visitedBlocks);
+            addPathToCodeEmittingOrder(mostLikelySuccessor, order, worklist, visitedBlocks, nodeProbabilities);
         }
     }
 
@@ -198,11 +199,12 @@
     /**
      * Find the highest likely unvisited successor block of a given block.
      */
-    private static Block findAndMarkMostLikelySuccessor(Block block, BitSet visitedBlocks) {
+    private static Block findAndMarkMostLikelySuccessor(Block block, BitSet visitedBlocks, NodesToDoubles nodeProbabilities) {
         Block result = null;
         for (Block successor : block.getSuccessors()) {
-            assert successor.getProbability() >= 0.0 : "Probabilities must be positive";
-            if (!visitedBlocks.get(successor.getId()) && successor.getLoopDepth() >= block.getLoopDepth() && (result == null || successor.getProbability() >= result.getProbability())) {
+            assert nodeProbabilities.get(successor.getBeginNode()) >= 0.0 : "Probabilities must be positive";
+            if (!visitedBlocks.get(successor.getId()) && successor.getLoopDepth() >= block.getLoopDepth() &&
+                            (result == null || nodeProbabilities.get(successor.getBeginNode()) >= nodeProbabilities.get(result.getBeginNode()))) {
                 result = successor;
             }
         }
@@ -243,7 +245,13 @@
     /**
      * Comparator for sorting blocks based on loop depth and probability.
      */
-    private static Comparator<Block> blockComparator = new Comparator<Block>() {
+    private static class BlockOrderComparator implements Comparator<Block> {
+
+        private final NodesToDoubles probabilities;
+
+        public BlockOrderComparator(NodesToDoubles probabilities) {
+            this.probabilities = probabilities;
+        }
 
         @Override
         public int compare(Block a, Block b) {
@@ -254,11 +262,11 @@
             }
 
             // Blocks with high probability before blocks with low probability.
-            if (a.getProbability() > b.getProbability()) {
+            if (probabilities.get(a.getBeginNode()) > probabilities.get(b.getBeginNode())) {
                 return -1;
             } else {
                 return 1;
             }
         }
-    };
+    }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -306,9 +306,8 @@
 
     private void processMethod(final String snippet) {
         graph = parse(snippet);
-        new ComputeProbabilityPhase().apply(graph);
         Assumptions assumptions = new Assumptions(false);
-        HighTierContext context = new HighTierContext(runtime(), assumptions);
+        HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
         new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
         new PartialEscapeAnalysisPhase(false, false).apply(graph, context);
         new CullFrameStatesPhase().apply(graph);
@@ -325,9 +324,8 @@
             public void run() {
                 graph = parse(snippet);
 
-                new ComputeProbabilityPhase().apply(graph);
                 Assumptions assumptions = new Assumptions(false);
-                HighTierContext context = new HighTierContext(runtime(), assumptions);
+                HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
                 new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
                 if (loopPeeling) {
                     new LoopTransformHighPhase().apply(graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -29,7 +29,9 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.Lowerable.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 public class FloatingReadTest extends GraphScheduleTest {
 
@@ -57,7 +59,8 @@
 
             public void run() {
                 StructuredGraph graph = parse(snippet);
-                new LoweringPhase(null, runtime(), replacements, new Assumptions(false)).apply(graph);
+                HighTierContext context = new HighTierContext(runtime(), new Assumptions(false), replacements);
+                new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
                 new FloatingReadPhase().apply(graph);
 
                 ReturnNode returnNode = null;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -33,10 +33,12 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.Lowerable.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.phases.tiers.*;
 
 /**
  * In these test the FrameStates are explicitly cleared out, so that the scheduling of
@@ -221,7 +223,8 @@
                     Assumptions assumptions = new Assumptions(false);
                     new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
                 }
-                new LoweringPhase(null, runtime(), replacements, new Assumptions(false)).apply(graph);
+                HighTierContext context = new HighTierContext(runtime(), new Assumptions(false), replacements);
+                new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
                 if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) {
                     for (Node node : graph.getNodes()) {
                         if (node instanceof StateSplit) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -32,7 +32,9 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.Lowerable.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 public class PushNodesThroughPiTest extends GraalCompilerTest {
 
@@ -82,10 +84,11 @@
 
     private StructuredGraph compileTestSnippet(final String snippet) {
         StructuredGraph graph = parse(snippet);
-        new LoweringPhase(null, runtime(), replacements, new Assumptions(false)).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), null).apply(graph);
+        HighTierContext context = new HighTierContext(runtime(), new Assumptions(false), replacements);
+        new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
+        new CanonicalizerPhase().apply(graph, context);
         new PushThroughPiPhase().apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), null).apply(graph);
+        new CanonicalizerPhase().apply(graph, context);
 
         return graph;
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -32,7 +32,9 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.Lowerable.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 /* consider
  *     B b = (B) a;
@@ -85,11 +87,12 @@
             // structure changes significantly
             public void run() {
                 StructuredGraph graph = parse(snippet);
-                new LoweringPhase(null, runtime(), replacements, new Assumptions(false)).apply(graph);
+                HighTierContext context = new HighTierContext(runtime(), new Assumptions(false), replacements);
+                new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
                 new FloatingReadPhase().apply(graph);
                 new EliminatePartiallyRedundantGuardsPhase(true, false).apply(graph);
                 new ReadEliminationPhase().apply(graph);
-                new CanonicalizerPhase.Instance(runtime(), null).apply(graph);
+                new CanonicalizerPhase().apply(graph, context);
 
                 Debug.dump(graph, "After lowering");
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/WriteBarrierAdditionTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2013, 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.
+ *
+ * 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.graal.compiler.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.hotspot.phases.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.extended.WriteNode.WriteBarrierType;
+import com.oracle.graal.nodes.spi.Lowerable.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+
+public class WriteBarrierAdditionTest extends GraalCompilerTest {
+
+    public static class Container {
+
+        public Container a;
+        public Container b;
+    }
+
+    public static void test1Snippet() {
+        Container main = new Container();
+        Container temp1 = new Container();
+        Container temp2 = new Container();
+        main.a = temp1;
+        main.b = temp2;
+    }
+
+    public static void test2Snippet(boolean test) {
+        Container main = new Container();
+        Container temp1 = new Container();
+        Container temp2 = new Container();
+        for (int i = 0; i < 10; i++) {
+            if (test) {
+                main.a = temp1;
+                main.b = temp2;
+            } else {
+                main.a = temp2;
+                main.b = temp1;
+            }
+        }
+    }
+
+    public static void test3Snippet() {
+        Container[] main = new Container[10];
+        Container temp1 = new Container();
+        Container temp2 = new Container();
+        for (int i = 0; i < 10; i++) {
+            main[i].a = main[i].b = temp1;
+        }
+
+        for (int i = 0; i < 10; i++) {
+            main[i].a = main[i].b = temp2;
+        }
+
+    }
+
+    @Test
+    public void test1() {
+        test("test1Snippet", 2);
+    }
+
+    @Test
+    public void test2() {
+        test("test2Snippet", 4);
+    }
+
+    @Test
+    public void test3() {
+        test("test3Snippet", 4);
+    }
+
+    private void test(final String snippet, final int expectedBarriers) {
+        Debug.scope("WriteBarrierAditionTest", new DebugDumpScope(snippet), new Runnable() {
+
+            public void run() {
+                StructuredGraph graph = parse(snippet);
+                HighTierContext context = new HighTierContext(runtime(), new Assumptions(false), replacements);
+                new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
+                new WriteBarrierAdditionPhase().apply(graph);
+                Debug.dump(graph, "After Write Barrier Addition");
+                final int barriers = graph.getNodes(SerialWriteBarrier.class).count();
+                Assert.assertTrue(barriers == expectedBarriers);
+                for (WriteNode write : graph.getNodes(WriteNode.class)) {
+                    if (write.getWriteBarrierType() != WriteBarrierType.NONE) {
+                        Assert.assertTrue(write.successors().count() == 1);
+                        Assert.assertTrue(write.next() instanceof SerialWriteBarrier);
+                    }
+                }
+            }
+        });
+    }
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -218,12 +218,9 @@
 
             public ReturnNode call() {
                 new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
-                for (Invoke n : graph.getInvokes()) {
-                    n.setInliningRelevance(1);
-                }
 
                 Assumptions assumptions = new Assumptions(false);
-                HighTierContext context = new HighTierContext(runtime(), assumptions);
+                HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
                 new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
                 new PartialEscapeAnalysisPhase(iterativeEscapeAnalysis, false).apply(graph, context);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -33,7 +33,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.phases.ea.*;
 
@@ -101,9 +100,8 @@
 
     private void processMethod(final String snippet) {
         graph = parse(snippet);
-        new ComputeProbabilityPhase().apply(graph);
         GraalOptions.OptEarlyReadElimination = true;
-        HighTierContext context = new HighTierContext(runtime(), new Assumptions(false));
+        HighTierContext context = new HighTierContext(runtime(), new Assumptions(false), replacements);
         new IterativeInliningPhase(replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL, false).apply(graph, context);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -221,9 +221,8 @@
 
     private void processMethod(final String snippet) {
         graph = parse(snippet);
-        new ComputeProbabilityPhase().apply(graph);
         Assumptions assumptions = new Assumptions(false);
-        HighTierContext context = new HighTierContext(runtime(), assumptions);
+        HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
         new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
         new PartialEscapeAnalysisPhase(false, true).apply(graph, context);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -34,8 +34,10 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.graph.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.nodes.*;
 import com.oracle.graal.virtual.phases.ea.*;
@@ -131,10 +133,12 @@
         try {
             Assert.assertTrue("partial escape analysis should have removed all NewInstanceNode allocations", result.getNodes(NewInstanceNode.class).isEmpty());
             Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", result.getNodes(NewArrayNode.class).isEmpty());
+
+            NodesToDoubles nodeProbabilities = new ComputeProbabilityClosure(result).apply();
             double probabilitySum = 0;
             int materializeCount = 0;
             for (MaterializeObjectNode materialize : result.getNodes(MaterializeObjectNode.class)) {
-                probabilitySum += materialize.probability();
+                probabilitySum += nodeProbabilities.get(materialize);
                 materializeCount++;
             }
             Assert.assertEquals("unexpected number of MaterializeObjectNodes", expectedCount, materializeCount);
@@ -156,12 +160,9 @@
             @Override
             public StructuredGraph call() {
                 StructuredGraph graph = parse(snippet);
-                new ComputeProbabilityPhase().apply(graph);
-                for (Invoke n : graph.getInvokes()) {
-                    n.asNode().setProbability(100000);
-                }
+
                 Assumptions assumptions = new Assumptions(false);
-                HighTierContext context = new HighTierContext(runtime(), assumptions);
+                HighTierContext context = new HighTierContext(runtime(), assumptions, replacements);
                 new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
                 new CanonicalizerPhase().apply(graph, context);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -158,7 +158,6 @@
                 StructuredGraph graph = eagerInfopointMode ? parseDebug(method) : parse(method);
                 PhasePlan phasePlan = getDefaultPhasePlan(eagerInfopointMode);
                 Assumptions assumptions = new Assumptions(true);
-                new ComputeProbabilityPhase().apply(graph);
                 Debug.dump(graph, "Graph");
                 new InliningPhase(runtime(), null, replacements, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
                 Debug.dump(graph, "Graph");
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Apr 25 16:53:29 2013 +0200
@@ -38,9 +38,11 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.graph.*;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.phases.ea.*;
@@ -99,8 +101,8 @@
      * 
      * @param target
      */
-    public static LIR emitHIR(GraalCodeCacheProvider runtime, TargetDescription target, StructuredGraph graph, Replacements replacements, Assumptions assumptions, GraphCache cache, PhasePlan plan,
-                    OptimisticOptimizations optimisticOpts, final SpeculationLog speculationLog) {
+    public static LIR emitHIR(GraalCodeCacheProvider runtime, TargetDescription target, final StructuredGraph graph, Replacements replacements, Assumptions assumptions, GraphCache cache,
+                    PhasePlan plan, OptimisticOptimizations optimisticOpts, final SpeculationLog speculationLog) {
 
         if (speculationLog != null) {
             speculationLog.snapshot();
@@ -113,15 +115,11 @@
             Debug.dump(graph, "initial state");
         }
 
-        if (GraalOptions.ProbabilityAnalysis && graph.start().probability() == 0) {
-            new ComputeProbabilityPhase().apply(graph);
-        }
-
         if (GraalOptions.OptCanonicalizer) {
             new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph);
         }
 
-        HighTierContext highTierContext = new HighTierContext(runtime, assumptions);
+        HighTierContext highTierContext = new HighTierContext(runtime, assumptions, replacements);
 
         if (GraalOptions.Inline && !plan.isPhaseDisabled(InliningPhase.class)) {
             if (GraalOptions.IterativeInlining) {
@@ -141,25 +139,13 @@
 
         Suites.DEFAULT.getHighTier().apply(graph, highTierContext);
 
-        new LoweringPhase(target, runtime, replacements, assumptions).apply(graph);
-
-        MidTierContext midTierContext = new MidTierContext(runtime, assumptions, replacements);
+        MidTierContext midTierContext = new MidTierContext(runtime, assumptions, replacements, target);
         Suites.DEFAULT.getMidTier().apply(graph, midTierContext);
 
-        plan.runPhases(PhasePosition.MID_LEVEL, graph);
-
-        // Add safepoints to loops
-        new SafepointInsertionPhase().apply(graph);
-
-        new GuardLoweringPhase(target).apply(graph);
-
         plan.runPhases(PhasePosition.LOW_LEVEL, graph);
 
-        new LoweringPhase(target, runtime, replacements, assumptions).apply(graph);
-
-        new FrameStateAssignmentPhase().apply(graph);
-
-        new DeadCodeEliminationPhase().apply(graph);
+        LowTierContext lowTierContext = new LowTierContext(runtime, assumptions, replacements, target);
+        Suites.DEFAULT.getLowTier().apply(graph, lowTierContext);
 
         final SchedulePhase schedule = new SchedulePhase();
         schedule.apply(graph);
@@ -170,14 +156,13 @@
         assert startBlock != null;
         assert startBlock.getPredecessorCount() == 0;
 
-        new ComputeProbabilityPhase().apply(graph);
-
         return Debug.scope("ComputeLinearScanOrder", new Callable<LIR>() {
 
             @Override
             public LIR call() {
-                List<Block> codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock);
-                List<Block> linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock);
+                NodesToDoubles nodeProbabilities = new ComputeProbabilityClosure(graph).apply();
+                List<Block> codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock, nodeProbabilities);
+                List<Block> linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock, nodeProbabilities);
 
                 LIR lir = new LIR(schedule.getCFG(), schedule.getBlockToNodesMap(), linearScanOrder, codeEmittingOrder, speculationLog);
                 Debug.dump(lir, "After linear scan order");
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/BasicCompilerConfiguration.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/BasicCompilerConfiguration.java	Thu Apr 25 16:53:29 2013 +0200
@@ -36,4 +36,8 @@
     public PhaseSuite<MidTierContext> createMidTier() {
         return new MidTier();
     }
+
+    public PhaseSuite<LowTierContext> createLowTier() {
+        return new LowTier();
+    }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Thu Apr 25 16:53:29 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.compiler.phases;
 
 import com.oracle.graal.loop.phases.*;
+import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -68,6 +69,8 @@
         if (GraalOptions.OptCanonicalizer) {
             addPhase(new CanonicalizerPhase());
         }
+
+        addPhase(new LoweringPhase(LoweringType.BEFORE_GUARDS));
     }
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, 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.
+ *
+ * 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.graal.compiler.phases;
+
+import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+
+public class LowTier extends PhaseSuite<LowTierContext> {
+
+    public LowTier() {
+        addPhase(new LoweringPhase(LoweringType.AFTER_GUARDS));
+
+        addPhase(new FrameStateAssignmentPhase());
+
+        addPhase(new DeadCodeEliminationPhase());
+    }
+}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Thu Apr 25 16:53:29 2013 +0200
@@ -65,5 +65,10 @@
         if (GraalOptions.OptCanonicalizer) {
             addPhase(new CanonicalizerPhase());
         }
+
+        // Add safepoints to loops
+        addPhase(new SafepointInsertionPhase());
+
+        addPhase(new GuardLoweringPhase());
     }
 }
--- a/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/AMD64HotSpotFrameOmissionTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/AMD64HotSpotFrameOmissionTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -30,6 +30,7 @@
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.Register.RegisterFlag;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.asm.amd64.*;
@@ -70,8 +71,9 @@
 
             @Override
             public void generateCode(AMD64Assembler asm) {
-                asm.addl(rsi, 5);
-                asm.movl(rax, rsi);
+                Register arg = getArgumentRegister(0, RegisterFlag.CPU);
+                asm.addl(arg, 5);
+                asm.movl(rax, arg);
                 asm.ret(0);
             }
         });
@@ -87,8 +89,9 @@
 
             @Override
             public void generateCode(AMD64Assembler asm) {
-                asm.addq(rsi, 1);
-                asm.movq(rax, rsi);
+                Register arg = getArgumentRegister(0, RegisterFlag.CPU);
+                asm.addq(arg, 1);
+                asm.movq(rax, arg);
                 asm.ret(0);
             }
         });
@@ -113,4 +116,9 @@
 
         Assert.assertArrayEquals(expectedCode, actualCode);
     }
+
+    private Register getArgumentRegister(int index, RegisterFlag flag) {
+        Register[] regs = runtime.lookupRegisterConfig().getCallingConventionRegisters(CallingConvention.Type.JavaCall, flag);
+        return regs[index];
+    }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Thu Apr 25 16:53:29 2013 +0200
@@ -43,11 +43,11 @@
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.ParametersOp;
+import com.oracle.graal.lir.StandardOp.PlaceholderOp;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 
 /**
@@ -71,15 +71,43 @@
     StackSlot deoptimizationRescueSlot;
 
     /**
-     * The position at which the instruction for saving RBP should be inserted.
+     * Utility for emitting the instruction to save RBP.
      */
-    Block saveRbpBlock;
-    int saveRbpIndex;
+    class SaveRbp {
+
+        final PlaceholderOp placeholder;
+
+        /**
+         * The slot reserved for saving RBP.
+         */
+        final StackSlot reservedSlot;
+
+        public SaveRbp(PlaceholderOp placeholder) {
+            this.placeholder = placeholder;
+            this.reservedSlot = frameMap.allocateSpillSlot(Kind.Long);
+            assert reservedSlot.getRawOffset() == -16 : reservedSlot.getRawOffset();
+        }
 
-    /**
-     * The slot reserved for saving RBP.
-     */
-    StackSlot rbpSlot;
+        /**
+         * Replaces this operation with the appropriate move for saving rbp.
+         * 
+         * @param useStack specifies if rbp must be saved to the stack
+         */
+        public AllocatableValue finalize(boolean useStack) {
+            AllocatableValue dst;
+            if (useStack) {
+                dst = reservedSlot;
+            } else {
+                frameMap.freeSpillSlot(reservedSlot);
+                dst = newVariable(Kind.Long);
+            }
+
+            placeholder.replace(lir, new MoveFromRegOp(dst, rbp.asValue(Kind.Long)));
+            return dst;
+        }
+    }
+
+    private SaveRbp saveRbp;
 
     /**
      * List of epilogue operations that need to restore RBP.
@@ -119,11 +147,9 @@
 
         ParametersOp paramsOp = new ParametersOp(params);
         append(paramsOp);
-        saveRbpBlock = currentBlock;
-        saveRbpIndex = lir.lir(saveRbpBlock).size();
-        append(paramsOp); // placeholder
-        rbpSlot = frameMap.allocateSpillSlot(Kind.Long);
-        assert rbpSlot.getRawOffset() == -16 : rbpSlot.getRawOffset();
+
+        saveRbp = new SaveRbp(new PlaceholderOp(currentBlock, lir.lir(currentBlock).size()));
+        append(saveRbp.placeholder);
 
         for (LocalNode local : graph.getNodes(LocalNode.class)) {
             Value param = params[local.index()];
@@ -238,23 +264,14 @@
 
     @Override
     public void beforeRegisterAllocation() {
-        assert rbpSlot != null;
-        RegisterValue rbpParam = rbp.asValue(Kind.Long);
-        AllocatableValue savedRbp;
-        LIRInstruction saveRbp;
-        if (lir.hasDebugInfo()) {
-            savedRbp = rbpSlot;
+        boolean hasDebugInfo = lir.hasDebugInfo();
+        AllocatableValue savedRbp = saveRbp.finalize(hasDebugInfo);
+        if (hasDebugInfo) {
             deoptimizationRescueSlot = frameMap.allocateSpillSlot(Kind.Long);
-        } else {
-            frameMap.freeSpillSlot(rbpSlot);
-            savedRbp = newVariable(Kind.Long);
         }
 
         for (AMD64HotSpotEpilogueOp op : epilogueOps) {
             op.savedRbp = savedRbp;
         }
-
-        saveRbp = new MoveFromRegOp(savedRbp, rbpParam);
-        lir.lir(saveRbpBlock).set(saveRbpIndex, saveRbp);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -44,7 +44,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         byte[] formatBytes = string.getBytes();
         long cstring = unsafe.allocateMemory(formatBytes.length + 1);
         for (int i = 0; i < formatBytes.length; i++) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -52,7 +52,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         if (code.isConstant() && code.asConstant().asObject() instanceof HotSpotInstalledCode) {
             HotSpotInstalledCode hsCode = (HotSpotInstalledCode) code.asConstant().asObject();
             InvokeNode invoke = replaceWithInvoke(tool.getRuntime());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -82,7 +82,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeObjectNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeObjectNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -64,7 +64,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -45,7 +45,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPost.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPost.java	Thu Apr 25 16:53:29 2013 +0200
@@ -58,7 +58,7 @@
         this.precise = precise;
     }
 
-    public void lower(LoweringTool generator) {
+    public void lower(LoweringTool generator, LoweringType loweringType) {
         generator.getRuntime().lower(this, generator);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPre.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPre.java	Thu Apr 25 16:53:29 2013 +0200
@@ -58,7 +58,7 @@
         this.expectedObject = expectedObject;
     }
 
-    public void lower(LoweringTool generator) {
+    public void lower(LoweringTool generator, LoweringType loweringType) {
         generator.getRuntime().lower(this, generator);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -82,7 +82,7 @@
         }
         // the canonicalization before loop unrolling is needed to propagate the length into
         // additions, etc.
-        HighTierContext context = new HighTierContext(tool.getRuntime(), tool.assumptions());
+        HighTierContext context = new HighTierContext(tool.getRuntime(), tool.assumptions(), tool.getReplacements());
         new CanonicalizerPhase().apply(snippetGraph, context);
         new LoopFullUnrollPhase().apply(snippetGraph, context);
         new CanonicalizerPhase().apply(snippetGraph, context);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -43,13 +43,14 @@
     private ConstantNode getConstantCallTarget(MetaAccessProvider metaAccessProvider, Assumptions assumptions) {
         if (getCallSite().isConstant() && !getCallSite().isNullConstant()) {
             CallSite callSite = (CallSite) getCallSite().asConstant().asObject();
-            if (callSite instanceof ConstantCallSite) {
-                return ConstantNode.forObject(callSite.getTarget(), metaAccessProvider, graph());
-            } else if (callSite instanceof MutableCallSite || callSite instanceof VolatileCallSite && assumptions != null && assumptions.useOptimisticAssumptions()) {
-                MethodHandle target = callSite.getTarget();
+            MethodHandle target = callSite.getTarget();
+            if (!(callSite instanceof ConstantCallSite)) {
+                if (assumptions == null || !assumptions.useOptimisticAssumptions()) {
+                    return null;
+                }
                 assumptions.record(new Assumptions.CallSiteTargetValue(callSite, target));
-                return ConstantNode.forObject(target, metaAccessProvider, graph());
             }
+            return ConstantNode.forObject(target, metaAccessProvider, graph());
         }
         return null;
     }
@@ -65,7 +66,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         StructuredGraph graph = (StructuredGraph) graph();
         ConstantNode target = getConstantCallTarget(tool.getRuntime(), tool.assumptions());
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Thu Apr 25 16:53:29 2013 +0200
@@ -96,11 +96,16 @@
 
     /**
      * Size of the area occupied by outgoing overflow arguments. This value is adjusted as calling
-     * conventions for outgoing calls are retrieved.
+     * conventions for outgoing calls are retrieved. On some platforms, there is a minimum
      */
     private int outgoingSize;
 
     /**
+     * Determines if this frame has values on the stack for outgoing calls.
+     */
+    private boolean hasOutgoingStackArguments;
+
+    /**
      * The list of stack areas allocated in this frame that are present in every reference map.
      */
     private final List<StackSlot> objectStackBlocks;
@@ -157,8 +162,8 @@
      * {@link Architecture#getReturnAddressSize() return address slot}.
      */
     public boolean frameNeedsAllocating() {
-        int unalignedFrameSize = outgoingSize + spillSize - returnAddressSize();
-        return unalignedFrameSize != 0;
+        int unalignedFrameSize = spillSize - returnAddressSize();
+        return hasOutgoingStackArguments || unalignedFrameSize != 0;
     }
 
     /**
@@ -247,6 +252,7 @@
     public void reserveOutgoing(int argsSize) {
         assert frameSize == -1 : "frame size must not yet be fixed";
         outgoingSize = Math.max(outgoingSize, argsSize);
+        hasOutgoingStackArguments = hasOutgoingStackArguments || argsSize > 0;
     }
 
     private StackSlot getSlot(Kind kind, int additionalOffset) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Thu Apr 25 16:53:29 2013 +0200
@@ -117,6 +117,6 @@
 
     @Override
     public String toString() {
-        return debugInfo != null ? debugInfo.toString() : topFrame.toString();
+        return debugInfo != null ? debugInfo.toString() : topFrame != null ? topFrame.toString() : "<empty>";
     }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Thu Apr 25 16:53:29 2013 +0200
@@ -24,7 +24,10 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.cfg.*;
+
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 /**
@@ -135,4 +138,34 @@
             // No code to emit.
         }
     }
+
+    /**
+     * Placeholder for a LIR instruction that will be subsequently replaced.
+     */
+    public static class PlaceholderOp extends LIRInstruction {
+
+        /**
+         * The block in which this instruction is located.
+         */
+        final Block block;
+
+        /**
+         * The block index of this instruction.
+         */
+        final int index;
+
+        public PlaceholderOp(Block block, int index) {
+            this.block = block;
+            this.index = index;
+        }
+
+        public void replace(LIR lir, LIRInstruction replacement) {
+            lir.lir(block).set(index, replacement);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm) {
+            throw new GraalInternalError(this + " should have been replaced");
+        }
+    }
 }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Thu Apr 25 16:53:29 2013 +0200
@@ -248,7 +248,6 @@
                 continue;
             }
             MergeNode merge = graph.add(new MergeNode());
-            merge.setProbability(next.probability());
             EndNode originalEnd = graph.add(new EndNode());
             EndNode newEnd = graph.add(new EndNode());
             merge.addForwardEnd(originalEnd);
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Thu Apr 25 16:53:29 2013 +0200
@@ -102,7 +102,6 @@
             GraphUtil.killWithUnusedFloatingInputs(state);
         }
         loop.entryPoint().replaceAtPredecessor(entry);
-        end.setProbability(loop.entryPoint().probability());
         end.setNext(loop.entryPoint());
     }
 
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Thu Apr 25 16:53:29 2013 +0200
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 
 public abstract class LoopPolicies {
@@ -35,9 +36,9 @@
     }
 
     // TODO (gd) change when inversion is available
-    public static boolean shouldPeel(LoopEx loop) {
+    public static boolean shouldPeel(LoopEx loop, NodesToDoubles probabilities) {
         LoopBeginNode loopBegin = loop.loopBegin();
-        double entryProbability = loopBegin.forwardEnd().probability();
+        double entryProbability = probabilities.get(loopBegin.forwardEnd());
         return entryProbability > GraalOptions.MinimumPeelProbability && loop.size() + loopBegin.graph().getNodeCount() < GraalOptions.MaximumDesiredSize;
     }
 
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java	Thu Apr 25 16:53:29 2013 +0200
@@ -27,7 +27,7 @@
 
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.loop.InductionVariable.*;
+import com.oracle.graal.loop.InductionVariable.Direction;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.cfg.*;
@@ -39,7 +39,6 @@
     private ControlFlowGraph cfg;
 
     public LoopsData(final StructuredGraph graph) {
-
         cfg = Debug.scope("ControlFlowGraph", new Callable<ControlFlowGraph>() {
 
             @Override
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java	Thu Apr 25 16:53:29 2013 +0200
@@ -25,7 +25,9 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.graph.*;
 
 public class LoopTransformHighPhase extends Phase {
 
@@ -33,9 +35,10 @@
     protected void run(StructuredGraph graph) {
         if (graph.hasLoops()) {
             if (GraalOptions.LoopPeeling) {
+                NodesToDoubles probabilities = new ComputeProbabilityClosure(graph).apply();
                 LoopsData data = new LoopsData(graph);
                 for (LoopEx loop : data.outterFirst()) {
-                    if (LoopPolicies.shouldPeel(loop)) {
+                    if (LoopPolicies.shouldPeel(loop, probabilities)) {
                         Debug.log("Peeling %s", loop);
                         LoopTransformations.peel(loop);
                         Debug.dump(graph, "After peeling %s", loop);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -51,7 +51,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -96,7 +96,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -28,8 +28,6 @@
 
 public abstract class FixedNode extends ValueNode {
 
-    private double probability;
-
     public FixedNode(Stamp stamp) {
         super(stamp);
     }
@@ -42,20 +40,6 @@
         super(stamp, dependencies);
     }
 
-    public double probability() {
-        return probability;
-    }
-
-    public void setProbability(double probability) {
-        assert probability >= 0 : String.format("Invalid argument %f, because the probability of a node must not be negative.", probability);
-        this.probability = probability;
-        assert !Double.isNaN(probability);
-    }
-
-    protected void copyInto(FixedNode newNode) {
-        newNode.setProbability(probability);
-    }
-
     @Override
     public boolean verify() {
         assertTrue(this.successors().isNotEmpty() || this.predecessor() != null, "FixedNode should not float");
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -361,13 +361,10 @@
                 PhiNode oldPhi = (PhiNode) oldMerge.usages().first();
                 PhiNode newPhi = graph().add(new PhiNode(oldPhi.stamp(), newMerge));
 
-                double probability = 0.0;
                 for (EndNode end : ends) {
                     newPhi.addInput(phiValues.get(end));
                     newMerge.addForwardEnd(end);
-                    probability += end.probability();
                 }
-                newMerge.setProbability(probability);
 
                 FrameState stateAfter = oldMerge.stateAfter();
                 if (stateAfter != null) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Thu Apr 25 16:53:29 2013 +0200
@@ -45,14 +45,6 @@
 
     void intrinsify(Node node);
 
-    double probability();
-
-    void setProbability(double value);
-
-    double inliningRelevance();
-
-    void setInliningRelevance(double value);
-
     boolean useForInlining();
 
     void setUseForInlining(boolean value);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -41,7 +41,6 @@
     private final int bci;
     private boolean polymorphic;
     private boolean useForInlining;
-    private double inliningRelevance;
 
     /**
      * Constructs a new Invoke instruction.
@@ -55,7 +54,6 @@
         this.bci = bci;
         this.polymorphic = false;
         this.useForInlining = true;
-        this.inliningRelevance = Double.NaN;
     }
 
     @Override
@@ -83,16 +81,6 @@
     }
 
     @Override
-    public double inliningRelevance() {
-        return inliningRelevance;
-    }
-
-    @Override
-    public void setInliningRelevance(double value) {
-        inliningRelevance = value;
-    }
-
-    @Override
     public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
         Map<Object, Object> debugProperties = super.getDebugProperties(map);
         debugProperties.put("targetMethod", callTarget.targetName());
@@ -105,7 +93,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -42,7 +42,6 @@
     private final int bci;
     private boolean polymorphic;
     private boolean useForInlining;
-    private double inliningRelevance;
 
     public InvokeWithExceptionNode(CallTargetNode callTarget, DispatchBeginNode exceptionEdge, int bci) {
         super(callTarget.returnStamp());
@@ -51,7 +50,6 @@
         this.callTarget = callTarget;
         this.polymorphic = false;
         this.useForInlining = true;
-        this.inliningRelevance = Double.NaN;
     }
 
     public DispatchBeginNode exceptionEdge() {
@@ -101,16 +99,6 @@
     }
 
     @Override
-    public double inliningRelevance() {
-        return inliningRelevance;
-    }
-
-    @Override
-    public void setInliningRelevance(double value) {
-        inliningRelevance = value;
-    }
-
-    @Override
     public String toString(Verbosity verbosity) {
         if (verbosity == Verbosity.Long) {
             return super.toString(Verbosity.Short) + "(bci=" + bci() + ")";
@@ -140,7 +128,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialArrayRangeWriteBarrier.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialArrayRangeWriteBarrier.java	Thu Apr 25 16:53:29 2013 +0200
@@ -51,7 +51,7 @@
 
     }
 
-    public void lower(LoweringTool generator) {
+    public void lower(LoweringTool generator, LoweringType loweringType) {
         generator.getRuntime().lower(this, generator);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialWriteBarrier.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialWriteBarrier.java	Thu Apr 25 16:53:29 2013 +0200
@@ -22,11 +22,12 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public final class SerialWriteBarrier extends FixedWithNextNode implements Lowerable {
+public final class SerialWriteBarrier extends FixedWithNextNode implements Lowerable, Node.IterableNodeType {
 
     @Input private ValueNode object;
     @Input private LocationNode location;
@@ -52,7 +53,8 @@
     }
 
     @Override
-    public void lower(LoweringTool generator) {
+    public void lower(LoweringTool generator, LoweringType loweringType) {
+        assert loweringType == LoweringType.AFTER_GUARDS;
         generator.getRuntime().lower(this, generator);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Thu Apr 25 16:53:29 2013 +0200
@@ -236,7 +236,6 @@
 
     public void replaceFixedWithFixed(FixedWithNextNode node, FixedWithNextNode replacement) {
         assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement;
-        replacement.setProbability(node.probability());
         FixedNode next = node.next();
         node.setNext(null);
         replacement.setNext(next);
@@ -307,7 +306,6 @@
 
     public void addAfterFixed(FixedWithNextNode node, FixedNode newNode) {
         assert node != null && newNode != null && node.isAlive() && newNode.isAlive() : "cannot add " + newNode + " after " + node;
-        newNode.setProbability(node.probability());
         FixedNode next = node.next();
         node.setNext(newNode);
         if (next != null) {
@@ -322,7 +320,6 @@
         assert node != null && newNode != null && node.isAlive() && newNode.isAlive() : "cannot add " + newNode + " before " + node;
         assert node.predecessor() != null && node.predecessor() instanceof FixedWithNextNode : "cannot add " + newNode + " before " + node;
         assert newNode.next() == null : newNode;
-        newNode.setProbability(node.probability());
         FixedWithNextNode pred = (FixedWithNextNode) node.predecessor();
         pred.setNext(newNode);
         newNode.setNext(node);
@@ -334,7 +331,6 @@
             reduceTrivialMerge(begin);
         } else { // convert to merge
             MergeNode merge = this.add(new MergeNode());
-            merge.setProbability(begin.probability());
             this.replaceFixedWithFixed(begin, merge);
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -51,7 +51,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -162,7 +162,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -103,7 +103,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -60,7 +60,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
 
 /**
  * An IsNullNode will be true if the supplied value is null, and false if it is non-null.
@@ -81,7 +82,13 @@
 
     @Override
     public boolean push(PiNode parent) {
-        replaceFirstInput(parent, parent.object());
-        return true;
+        ObjectStamp piStamp = parent.objectStamp();
+        ObjectStamp piValueStamp = parent.object().objectStamp();
+        if (piStamp.nonNull() == piValueStamp.nonNull() && piStamp.alwaysNull() == piValueStamp.alwaysNull()) {
+            replaceFirstInput(parent, parent.object());
+            return true;
+        } else {
+            return false;
+        }
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -48,7 +48,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         StructuredGraph graph = (StructuredGraph) graph();
 
         LogicNode equalComp;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -61,7 +61,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -60,7 +60,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Thu Apr 25 16:53:29 2013 +0200
@@ -29,9 +29,10 @@
 
 public final class Block {
 
+    protected final BeginNode beginNode;
+
     protected int id;
 
-    protected BeginNode beginNode;
     protected FixedNode endNode;
     protected Loop loop;
 
@@ -45,8 +46,10 @@
     private boolean align;
     private int linearScanNumber;
 
-    protected Block() {
-        id = ControlFlowGraph.BLOCK_ID_INITIAL;
+    protected Block(BeginNode node) {
+        this.beginNode = node;
+
+        this.id = ControlFlowGraph.BLOCK_ID_INITIAL;
         this.linearScanNumber = -1;
     }
 
@@ -206,10 +209,6 @@
         return dominator.isDominatedBy(block);
     }
 
-    public double getProbability() {
-        return getBeginNode().probability();
-    }
-
     public int getLinearScanNumber() {
         return linearScanNumber;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Thu Apr 25 16:53:29 2013 +0200
@@ -39,6 +39,7 @@
     public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlocks, boolean computeLoops, boolean computeDominators, boolean computePostdominators) {
         ControlFlowGraph cfg = new ControlFlowGraph(graph);
         cfg.identifyBlocks();
+
         if (connectBlocks || computeLoops || computeDominators || computePostdominators) {
             cfg.connectBlocks();
         }
@@ -111,16 +112,15 @@
     public void clearNodeToBlock() {
         nodeToBlock.clear();
         for (Block block : reversePostOrder) {
-            identifyBlock(block, block.beginNode);
+            identifyBlock(block);
         }
     }
 
     protected static final int BLOCK_ID_INITIAL = -1;
     protected static final int BLOCK_ID_VISITED = -2;
 
-    private void identifyBlock(Block block, BeginNode begin) {
-        block.beginNode = begin;
-        Node cur = begin;
+    private void identifyBlock(Block block) {
+        Node cur = block.getBeginNode();
         Node last;
         do {
             assert !cur.isDeleted();
@@ -145,9 +145,9 @@
         int numBlocks = 0;
         for (Node node : graph.getNodes()) {
             if (node instanceof BeginNode) {
-                Block block = new Block();
+                Block block = new Block((BeginNode) node);
                 numBlocks++;
-                identifyBlock(block, (BeginNode) node);
+                identifyBlock(block);
             }
         }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -45,20 +45,24 @@
 
     private static final int MAX_COUNTERS = 10 * 1024;
     private static final long[] COUNTERS = new long[MAX_COUNTERS];
+    private static final long[] STATIC_COUNTERS = new long[MAX_COUNTERS];
+    private static final String[] GROUPS = new String[MAX_COUNTERS];
     private static final HashMap<String, Integer> INDEXES = new HashMap<>();
     public static String excludedClassPrefix = null;
     public static boolean enabled = false;
 
     private final String name;
+    private final String group;
     private final long increment;
     private final boolean addContext;
 
-    public DynamicCounterNode(String name, long increment, boolean addContext) {
+    public DynamicCounterNode(String name, String group, long increment, boolean addContext) {
         super(StampFactory.forVoid());
         if (!enabled) {
             throw new GraalInternalError("dynamic counters not enabled");
         }
         this.name = name;
+        this.group = group;
         this.increment = increment;
         this.addContext = addContext;
     }
@@ -90,29 +94,51 @@
     }
 
     public static synchronized void dump(PrintStream out, double seconds) {
+        for (String group : new HashSet<>(Arrays.asList(GROUPS))) {
+            dumpCounters(out, seconds, true, group);
+            dumpCounters(out, seconds, false, group);
+        }
+        out.println("============================");
+
+        clear();
+    }
+
+    private static void dumpCounters(PrintStream out, double seconds, boolean staticCounter, String group) {
         TreeMap<Long, String> sorted = new TreeMap<>();
 
+        long[] array = staticCounter ? STATIC_COUNTERS : COUNTERS;
         long sum = 0;
-        for (int i = 0; i < MAX_COUNTERS; i++) {
-            sum += COUNTERS[i];
-        }
-        long cutoff = sum / 1000;
-        int cnt = 0;
         for (Map.Entry<String, Integer> entry : INDEXES.entrySet()) {
-            if (COUNTERS[entry.getValue()] > cutoff) {
-                sorted.put(COUNTERS[entry.getValue()] * MAX_COUNTERS + cnt++, entry.getKey());
+            int index = entry.getValue();
+            if (GROUPS[index].equals(group)) {
+                sum += array[index];
+                sorted.put(array[index] * MAX_COUNTERS + index, entry.getKey());
             }
         }
 
-        out.println("=========== dynamic counters, time = " + seconds + " s");
-        for (Map.Entry<Long, String> entry : sorted.entrySet()) {
-            long counter = entry.getKey() / MAX_COUNTERS;
-            out.println((int) (counter / seconds) + "/s \t" + (counter * 100 / sum) + "% \t" + entry.getValue());
+        long cutoff = sum / 1000;
+        long sum2 = 0;
+        if (staticCounter) {
+            out.println("=========== " + group + " static counters: ");
+            for (Map.Entry<Long, String> entry : sorted.entrySet()) {
+                long counter = entry.getKey() / MAX_COUNTERS;
+                sum2 += counter;
+                if (sum2 >= cutoff) {
+                    out.println(counter + " \t" + ((counter * 200 + 1) / sum / 2) + "% \t" + entry.getValue());
+                }
+            }
+            out.println(sum + ": total");
+        } else {
+            out.println("=========== " + group + " dynamic counters, time = " + seconds + " s");
+            for (Map.Entry<Long, String> entry : sorted.entrySet()) {
+                long counter = entry.getKey() / MAX_COUNTERS;
+                sum2 += counter;
+                if (sum2 >= cutoff) {
+                    out.println((int) (counter / seconds) + "/s \t" + ((counter * 200 + 1) / sum / 2) + "% \t" + entry.getValue());
+                }
+            }
+            out.println((int) (sum / seconds) + "/s: total");
         }
-        out.println((int) (sum / seconds) + "/s: total");
-        out.println("============================");
-
-        clear();
     }
 
     public static void clear() {
@@ -120,13 +146,15 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         if (!enabled) {
             throw new GraalInternalError("counter nodes shouldn't exist when not enabled");
         }
         StructuredGraph graph = (StructuredGraph) graph();
         if (excludedClassPrefix == null || !graph.method().getDeclaringClass().getName().startsWith(excludedClassPrefix)) {
             int index = addContext ? getIndex(name + " @ " + MetaUtil.format("%h.%n", ((StructuredGraph) graph()).method())) : getIndex(name);
+            STATIC_COUNTERS[index] += increment;
+            GROUPS[index] = group;
 
             ConstantNode arrayConstant = ConstantNode.forObject(COUNTERS, tool.getRuntime(), graph);
             ConstantNode indexConstant = ConstantNode.forInt(index, graph);
@@ -140,10 +168,10 @@
         graph.removeFixed(this);
     }
 
-    public static void addCounterBefore(String name, long increment, boolean addContext, FixedNode position) {
+    public static void addCounterBefore(String group, String name, long increment, boolean addContext, FixedNode position) {
         if (enabled) {
             StructuredGraph graph = (StructuredGraph) position.graph();
-            DynamicCounterNode counter = graph.add(new DynamicCounterNode(name, increment, addContext));
+            DynamicCounterNode counter = graph.add(new DynamicCounterNode(name, group, increment, addContext));
             graph.addBeforeFixed(position, counter);
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/SurvivingCounterNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/SurvivingCounterNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -35,8 +35,8 @@
 
     @Input private ValueNode checkedValue;
 
-    public SurvivingCounterNode(String name, long increment, boolean addContext, ValueNode checkedValue) {
-        super(name, increment, addContext);
+    public SurvivingCounterNode(String group, String name, long increment, boolean addContext, ValueNode checkedValue) {
+        super(group, name, increment, addContext);
         this.checkedValue = checkedValue;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -48,11 +48,11 @@
 
     public static AddLocationNode create(LocationNode x, LocationNode y, Graph graph) {
         assert x.getValueKind().equals(y.getValueKind()) && x.locationIdentity() == y.locationIdentity();
-        return graph.unique(new AddLocationNode(x, y));
+        return graph.unique(new AddLocationNode(x.locationIdentity(), x.getValueKind(), x, y));
     }
 
-    private AddLocationNode(LocationNode x, LocationNode y) {
-        super(x.locationIdentity(), x.getValueKind());
+    private AddLocationNode(Object identity, Kind kind, ValueNode x, ValueNode y) {
+        super(identity, kind);
         this.x = x;
         this.y = y;
     }
@@ -60,7 +60,7 @@
     @Override
     protected LocationNode addDisplacement(long displacement) {
         LocationNode added = getX().addDisplacement(displacement);
-        return graph().unique(new AddLocationNode(added, getY()));
+        return graph().unique(new AddLocationNode(locationIdentity(), getValueKind(), added, getY()));
     }
 
     @Override
@@ -86,20 +86,23 @@
     }
 
     @Override
-    public Value generateLea(LIRGeneratorTool gen, Value base) {
-        Value xAddr = getX().generateLea(gen, base);
-        return getY().generateLea(gen, xAddr);
+    public Value generateAddress(LIRGeneratorTool gen, Value base) {
+        Value xAddr = getX().generateAddress(gen, base);
+        return getY().generateAddress(gen, xAddr);
     }
 
     @Override
     public Value generateLoad(LIRGeneratorTool gen, Value base, DeoptimizingNode deopting) {
-        Value xAddr = getX().generateLea(gen, base);
+        Value xAddr = getX().generateAddress(gen, base);
         return getY().generateLoad(gen, xAddr, deopting);
     }
 
     @Override
     public void generateStore(LIRGeneratorTool gen, Value base, Value value, DeoptimizingNode deopting) {
-        Value xAddr = getX().generateLea(gen, base);
+        Value xAddr = getX().generateAddress(gen, base);
         getY().generateStore(gen, xAddr, value, deopting);
     }
+
+    @NodeIntrinsic
+    public static native Location addLocation(@ConstantNodeParameter Object identity, @ConstantNodeParameter Kind kind, Location x, Location y);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -52,7 +52,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -49,7 +49,7 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        Value addr = getLocation().generateLea(gen, gen.operand(getObject()));
+        Value addr = getLocation().generateAddress(gen, gen.operand(getObject()));
         gen.setResult(this, addr);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -55,7 +55,7 @@
     }
 
     @Override
-    public Value generateLea(LIRGeneratorTool gen, Value base) {
+    public Value generateAddress(LIRGeneratorTool gen, Value base) {
         return gen.emitLea(base, displacement(), Value.ILLEGAL, 0);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -58,10 +58,14 @@
     }
 
     public static IndexedLocationNode create(Object identity, Kind kind, long displacement, ValueNode index, Graph graph, int indexScaling) {
-        return graph.unique(new IndexedLocationNode(identity, kind, index, displacement, indexScaling));
+        return graph.unique(new IndexedLocationNode(identity, kind, displacement, index, indexScaling));
     }
 
-    private IndexedLocationNode(Object identity, Kind kind, ValueNode index, long displacement, int indexScaling) {
+    private IndexedLocationNode(Object identity, Kind kind, ValueNode index, int indexScaling) {
+        this(identity, kind, 0, index, indexScaling);
+    }
+
+    private IndexedLocationNode(Object identity, Kind kind, long displacement, ValueNode index, int indexScaling) {
         super(identity, kind);
         this.index = index;
         this.displacement = displacement;
@@ -86,7 +90,7 @@
     }
 
     @Override
-    public Value generateLea(LIRGeneratorTool gen, Value base) {
+    public Value generateAddress(LIRGeneratorTool gen, Value base) {
         return gen.emitLea(base, displacement, gen.operand(index()), indexScaling());
     }
 
@@ -99,4 +103,7 @@
     public void generateStore(LIRGeneratorTool gen, Value base, Value value, DeoptimizingNode deopting) {
         gen.emitStore(getValueKind(), base, displacement, gen.operand(index()), indexScaling(), value, deopting);
     }
+
+    @NodeIntrinsic
+    public static native Location indexedLocation(@ConstantNodeParameter Object identity, @ConstantNodeParameter Kind kind, int index, @ConstantNodeParameter int indexScaling);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -45,7 +45,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -30,9 +30,9 @@
 import com.oracle.graal.nodes.type.*;
 
 /**
- * A location for a memory access in terms of the kind of value accessed and how to access it.
- * All locations have the form [base + location], where base is a node and location is defined
- * by subclasses of the {@link LocationNode}.
+ * A location for a memory access in terms of the kind of value accessed and how to access it. All
+ * locations have the form [base + location], where base is a node and location is defined by
+ * subclasses of the {@link LocationNode}.
  */
 public abstract class LocationNode extends FloatingNode implements LIRLowerable, ValueNumberable {
 
@@ -41,7 +41,7 @@
 
     /**
      * Creates a new unique location identity for read and write operations.
-     *
+     * 
      * @param name the name of the new location identity, for debugging purposes
      * @return the new location identity
      */
@@ -67,6 +67,12 @@
      */
     public static final Object FINAL_LOCATION = createLocation("FINAL_LOCATION");
 
+    /**
+     * Marker interface for locations in snippets.
+     */
+    public interface Location {
+    }
+
     public static Object getArrayLocation(Kind elementKind) {
         return elementKind;
     }
@@ -93,7 +99,7 @@
         // nothing to do...
     }
 
-    public abstract Value generateLea(LIRGeneratorTool gen, Value base);
+    public abstract Value generateAddress(LIRGeneratorTool gen, Value base);
 
     public abstract Value generateLoad(LIRGeneratorTool gen, Value base, DeoptimizingNode deopting);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -103,11 +103,15 @@
         Object locId = location().locationIdentity();
         if (locId instanceof ResolvedJavaField) {
             ResolvedJavaType fieldType = ((ResolvedJavaField) locId).getDeclaringClass();
-            ResolvedJavaType beforePiType = parent.object().objectStamp().type();
+            ValueNode piValueStamp = parent.object();
+            ResolvedJavaType beforePiType = piValueStamp.objectStamp().type();
 
             if (beforePiType != null && fieldType.isAssignableFrom(beforePiType)) {
-                replaceFirstInput(parent, parent.object());
-                return true;
+                ObjectStamp piStamp = parent.objectStamp();
+                if (piStamp.nonNull() == piValueStamp.objectStamp().nonNull() && piStamp.alwaysNull() == piValueStamp.objectStamp().alwaysNull()) {
+                    replaceFirstInput(parent, piValueStamp);
+                    return true;
+                }
             }
         }
         return false;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -47,7 +47,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -50,7 +50,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -69,7 +69,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -83,7 +83,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -64,7 +64,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -62,7 +62,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -47,7 +47,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -52,7 +52,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -105,7 +105,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -53,7 +53,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         if (isLowered()) {
             return;
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -54,7 +54,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -52,7 +52,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -37,7 +37,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -48,7 +48,7 @@
         return new Object[]{LocationNode.ANY_LOCATION};
     }
 
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -49,7 +49,7 @@
         return new Object[]{LocationNode.ANY_LOCATION};
     }
 
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -110,7 +110,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -87,7 +87,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -62,7 +62,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         tool.getRuntime().lower(this, tool);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Lowerable.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Lowerable.java	Thu Apr 25 16:53:29 2013 +0200
@@ -24,5 +24,9 @@
 
 public interface Lowerable {
 
-    void lower(LoweringTool tool);
+    public enum LoweringType {
+        BEFORE_GUARDS, AFTER_GUARDS
+    }
+
+    void lower(LoweringTool tool, LoweringType loweringType);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java	Thu Apr 25 16:53:29 2013 +0200
@@ -30,8 +30,6 @@
 
 public interface LoweringTool {
 
-    TargetDescription getTarget();
-
     GraalCodeCacheProvider getRuntime();
 
     Replacements getReplacements();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java	Thu Apr 25 16:53:29 2013 +0200
@@ -33,7 +33,7 @@
     private final GenericStampType type;
 
     protected GenericStamp(GenericStampType type) {
-        super(Kind.Void);
+        super(type == GenericStampType.Void ? Kind.Void : Kind.Illegal);
         this.type = type;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/NodesToDoubles.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013, 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.
+ *
+ * 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.graal.nodes.util;
+
+import java.util.*;
+
+import com.oracle.graal.nodes.*;
+
+public class NodesToDoubles {
+
+    private final IdentityHashMap<FixedNode, Double> nodeProbabilities;
+
+    public NodesToDoubles(int numberOfNodes) {
+        this.nodeProbabilities = new IdentityHashMap<>(numberOfNodes);
+    }
+
+    public void put(FixedNode n, double value) {
+        nodeProbabilities.put(n, value);
+    }
+
+    public double get(FixedNode n) {
+        Double value = nodeProbabilities.get(n);
+        assert value != null;
+        return value;
+    }
+}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java	Mon Apr 22 18:30:33 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,459 +0,0 @@
-/*
- * Copyright (c) 2011, 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.
- *
- * 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.graal.phases.common;
-
-import java.util.*;
-
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.cfg.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.graph.*;
-
-/**
- * Computes probabilities for nodes in a graph.
- * <p>
- * The computation of absolute probabilities works in three steps:
- * <ol>
- * <li>{@link PropagateProbability} traverses the graph in post order (merges after their ends, ...)
- * and keeps track of the "probability state". Whenever it encounters a {@link ControlSplitNode} it
- * uses the split's probability information to divide the probability upon the successors. Whenever
- * it encounters an {@link Invoke} it assumes that the exception edge is unlikely and propagates the
- * whole probability to the normal successor. Whenever it encounters a {@link MergeNode} it sums up
- * the probability of all predecessors. It also maintains a set of active loops (whose
- * {@link LoopBeginNode} has been visited) and builds def/use information for step 2.</li>
- * <li></li>
- * <li>{@link PropagateLoopFrequency} propagates the loop frequencies and multiplies each
- * {@link FixedNode}'s probability with its loop frequency.</li>
- * </ol>
- * TODO: add exception probability information to Invokes
- */
-public class ComputeProbabilityPhase extends Phase {
-
-    private static final double EPSILON = 1d / Integer.MAX_VALUE;
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        new PropagateProbability(graph.start()).apply();
-        Debug.dump(graph, "After PropagateProbability");
-        computeLoopFactors();
-        Debug.dump(graph, "After computeLoopFactors");
-        new PropagateLoopFrequency(graph.start()).apply();
-        new ComputeInliningRelevanceIterator(graph).apply();
-    }
-
-    private void computeLoopFactors() {
-        for (LoopInfo info : loopInfos) {
-            double frequency = info.loopFrequency();
-            assert frequency != -1;
-        }
-    }
-
-    private static boolean isRelativeProbability(double prob) {
-        // 1.01 to allow for some rounding errors
-        return prob >= 0 && prob <= 1.01;
-    }
-
-    public static class LoopInfo {
-
-        public final LoopBeginNode loopBegin;
-
-        public final NodeMap<Set<LoopInfo>> requires;
-
-        private double loopFrequency = -1;
-        public boolean ended = false;
-
-        public LoopInfo(LoopBeginNode loopBegin) {
-            this.loopBegin = loopBegin;
-            this.requires = loopBegin.graph().createNodeMap();
-        }
-
-        public double loopFrequency() {
-            if (loopFrequency == -1 && ended) {
-                double backEdgeProb = 0.0;
-                for (LoopEndNode le : loopBegin.loopEnds()) {
-                    double factor = 1;
-                    Set<LoopInfo> requireds = requires.get(le);
-                    for (LoopInfo required : requireds) {
-                        double t = required.loopFrequency();
-                        if (t == -1) {
-                            return -1;
-                        }
-                        factor *= t;
-                    }
-                    backEdgeProb += le.probability() * factor;
-                }
-                double d = loopBegin.probability() - backEdgeProb;
-                if (d < EPSILON) {
-                    d = EPSILON;
-                }
-                loopFrequency = loopBegin.probability() / d;
-                loopBegin.setLoopFrequency(loopFrequency);
-            }
-            return loopFrequency;
-        }
-    }
-
-    public Set<LoopInfo> loopInfos = new HashSet<>();
-    public Map<MergeNode, Set<LoopInfo>> mergeLoops = new IdentityHashMap<>();
-
-    private class Probability implements MergeableState<Probability> {
-
-        public double probability;
-        public HashSet<LoopInfo> loops;
-        public LoopInfo loopInfo;
-
-        public Probability(double probability, HashSet<LoopInfo> loops) {
-            this.probability = probability;
-            this.loops = new HashSet<>(4);
-            if (loops != null) {
-                this.loops.addAll(loops);
-            }
-        }
-
-        @Override
-        public Probability clone() {
-            return new Probability(probability, loops);
-        }
-
-        @Override
-        public boolean merge(MergeNode merge, List<Probability> withStates) {
-            if (merge.forwardEndCount() > 1) {
-                HashSet<LoopInfo> intersection = new HashSet<>(loops);
-                for (Probability other : withStates) {
-                    intersection.retainAll(other.loops);
-                }
-                for (LoopInfo info : loops) {
-                    if (!intersection.contains(info)) {
-                        double loopFrequency = info.loopFrequency();
-                        if (loopFrequency == -1) {
-                            return false;
-                        }
-                        probability *= loopFrequency;
-                    }
-                }
-                for (Probability other : withStates) {
-                    double prob = other.probability;
-                    for (LoopInfo info : other.loops) {
-                        if (!intersection.contains(info)) {
-                            double loopFrequency = info.loopFrequency();
-                            if (loopFrequency == -1) {
-                                return false;
-                            }
-                            prob *= loopFrequency;
-                        }
-                    }
-                    probability += prob;
-                }
-                loops = intersection;
-                mergeLoops.put(merge, new HashSet<>(intersection));
-                assert isRelativeProbability(probability) : probability;
-            }
-            return true;
-        }
-
-        @Override
-        public void loopBegin(LoopBeginNode loopBegin) {
-            loopInfo = new LoopInfo(loopBegin);
-            loopInfos.add(loopInfo);
-            loops.add(loopInfo);
-        }
-
-        @Override
-        public void loopEnds(LoopBeginNode loopBegin, List<Probability> loopEndStates) {
-            assert loopInfo != null;
-            List<LoopEndNode> loopEnds = loopBegin.orderedLoopEnds();
-            int i = 0;
-            for (Probability proba : loopEndStates) {
-                LoopEndNode loopEnd = loopEnds.get(i++);
-                Set<LoopInfo> requires = loopInfo.requires.get(loopEnd);
-                if (requires == null) {
-                    requires = new HashSet<>();
-                    loopInfo.requires.set(loopEnd, requires);
-                }
-                for (LoopInfo innerLoop : proba.loops) {
-                    if (innerLoop != loopInfo && !this.loops.contains(innerLoop)) {
-                        requires.add(innerLoop);
-                    }
-                }
-            }
-            loopInfo.ended = true;
-        }
-
-        @Override
-        public void afterSplit(BeginNode node) {
-            assert node.predecessor() != null;
-            Node pred = node.predecessor();
-            if (pred instanceof Invoke) {
-                Invoke x = (Invoke) pred;
-                if (x.next() != node) {
-                    probability = 0;
-                }
-            } else {
-                assert pred instanceof ControlSplitNode;
-                ControlSplitNode x = (ControlSplitNode) pred;
-                probability *= x.probability(node);
-            }
-        }
-    }
-
-    private class PropagateProbability extends PostOrderNodeIterator<Probability> {
-
-        public PropagateProbability(FixedNode start) {
-            super(start, new Probability(1d, null));
-        }
-
-        @Override
-        protected void node(FixedNode node) {
-            node.setProbability(state.probability);
-        }
-    }
-
-    private class LoopCount implements MergeableState<LoopCount> {
-
-        public double count;
-
-        public LoopCount(double count) {
-            this.count = count;
-        }
-
-        @Override
-        public LoopCount clone() {
-            return new LoopCount(count);
-        }
-
-        @Override
-        public boolean merge(MergeNode merge, List<LoopCount> withStates) {
-            assert merge.forwardEndCount() == withStates.size() + 1;
-            if (merge.forwardEndCount() > 1) {
-                Set<LoopInfo> loops = mergeLoops.get(merge);
-                assert loops != null;
-                double countProd = 1;
-                for (LoopInfo loop : loops) {
-                    countProd *= loop.loopFrequency();
-                }
-                count = countProd;
-            }
-            return true;
-        }
-
-        @Override
-        public void loopBegin(LoopBeginNode loopBegin) {
-            count *= loopBegin.loopFrequency();
-        }
-
-        @Override
-        public void loopEnds(LoopBeginNode loopBegin, List<LoopCount> loopEndStates) {
-            // nothing to do...
-        }
-
-        @Override
-        public void afterSplit(BeginNode node) {
-            // nothing to do...
-        }
-    }
-
-    private class PropagateLoopFrequency extends PostOrderNodeIterator<LoopCount> {
-
-        public PropagateLoopFrequency(FixedNode start) {
-            super(start, new LoopCount(1d));
-        }
-
-        @Override
-        protected void node(FixedNode node) {
-            node.setProbability(node.probability() * state.count);
-        }
-
-    }
-
-    private static class ComputeInliningRelevanceIterator extends ScopedPostOrderNodeIterator {
-
-        private final HashMap<FixedNode, Scope> scopes;
-        private double currentProbability;
-        private double parentRelevance;
-
-        public ComputeInliningRelevanceIterator(StructuredGraph graph) {
-            super(graph);
-            this.scopes = computeLowestPathProbabilities(computeScopeInformation(graph));
-        }
-
-        @Override
-        protected void initializeScope() {
-            Scope scope = scopes.get(currentScopeStart);
-            parentRelevance = getParentScopeRelevance(scope);
-            currentProbability = scope.minPathProbability;
-        }
-
-        private static double getParentScopeRelevance(Scope scope) {
-            if (scope.start instanceof LoopBeginNode) {
-                assert scope.parent != null;
-                double parentProbability = 0;
-                for (EndNode end : ((LoopBeginNode) scope.start).forwardEnds()) {
-                    parentProbability += end.probability();
-                }
-                return parentProbability / scope.parent.minPathProbability;
-            } else {
-                assert scope.parent == null;
-                return 1.0;
-            }
-        }
-
-        @Override
-        protected void invoke(Invoke invoke) {
-            assert !Double.isNaN(invoke.probability());
-            invoke.setInliningRelevance((invoke.probability() / currentProbability) * Math.min(1.0, parentRelevance));
-            assert !Double.isNaN(invoke.inliningRelevance());
-        }
-
-        private static Scope[] computeScopeInformation(StructuredGraph graph) {
-            ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, false, false);
-
-            Loop[] loops = cfg.getLoops();
-            HashMap<Loop, Scope> processedScopes = new HashMap<>();
-            Scope[] scopes = new Scope[loops.length + 1];
-            Scope methodScope = new Scope(graph.start(), null);
-            processedScopes.put(null, methodScope);
-
-            scopes[0] = methodScope;
-            for (int i = 0; i < loops.length; i++) {
-                scopes[i + 1] = createScope(loops[i], processedScopes);
-            }
-
-            return scopes;
-        }
-
-        private static Scope createScope(Loop loop, HashMap<Loop, Scope> processedLoops) {
-            Scope parent = processedLoops.get(loop.parent);
-            if (parent == null) {
-                parent = createScope(loop.parent, processedLoops);
-            }
-            Scope result = new Scope(loop.loopBegin(), parent);
-            processedLoops.put(loop, result);
-            return result;
-        }
-
-        private static HashMap<FixedNode, Scope> computeLowestPathProbabilities(Scope[] scopes) {
-            HashMap<FixedNode, Scope> result = new HashMap<>();
-
-            for (Scope scope : scopes) {
-                double lowestPathProbability = computeLowestPathProbability(scope);
-                scope.minPathProbability = Math.max(EPSILON, lowestPathProbability);
-                result.put(scope.start, scope);
-            }
-
-            return result;
-        }
-
-        private static double computeLowestPathProbability(Scope scope) {
-            FixedNode scopeStart = scope.start;
-            ArrayList<FixedNode> pathBeginNodes = new ArrayList<>();
-            pathBeginNodes.add(scopeStart);
-            double minPathProbability = scopeStart.probability();
-            boolean isLoopScope = scopeStart instanceof LoopBeginNode;
-
-            do {
-                Node current = pathBeginNodes.remove(pathBeginNodes.size() - 1);
-                do {
-                    if (isLoopScope && current instanceof LoopExitNode && ((LoopBeginNode) scopeStart).loopExits().contains((LoopExitNode) current)) {
-                        return minPathProbability;
-                    } else if (current instanceof LoopBeginNode && current != scopeStart) {
-                        current = getMaxProbabilityLoopExit((LoopBeginNode) current, pathBeginNodes);
-                        minPathProbability = getMinPathProbability((FixedNode) current, minPathProbability);
-                    } else if (current instanceof ControlSplitNode) {
-                        current = getMaxProbabilitySux((ControlSplitNode) current, pathBeginNodes);
-                        minPathProbability = getMinPathProbability((FixedNode) current, minPathProbability);
-                    } else {
-                        assert current.successors().count() <= 1;
-                        current = current.successors().first();
-                    }
-                } while (current != null);
-            } while (!pathBeginNodes.isEmpty());
-
-            return minPathProbability;
-        }
-
-        private static double getMinPathProbability(FixedNode current, double minPathProbability) {
-            if (current != null && current.probability() < minPathProbability) {
-                return current.probability();
-            }
-            return minPathProbability;
-        }
-
-        private static Node getMaxProbabilitySux(ControlSplitNode controlSplit, ArrayList<FixedNode> pathBeginNodes) {
-            Node maxSux = null;
-            double maxProbability = 0.0;
-            int pathBeginCount = pathBeginNodes.size();
-
-            for (Node sux : controlSplit.successors()) {
-                double probability = controlSplit.probability((BeginNode) sux);
-                if (probability > maxProbability) {
-                    maxProbability = probability;
-                    maxSux = sux;
-                    truncate(pathBeginNodes, pathBeginCount);
-                } else if (probability == maxProbability) {
-                    pathBeginNodes.add((FixedNode) sux);
-                }
-            }
-
-            return maxSux;
-        }
-
-        private static Node getMaxProbabilityLoopExit(LoopBeginNode loopBegin, ArrayList<FixedNode> pathBeginNodes) {
-            Node maxSux = null;
-            double maxProbability = 0.0;
-            int pathBeginCount = pathBeginNodes.size();
-
-            for (LoopExitNode sux : loopBegin.loopExits()) {
-                double probability = sux.probability();
-                if (probability > maxProbability) {
-                    maxProbability = probability;
-                    maxSux = sux;
-                    truncate(pathBeginNodes, pathBeginCount);
-                } else if (probability == maxProbability) {
-                    pathBeginNodes.add(sux);
-                }
-            }
-
-            return maxSux;
-        }
-
-        public static void truncate(ArrayList<FixedNode> pathBeginNodes, int pathBeginCount) {
-            for (int i = pathBeginNodes.size() - pathBeginCount; i > 0; i--) {
-                pathBeginNodes.remove(pathBeginNodes.size() - 1);
-            }
-        }
-    }
-
-    private static class Scope {
-
-        public final FixedNode start;
-        public final Scope parent;
-        public double minPathProbability;
-
-        public Scope(FixedNode start, Scope parent) {
-            this.start = start;
-            this.parent = parent;
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java	Thu Apr 25 16:53:29 2013 +0200
@@ -32,17 +32,15 @@
     // Metrics
     private static final DebugMetric metricNodesRemoved = Debug.metric("NodesRemoved");
 
-    private NodeFlood flood;
-
     @Override
     protected void run(StructuredGraph graph) {
-        this.flood = graph.createNodeFlood();
+        NodeFlood flood = graph.createNodeFlood();
 
         flood.add(graph.start());
-        iterateSuccessors();
-        disconnectCFGNodes(graph);
-        iterateInputs(graph);
-        deleteNodes(graph);
+        iterateSuccessors(flood);
+        disconnectCFGNodes(flood, graph);
+        iterateInputs(flood, graph);
+        deleteNodes(flood, graph);
 
         // remove chained Merges
         for (MergeNode merge : graph.getNodes(MergeNode.class)) {
@@ -52,7 +50,7 @@
         }
     }
 
-    private void iterateSuccessors() {
+    private static void iterateSuccessors(NodeFlood flood) {
         for (Node current : flood) {
             if (current instanceof EndNode) {
                 EndNode end = (EndNode) current;
@@ -65,7 +63,7 @@
         }
     }
 
-    private void disconnectCFGNodes(StructuredGraph graph) {
+    private static void disconnectCFGNodes(NodeFlood flood, StructuredGraph graph) {
         for (EndNode node : graph.getNodes(EndNode.class)) {
             if (!flood.isMarked(node)) {
                 MergeNode merge = node.merge();
@@ -95,7 +93,7 @@
         }
     }
 
-    private void deleteNodes(StructuredGraph graph) {
+    private static void deleteNodes(NodeFlood flood, StructuredGraph graph) {
         for (Node node : graph.getNodes()) {
             if (!flood.isMarked(node)) {
                 node.clearInputs();
@@ -110,7 +108,7 @@
         }
     }
 
-    private void iterateInputs(StructuredGraph graph) {
+    private static void iterateInputs(NodeFlood flood, StructuredGraph graph) {
         for (Node node : graph.getNodes()) {
             if (node instanceof LocalNode) {
                 flood.add(node);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Thu Apr 25 16:53:29 2013 +0200
@@ -25,7 +25,6 @@
 import java.util.*;
 import java.util.Map.Entry;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -34,8 +33,9 @@
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.phases.tiers.*;
 
-public class GuardLoweringPhase extends Phase {
+public class GuardLoweringPhase extends BasePhase<MidTierContext> {
 
     private abstract static class ScheduledNodeIterator {
 
@@ -81,9 +81,14 @@
         protected abstract void processNode(Node node);
     }
 
-    private class UseImplicitNullChecks extends ScheduledNodeIterator {
+    private static class UseImplicitNullChecks extends ScheduledNodeIterator {
 
         private final IdentityHashMap<ValueNode, GuardNode> nullGuarded = new IdentityHashMap<>();
+        private final int implicitNullCheckLimit;
+
+        UseImplicitNullChecks(int implicitNullCheckLimit) {
+            this.implicitNullCheckLimit = implicitNullCheckLimit;
+        }
 
         @Override
         protected void processNode(Node node) {
@@ -134,9 +139,17 @@
                 nullGuarded.put(obj, guard);
             }
         }
+
+        private boolean isImplicitNullCheck(LocationNode location) {
+            if (location instanceof ConstantLocationNode) {
+                return ((ConstantLocationNode) location).displacement() < implicitNullCheckLimit;
+            } else {
+                return false;
+            }
+        }
     }
 
-    private class LowerGuards extends ScheduledNodeIterator {
+    private static class LowerGuards extends ScheduledNodeIterator {
 
         private final Block block;
 
@@ -193,35 +206,21 @@
         }
     }
 
-    private TargetDescription target;
-
-    public GuardLoweringPhase(TargetDescription target) {
-        this.target = target;
-    }
-
     @Override
-    protected void run(StructuredGraph graph) {
+    protected void run(StructuredGraph graph, MidTierContext context) {
         SchedulePhase schedule = new SchedulePhase();
         schedule.apply(graph);
 
         for (Block block : schedule.getCFG().getBlocks()) {
-            processBlock(block, schedule);
+            processBlock(block, schedule, context.getTarget().implicitNullCheckLimit);
         }
     }
 
-    private void processBlock(Block block, SchedulePhase schedule) {
+    private static void processBlock(Block block, SchedulePhase schedule, int implicitNullCheckLimit) {
         List<ScheduledNode> nodes = schedule.nodesFor(block);
-        if (GraalOptions.OptImplicitNullChecks && target.implicitNullCheckLimit > 0) {
-            new UseImplicitNullChecks().processNodes(nodes, block.getBeginNode());
+        if (GraalOptions.OptImplicitNullChecks && implicitNullCheckLimit > 0) {
+            new UseImplicitNullChecks(implicitNullCheckLimit).processNodes(nodes, block.getBeginNode());
         }
         new LowerGuards(block).processNodes(nodes, block.getBeginNode());
     }
-
-    private boolean isImplicitNullCheck(LocationNode location) {
-        if (location instanceof ConstantLocationNode) {
-            return ((ConstantLocationNode) location).displacement() < target.implicitNullCheckLimit;
-        } else {
-            return false;
-        }
-    }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Thu Apr 25 16:53:29 2013 +0200
@@ -33,12 +33,14 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer;
 import com.oracle.graal.phases.common.InliningUtil.InlineInfo;
 import com.oracle.graal.phases.common.InliningUtil.InliningCallback;
 import com.oracle.graal.phases.common.InliningUtil.InliningPolicy;
+import com.oracle.graal.phases.graph.*;
 
 public class InliningPhase extends Phase implements InliningCallback {
 
@@ -99,13 +101,15 @@
 
     @Override
     protected void run(final StructuredGraph graph) {
+        NodesToDoubles nodeProbabilities = new ComputeProbabilityClosure(graph).apply();
+        NodesToDoubles nodeRelevance = new ComputeInliningRelevanceClosure(graph, nodeProbabilities).apply();
         inliningPolicy.initialize(graph);
 
         while (inliningPolicy.continueInlining(graph)) {
             final InlineInfo candidate = inliningPolicy.next();
 
             if (candidate != null) {
-                boolean isWorthInlining = inliningPolicy.isWorthInlining(candidate);
+                boolean isWorthInlining = inliningPolicy.isWorthInlining(candidate, nodeProbabilities, nodeRelevance);
                 isWorthInlining &= candidate.numberOfMethods() <= maxMethodPerInlining;
 
                 metricInliningConsidered.increment();
@@ -120,6 +124,10 @@
                         if (GraalOptions.OptCanonicalizer) {
                             new CanonicalizerPhase.Instance(runtime, assumptions, invokeUsages, mark, customCanonicalizer).apply(graph);
                         }
+
+                        nodeProbabilities = new ComputeProbabilityClosure(graph).apply();
+                        nodeRelevance = new ComputeInliningRelevanceClosure(graph, nodeProbabilities).apply();
+
                         inliningCount++;
                         metricInliningPerformed.increment();
                     } catch (BailoutException bailout) {
@@ -157,10 +165,8 @@
                 }
                 assert newGraph.start().next() != null : "graph needs to be populated during PhasePosition.AFTER_PARSING";
 
-                if (GraalOptions.ProbabilityAnalysis) {
-                    new DeadCodeEliminationPhase().apply(newGraph);
-                    new ComputeProbabilityPhase().apply(newGraph);
-                }
+                new DeadCodeEliminationPhase().apply(newGraph);
+
                 if (GraalOptions.OptCanonicalizer) {
                     new CanonicalizerPhase.Instance(runtime, assumptions).apply(newGraph);
                 }
@@ -177,7 +183,7 @@
 
     private interface InliningDecision {
 
-        boolean isWorthInlining(InlineInfo info);
+        boolean isWorthInlining(InlineInfo info, NodesToDoubles nodeProbabilities, NodesToDoubles nodeRelevance);
     }
 
     private static class GreedySizeBasedInliningDecision implements InliningDecision {
@@ -193,8 +199,7 @@
         }
 
         @Override
-        public boolean isWorthInlining(InlineInfo info) {
-            assert GraalOptions.ProbabilityAnalysis;
+        public boolean isWorthInlining(InlineInfo info, NodesToDoubles nodeProbabilities, NodesToDoubles nodeRelevance) {
             /*
              * TODO (chaeubl): invoked methods that are on important paths but not yet compiled ->
              * will be compiled anyways and it is likely that we are the only caller... might be
@@ -220,8 +225,7 @@
             int bytecodeSize = (int) (bytecodeCodeSize(info) / bonus);
             int complexity = (int) (compilationComplexity(info) / bonus);
             int compiledCodeSize = (int) (compiledCodeSize(info) / bonus);
-            double relevance = info.invoke().inliningRelevance();
-
+            double relevance = nodeRelevance.get(info.invoke().asNode());
             /*
              * as long as the compiled code size is small enough (or the method was not yet
              * compiled), we can do a pretty general inlining that suits most situations
@@ -240,7 +244,7 @@
              * the normal inlining did not fit this invoke, so check if we have any reason why we
              * should still do the inlining
              */
-            double probability = info.invoke().probability();
+            double probability = nodeProbabilities.get(info.invoke().asNode());
             int transferredValues = numberOfTransferredValues(info);
             int invokeUsages = countInvokeUsages(info);
             int moreSpecificArguments = countMoreSpecificArgumentInfo(info);
@@ -409,8 +413,9 @@
             return info;
         }
 
-        public boolean isWorthInlining(InlineInfo info) {
-            return inliningDecision.isWorthInlining(info);
+        @Override
+        public boolean isWorthInlining(InlineInfo info, NodesToDoubles nodeProbabilities, NodesToDoubles nodeRelevance) {
+            return inliningDecision.isWorthInlining(info, nodeProbabilities, nodeRelevance);
         }
 
         public void initialize(StructuredGraph graph) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Thu Apr 25 16:53:29 2013 +0200
@@ -70,7 +70,7 @@
 
         void scanInvokes(Iterable<? extends Node> newNodes);
 
-        boolean isWorthInlining(InlineInfo info);
+        boolean isWorthInlining(InlineInfo info, NodesToDoubles nodeProbabilities, NodesToDoubles nodeRelevance);
     }
 
     /**
@@ -260,7 +260,6 @@
                 } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
                     throw new GraalInternalError(e).addContext(invoke.asNode()).addContext("macroSubstitution", macroNodeClass);
                 }
-                macroNode.setProbability(invoke.asNode().probability());
                 CallTargetNode callTarget = invoke.callTarget();
                 if (invoke instanceof InvokeNode) {
                     graph.replaceFixedWithFixed((InvokeNode) invoke, graph.add(macroNode));
@@ -466,7 +465,6 @@
             ValueNode originalReceiver = ((MethodCallTargetNode) invoke.callTarget()).receiver();
             // setup merge and phi nodes for results and exceptions
             MergeNode returnMerge = graph.add(new MergeNode());
-            returnMerge.setProbability(invoke.probability());
             returnMerge.setStateAfter(invoke.stateAfter().duplicate(invoke.stateAfter().bci));
 
             PhiNode returnValuePhi = null;
@@ -481,7 +479,6 @@
                 ExceptionObjectNode exceptionEdge = (ExceptionObjectNode) invokeWithException.exceptionEdge();
 
                 exceptionMerge = graph.add(new MergeNode());
-                exceptionMerge.setProbability(exceptionEdge.probability());
 
                 FixedNode exceptionSux = exceptionEdge.next();
                 graph.addBeforeFixed(exceptionSux, exceptionMerge);
@@ -492,20 +489,13 @@
             // create one separate block for each invoked method
             BeginNode[] successors = new BeginNode[numberOfMethods + 1];
             for (int i = 0; i < numberOfMethods; i++) {
-                double probability = 0;
-                for (int j = 0; j < typesToConcretes.length; j++) {
-                    if (typesToConcretes[j] == i) {
-                        probability += ptypes.get(j).getProbability();
-                    }
-                }
-
-                successors[i] = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, invoke.probability() * probability, true);
+                successors[i] = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, true);
             }
 
             // create the successor for an unknown type
             FixedNode unknownTypeSux;
             if (shouldFallbackToInvoke()) {
-                unknownTypeSux = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, notRecordedTypeProbability, false);
+                unknownTypeSux = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, false);
             } else {
                 unknownTypeSux = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated));
             }
@@ -612,7 +602,6 @@
             assert concretes.size() == 1 && ptypes.size() > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0;
 
             BeginNode calleeEntryNode = graph.add(new BeginNode());
-            calleeEntryNode.setProbability(invoke.probability());
 
             BeginNode unknownTypeSux = createUnknownTypeSuccessor(graph);
             BeginNode[] successors = new BeginNode[]{calleeEntryNode, unknownTypeSux};
@@ -649,15 +638,12 @@
         }
 
         private static BeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, MergeNode returnMerge, PhiNode returnValuePhi, MergeNode exceptionMerge, PhiNode exceptionObjectPhi,
-                        double probability, boolean useForInlining) {
-            Invoke duplicatedInvoke = duplicateInvokeForInlining(graph, invoke, exceptionMerge, exceptionObjectPhi, useForInlining, probability);
+                        boolean useForInlining) {
+            Invoke duplicatedInvoke = duplicateInvokeForInlining(graph, invoke, exceptionMerge, exceptionObjectPhi, useForInlining);
             BeginNode calleeEntryNode = graph.add(new BeginNode());
             calleeEntryNode.setNext(duplicatedInvoke.asNode());
-            calleeEntryNode.setProbability(probability);
 
             EndNode endNode = graph.add(new EndNode());
-            endNode.setProbability(probability);
-
             duplicatedInvoke.setNext(endNode);
             returnMerge.addForwardEnd(endNode);
 
@@ -667,13 +653,11 @@
             return calleeEntryNode;
         }
 
-        private static Invoke duplicateInvokeForInlining(StructuredGraph graph, Invoke invoke, MergeNode exceptionMerge, PhiNode exceptionObjectPhi, boolean useForInlining, double probability) {
+        private static Invoke duplicateInvokeForInlining(StructuredGraph graph, Invoke invoke, MergeNode exceptionMerge, PhiNode exceptionObjectPhi, boolean useForInlining) {
             Invoke result = (Invoke) invoke.asNode().copyWithInputs();
             Node callTarget = result.callTarget().copyWithInputs();
             result.asNode().replaceFirstInput(result.callTarget(), callTarget);
             result.setUseForInlining(useForInlining);
-            result.setProbability(probability);
-            result.setInliningRelevance(invoke.inliningRelevance() * probability);
 
             Kind kind = invoke.asNode().kind();
             if (kind != Kind.Void) {
@@ -738,8 +722,6 @@
             InliningUtil.receiverNullCheck(invoke);
 
             BeginNode invocationEntry = graph.add(new BeginNode());
-            invocationEntry.setProbability(invoke.probability());
-
             BeginNode unknownTypeSux = createUnknownTypeSuccessor(graph);
             BeginNode[] successors = new BeginNode[]{invocationEntry, unknownTypeSux};
             createDispatchOnTypeBeforeInvoke(graph, successors, true);
@@ -966,6 +948,7 @@
         return graph.unique(new PiNode(receiver, exact ? StampFactory.exactNonNull(commonType) : StampFactory.declaredNonNull(commonType), anchor));
     }
 
+    // TODO (chaeubl): cleanup this method
     private static boolean checkInvokeConditions(Invoke invoke) {
         if (invoke.predecessor() == null || !invoke.asNode().isAlive()) {
             return logNotInlinedMethodAndReturnFalse(invoke, "the invoke is dead code");
@@ -974,6 +957,7 @@
         } else if (((MethodCallTargetNode) invoke.callTarget()).targetMethod() == null) {
             return logNotInlinedMethodAndReturnFalse(invoke, "target method is null");
         } else if (invoke.stateAfter() == null) {
+            // TODO (chaeubl): why should an invoke not have a state after?
             return logNotInlinedMethodAndReturnFalse(invoke, "the invoke has no after state");
         } else if (!invoke.useForInlining()) {
             return logNotInlinedMethodAndReturnFalse(invoke, "the invoke is marked to be not used for inlining");
@@ -1127,27 +1111,8 @@
         }
 
         FrameState outerFrameState = null;
-        double invokeProbability = invoke.asNode().probability();
         int callerLockDepth = stateAfter.nestedLockDepth();
         for (Node node : duplicates.values()) {
-            if (GraalOptions.ProbabilityAnalysis) {
-                if (node instanceof FixedNode) {
-                    FixedNode fixed = (FixedNode) node;
-                    double newProbability = fixed.probability() * invokeProbability;
-                    if (GraalOptions.LimitInlinedProbability) {
-                        newProbability = Math.min(newProbability, invokeProbability);
-                    }
-                    fixed.setProbability(newProbability);
-                }
-                if (node instanceof Invoke) {
-                    Invoke newInvoke = (Invoke) node;
-                    double newRelevance = newInvoke.inliningRelevance() * invoke.inliningRelevance();
-                    if (GraalOptions.LimitInlinedRelevance) {
-                        newRelevance = Math.min(newRelevance, invoke.inliningRelevance());
-                    }
-                    newInvoke.setInliningRelevance(newRelevance);
-                }
-            }
             if (node instanceof FrameState) {
                 FrameState frameState = (FrameState) node;
                 assert frameState.bci != FrameState.BEFORE_BCI : frameState;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Thu Apr 25 16:53:29 2013 +0200
@@ -26,47 +26,45 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.phases.tiers.*;
 
 /**
  * Processes all {@link Lowerable} nodes to do their lowering.
  */
-public class LoweringPhase extends Phase {
+public class LoweringPhase extends BasePhase<PhaseContext> {
 
     final class LoweringToolImpl implements LoweringTool {
 
+        private final PhaseContext context;
         private final FixedNode guardAnchor;
         private final NodeBitMap activeGuards;
         private FixedWithNextNode lastFixedNode;
         private ControlFlowGraph cfg;
 
-        public LoweringToolImpl(FixedNode guardAnchor, NodeBitMap activeGuards, ControlFlowGraph cfg) {
+        public LoweringToolImpl(PhaseContext context, FixedNode guardAnchor, NodeBitMap activeGuards, ControlFlowGraph cfg) {
+            this.context = context;
             this.guardAnchor = guardAnchor;
             this.activeGuards = activeGuards;
             this.cfg = cfg;
         }
 
         @Override
-        public TargetDescription getTarget() {
-            return target;
-        }
-
-        @Override
         public GraalCodeCacheProvider getRuntime() {
-            return runtime;
+            return (GraalCodeCacheProvider) context.getRuntime();
         }
 
         @Override
         public Replacements getReplacements() {
-            return replacements;
+            return context.getReplacements();
         }
 
         @Override
@@ -81,11 +79,14 @@
 
         @Override
         public Assumptions assumptions() {
-            return assumptions;
+            return context.getAssumptions();
         }
 
         @Override
         public ValueNode createGuard(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
+            if (loweringType == LoweringType.AFTER_GUARDS) {
+                throw new GraalInternalError("Cannot create guards in after-guard lowering");
+            }
             if (GraalOptions.OptEliminateGuards) {
                 for (Node usage : condition.usages()) {
                     if (!activeGuards.isNew(usage) && activeGuards.isMarked(usage) && ((GuardNode) usage).negated() == negated) {
@@ -116,18 +117,10 @@
         }
     }
 
-    private final TargetDescription target;
-    private final GraalCodeCacheProvider runtime;
-    private final Replacements replacements;
-    private final Assumptions assumptions;
+    private final LoweringType loweringType;
 
-    private boolean deferred;
-
-    public LoweringPhase(TargetDescription target, GraalCodeCacheProvider runtime, Replacements replacements, Assumptions assumptions) {
-        this.target = target;
-        this.runtime = runtime;
-        this.replacements = replacements;
-        this.assumptions = assumptions;
+    public LoweringPhase(LoweringType loweringType) {
+        this.loweringType = loweringType;
     }
 
     private static boolean containsLowerable(NodeIterable<Node> nodes) {
@@ -140,20 +133,18 @@
     }
 
     @Override
-    protected void run(final StructuredGraph graph) {
+    protected void run(final StructuredGraph graph, PhaseContext context) {
         int i = 0;
         NodeBitMap processed = graph.createNodeBitMap();
         while (true) {
+            Round round = new Round(i++, context, processed);
             int mark = graph.getMark();
-            final SchedulePhase schedule = new SchedulePhase();
-            schedule.apply(graph, false);
 
-            deferred = false;
-            processBlock(schedule.getCFG().getStartBlock(), graph.createNodeBitMap(), null, schedule, processed);
-            Debug.dump(graph, "Lowering iteration %d", i++);
-            new CanonicalizerPhase.Instance(runtime, assumptions, mark, null).apply(graph);
+            IncrementalCanonicalizerPhase<PhaseContext> canonicalizer = new IncrementalCanonicalizerPhase<>();
+            canonicalizer.addPhase(round);
+            canonicalizer.apply(graph, context);
 
-            if (!deferred && !containsLowerable(graph.getNewNodes(mark))) {
+            if (!round.deferred && !containsLowerable(graph.getNewNodes(mark))) {
                 // No new lowerable nodes - done!
                 break;
             }
@@ -162,76 +153,98 @@
         }
     }
 
-    private void processBlock(Block block, NodeBitMap activeGuards, FixedNode parentAnchor, SchedulePhase schedule, NodeBitMap processed) {
+    private final class Round extends Phase {
 
-        FixedNode anchor = parentAnchor;
-        if (anchor == null) {
-            anchor = block.getBeginNode();
+        private final PhaseContext context;
+        private final NodeBitMap processed;
+        private final SchedulePhase schedule;
+        private boolean deferred = false;
+
+        private Round(int iteration, PhaseContext context, NodeBitMap processed) {
+            super(String.format("Lowering iteration %d", iteration));
+            this.context = context;
+            this.processed = processed;
+            this.schedule = new SchedulePhase();
         }
-        process(block, activeGuards, anchor, schedule, processed);
 
-        // Process always reached block first.
-        Block alwaysReachedBlock = block.getPostdominator();
-        if (alwaysReachedBlock != null && alwaysReachedBlock.getDominator() == block) {
-            processBlock(alwaysReachedBlock, activeGuards, anchor, schedule, processed);
+        @Override
+        public void run(StructuredGraph graph) {
+            schedule.apply(graph, false);
+            processBlock(schedule.getCFG().getStartBlock(), graph.createNodeBitMap(), null);
         }
 
-        // Now go for the other dominators.
-        for (Block dominated : block.getDominated()) {
-            if (dominated != alwaysReachedBlock) {
-                assert dominated.getDominator() == block;
-                processBlock(dominated, activeGuards, null, schedule, processed);
+        private void processBlock(Block block, NodeBitMap activeGuards, FixedNode parentAnchor) {
+
+            FixedNode anchor = parentAnchor;
+            if (anchor == null) {
+                anchor = block.getBeginNode();
+            }
+            process(block, activeGuards, anchor);
+
+            // Process always reached block first.
+            Block alwaysReachedBlock = block.getPostdominator();
+            if (alwaysReachedBlock != null && alwaysReachedBlock.getDominator() == block) {
+                processBlock(alwaysReachedBlock, activeGuards, anchor);
+            }
+
+            // Now go for the other dominators.
+            for (Block dominated : block.getDominated()) {
+                if (dominated != alwaysReachedBlock) {
+                    assert dominated.getDominator() == block;
+                    processBlock(dominated, activeGuards, null);
+                }
+            }
+
+            if (parentAnchor == null && GraalOptions.OptEliminateGuards) {
+                for (GuardNode guard : anchor.usages().filter(GuardNode.class)) {
+                    activeGuards.clear(guard);
+                }
             }
         }
 
-        if (parentAnchor == null && GraalOptions.OptEliminateGuards) {
-            for (GuardNode guard : anchor.usages().filter(GuardNode.class)) {
-                activeGuards.clear(guard);
-            }
-        }
-    }
+        private void process(final Block b, final NodeBitMap activeGuards, final FixedNode anchor) {
 
-    private void process(final Block b, final NodeBitMap activeGuards, final FixedNode anchor, SchedulePhase schedule, NodeBitMap processed) {
+            final LoweringToolImpl loweringTool = new LoweringToolImpl(context, anchor, activeGuards, schedule.getCFG());
 
-        final LoweringToolImpl loweringTool = new LoweringToolImpl(anchor, activeGuards, schedule.getCFG());
+            // Lower the instructions of this block.
+            List<ScheduledNode> nodes = schedule.nodesFor(b);
 
-        // Lower the instructions of this block.
-        List<ScheduledNode> nodes = schedule.nodesFor(b);
-
-        for (Node node : nodes) {
-            FixedNode nextFixedNode = null;
-            if (node instanceof FixedWithNextNode && node.isAlive()) {
-                FixedWithNextNode fixed = (FixedWithNextNode) node;
-                nextFixedNode = fixed.next();
-                loweringTool.setLastFixedNode(fixed);
-            }
+            for (Node node : nodes) {
+                FixedNode nextFixedNode = null;
+                if (node instanceof FixedWithNextNode && node.isAlive()) {
+                    FixedWithNextNode fixed = (FixedWithNextNode) node;
+                    nextFixedNode = fixed.next();
+                    loweringTool.setLastFixedNode(fixed);
+                }
 
-            if (node.isAlive() && !processed.isMarked(node) && node instanceof Lowerable) {
-                if (loweringTool.lastFixedNode() == null) {
-                    // We cannot lower the node now because we don't have a fixed node to anchor the
-                    // replacements.
-                    // This can happen when previous lowerings in this lowering iteration deleted
-                    // the BeginNode of this block.
-                    // In the next iteration, we will have the new BeginNode available, and we can
-                    // lower this node.
-                    deferred = true;
-                } else {
-                    processed.mark(node);
-                    ((Lowerable) node).lower(loweringTool);
+                if (node.isAlive() && !processed.isMarked(node) && node instanceof Lowerable) {
+                    if (loweringTool.lastFixedNode() == null) {
+                        /*
+                         * We cannot lower the node now because we don't have a fixed node to anchor
+                         * the replacements. This can happen when previous lowerings in this
+                         * lowering iteration deleted the BeginNode of this block. In the next
+                         * iteration, we will have the new BeginNode available, and we can lower
+                         * this node.
+                         */
+                        deferred = true;
+                    } else {
+                        processed.mark(node);
+                        ((Lowerable) node).lower(loweringTool, loweringType);
+                    }
                 }
-            }
 
-            if (loweringTool.lastFixedNode() == node && !node.isAlive()) {
-                if (nextFixedNode == null || !nextFixedNode.isAlive()) {
-                    loweringTool.setLastFixedNode(null);
-                } else {
-                    Node prev = nextFixedNode.predecessor();
-                    if (prev != node && prev instanceof FixedWithNextNode) {
-                        loweringTool.setLastFixedNode((FixedWithNextNode) prev);
-                    } else if (nextFixedNode instanceof FixedWithNextNode) {
-                        loweringTool.setLastFixedNode((FixedWithNextNode) nextFixedNode);
+                if (loweringTool.lastFixedNode() == node && !node.isAlive()) {
+                    if (nextFixedNode == null || !nextFixedNode.isAlive()) {
+                        loweringTool.setLastFixedNode(null);
                     } else {
-                        loweringTool.setLastFixedNode(null);
+                        Node prev = nextFixedNode.predecessor();
+                        if (prev != node && prev instanceof FixedWithNextNode) {
+                            loweringTool.setLastFixedNode((FixedWithNextNode) prev);
+                        } else if (nextFixedNode instanceof FixedWithNextNode) {
+                            loweringTool.setLastFixedNode((FixedWithNextNode) nextFixedNode);
+                        } else {
+                            loweringTool.setLastFixedNode(null);
+                        }
                     }
                 }
             }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Thu Apr 25 16:53:29 2013 +0200
@@ -35,6 +35,7 @@
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.graph.*;
 
 /**
  * This class is a phase that looks for opportunities for tail duplication. The static method
@@ -129,10 +130,12 @@
 
     @Override
     protected void run(StructuredGraph graph) {
+        NodesToDoubles nodeProbabilities = new ComputeProbabilityClosure(graph).apply();
+
         // A snapshot is taken here, so that new MergeNode instances aren't considered for tail
         // duplication.
         for (MergeNode merge : graph.getNodes(MergeNode.class).snapshot()) {
-            if (!(merge instanceof LoopBeginNode) && merge.probability() >= GraalOptions.TailDuplicationProbability) {
+            if (!(merge instanceof LoopBeginNode) && nodeProbabilities.get(merge) >= GraalOptions.TailDuplicationProbability) {
                 tailDuplicate(merge, DEFAULT_DECISION, null);
             }
         }
@@ -219,7 +222,7 @@
          * </ul>
          */
         private void duplicate() {
-            Debug.log("tail duplication at merge %s in %s (prob %f)", merge, graph.method(), merge.probability());
+            Debug.log("tail duplication at merge %s in %s", merge, graph.method());
 
             ValueAnchorNode anchor = addValueAnchor();
 
@@ -420,9 +423,7 @@
          */
         private EndNode createNewMerge(FixedNode successor, FrameState stateAfterMerge) {
             MergeNode newBottomMerge = graph.add(new MergeNode());
-            newBottomMerge.setProbability(successor.probability());
             EndNode newBottomEnd = graph.add(new EndNode());
-            newBottomEnd.setProbability(successor.probability());
             newBottomMerge.addForwardEnd(newBottomEnd);
             newBottomMerge.setStateAfter(stateAfterMerge);
             ((FixedWithNextNode) successor.predecessor()).setNext(newBottomEnd);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Thu Apr 25 16:53:29 2013 +0200
@@ -47,8 +47,6 @@
            static boolean InlineMegamorphicCalls             = ____;
     public static int     MaximumDesiredSize                 = 5000;
     public static int     MaximumRecursiveInlining           = 1;
-    public static boolean LimitInlinedProbability            = ____;
-    public static boolean LimitInlinedRelevance              = true;
     public static float   BoostInliningForEscapeAnalysis     = 2f;
     public static float   RelevanceCapForInlining            = 1f;
     public static boolean IterativeInlining                  = ____;
@@ -75,9 +73,6 @@
     public static double  TailDuplicationProbability         = 0.5;
     public static int     TailDuplicationTrivialSize         = 1;
 
-    // absolute probability analysis
-    public static boolean ProbabilityAnalysis                = true;
-
     // profiling information
     public static int     DeoptsToDisableOptimisticOptimization = 40;
     public static int     MatureExecutionsBranch             = 1;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java	Thu Apr 25 16:53:29 2013 +0200
@@ -53,10 +53,6 @@
         if (checkDeoptimizations(method.getProfilingInfo(), deoptReason)) {
             enabledOpts.add(optimization);
         } else {
-            /*
-             * TODO (chaeubl): see GRAAL-75 (remove when we are sure that optimistic optimizations
-             * are not disabled unnecessarily
-             */
             disabledOptimisticOptsMetric.increment();
         }
     }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhasePlan.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhasePlan.java	Thu Apr 25 16:53:29 2013 +0200
@@ -51,7 +51,6 @@
     public static enum PhasePosition {
         AFTER_PARSING,
         HIGH_LEVEL,
-        MID_LEVEL,
         LOW_LEVEL
     }
     // @formatter:on
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeInliningRelevanceClosure.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2013, 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.
+ *
+ * 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.graal.phases.graph;
+
+import java.util.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.util.*;
+
+public class ComputeInliningRelevanceClosure {
+
+    private static final double EPSILON = 1d / Integer.MAX_VALUE;
+
+    private final StructuredGraph graph;
+    private final NodesToDoubles nodeProbabilities;
+    private final NodesToDoubles nodeRelevances;
+
+    public ComputeInliningRelevanceClosure(StructuredGraph graph, NodesToDoubles nodeProbabilities) {
+        this.graph = graph;
+        this.nodeProbabilities = nodeProbabilities;
+        this.nodeRelevances = new NodesToDoubles(graph.getNodeCount());
+    }
+
+    public NodesToDoubles apply() {
+        new ComputeInliningRelevanceIterator(graph).apply();
+        return nodeRelevances;
+    }
+
+    private class ComputeInliningRelevanceIterator extends ScopedPostOrderNodeIterator {
+
+        private final HashMap<FixedNode, Scope> scopes;
+        private double currentProbability;
+        private double parentRelevance;
+
+        public ComputeInliningRelevanceIterator(StructuredGraph graph) {
+            super(graph);
+            this.scopes = computeLowestPathProbabilities();
+        }
+
+        @Override
+        protected void initializeScope() {
+            Scope scope = scopes.get(currentScopeStart);
+            parentRelevance = getParentScopeRelevance(scope);
+            currentProbability = scope.minPathProbability;
+        }
+
+        private double getParentScopeRelevance(Scope scope) {
+            if (scope.start instanceof LoopBeginNode) {
+                assert scope.parent != null;
+                double parentProbability = 0;
+                for (EndNode end : ((LoopBeginNode) scope.start).forwardEnds()) {
+                    parentProbability += nodeProbabilities.get(end);
+                }
+                return parentProbability / scope.parent.minPathProbability;
+            } else {
+                assert scope.parent == null;
+                return 1.0;
+            }
+        }
+
+        @Override
+        protected void invoke(Invoke invoke) {
+            double probability = nodeProbabilities.get(invoke.asNode());
+            assert !Double.isNaN(probability);
+
+            double relevance = (probability / currentProbability) * Math.min(1.0, parentRelevance);
+            nodeRelevances.put(invoke.asNode(), relevance);
+            assert !Double.isNaN(relevance);
+        }
+
+        private HashMap<FixedNode, Scope> computeLowestPathProbabilities() {
+            HashMap<FixedNode, Scope> result = new HashMap<>();
+
+            for (Scope scope : computeScopes()) {
+                double lowestPathProbability = computeLowestPathProbability(scope);
+                scope.minPathProbability = Math.max(EPSILON, lowestPathProbability);
+                result.put(scope.start, scope);
+            }
+
+            return result;
+        }
+
+        private Scope[] computeScopes() {
+            ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, false, false);
+
+            Loop[] loops = cfg.getLoops();
+            HashMap<Loop, Scope> processedScopes = new HashMap<>();
+            Scope[] result = new Scope[loops.length + 1];
+            Scope methodScope = new Scope(graph.start(), null);
+            processedScopes.put(null, methodScope);
+
+            result[0] = methodScope;
+            for (int i = 0; i < loops.length; i++) {
+                result[i + 1] = createScope(loops[i], processedScopes);
+            }
+
+            return result;
+        }
+
+        private Scope createScope(Loop loop, HashMap<Loop, Scope> processedLoops) {
+            Scope parent = processedLoops.get(loop.parent);
+            if (parent == null) {
+                parent = createScope(loop.parent, processedLoops);
+            }
+            Scope result = new Scope(loop.loopBegin(), parent);
+            processedLoops.put(loop, result);
+            return result;
+        }
+
+        private double computeLowestPathProbability(Scope scope) {
+            FixedNode scopeStart = scope.start;
+            ArrayList<FixedNode> pathBeginNodes = new ArrayList<>();
+            pathBeginNodes.add(scopeStart);
+            double minPathProbability = nodeProbabilities.get(scopeStart);
+            boolean isLoopScope = scopeStart instanceof LoopBeginNode;
+
+            do {
+                Node current = pathBeginNodes.remove(pathBeginNodes.size() - 1);
+                do {
+                    if (isLoopScope && current instanceof LoopExitNode && ((LoopBeginNode) scopeStart).loopExits().contains((LoopExitNode) current)) {
+                        return minPathProbability;
+                    } else if (current instanceof LoopBeginNode && current != scopeStart) {
+                        current = getMaxProbabilityLoopExit((LoopBeginNode) current, pathBeginNodes);
+                        minPathProbability = getMinPathProbability((FixedNode) current, minPathProbability);
+                    } else if (current instanceof ControlSplitNode) {
+                        current = getMaxProbabilitySux((ControlSplitNode) current, pathBeginNodes);
+                        minPathProbability = getMinPathProbability((FixedNode) current, minPathProbability);
+                    } else {
+                        assert current.successors().count() <= 1;
+                        current = current.successors().first();
+                    }
+                } while (current != null);
+            } while (!pathBeginNodes.isEmpty());
+
+            return minPathProbability;
+        }
+
+        private double getMinPathProbability(FixedNode current, double minPathProbability) {
+            if (current != null && nodeProbabilities.get(current) < minPathProbability) {
+                return nodeProbabilities.get(current);
+            }
+            return minPathProbability;
+        }
+
+        private Node getMaxProbabilitySux(ControlSplitNode controlSplit, ArrayList<FixedNode> pathBeginNodes) {
+            Node maxSux = null;
+            double maxProbability = 0.0;
+            int pathBeginCount = pathBeginNodes.size();
+
+            for (Node sux : controlSplit.successors()) {
+                double probability = controlSplit.probability((BeginNode) sux);
+                if (probability > maxProbability) {
+                    maxProbability = probability;
+                    maxSux = sux;
+                    truncate(pathBeginNodes, pathBeginCount);
+                } else if (probability == maxProbability) {
+                    pathBeginNodes.add((FixedNode) sux);
+                }
+            }
+
+            return maxSux;
+        }
+
+        private Node getMaxProbabilityLoopExit(LoopBeginNode loopBegin, ArrayList<FixedNode> pathBeginNodes) {
+            Node maxSux = null;
+            double maxProbability = 0.0;
+            int pathBeginCount = pathBeginNodes.size();
+
+            for (LoopExitNode sux : loopBegin.loopExits()) {
+                double probability = nodeProbabilities.get(sux);
+                if (probability > maxProbability) {
+                    maxProbability = probability;
+                    maxSux = sux;
+                    truncate(pathBeginNodes, pathBeginCount);
+                } else if (probability == maxProbability) {
+                    pathBeginNodes.add(sux);
+                }
+            }
+
+            return maxSux;
+        }
+
+        private void truncate(ArrayList<FixedNode> pathBeginNodes, int pathBeginCount) {
+            for (int i = pathBeginNodes.size() - pathBeginCount; i > 0; i--) {
+                pathBeginNodes.remove(pathBeginNodes.size() - 1);
+            }
+        }
+    }
+
+    private static class Scope {
+
+        public final FixedNode start;
+        public final Scope parent;
+        public double minPathProbability;
+
+        public Scope(FixedNode start, Scope parent) {
+            this.start = start;
+            this.parent = parent;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2011, 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.
+ *
+ * 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.graal.phases.graph;
+
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.util.*;
+
+/**
+ * Computes probabilities for nodes in a graph.
+ * <p>
+ * The computation of absolute probabilities works in three steps:
+ * <ol>
+ * <li>{@link PropagateProbability} traverses the graph in post order (merges after their ends, ...)
+ * and keeps track of the "probability state". Whenever it encounters a {@link ControlSplitNode} it
+ * uses the split's probability information to divide the probability upon the successors. Whenever
+ * it encounters an {@link Invoke} it assumes that the exception edge is unlikely and propagates the
+ * whole probability to the normal successor. Whenever it encounters a {@link MergeNode} it sums up
+ * the probability of all predecessors. It also maintains a set of active loops (whose
+ * {@link LoopBeginNode} has been visited) and builds def/use information for step 2.</li>
+ * <li></li>
+ * <li>{@link PropagateLoopFrequency} propagates the loop frequencies and multiplies each
+ * {@link FixedNode}'s probability with its loop frequency.</li>
+ * </ol>
+ * TODO: add exception probability information to Invokes
+ */
+public class ComputeProbabilityClosure {
+
+    private static final double EPSILON = 1d / Integer.MAX_VALUE;
+
+    private final StructuredGraph graph;
+    private final NodesToDoubles nodeProbabilities;
+    private final Set<LoopInfo> loopInfos;
+    private final Map<MergeNode, Set<LoopInfo>> mergeLoops;
+
+    public ComputeProbabilityClosure(StructuredGraph graph) {
+        this.graph = graph;
+        this.nodeProbabilities = new NodesToDoubles(graph.getNodeCount());
+        this.loopInfos = new HashSet<>();
+        this.mergeLoops = new IdentityHashMap<>();
+    }
+
+    public NodesToDoubles apply() {
+        new PropagateProbability(graph.start()).apply();
+        Debug.dump(graph, "After PropagateProbability");
+        computeLoopFactors();
+        Debug.dump(graph, "After computeLoopFactors");
+        new PropagateLoopFrequency(graph.start()).apply();
+        return nodeProbabilities;
+    }
+
+    private void computeLoopFactors() {
+        for (LoopInfo info : loopInfos) {
+            double frequency = info.loopFrequency(nodeProbabilities);
+            assert frequency != -1;
+        }
+    }
+
+    private static boolean isRelativeProbability(double prob) {
+        // 1.01 to allow for some rounding errors
+        return prob >= 0 && prob <= 1.01;
+    }
+
+    public static class LoopInfo {
+
+        public final LoopBeginNode loopBegin;
+
+        public final NodeMap<Set<LoopInfo>> requires;
+
+        private double loopFrequency = -1;
+        public boolean ended = false;
+
+        public LoopInfo(LoopBeginNode loopBegin) {
+            this.loopBegin = loopBegin;
+            this.requires = loopBegin.graph().createNodeMap();
+        }
+
+        public double loopFrequency(NodesToDoubles nodeProbabilities) {
+            if (loopFrequency == -1 && ended) {
+                double backEdgeProb = 0.0;
+                for (LoopEndNode le : loopBegin.loopEnds()) {
+                    double factor = 1;
+                    Set<LoopInfo> requireds = requires.get(le);
+                    for (LoopInfo required : requireds) {
+                        double t = required.loopFrequency(nodeProbabilities);
+                        if (t == -1) {
+                            return -1;
+                        }
+                        factor *= t;
+                    }
+                    backEdgeProb += nodeProbabilities.get(le) * factor;
+                }
+                double d = nodeProbabilities.get(loopBegin) - backEdgeProb;
+                if (d < EPSILON) {
+                    d = EPSILON;
+                }
+                loopFrequency = nodeProbabilities.get(loopBegin) / d;
+                loopBegin.setLoopFrequency(loopFrequency);
+            }
+            return loopFrequency;
+        }
+    }
+
+    private class Probability implements MergeableState<Probability> {
+
+        public double probability;
+        public HashSet<LoopInfo> loops;
+        public LoopInfo loopInfo;
+
+        public Probability(double probability, HashSet<LoopInfo> loops) {
+            this.probability = probability;
+            this.loops = new HashSet<>(4);
+            if (loops != null) {
+                this.loops.addAll(loops);
+            }
+        }
+
+        @Override
+        public Probability clone() {
+            return new Probability(probability, loops);
+        }
+
+        @Override
+        public boolean merge(MergeNode merge, List<Probability> withStates) {
+            if (merge.forwardEndCount() > 1) {
+                HashSet<LoopInfo> intersection = new HashSet<>(loops);
+                for (Probability other : withStates) {
+                    intersection.retainAll(other.loops);
+                }
+                for (LoopInfo info : loops) {
+                    if (!intersection.contains(info)) {
+                        double loopFrequency = info.loopFrequency(nodeProbabilities);
+                        if (loopFrequency == -1) {
+                            return false;
+                        }
+                        probability *= loopFrequency;
+                    }
+                }
+                for (Probability other : withStates) {
+                    double prob = other.probability;
+                    for (LoopInfo info : other.loops) {
+                        if (!intersection.contains(info)) {
+                            double loopFrequency = info.loopFrequency(nodeProbabilities);
+                            if (loopFrequency == -1) {
+                                return false;
+                            }
+                            prob *= loopFrequency;
+                        }
+                    }
+                    probability += prob;
+                }
+                loops = intersection;
+                mergeLoops.put(merge, new HashSet<>(intersection));
+                assert isRelativeProbability(probability) : probability;
+            }
+            return true;
+        }
+
+        @Override
+        public void loopBegin(LoopBeginNode loopBegin) {
+            loopInfo = new LoopInfo(loopBegin);
+            loopInfos.add(loopInfo);
+            loops.add(loopInfo);
+        }
+
+        @Override
+        public void loopEnds(LoopBeginNode loopBegin, List<Probability> loopEndStates) {
+            assert loopInfo != null;
+            List<LoopEndNode> loopEnds = loopBegin.orderedLoopEnds();
+            int i = 0;
+            for (Probability proba : loopEndStates) {
+                LoopEndNode loopEnd = loopEnds.get(i++);
+                Set<LoopInfo> requires = loopInfo.requires.get(loopEnd);
+                if (requires == null) {
+                    requires = new HashSet<>();
+                    loopInfo.requires.set(loopEnd, requires);
+                }
+                for (LoopInfo innerLoop : proba.loops) {
+                    if (innerLoop != loopInfo && !this.loops.contains(innerLoop)) {
+                        requires.add(innerLoop);
+                    }
+                }
+            }
+            loopInfo.ended = true;
+        }
+
+        @Override
+        public void afterSplit(BeginNode node) {
+            assert node.predecessor() != null;
+            Node pred = node.predecessor();
+            if (pred instanceof Invoke) {
+                Invoke x = (Invoke) pred;
+                if (x.next() != node) {
+                    probability = 0;
+                }
+            } else {
+                assert pred instanceof ControlSplitNode;
+                ControlSplitNode x = (ControlSplitNode) pred;
+                probability *= x.probability(node);
+            }
+        }
+    }
+
+    private class PropagateProbability extends PostOrderNodeIterator<Probability> {
+
+        public PropagateProbability(FixedNode start) {
+            super(start, new Probability(1d, null));
+        }
+
+        @Override
+        protected void node(FixedNode node) {
+            nodeProbabilities.put(node, state.probability);
+        }
+    }
+
+    private class LoopCount implements MergeableState<LoopCount> {
+
+        public double count;
+
+        public LoopCount(double count) {
+            this.count = count;
+        }
+
+        @Override
+        public LoopCount clone() {
+            return new LoopCount(count);
+        }
+
+        @Override
+        public boolean merge(MergeNode merge, List<LoopCount> withStates) {
+            assert merge.forwardEndCount() == withStates.size() + 1;
+            if (merge.forwardEndCount() > 1) {
+                Set<LoopInfo> loops = mergeLoops.get(merge);
+                assert loops != null;
+                double countProd = 1;
+                for (LoopInfo loop : loops) {
+                    countProd *= loop.loopFrequency(nodeProbabilities);
+                }
+                count = countProd;
+            }
+            return true;
+        }
+
+        @Override
+        public void loopBegin(LoopBeginNode loopBegin) {
+            count *= loopBegin.loopFrequency();
+        }
+
+        @Override
+        public void loopEnds(LoopBeginNode loopBegin, List<LoopCount> loopEndStates) {
+            // nothing to do...
+        }
+
+        @Override
+        public void afterSplit(BeginNode node) {
+            // nothing to do...
+        }
+    }
+
+    private class PropagateLoopFrequency extends PostOrderNodeIterator<LoopCount> {
+
+        public PropagateLoopFrequency(FixedNode start) {
+            super(start, new LoopCount(1d));
+        }
+
+        @Override
+        protected void node(FixedNode node) {
+            nodeProbabilities.put(node, nodeProbabilities.get(node) * state.count);
+        }
+
+    }
+}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/CompilerConfiguration.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/CompilerConfiguration.java	Thu Apr 25 16:53:29 2013 +0200
@@ -29,4 +29,6 @@
     PhaseSuite<HighTierContext> createHighTier();
 
     PhaseSuite<MidTierContext> createMidTier();
+
+    PhaseSuite<LowTierContext> createLowTier();
 }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java	Thu Apr 25 16:53:29 2013 +0200
@@ -24,10 +24,11 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.spi.*;
 
 public class HighTierContext extends PhaseContext {
 
-    public HighTierContext(MetaAccessProvider runtime, Assumptions assumptions) {
-        super(runtime, assumptions);
+    public HighTierContext(MetaAccessProvider runtime, Assumptions assumptions, Replacements replacements) {
+        super(runtime, assumptions, replacements);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/LowTierContext.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, 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.
+ *
+ * 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.graal.phases.tiers;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.spi.*;
+
+public class LowTierContext extends PhaseContext {
+
+    private final TargetDescription target;
+
+    public LowTierContext(MetaAccessProvider runtime, Assumptions assumptions, Replacements replacements, TargetDescription target) {
+        super(runtime, assumptions, replacements);
+        this.target = target;
+    }
+
+    public TargetDescription getTarget() {
+        return target;
+    }
+}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/MidTierContext.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/MidTierContext.java	Thu Apr 25 16:53:29 2013 +0200
@@ -28,14 +28,14 @@
 
 public class MidTierContext extends PhaseContext {
 
-    private final Replacements replacements;
+    private final TargetDescription target;
 
-    public MidTierContext(MetaAccessProvider runtime, Assumptions assumptions, Replacements replacements) {
-        super(runtime, assumptions);
-        this.replacements = replacements;
+    public MidTierContext(MetaAccessProvider runtime, Assumptions assumptions, Replacements replacements, TargetDescription target) {
+        super(runtime, assumptions, replacements);
+        this.target = target;
     }
 
-    public Replacements getReplacements() {
-        return replacements;
+    public TargetDescription getTarget() {
+        return target;
     }
 }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/PhaseContext.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/PhaseContext.java	Thu Apr 25 16:53:29 2013 +0200
@@ -24,15 +24,18 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.spi.*;
 
 public class PhaseContext {
 
     private final MetaAccessProvider runtime;
     private final Assumptions assumptions;
+    private final Replacements replacements;
 
-    public PhaseContext(MetaAccessProvider runtime, Assumptions assumptions) {
+    public PhaseContext(MetaAccessProvider runtime, Assumptions assumptions, Replacements replacements) {
         this.runtime = runtime;
         this.assumptions = assumptions;
+        this.replacements = replacements;
     }
 
     public MetaAccessProvider getRuntime() {
@@ -42,4 +45,8 @@
     public Assumptions getAssumptions() {
         return assumptions;
     }
+
+    public Replacements getReplacements() {
+        return replacements;
+    }
 }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java	Thu Apr 25 16:53:29 2013 +0200
@@ -33,6 +33,7 @@
 
     private final PhaseSuite<HighTierContext> highTier;
     private final PhaseSuite<MidTierContext> midTier;
+    private final PhaseSuite<LowTierContext> lowTier;
 
     private static final Map<String, CompilerConfiguration> configurations;
 
@@ -44,6 +45,10 @@
         return midTier;
     }
 
+    public PhaseSuite<LowTierContext> getLowTier() {
+        return lowTier;
+    }
+
     static {
         configurations = new HashMap<>();
         for (CompilerConfiguration config : ServiceLoader.loadInstalled(CompilerConfiguration.class)) {
@@ -60,6 +65,7 @@
     private Suites(CompilerConfiguration config) {
         highTier = config.createHighTier();
         midTier = config.createMidTier();
+        lowTier = config.createLowTier();
     }
 
     public static Suites createDefaultSuites() {
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Thu Apr 25 16:53:29 2013 +0200
@@ -146,7 +146,8 @@
 
         } else if (object instanceof StructuredGraph) {
             if (cfgPrinter.cfg == null) {
-                cfgPrinter.cfg = ControlFlowGraph.compute((StructuredGraph) object, true, true, true, false);
+                StructuredGraph graph = (StructuredGraph) object;
+                cfgPrinter.cfg = ControlFlowGraph.compute(graph, true, true, true, false);
             }
             cfgPrinter.printCFG(message, Arrays.asList(cfgPrinter.cfg.getBlocks()));
 
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -50,7 +50,6 @@
                 StructuredGraph graph = parse(snippet);
                 PhasePlan phasePlan = getDefaultPhasePlan();
                 Assumptions assumptions = new Assumptions(true);
-                new ComputeProbabilityPhase().apply(graph);
                 Debug.dump(graph, "Graph");
                 new InliningPhase(runtime(), null, replacements, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
                 Debug.dump(graph, "Graph");
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Thu Apr 25 16:53:29 2013 +0200
@@ -379,10 +379,7 @@
                 end.disableSafepoint();
             }
 
-            if (GraalOptions.ProbabilityAnalysis) {
-                new DeadCodeEliminationPhase().apply(graph);
-                new ComputeProbabilityPhase().apply(graph);
-            }
+            new DeadCodeEliminationPhase().apply(graph);
             return graph;
         }
     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -61,7 +61,7 @@
     public static native void storeInt(Object obj, @ConstantNodeParameter int displacement, long offset, int value);
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         StructuredGraph graph = (StructuredGraph) this.graph();
         IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), displacement, offset, graph, 1);
         WriteNode write = graph.add(new WriteNode(object, value, location, WriteBarrierType.NONE));
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -67,7 +67,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         StructuredGraph snippetGraph = getSnippetGraph(tool);
 
         InvokeNode invoke = replaceWithInvoke();
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/CyclicMaterializeStoreNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/CyclicMaterializeStoreNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -68,7 +68,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         StructuredGraph graph = (StructuredGraph) graph();
         ResolvedJavaType type = object.objectStamp().type();
         FixedWithNextNode store;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -79,7 +79,7 @@
     }
 
     @Override
-    public void lower(LoweringTool tool) {
+    public void lower(LoweringTool tool, LoweringType loweringType) {
         virtualObject.materializeAt(this, values, isDefault(), lockCount);
     }
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java	Thu Apr 25 16:53:29 2013 +0200
@@ -169,7 +169,6 @@
 
         MaterializeObjectNode materialize = new MaterializeObjectNode(virtual, obj.getLockCount());
         ValueNode[] values = new ValueNode[obj.getEntries().length];
-        materialize.setProbability(fixed.probability());
         obj.escape(materialize, state);
         deferred.add(virtual);
         for (int i = 0; i < fieldState.length; i++) {
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Thu Apr 25 16:53:29 2013 +0200
@@ -33,7 +33,7 @@
 
 public class GraphEffectList extends EffectList {
 
-    public void addCounterBefore(final String name, final int increment, final boolean addContext, final FixedNode position) {
+    public void addCounterBefore(final String group, final String name, final int increment, final boolean addContext, final FixedNode position) {
         if (!DynamicCounterNode.enabled) {
             return;
         }
@@ -47,14 +47,13 @@
             @Override
             public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
                 assert position.isAlive();
-                DynamicCounterNode node = graph.add(new DynamicCounterNode(name, increment, addContext));
+                DynamicCounterNode node = graph.add(new DynamicCounterNode(group, name, increment, addContext));
                 graph.addBeforeFixed(position, node);
-                node.setProbability(position.probability());
             }
         });
     }
 
-    public void addSurvivingCounterBefore(final String name, final int increment, final boolean addContext, final ValueNode checkedValue, final FixedNode position) {
+    public void addSurvivingCounterBefore(final String group, final String name, final int increment, final boolean addContext, final ValueNode checkedValue, final FixedNode position) {
         if (!DynamicCounterNode.enabled) {
             return;
         }
@@ -68,9 +67,8 @@
             @Override
             public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
                 assert position.isAlive();
-                DynamicCounterNode node = graph.add(new SurvivingCounterNode(name, increment, addContext, checkedValue));
+                DynamicCounterNode node = graph.add(new SurvivingCounterNode(group, name, increment, addContext, checkedValue));
                 graph.addBeforeFixed(position, node);
-                node.setProbability(position.probability());
             }
         });
     }
@@ -94,7 +92,6 @@
             public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
                 assert !node.isAlive() && !node.isDeleted() && position.isAlive();
                 graph.addBeforeFixed(position, graph.add(node));
-                node.setProbability(position.probability());
             }
         });
     }
@@ -140,7 +137,6 @@
             public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
                 assert !node.isAlive() && !node.isDeleted() && position.isAlive();
                 graph.addBeforeFixed(position, graph.add(node));
-                node.setProbability(position.probability());
                 for (int i = 0; i < values.length; i++) {
                     node.getValues().set(i, values[i]);
                 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java	Thu Apr 25 16:53:29 2013 +0200
@@ -31,6 +31,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer;
@@ -200,20 +201,21 @@
     }
 
     public static Map<Invoke, Double> getHints(StructuredGraph graph) {
+        NodesToDoubles probabilities = new ComputeProbabilityClosure(graph).apply();
         Map<Invoke, Double> hints = null;
         for (MaterializeObjectNode materialize : graph.getNodes(MaterializeObjectNode.class)) {
             double sum = 0;
             double invokeSum = 0;
             for (Node usage : materialize.usages()) {
                 if (usage instanceof FixedNode) {
-                    sum += ((FixedNode) usage).probability();
+                    sum += probabilities.get((FixedNode) usage);
                 } else {
                     if (usage instanceof MethodCallTargetNode) {
-                        invokeSum += ((MethodCallTargetNode) usage).invoke().probability();
+                        invokeSum += probabilities.get(((MethodCallTargetNode) usage).invoke().asNode());
                     }
                     for (Node secondLevelUage : materialize.usages()) {
                         if (secondLevelUage instanceof FixedNode) {
-                            sum += ((FixedNode) secondLevelUage).probability();
+                            sum += probabilities.get(((FixedNode) secondLevelUage));
                         }
                     }
                 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/AssumptionsTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2012, 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.
+ *
+ * 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.codegen.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.api.codegen.test.AssumptionsTestFactory.DerivedAssumptionNodeFactory;
+import com.oracle.truffle.api.codegen.test.AssumptionsTestFactory.DerivedAssumptionRedeclaredNodeFactory;
+import com.oracle.truffle.api.codegen.test.AssumptionsTestFactory.MultipleAssumptionsNodeFactory;
+import com.oracle.truffle.api.codegen.test.AssumptionsTestFactory.SingleAssumptionNodeFactory;
+import com.oracle.truffle.api.codegen.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode;
+
+public class AssumptionsTest {
+
+    @Test
+    public void testSingleAssumption() {
+        Assumption assumption = Truffle.getRuntime().createAssumption();
+        TestRootNode<?> root = TestHelper.createRoot(SingleAssumptionNodeFactory.getInstance(), assumption);
+
+        Assert.assertEquals(42, TestHelper.executeWith(root));
+        assumption.invalidate();
+        Assert.assertEquals("42", TestHelper.executeWith(root));
+    }
+
+    @NodeAssumptions("assumption")
+    abstract static class SingleAssumptionNode extends ValueNode {
+
+        @Specialization(order = 0, assumptions = "assumption")
+        int doInt() {
+            return 42;
+        }
+
+        @Specialization
+        Object doObject() {
+            return "42";
+        }
+    }
+
+    @Test
+    public void testMultipleAssumption() {
+        Assumption assumption1 = Truffle.getRuntime().createAssumption();
+        Assumption assumption2 = Truffle.getRuntime().createAssumption();
+        TestRootNode<?> root = TestHelper.createRoot(MultipleAssumptionsNodeFactory.getInstance(), assumption1, assumption2);
+
+        Assert.assertEquals(42, TestHelper.executeWith(root));
+        assumption2.invalidate();
+        Assert.assertEquals("42", TestHelper.executeWith(root));
+        assumption1.invalidate();
+        Assert.assertEquals("43", TestHelper.executeWith(root));
+    }
+
+    @NodeAssumptions({"assumption1", "assumption2"})
+    abstract static class MultipleAssumptionsNode extends ValueNode {
+
+        @Specialization(assumptions = {"assumption1", "assumption2"})
+        int doInt() {
+            return 42;
+        }
+
+        @Specialization(assumptions = "assumption1")
+        Object doObject() {
+            return "42";
+        }
+
+        @Generic
+        Object doGeneric() {
+            return "43";
+        }
+    }
+
+    @Test
+    public void testDerivedAssumption() {
+        Assumption additionalAssumption = Truffle.getRuntime().createAssumption();
+        Assumption assumption = Truffle.getRuntime().createAssumption();
+        TestRootNode<?> root = TestHelper.createRoot(DerivedAssumptionNodeFactory.getInstance(), assumption, additionalAssumption);
+
+        Assert.assertEquals(42, TestHelper.executeWith(root));
+        assumption.invalidate();
+        Assert.assertEquals(43, TestHelper.executeWith(root));
+        additionalAssumption.invalidate();
+        Assert.assertEquals("42", TestHelper.executeWith(root));
+    }
+
+    @NodeAssumptions({"additionalAssumption"})
+    abstract static class DerivedAssumptionNode extends SingleAssumptionNode {
+
+        @Specialization(order = 1, assumptions = "additionalAssumption")
+        int doIntDerived() {
+            return 43;
+        }
+    }
+
+    @Test
+    public void testDerivedAssumptionRedeclared() {
+        Assumption additionalAssumption = Truffle.getRuntime().createAssumption();
+        Assumption assumption = Truffle.getRuntime().createAssumption();
+        TestRootNode<?> root = TestHelper.createRoot(DerivedAssumptionRedeclaredNodeFactory.getInstance(), additionalAssumption, assumption);
+
+        Assert.assertEquals(42, TestHelper.executeWith(root));
+        assumption.invalidate();
+        Assert.assertEquals(43, TestHelper.executeWith(root));
+        additionalAssumption.invalidate();
+        Assert.assertEquals("42", TestHelper.executeWith(root));
+    }
+
+    @NodeAssumptions({"additionalAssumption", "assumption"})
+    abstract static class DerivedAssumptionRedeclaredNode extends SingleAssumptionNode {
+
+        @Specialization(order = 1, assumptions = "additionalAssumption")
+        int doIntDerived() {
+            return 43;
+        }
+
+    }
+
+}
--- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BinaryNodeTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BinaryNodeTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -36,7 +36,7 @@
 
     @Test
     public void testAdd() {
-        TestRootNode<AddNode> node = create(AddNodeFactory.getInstance());
+        TestRootNode<AddNode> node = createRoot(AddNodeFactory.getInstance());
         assertEquals(42, executeWith(node, 19, 23));
         assertEquals(42d, executeWith(node, 19d, 23d));
         assertEquals(42d, executeWith(node, "19", "23"));
@@ -45,7 +45,7 @@
 
     @Test(expected = RuntimeException.class)
     public void testAddUnsupported() {
-        TestRootNode<AddNode> node = create(AddNodeFactory.getInstance());
+        TestRootNode<AddNode> node = createRoot(AddNodeFactory.getInstance());
         executeWith(node, new Object(), new Object());
     }
 
--- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BuiltinTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/BuiltinTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -39,7 +39,7 @@
 
     @Test
     public void testConcat() {
-        TestRootNode<BuiltinNode> node = create(StrConcatFactory.getInstance(), new Context());
+        TestRootNode<BuiltinNode> node = createRoot(StrConcatFactory.getInstance(), new Context());
         Str str1 = new Str("42");
         Str str2 = new Str(" is the number.");
         assertEquals(str1.concat(str2), executeWith(node, str1, str2));
@@ -47,13 +47,13 @@
 
     @Test(expected = UnsupportedOperationException.class)
     public void testConcatUnsupported() {
-        TestRootNode<BuiltinNode> node = create(StrConcatFactory.getInstance(), new Context());
+        TestRootNode<BuiltinNode> node = createRoot(StrConcatFactory.getInstance(), new Context());
         executeWith(node, 42, new Str(" is the number."));
     }
 
     @Test
     public void testSubstrSpecialized() {
-        TestRootNode<BuiltinNode> node = create(StrSubstrFactory.getInstance(), new Context());
+        TestRootNode<BuiltinNode> node = createRoot(StrSubstrFactory.getInstance(), new Context());
         Str str = new Str("test 42");
 
         assertEquals(str.substr(5, 7), executeWith(node, str, 5, 7));
@@ -61,7 +61,7 @@
 
     @Test
     public void testSubstrGeneric() {
-        TestRootNode<BuiltinNode> node = create(StrSubstrFactory.getInstance(), new Context());
+        TestRootNode<BuiltinNode> node = createRoot(StrSubstrFactory.getInstance(), new Context());
         Str str = new Str("test 42");
 
         assertEquals(Str.substr(str, "5", "7"), executeWith(node, str, "5", "7"));
@@ -69,27 +69,27 @@
 
     @Test(expected = UnsupportedOperationException.class)
     public void testSubstrUnsupported() {
-        TestRootNode<BuiltinNode> node = create(StrSubstrFactory.getInstance(), new Context());
+        TestRootNode<BuiltinNode> node = createRoot(StrSubstrFactory.getInstance(), new Context());
         executeWith(node, new Object(), "5", "7");
     }
 
     @Test
     public void testLength() {
-        TestRootNode<BuiltinNode> node = create(StrLengthFactory.getInstance(), new Context());
+        TestRootNode<BuiltinNode> node = createRoot(StrLengthFactory.getInstance(), new Context());
         Str testStr = new Str("test 42");
         assertEquals(testStr.length(), executeWith(node, testStr));
     }
 
     @Test(expected = UnsupportedOperationException.class)
     public void testLengthUnsupported() {
-        TestRootNode<BuiltinNode> node = create(StrLengthFactory.getInstance(), new Context());
+        TestRootNode<BuiltinNode> node = createRoot(StrLengthFactory.getInstance(), new Context());
         executeWith(node, new Object());
     }
 
     @Test
     public void testAccessContext() {
         Context context = new Context();
-        TestRootNode<BuiltinNode> node = create(StrAccessContextFactory.getInstance(), context);
+        TestRootNode<BuiltinNode> node = createRoot(StrAccessContextFactory.getInstance(), context);
         // accessible by node
         assertSame(context, node.getNode().getContext());
         // accessible by execution
--- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/ExecuteEvaluatedTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/ExecuteEvaluatedTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -22,48 +22,86 @@
  */
 package com.oracle.truffle.api.codegen.test;
 
+import org.junit.*;
+
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.codegen.*;
+import com.oracle.truffle.api.codegen.test.ExecuteEvaluatedTestFactory.DoubleEvaluatedNodeFactory;
+import com.oracle.truffle.api.codegen.test.ExecuteEvaluatedTestFactory.EvaluatedNodeFactory;
+import com.oracle.truffle.api.codegen.test.ExecuteEvaluatedTestFactory.UseDoubleEvaluatedNodeFactory;
+import com.oracle.truffle.api.codegen.test.ExecuteEvaluatedTestFactory.UseEvaluatedNodeFactory;
+import com.oracle.truffle.api.codegen.test.TypeSystemTest.ArgumentNode;
+import com.oracle.truffle.api.codegen.test.TypeSystemTest.TestArguments;
 import com.oracle.truffle.api.codegen.test.TypeSystemTest.ValueNode;
 import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
 
 public class ExecuteEvaluatedTest {
 
-    /* Represents target[element] */
-    @NodeChildren({@NodeChild("target"), @NodeChild("element")})
-    abstract static class ReadElementNode extends ValueNode {
+    @Test
+    public void testSingleEvaluated() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        CallTarget callTarget = TestHelper.createCallTarget(UseEvaluatedNodeFactory.create(arg0, EvaluatedNodeFactory.create(null)));
+
+        Assert.assertEquals(43, callTarget.call(new TestArguments(42)));
+        Assert.assertEquals(1, arg0.getInvocationCount());
+    }
+
+    @NodeChild("exp")
+    abstract static class EvaluatedNode extends ValueNode {
 
         @Specialization
-        int getInt(Object[] target, int element) {
-            return (int) target[element];
+        int doExecuteWith(int exp) {
+            return exp + 1;
         }
 
-        public abstract Object executeWith(VirtualFrame frame, Object targetValue);
+        public abstract Object executeEvaluated(VirtualFrame frame, Object targetValue);
+
+        public abstract int executeIntEvaluated(VirtualFrame frame, Object targetValue) throws UnexpectedResultException;
     }
 
-    /* Represents target[element]() */
-    @NodeChildren({@NodeChild("target"), @NodeChild(value = "element", type = ReadElementNode.class, executeWith = "target")})
-    abstract static class ElementCallNode extends ValueNode {
+    @NodeChildren({@NodeChild("exp0"), @NodeChild(value = "exp1", type = EvaluatedNode.class, executeWith = "exp0")})
+    abstract static class UseEvaluatedNode extends ValueNode {
 
         @Specialization
-        Object call(Object receiver, Object callTarget) {
-            return ((CallTarget) callTarget).call(new TestArguments(receiver));
+        int call(int exp0, int exp1) {
+            Assert.assertEquals(exp0 + 1, exp1);
+            return exp1;
         }
+    }
 
+    @Test
+    public void testDoubleEvaluated() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        ArgumentNode arg1 = new ArgumentNode(1);
+        CallTarget callTarget = TestHelper.createCallTarget(UseDoubleEvaluatedNodeFactory.create(arg0, arg1, DoubleEvaluatedNodeFactory.create(null, null)));
+
+        Assert.assertEquals(85, callTarget.call(new TestArguments(42, 43)));
+        Assert.assertEquals(1, arg0.getInvocationCount());
+        Assert.assertEquals(1, arg1.getInvocationCount());
     }
 
-    public static class TestArguments extends Arguments {
+    @NodeChildren({@NodeChild("exp0"), @NodeChild("exp1")})
+    abstract static class DoubleEvaluatedNode extends ValueNode {
 
-        private final Object receiver;
-
-        public TestArguments(Object receiver) {
-            this.receiver = receiver;
+        @Specialization
+        int doExecuteWith(int exp0, int exp1) {
+            return exp0 + exp1;
         }
 
-        public Object getReceiver() {
-            return receiver;
+        public abstract Object executeEvaluated(VirtualFrame frame, Object exp0, Object exp1);
+
+        public abstract int executeIntEvaluated(VirtualFrame frame, Object exp0, Object exp1) throws UnexpectedResultException;
+    }
+
+    @NodeChildren({@NodeChild("exp0"), @NodeChild("exp1"), @NodeChild(value = "exp2", type = DoubleEvaluatedNode.class, executeWith = {"exp0", "exp1"})})
+    abstract static class UseDoubleEvaluatedNode extends ValueNode {
+
+        @Specialization
+        int call(int exp0, int exp1, int exp2) {
+            Assert.assertEquals(exp0 + exp1, exp2);
+            return exp2;
         }
-
     }
 
 }
--- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/GuardsTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/GuardsTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -40,7 +40,7 @@
 
     @Test
     public void testGuardInvocations() {
-        TestRootNode<InvocationGuard> root = create(InvocationGuardFactory.getInstance());
+        TestRootNode<InvocationGuard> root = createRoot(InvocationGuardFactory.getInstance());
 
         assertEquals(Integer.MAX_VALUE, executeWith(root, Integer.MAX_VALUE - 1, 1));
         assertEquals(1, InvocationGuard.specializedInvocations);
@@ -76,7 +76,7 @@
 
     @Test
     public void testGuardGlobal() {
-        TestRootNode<GlobalFlagGuard> root = create(GlobalFlagGuardFactory.getInstance());
+        TestRootNode<GlobalFlagGuard> root = createRoot(GlobalFlagGuardFactory.getInstance());
 
         assertEquals(42, executeWith(root, NULL));
 
--- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TestHelper.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TestHelper.java	Thu Apr 25 16:53:29 2013 +0200
@@ -42,7 +42,7 @@
         return nodes;
     }
 
-    static <E extends ValueNode> TestRootNode<E> create(NodeFactory<E> factory, Object... constants) {
+    static <E extends ValueNode> E createNode(NodeFactory<E> factory, Object... constants) {
         ArgumentNode[] argumentNodes = arguments(factory.getExecutionSignature().size());
 
         List<Object> argumentList = new ArrayList<>();
@@ -52,11 +52,23 @@
         } else {
             argumentList.addAll(Arrays.asList(argumentNodes));
         }
-        return new TestRootNode<>(factory.createNode(argumentList.toArray(new Object[argumentList.size()])));
+        return factory.createNode(argumentList.toArray(new Object[argumentList.size()]));
+    }
+
+    static <E extends ValueNode> TestRootNode<E> createRoot(NodeFactory<E> factory, Object... constants) {
+        return new TestRootNode<>(createNode(factory, constants));
+    }
+
+    static CallTarget createCallTarget(ValueNode node) {
+        return createCallTarget(new TestRootNode<>(node));
+    }
+
+    static CallTarget createCallTarget(TestRootNode<? extends ValueNode> node) {
+        return Truffle.getRuntime().createCallTarget(node);
     }
 
     static <E> Object executeWith(TestRootNode<? extends ValueNode> node, Object... values) {
-        return Truffle.getRuntime().createCallTarget(node).call(new TestArguments(values));
+        return createCallTarget(node).call(new TestArguments(values));
     }
 
 }
--- a/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -101,14 +101,20 @@
 
     public static class ArgumentNode extends ValueNode {
 
+        private int invocationCount;
         final int index;
 
         public ArgumentNode(int index) {
             this.index = index;
         }
 
+        public int getInvocationCount() {
+            return invocationCount;
+        }
+
         @Override
         public Object execute(VirtualFrame frame) {
+            invocationCount++;
             return ((TestArguments) frame.getArguments()).get(index);
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeAssumptions.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012, 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.
+ *
+ * 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.codegen;
+
+import java.lang.annotation.*;
+
+/**
+ * Declares one or multiple assumptions for use inside a source code generation enabled node.
+ * Declared assumptions must be passed to the {@link NodeFactory#createNode(Object...)} method as
+ * parameters.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.TYPE})
+public @interface NodeAssumptions {
+
+    String[] value();
+
+}
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChild.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeChild.java	Thu Apr 25 16:53:29 2013 +0200
@@ -24,6 +24,8 @@
 
 import java.lang.annotation.*;
 
+import com.oracle.truffle.api.nodes.*;
+
 @Retention(RetentionPolicy.CLASS)
 @Target({ElementType.TYPE})
 public @interface NodeChild {
@@ -32,5 +34,14 @@
 
     Class<?> type() default NodeClass.InheritNode.class;
 
+    /**
+     * Executes the {@link NodeChild} with values from other defined {@link NodeChild} elements.
+     * These referenced children must be defined before the current node in the execution order. The
+     * current node {@link #type()} attribute must be set to a {@link Node} which supports the
+     * evaluated execution with the number of {@link #executeWith()} arguments that are defined. For
+     * example if this child is executed with one argument, the {@link #type()} attribute must
+     * define a node which publicly declares a method with the signature
+     * <code>Object execute*(VirtualFrame, Object)</code>.
+     */
     String[] executeWith() default {};
 }
--- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Specialization.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Specialization.java	Thu Apr 25 16:53:29 2013 +0200
@@ -36,4 +36,11 @@
 
     String[] guards() default {};
 
+    /**
+     * Defines the assumptions to check for this specialization. When the specialization method is
+     * invoked it is guaranteed that the assigned assumptions still hold. To declare assumptions use
+     * the {@link NodeAssumptions} annotation at class level.
+     */
+    String[] assumptions() default {};
+
 }
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -34,12 +34,7 @@
  * <p>
  * Dynamically typed languages can speculate on the type of a frame slot and only fall back at run
  * time to a more generic type if necessary. The new type of a frame slot can be set using the
- * {@link FrameSlot#setType(Class)} method. It is the responsibility of the language implementor to
- * update the content of currently active frames (using {@link Frame#updateToLatestVersion()}).
- * Also, nodes that depend a specific type of a frame slot must be replaced. Such node can register
- * a listener that implements {@link FrameSlotTypeListener} using
- * {@link FrameSlot#registerOneShotTypeListener(FrameSlotTypeListener)}. The event of a type change
- * on the frame slot will fire only once for the next upcoming change.
+ * {@link FrameSlot#setType(Class)} method.
  * </p>
  * 
  * <p>
@@ -53,10 +48,10 @@
     public void test() {
         TruffleRuntime runtime = Truffle.getRuntime();
         FrameDescriptor frameDescriptor = new FrameDescriptor();
-        FrameSlot slot = frameDescriptor.addFrameSlot("localVar", Integer.class);
+        FrameSlot slot = frameDescriptor.addFrameSlot("localVar", int.class);
         TestRootNode rootNode = new TestRootNode(new IntAssignLocal(slot, new StringTestChildNode()), new IntReadLocal(slot));
         CallTarget target = runtime.createCallTarget(rootNode, frameDescriptor);
-        Assert.assertEquals(Integer.class, slot.getType());
+        Assert.assertEquals(int.class, slot.getType());
         Object result = target.call();
         Assert.assertEquals("42", result);
         Assert.assertEquals(Object.class, slot.getType());
@@ -102,35 +97,29 @@
 
     }
 
-    class IntAssignLocal extends FrameSlotNode implements FrameSlotTypeListener {
+    class IntAssignLocal extends FrameSlotNode {
 
         @Child private TestChildNode value;
 
         IntAssignLocal(FrameSlot slot, TestChildNode value) {
             super(slot);
             this.value = adoptChild(value);
-            slot.registerOneShotTypeListener(this);
         }
 
         @Override
         Object execute(VirtualFrame frame) {
             Object o = value.execute(frame);
             if (o instanceof Integer) {
-                frame.setInt(slot, (Integer) o);
-            } else {
-                slot.setType(Object.class);
-                frame.updateToLatestVersion();
-                frame.setObject(slot, o);
+                try {
+                    frame.setInt(slot, (Integer) o);
+                } catch (FrameSlotTypeException e) {
+                    // fall through
+                }
             }
+            FrameUtil.setObjectSafe(frame, slot, o);
+            this.replace(new ObjectAssignLocal(slot, value));
             return null;
         }
-
-        @Override
-        public void typeChanged(FrameSlot changedSlot, Class<?> oldType) {
-            if (changedSlot.getType() == Object.class) {
-                this.replace(new ObjectAssignLocal(changedSlot, value));
-            }
-        }
     }
 
     class ObjectAssignLocal extends FrameSlotNode {
@@ -145,27 +134,27 @@
         @Override
         Object execute(VirtualFrame frame) {
             Object o = value.execute(frame);
-            frame.setObject(slot, o);
+            try {
+                frame.setObject(slot, o);
+            } catch (FrameSlotTypeException e) {
+                FrameUtil.setObjectSafe(frame, slot, o);
+            }
             return null;
         }
     }
 
-    class IntReadLocal extends FrameSlotNode implements FrameSlotTypeListener {
+    class IntReadLocal extends FrameSlotNode {
 
         IntReadLocal(FrameSlot slot) {
             super(slot);
-            slot.registerOneShotTypeListener(this);
         }
 
         @Override
         Object execute(VirtualFrame frame) {
-            return frame.getInt(slot);
-        }
-
-        @Override
-        public void typeChanged(FrameSlot changedSlot, Class<?> oldType) {
-            if (changedSlot.getType() == Object.class) {
-                this.replace(new ObjectReadLocal(changedSlot));
+            try {
+                return frame.getInt(slot);
+            } catch (FrameSlotTypeException e) {
+                return this.replace(new ObjectReadLocal(slot)).execute(frame);
             }
         }
     }
@@ -178,7 +167,11 @@
 
         @Override
         Object execute(VirtualFrame frame) {
-            return frame.getObject(slot);
+            try {
+                return frame.getObject(slot);
+            } catch (FrameSlotTypeException e) {
+                throw new IllegalStateException(e);
+            }
         }
     }
 }
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -64,7 +64,7 @@
     public void test() {
         TruffleRuntime runtime = Truffle.getRuntime();
         FrameDescriptor frameDescriptor = new FrameDescriptor();
-        FrameSlot slot = frameDescriptor.addFrameSlot("localVar", Integer.class);
+        FrameSlot slot = frameDescriptor.addFrameSlot("localVar", int.class);
         TestRootNode rootNode = new TestRootNode(new AssignLocal(slot), new ReadLocal(slot));
         CallTarget target = runtime.createCallTarget(rootNode, frameDescriptor);
         Object result = target.call();
@@ -109,7 +109,11 @@
 
         @Override
         int execute(VirtualFrame frame) {
-            frame.setInt(slot, 42);
+            try {
+                frame.setInt(slot, 42);
+            } catch (FrameSlotTypeException e) {
+                throw new IllegalStateException(e);
+            }
             return 0;
         }
     }
@@ -122,7 +126,11 @@
 
         @Override
         int execute(VirtualFrame frame) {
-            return frame.getInt(slot);
+            try {
+                return frame.getInt(slot);
+            } catch (FrameSlotTypeException e) {
+                throw new IllegalStateException(e);
+            }
         }
     }
 }
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -47,10 +47,10 @@
     public void test() {
         TruffleRuntime runtime = Truffle.getRuntime();
         FrameDescriptor frameDescriptor = new FrameDescriptor();
-        FrameSlot slot = frameDescriptor.addFrameSlot("localVar", Integer.class);
+        FrameSlot slot = frameDescriptor.addFrameSlot("localVar", int.class);
         TestRootNode rootNode = new TestRootNode(new IntAssignLocal(slot, new StringTestChildNode()), new IntReadLocal(slot));
         CallTarget target = runtime.createCallTarget(rootNode, frameDescriptor);
-        Assert.assertEquals(Integer.class, slot.getType());
+        Assert.assertEquals(int.class, slot.getType());
         Object result = target.call();
         Assert.assertEquals("42", result);
         Assert.assertEquals(Object.class, slot.getType());
@@ -104,34 +104,31 @@
 
     }
 
-    class IntAssignLocal extends FrameSlotNode implements FrameSlotTypeListener {
+    class IntAssignLocal extends FrameSlotNode {
 
         @Child private TestChildNode value;
 
         IntAssignLocal(FrameSlot slot, TestChildNode value) {
             super(slot);
             this.value = adoptChild(value);
-            slot.registerOneShotTypeListener(this);
         }
 
         @Override
         Object execute(VirtualFrame frame) {
             try {
-                frame.setInt(slot, value.executeInt(frame));
+                int result = value.executeInt(frame);
+                try {
+                    frame.setInt(slot, result);
+                } catch (FrameSlotTypeException e) {
+                    FrameUtil.setObjectSafe(frame, slot, result);
+                    replace(new ObjectAssignLocal(slot, value));
+                }
             } catch (UnexpectedResultException e) {
-                slot.setType(Object.class);
-                frame.updateToLatestVersion();
-                frame.setObject(slot, e.getResult());
+                FrameUtil.setObjectSafe(frame, slot, e.getResult());
+                replace(new ObjectAssignLocal(slot, value));
             }
             return null;
         }
-
-        @Override
-        public void typeChanged(FrameSlot changedSlot, Class<?> oldType) {
-            if (changedSlot.getType() == Object.class) {
-                this.replace(new ObjectAssignLocal(changedSlot, value));
-            }
-        }
     }
 
     class ObjectAssignLocal extends FrameSlotNode {
@@ -146,32 +143,36 @@
         @Override
         Object execute(VirtualFrame frame) {
             Object o = value.execute(frame);
-            frame.setObject(slot, o);
+            try {
+                frame.setObject(slot, o);
+            } catch (FrameSlotTypeException e) {
+                FrameUtil.setObjectSafe(frame, slot, o);
+            }
             return null;
         }
     }
 
-    class IntReadLocal extends FrameSlotNode implements FrameSlotTypeListener {
+    class IntReadLocal extends FrameSlotNode {
 
         IntReadLocal(FrameSlot slot) {
             super(slot);
-            slot.registerOneShotTypeListener(this);
         }
 
         @Override
         Object execute(VirtualFrame frame) {
-            return executeInt(frame);
+            try {
+                return frame.getInt(slot);
+            } catch (FrameSlotTypeException e) {
+                return replace(new ObjectReadLocal(slot)).execute(frame);
+            }
         }
 
         @Override
-        int executeInt(VirtualFrame frame) {
-            return frame.getInt(slot);
-        }
-
-        @Override
-        public void typeChanged(FrameSlot changedSlot, Class<?> oldType) {
-            if (changedSlot.getType() == Object.class) {
-                this.replace(new ObjectReadLocal(changedSlot));
+        int executeInt(VirtualFrame frame) throws UnexpectedResultException {
+            try {
+                return frame.getInt(slot);
+            } catch (FrameSlotTypeException e) {
+                return replace(new ObjectReadLocal(slot)).executeInt(frame);
             }
         }
     }
@@ -184,7 +185,11 @@
 
         @Override
         Object execute(VirtualFrame frame) {
-            return frame.getObject(slot);
+            try {
+                return frame.getObject(slot);
+            } catch (FrameSlotTypeException e) {
+                throw new IllegalStateException(e);
+            }
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Assumption.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ *
+ * 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;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * An assumption is a global boolean flag that starts with the value true (i.e., the assumption is
+ * valid) and can subsequently be invalidated (using {@link Assumption#invalidate()}). Once
+ * invalidated, an assumption can never get valid again. Assumptions can be created using the
+ * {@link TruffleRuntime#createAssumption()} or the {@link TruffleRuntime#createAssumption(String)}
+ * method. The Truffle compiler has special knowledge of this class in order to produce efficient
+ * machine code for checking an assumption in case the assumption object is a compile time constant.
+ * Therefore, assumptions should be stored in final fields in Truffle nodes.
+ */
+public interface Assumption {
+
+    /**
+     * Checks that this assumption is still valid. The method throws an exception, if this is no
+     * longer the case. This method is preferred over the {@link #isValid()} method when writing
+     * guest language interpreter code. The catch block should perform a node rewrite (see
+     * {@link Node#replace(Node)}) with a node that no longer relies on the assumption.
+     * 
+     * @throws InvalidAssumptionException If the assumption is no longer valid.
+     */
+    void check() throws InvalidAssumptionException;
+
+    /**
+     * Checks whether the assumption is still valid.
+     * 
+     * @return a boolean value indicating the validity of the assumption
+     */
+    boolean isValid();
+
+    /**
+     * Invalidates this assumption. Performs no operation, if the assumption is already invalid.
+     */
+    void invalidate();
+
+    /**
+     * A name for the assumption that is used for debug output.
+     * 
+     * @return the name of the assumption
+     */
+    String getName();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerAsserts.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2013, 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.
+ *
+ * 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;
+
+/**
+ * Assertions about the code produced by the Truffle compiler. All operations have no effect when
+ * either executed in the interpreter or in the compiled code. The assertions are checked during
+ * code generation and the Truffle compiler produces for failing assertions a stack trace that
+ * identifies the code position of the assertion in the context of the current compilation.
+ * 
+ */
+public class CompilerAsserts {
+
+    /**
+     * Assertion that this code position should never be reached during compilation. It can be used
+     * for exceptional code paths or rare code paths that should never be included in a compilation
+     * unit. See {@link CompilerDirectives#transferToInterpreter()} for the corresponding compiler
+     * directive.
+     */
+    public static void neverPartOfCompilation() {
+    }
+
+    /**
+     * Assertion that the corresponding value is reduced to a constant during compilation.
+     * 
+     * @param value the value that must be constant during compilation
+     * @return the value given as parameter
+     */
+    public static boolean compilationConstant(boolean value) {
+        return value;
+    }
+
+    /**
+     * Assertion that the corresponding value is reduced to a constant during compilation.
+     * 
+     * @param value the value that must be constant during compilation
+     * @return the value given as parameter
+     */
+    public static byte compilationConstant(byte value) {
+        return value;
+    }
+
+    /**
+     * Assertion that the corresponding value is reduced to a constant during compilation.
+     * 
+     * @param value the value that must be constant during compilation
+     * @return the value given as parameter
+     */
+    public static char compilationConstant(char value) {
+        return value;
+    }
+
+    /**
+     * Assertion that the corresponding value is reduced to a constant during compilation.
+     * 
+     * @param value the value that must be constant during compilation
+     * @return the value given as parameter
+     */
+    public static short compilationConstant(short value) {
+        return value;
+    }
+
+    /**
+     * Assertion that the corresponding value is reduced to a constant during compilation.
+     * 
+     * @param value the value that must be constant during compilation
+     * @return the value given as parameter
+     */
+    public static int compilationConstant(int value) {
+        return value;
+    }
+
+    /**
+     * Assertion that the corresponding value is reduced to a constant during compilation.
+     * 
+     * @param value the value that must be constant during compilation
+     * @return the value given as parameter
+     */
+    public static long compilationConstant(long value) {
+        return value;
+    }
+
+    /**
+     * Assertion that the corresponding value is reduced to a constant during compilation.
+     * 
+     * @param value the value that must be constant during compilation
+     * @return the value given as parameter
+     */
+    public static float compilationConstant(float value) {
+        return value;
+    }
+
+    /**
+     * Assertion that the corresponding value is reduced to a constant during compilation.
+     * 
+     * @param value the value that must be constant during compilation
+     * @return the value given as parameter
+     */
+    public static double compilationConstant(double value) {
+        return value;
+    }
+
+    /**
+     * Assertion that the corresponding value is reduced to a constant during compilation.
+     * 
+     * @param value the value that must be constant during compilation
+     * @return the value given as parameter
+     */
+    public static Object compilationConstant(Object value) {
+        return value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2013, 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.
+ *
+ * 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;
+
+import java.util.concurrent.*;
+
+/**
+ * Directives that influence the optimizations of the Truffle compiler. All of the operations have
+ * no effect when executed in the Truffle interpreter.
+ */
+public class CompilerDirectives {
+
+    private static final double SLOWPATH_PROBABILITY = 0.0001;
+
+    /**
+     * Directive for the compiler to discontinue compilation at this code position and instead
+     * insert a transfer to the interpreter.
+     */
+    public static void transferToInterpreter() {
+    }
+
+    /**
+     * Directive for the compiler that the given runnable should only be executed in the interpreter
+     * and ignored in the compiled code.
+     * 
+     * @param runnable the closure that should only be executed in the interpreter
+     */
+    public static void interpreterOnly(Runnable runnable) {
+        runnable.run();
+    }
+
+    /**
+     * Directive for the compiler that the given callable should only be executed in the
+     * interpreter.
+     * 
+     * @param callable the closure that should only be executed in the interpreter
+     * @return the result of executing the closure in the interpreter and null in the compiled code
+     * @throws Exception If the closure throws an exception when executed in the interpreter.
+     */
+    public static <T> T interpreterOnly(Callable<T> callable) throws Exception {
+        return callable.call();
+    }
+
+    /**
+     * Directive for the compiler that the current path has a very low probability to be executed.
+     */
+    public static void slowpath() {
+        injectBranchProbability(SLOWPATH_PROBABILITY);
+    }
+
+    /**
+     * Injects a probability for the current path into the probability information of the
+     * immediately preceeding branch instruction.
+     * 
+     * @param probability the probability value between 0.0 and 1.0 that should be injected
+     */
+    public static void injectBranchProbability(double probability) {
+        assert probability >= 0.0 && probability <= 1.0;
+    }
+
+    /**
+     * Bails out of a compilation (e.g., for guest language features that should never be compiled).
+     * 
+     * @param reason the reason for the bailout
+     */
+    public static void bailout(String reason) {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExactMath.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ *
+ * 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;
+
+/**
+ * This class contains methods that will be part of java.lang.Math starting with JDK 8. Until JDK 8
+ * is release, we duplicate them here because they are generally useful for dynamic language
+ * implementations.
+ */
+public class ExactMath {
+
+    public static int addExact(int x, int y) {
+        int r = x + y;
+        // HD 2-12 Overflow iff both arguments have the opposite sign of the result
+        if (((x ^ r) & (y ^ r)) < 0) {
+            throw new ArithmeticException("integer overflow");
+        }
+        return r;
+    }
+
+    public static long addExact(long x, long y) {
+        long r = x + y;
+        // HD 2-12 Overflow iff both arguments have the opposite sign of the result
+        if (((x ^ r) & (y ^ r)) < 0) {
+            throw new ArithmeticException("long overflow");
+        }
+        return r;
+    }
+
+    public static int subtractExact(int x, int y) {
+        int r = x - y;
+        // HD 2-12 Overflow iff the arguments have different signs and
+        // the sign of the result is different than the sign of x
+        if (((x ^ y) & (x ^ r)) < 0) {
+            throw new ArithmeticException("integer overflow");
+        }
+        return r;
+    }
+
+    public static long subtractExact(long x, long y) {
+        long r = x - y;
+        // HD 2-12 Overflow iff the arguments have different signs and
+        // the sign of the result is different than the sign of x
+        if (((x ^ y) & (x ^ r)) < 0) {
+            throw new ArithmeticException("long overflow");
+        }
+        return r;
+    }
+
+    public static int multiplyExact(int x, int y) {
+        long r = (long) x * (long) y;
+        if ((int) r != r) {
+            throw new ArithmeticException("long overflow");
+        }
+        return (int) r;
+    }
+
+    public static long multiplyExact(long x, long y) {
+        long r = x * y;
+        long ax = Math.abs(x);
+        long ay = Math.abs(y);
+        if (((ax | ay) >>> 31 != 0)) {
+            // Some bits greater than 2^31 that might cause overflow
+            // Check the result using the divide operator
+            // and check for the special case of Long.MIN_VALUE * -1
+            if (((y != 0) && (r / y != x)) || (x == Long.MIN_VALUE && y == -1)) {
+                throw new ArithmeticException("long overflow");
+            }
+        }
+        return r;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/LoopCountReceiver.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ *
+ * 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;
+
+public interface LoopCountReceiver {
+
+    void reportLoopCount(int count);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Source.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, 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.
+ *
+ * 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;
+
+/**
+ * Represents the source code of a guest language program.
+ */
+public interface Source {
+
+    /**
+     * Returns the name of this resource holding a guest language program. An example would be the
+     * name of a guest language source code file.
+     * 
+     * @return the name of the guest language program
+     */
+    String getName();
+
+    /**
+     * Returns the guest language source code represented by this source object.
+     * 
+     * @return the source code as a String object
+     */
+    String getCode();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2013, 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.
+ *
+ * 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;
+
+/**
+ * Represents a section in the source code of a guest language program.
+ */
+public class SourceSection {
+
+    private final Source source;
+    private final String identifier;
+    private final int startLine;
+    private final int startColumn;
+    private final int charIndex;
+    private final int charLength;
+
+    /**
+     * Creates a new object representing a section in the source code of a guest language program.
+     * 
+     * @param source object representing the source program this is should be a section of
+     * @param identifier an identifier used when printing the section
+     * @param startLine the index of the start line of the section
+     * @param startColumn the index of the start column of the section
+     * @param charIndex the index of the first character of the section
+     * @param charLength the length of the section in number of characters
+     */
+    public SourceSection(Source source, String identifier, int startLine, int startColumn, int charIndex, int charLength) {
+        this.source = source;
+        this.identifier = identifier;
+        this.startLine = startLine;
+        this.startColumn = startColumn;
+        this.charIndex = charIndex;
+        this.charLength = charLength;
+    }
+
+    /**
+     * Returns the source object representing the source program this is a section of.
+     * 
+     * @return the source object
+     */
+    public final Source getSource() {
+        return source;
+    }
+
+    /**
+     * Returns the index of the start line of this source section (inclusive).
+     * 
+     * @return the start line
+     */
+    public final int getStartLine() {
+        return startLine;
+    }
+
+    /**
+     * Returns the index of the start column of this source section (inclusive).
+     * 
+     * @return the start column
+     */
+    public final int getStartColumn() {
+        return startColumn;
+    }
+
+    /**
+     * Returns the index of the first character of this section. All characters of the source can be
+     * retrieved via the {@link Source#getCode()} method.
+     * 
+     * @return the character index
+     */
+    public final int getCharIndex() {
+        return charIndex;
+    }
+
+    /**
+     * Returns the length of this section in characters. All characters of the source can be
+     * retrieved via the {@link Source#getCode()} method.
+     * 
+     * @return the character length
+     */
+    public final int getCharLength() {
+        return charLength;
+    }
+
+    /**
+     * Returns the identifier of this source section that is used for printing the section.
+     * 
+     * @return the identifier of the section
+     */
+    public final String getIdentifier() {
+        return identifier;
+    }
+
+    /**
+     * Returns the code represented by this code section.
+     * 
+     * @return the code as a String object
+     */
+    public final String getCode() {
+        return getSource().getCode().substring(charIndex, charLength);
+    }
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java	Thu Apr 25 16:53:29 2013 +0200
@@ -60,6 +60,21 @@
     CallTarget createCallTarget(RootNode rootNode, FrameDescriptor frameDescriptor);
 
     /**
+     * Creates a new assumption object that can be checked and invalidated.
+     * 
+     * @return the newly created assumption object
+     */
+    Assumption createAssumption();
+
+    /**
+     * Creates a new assumption object with a given name that can be checked and invalidated.
+     * 
+     * @param name the name for the new assumption
+     * @return the newly created assumption object
+     */
+    Assumption createAssumption(String name);
+
+    /**
      * Creates a new materialized frame object that can be used to store values.
      * 
      * @return the newly created materialized frame object
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/DefaultTypeConversion.java	Mon Apr 22 18:30:33 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * 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.
- *
- * 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.frame;
-
-/**
- * Default type conversion semantics where a conversion is without changing any data.
- */
-public final class DefaultTypeConversion implements TypeConversion {
-
-    private static DefaultTypeConversion instance = new DefaultTypeConversion();
-
-    public static TypeConversion getInstance() {
-        return instance;
-    }
-
-    private DefaultTypeConversion() {
-
-    }
-
-    @Override
-    public Class<?> getTopType() {
-        return Object.class;
-    }
-
-    @Override
-    public Object convertTo(Class<?> targetType, Object value) {
-        return value;
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java	Thu Apr 25 16:53:29 2013 +0200
@@ -46,7 +46,7 @@
      * @param slot the slot of the local variable
      * @return the current value of the local variable
      */
-    Object getObject(FrameSlot slot);
+    Object getObject(FrameSlot slot) throws FrameSlotTypeException;
 
     /**
      * Write access to a local variable of type {@link Object}.
@@ -54,7 +54,7 @@
      * @param slot the slot of the local variable
      * @param value the new value of the local variable
      */
-    void setObject(FrameSlot slot, Object value);
+    void setObject(FrameSlot slot, Object value) throws FrameSlotTypeException;
 
     /**
      * Read access to a local variable of type boolean.
@@ -62,7 +62,7 @@
      * @param slot the slot of the local variable
      * @return the current value of the local variable
      */
-    boolean getBoolean(FrameSlot slot);
+    boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException;
 
     /**
      * Write access to a local variable of type boolean.
@@ -70,7 +70,7 @@
      * @param slot the slot of the local variable
      * @param value the new value of the local variable
      */
-    void setBoolean(FrameSlot slot, boolean value);
+    void setBoolean(FrameSlot slot, boolean value) throws FrameSlotTypeException;
 
     /**
      * Read access to a local variable of type int.
@@ -78,7 +78,7 @@
      * @param slot the slot of the local variable
      * @return the current value of the local variable
      */
-    int getInt(FrameSlot slot);
+    int getInt(FrameSlot slot) throws FrameSlotTypeException;
 
     /**
      * Write access to a local variable of type int.
@@ -86,7 +86,7 @@
      * @param slot the slot of the local variable
      * @param value the new value of the local variable
      */
-    void setInt(FrameSlot slot, int value);
+    void setInt(FrameSlot slot, int value) throws FrameSlotTypeException;
 
     /**
      * Read access to a local variable of type long.
@@ -94,7 +94,7 @@
      * @param slot the slot of the local variable
      * @return the current value of the local variable
      */
-    long getLong(FrameSlot slot);
+    long getLong(FrameSlot slot) throws FrameSlotTypeException;
 
     /**
      * Write access to a local variable of type long.
@@ -102,7 +102,7 @@
      * @param slot the slot of the local variable
      * @param value the new value of the local variable
      */
-    void setLong(FrameSlot slot, long value);
+    void setLong(FrameSlot slot, long value) throws FrameSlotTypeException;
 
     /**
      * Read access to a local variable of type float.
@@ -110,7 +110,7 @@
      * @param slot the slot of the local variable
      * @return the current value of the local variable
      */
-    float getFloat(FrameSlot slot);
+    float getFloat(FrameSlot slot) throws FrameSlotTypeException;
 
     /**
      * Write access to a local variable of type float.
@@ -118,7 +118,7 @@
      * @param slot the slot of the local variable
      * @param value the new value of the local variable
      */
-    void setFloat(FrameSlot slot, float value);
+    void setFloat(FrameSlot slot, float value) throws FrameSlotTypeException;
 
     /**
      * Read access to a local variable of type double.
@@ -126,7 +126,7 @@
      * @param slot the slot of the local variable
      * @return the current value of the local variable
      */
-    double getDouble(FrameSlot slot);
+    double getDouble(FrameSlot slot) throws FrameSlotTypeException;
 
     /**
      * Write access to a local variable of type double.
@@ -134,9 +134,15 @@
      * @param slot the slot of the local variable
      * @param value the new value of the local variable
      */
-    void setDouble(FrameSlot slot, double value);
+    void setDouble(FrameSlot slot, double value) throws FrameSlotTypeException;
 
-    void updateToLatestVersion();
+    /**
+     * Read access to a local variable of any type.
+     * 
+     * @param slot the slot of the local variable
+     * @return the current value of the local variable or defaultValue if unset
+     */
+    Object getValue(FrameSlot slot);
 
     /**
      * Converts this virtual frame into a packed frame that has no longer direct access to the local
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Thu Apr 25 16:53:29 2013 +0200
@@ -24,30 +24,33 @@
 
 import java.util.*;
 
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.impl.*;
+
 /**
  * Descriptor of the slots of frame objects. Multiple frame instances are associated with one such
  * descriptor.
  */
-public final class FrameDescriptor {
+public final class FrameDescriptor implements Cloneable {
 
-    protected final TypeConversion typeConversion;
+    private final FrameTypeConversion typeConversion;
     private final ArrayList<FrameSlotImpl> slots;
-    private FrameVersionImpl lastVersion;
     private final HashMap<Object, FrameSlotImpl> identifierToSlotMap;
+    private Assumption version;
 
     public FrameDescriptor() {
-        this(DefaultTypeConversion.getInstance());
+        this(DefaultFrameTypeConversion.getInstance());
     }
 
-    public FrameDescriptor(TypeConversion typeConversion) {
+    public FrameDescriptor(FrameTypeConversion typeConversion) {
         this.typeConversion = typeConversion;
         slots = new ArrayList<>();
         identifierToSlotMap = new HashMap<>();
-        lastVersion = new FrameVersionImpl();
+        version = createVersion();
     }
 
     public FrameSlot addFrameSlot(Object identifier) {
-        return addFrameSlot(identifier, typeConversion.getTopType());
+        return addFrameSlot(identifier, null);
     }
 
     public FrameSlot addFrameSlot(Object identifier, Class<?> type) {
@@ -55,6 +58,7 @@
         FrameSlotImpl slot = new FrameSlotImpl(this, identifier, slots.size(), type);
         slots.add(slot);
         identifierToSlotMap.put(identifier, slot);
+        updateVersion();
         return slot;
     }
 
@@ -70,8 +74,12 @@
         return addFrameSlot(identifier);
     }
 
-    public FrameVersion getCurrentVersion() {
-        return lastVersion;
+    public FrameSlot findOrAddFrameSlot(Object identifier, Class<?> type) {
+        FrameSlot result = findFrameSlot(identifier);
+        if (result != null) {
+            return result;
+        }
+        return addFrameSlot(identifier, type);
     }
 
     public int getSize() {
@@ -82,121 +90,42 @@
         return Collections.unmodifiableList(slots);
     }
 
-    protected void appendVersion(FrameVersionImpl newVersion) {
-        lastVersion.next = newVersion;
-        lastVersion = newVersion;
-    }
-}
-
-class FrameVersionImpl implements FrameVersion {
-
-    protected FrameVersionImpl next;
-
-    @Override
-    public final FrameVersion getNext() {
-        return next;
-    }
-}
-
-class TypeChangeFrameVersionImpl extends FrameVersionImpl implements FrameVersion.TypeChange {
-
-    private final FrameSlotImpl slot;
-    private final Class<?> oldType;
-    private final Class<?> newType;
-
-    protected TypeChangeFrameVersionImpl(FrameSlotImpl slot, Class<?> oldType, Class<?> newType) {
-        this.slot = slot;
-        this.oldType = oldType;
-        this.newType = newType;
-    }
-
-    @Override
-    public final void applyTransformation(Frame frame) {
-        Object value = slot.getValue(oldType, frame);
-        slot.setValue(newType, frame, value);
-    }
-}
-
-class FrameSlotImpl implements FrameSlot {
-
-    private final FrameDescriptor descriptor;
-    private final Object identifier;
-    private final int index;
-    private Class<?> type;
-    private ArrayList<FrameSlotTypeListener> listeners;
-
-    protected FrameSlotImpl(FrameDescriptor descriptor, Object identifier, int index, Class<?> type) {
-        this.descriptor = descriptor;
-        this.identifier = identifier;
-        this.index = index;
-        this.type = type;
-        assert type != null;
-    }
-
-    public Object getIdentifier() {
-        return identifier;
-    }
-
-    public int getIndex() {
-        return index;
+    /**
+     * (db) to retrieve the list of all the identifiers associated with this frame descriptor.
+     * 
+     * @return the list of all the identifiers in this frame descriptor
+     */
+    public Set<Object> getIdentifiers() {
+        return Collections.unmodifiableSet(identifierToSlotMap.keySet());
     }
 
-    public Class<?> getType() {
-        return type;
-    }
-
-    protected Object getValue(Class<?> accessType, Frame frame) {
-        if (accessType == Integer.class) {
-            return frame.getInt(this);
-        } else if (accessType == Long.class) {
-            return frame.getLong(this);
-        } else if (accessType == Float.class) {
-            return frame.getFloat(this);
-        } else if (accessType == Double.class) {
-            return frame.getDouble(this);
-        } else {
-            return frame.getObject(this);
+    /**
+     * (db): this method is used for creating a clone of the {@link FrameDescriptor} object ready
+     * for parallel execution.
+     */
+    public FrameDescriptor copy() {
+        FrameDescriptor clonedFrameDescriptor = new FrameDescriptor(this.typeConversion);
+        for (int i = 0; i < this.getSlots().size(); i++) {
+            Object identifier = this.getSlots().get(i).getIdentifier();
+            clonedFrameDescriptor.addFrameSlot(identifier);
         }
+        return clonedFrameDescriptor;
     }
 
-    protected void setValue(Class<?> accessType, Frame frame, Object value) {
-        Object newValue = descriptor.typeConversion.convertTo(accessType, value);
-        if (accessType == Integer.class) {
-            frame.setInt(this, (Integer) newValue);
-        } else if (accessType == Long.class) {
-            frame.setLong(this, (Long) newValue);
-        } else if (accessType == Float.class) {
-            frame.setFloat(this, (Float) newValue);
-        } else if (accessType == Double.class) {
-            frame.setDouble(this, (Double) newValue);
-        } else {
-            frame.setObject(this, newValue);
-        }
+    void updateVersion() {
+        version.invalidate();
+        version = createVersion();
+    }
+
+    public Assumption getVersion() {
+        return version;
     }
 
-    public void setType(final Class<?> type) {
-        final Class<?> oldType = this.type;
-        this.type = type;
-        ArrayList<FrameSlotTypeListener> oldListeners = this.listeners;
-        this.listeners = null;
-        if (oldListeners != null) {
-            for (FrameSlotTypeListener listener : oldListeners) {
-                listener.typeChanged(this, oldType);
-            }
-        }
-        descriptor.appendVersion(new TypeChangeFrameVersionImpl(this, oldType, type));
+    private static Assumption createVersion() {
+        return Truffle.getRuntime().createAssumption("frame version");
     }
 
-    @Override
-    public String toString() {
-        return "[" + index + "," + identifier + "]";
-    }
-
-    @Override
-    public void registerOneShotTypeListener(FrameSlotTypeListener listener) {
-        if (listeners == null) {
-            listeners = new ArrayList<>();
-        }
-        listeners.add(listener);
+    public FrameTypeConversion getTypeConversion() {
+        return typeConversion;
     }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java	Thu Apr 25 16:53:29 2013 +0200
@@ -25,7 +25,7 @@
 /**
  * A slot in a frame that can store a value of a given type.
  */
-public interface FrameSlot {
+public interface FrameSlot extends Cloneable {
 
     Object getIdentifier();
 
@@ -35,5 +35,5 @@
 
     void setType(Class<?> type);
 
-    void registerOneShotTypeListener(FrameSlotTypeListener listener);
+    FrameDescriptor getFrameDescriptor();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotImpl.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ *
+ * 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.frame;
+
+public final class FrameSlotImpl implements FrameSlot {
+
+    private final FrameDescriptor descriptor;
+    private final Object identifier;
+    private final int index;
+    private Class<?> type;
+
+    protected FrameSlotImpl(FrameDescriptor descriptor, Object identifier, int index, Class<?> type) {
+        this.descriptor = descriptor;
+        this.identifier = identifier;
+        this.index = index;
+        this.type = type;
+    }
+
+    public Object getIdentifier() {
+        return identifier;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public Class<?> getType() {
+        return type;
+    }
+
+    public void setType(final Class<?> type) {
+        assert this.type != type;
+        this.type = type;
+        this.descriptor.updateVersion();
+    }
+
+    @Override
+    public String toString() {
+        return "[" + index + "," + identifier + "," + type + "]";
+    }
+
+    @Override
+    public FrameDescriptor getFrameDescriptor() {
+        return this.descriptor;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotTypeException.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ *
+ * 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.frame;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Exception thrown if the frame slot type does not match the access type.
+ */
+public final class FrameSlotTypeException extends SlowPathException {
+
+    private static final long serialVersionUID = 6972120475215757452L;
+
+    public FrameSlotTypeException() {
+    }
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotTypeListener.java	Mon Apr 22 18:30:33 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * 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.
- *
- * 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.frame;
-
-/**
- * Listener for the event of a type change of a frame slot.
- */
-public interface FrameSlotTypeListener {
-
-    void typeChanged(FrameSlot slot, Class<?> oldType);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameTypeConversion.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013, 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.
+ *
+ * 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.frame;
+
+/**
+ * Interface for defining type conversions for frame slot values.
+ */
+public interface FrameTypeConversion {
+
+    Object getDefaultValue();
+
+    void updateFrameSlot(Frame frame, FrameSlot slot, Object value);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameUtil.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2013, 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.
+ *
+ * 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.frame;
+
+public final class FrameUtil {
+
+    /**
+     * Write access to a local variable of type {@link Object}.
+     * 
+     * Sets the frame slot type to {@link Object} if it isn't already.
+     * 
+     * @param slot the slot of the local variable
+     * @param value the new value of the local variable
+     */
+    public static void setObjectSafe(Frame frame, FrameSlot slot, Object value) {
+        if (slot.getType() != Object.class) {
+            slot.setType(Object.class);
+        }
+        try {
+            frame.setObject(slot, value);
+        } catch (FrameSlotTypeException e) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Write access to a local variable of type {@code boolean}.
+     * 
+     * Sets the frame slot type to {@code boolean} if it isn't already.
+     * 
+     * @param slot the slot of the local variable
+     * @param value the new value of the local variable
+     */
+    public static void setBooleanSafe(Frame frame, FrameSlot slot, boolean value) {
+        if (slot.getType() != boolean.class) {
+            slot.setType(boolean.class);
+        }
+        try {
+            frame.setBoolean(slot, value);
+        } catch (FrameSlotTypeException e) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Write access to a local variable of type {@code int}.
+     * 
+     * Sets the frame slot type to {@code int} if it isn't already.
+     * 
+     * @param slot the slot of the local variable
+     * @param value the new value of the local variable
+     */
+    public static void setIntSafe(Frame frame, FrameSlot slot, int value) {
+        if (slot.getType() != int.class) {
+            slot.setType(int.class);
+        }
+        try {
+            frame.setInt(slot, value);
+        } catch (FrameSlotTypeException e) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Write access to a local variable of type {@code long}.
+     * 
+     * Sets the frame slot type to {@code long} if it isn't already.
+     * 
+     * @param slot the slot of the local variable
+     * @param value the new value of the local variable
+     */
+    public static void setLongSafe(Frame frame, FrameSlot slot, long value) {
+        if (slot.getType() != long.class) {
+            slot.setType(long.class);
+        }
+        try {
+            frame.setLong(slot, value);
+        } catch (FrameSlotTypeException e) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Write access to a local variable of type {@code float}.
+     * 
+     * Sets the frame slot type to {@code float} if it isn't already.
+     * 
+     * @param slot the slot of the local variable
+     * @param value the new value of the local variable
+     */
+    public static void setFloatSafe(Frame frame, FrameSlot slot, float value) {
+        if (slot.getType() != float.class) {
+            slot.setType(float.class);
+        }
+        try {
+            frame.setFloat(slot, value);
+        } catch (FrameSlotTypeException e) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Write access to a local variable of type {@code double}.
+     * 
+     * Sets the frame slot type to {@code double} if it isn't already.
+     * 
+     * @param slot the slot of the local variable
+     * @param value the new value of the local variable
+     */
+    public static void setDoubleSafe(Frame frame, FrameSlot slot, double value) {
+        if (slot.getType() != double.class) {
+            slot.setType(double.class);
+        }
+        try {
+            frame.setDouble(slot, value);
+        } catch (FrameSlotTypeException e) {
+            throw new IllegalStateException();
+        }
+    }
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameVersion.java	Mon Apr 22 18:30:33 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * 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.
- *
- * 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.frame;
-
-/**
- * Represents a specific version of a frame.
- */
-public interface FrameVersion {
-
-    FrameVersion getNext();
-
-    public interface Resize {
-
-        int getNewSize();
-    }
-
-    public interface TypeChange {
-
-        void applyTransformation(Frame frame);
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/MaterializedFrame.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/MaterializedFrame.java	Thu Apr 25 16:53:29 2013 +0200
@@ -30,4 +30,5 @@
  * also does not provide access to the caller frame.
  */
 public interface MaterializedFrame extends Frame {
+
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/NativeFrame.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/NativeFrame.java	Thu Apr 25 16:53:29 2013 +0200
@@ -104,6 +104,11 @@
     }
 
     @Override
+    public Object getValue(FrameSlot slot) {
+        throw new UnsupportedOperationException("native frame");
+    }
+
+    @Override
     public PackedFrame pack() {
         return this;
     }
@@ -124,10 +129,6 @@
     }
 
     @Override
-    public void updateToLatestVersion() {
-    }
-
-    @Override
     public FrameDescriptor getFrameDescriptor() {
         throw new UnsupportedOperationException("native frame");
     }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/TypeConversion.java	Mon Apr 22 18:30:33 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * 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.
- *
- * 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.frame;
-
-/**
- * Interface for defining type conversions for frame slot values.
- */
-public interface TypeConversion {
-
-    Class<?> getTopType();
-
-    Object convertTo(Class<?> targetType, Object value);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/AbstractAssumption.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ *
+ * 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.impl;
+
+import com.oracle.truffle.api.*;
+
+public abstract class AbstractAssumption implements Assumption {
+
+    protected final String name;
+    protected boolean isValid;
+
+    protected AbstractAssumption(String name) {
+        this.name = name;
+        this.isValid = true;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String toString() {
+        return "Assumption: " + name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultAssumption.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ *
+ * 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.impl;
+
+import com.oracle.truffle.api.nodes.*;
+
+public final class DefaultAssumption extends AbstractAssumption {
+
+    public DefaultAssumption(String name) {
+        super(name);
+    }
+
+    @Override
+    public void check() throws InvalidAssumptionException {
+        if (!isValid) {
+            throw new InvalidAssumptionException();
+        }
+    }
+
+    @Override
+    public void invalidate() {
+        isValid = false;
+    }
+
+    @Override
+    public boolean isValid() {
+        return isValid;
+    }
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java	Thu Apr 25 16:53:29 2013 +0200
@@ -31,14 +31,15 @@
     protected final RootNode rootNode;
     protected final FrameDescriptor frameDescriptor;
 
-    protected DefaultCallTarget(RootNode function, FrameDescriptor frameDescriptor) {
+    public DefaultCallTarget(RootNode function, FrameDescriptor frameDescriptor) {
         this.rootNode = function;
         this.frameDescriptor = frameDescriptor;
+        this.rootNode.setCallTarget(this);
     }
 
     @Override
     public String toString() {
-        return "DefaultCallTarget " + rootNode;
+        return "CallTarget " + rootNode;
     }
 
     @Override
@@ -46,4 +47,8 @@
         VirtualFrame frame = new DefaultVirtualFrame(frameDescriptor, caller, args);
         return rootNode.execute(frame);
     }
+
+    public RootNode getRootNode() {
+        return rootNode;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultFrameTypeConversion.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013, 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.
+ *
+ * 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.impl;
+
+import com.oracle.truffle.api.frame.*;
+
+/**
+ * Interface for defining type conversions for frame slot values.
+ */
+public class DefaultFrameTypeConversion implements FrameTypeConversion {
+
+    private static final DefaultFrameTypeConversion INSTANCE = new DefaultFrameTypeConversion();
+
+    @Override
+    public Object getDefaultValue() {
+        return null;
+    }
+
+    @Override
+    public void updateFrameSlot(Frame frame, FrameSlot slot, Object value) {
+        FrameUtil.setObjectSafe(frame, slot, value);
+    }
+
+    public static DefaultFrameTypeConversion getInstance() {
+        return INSTANCE;
+    }
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java	Thu Apr 25 16:53:29 2013 +0200
@@ -39,68 +39,68 @@
     }
 
     @Override
-    public Object getObject(FrameSlot slot) {
+    public Object getObject(FrameSlot slot) throws FrameSlotTypeException {
         return wrapped.getObject(slot);
     }
 
     @Override
-    public void setObject(FrameSlot slot, Object value) {
+    public void setObject(FrameSlot slot, Object value) throws FrameSlotTypeException {
         wrapped.setObject(slot, value);
     }
 
     @Override
-    public boolean getBoolean(FrameSlot slot) {
+    public boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException {
         return wrapped.getBoolean(slot);
     }
 
     @Override
-    public void setBoolean(FrameSlot slot, boolean value) {
+    public void setBoolean(FrameSlot slot, boolean value) throws FrameSlotTypeException {
         wrapped.setBoolean(slot, value);
     }
 
     @Override
-    public int getInt(FrameSlot slot) {
+    public int getInt(FrameSlot slot) throws FrameSlotTypeException {
         return wrapped.getInt(slot);
     }
 
     @Override
-    public void setInt(FrameSlot slot, int value) {
+    public void setInt(FrameSlot slot, int value) throws FrameSlotTypeException {
         wrapped.setInt(slot, value);
     }
 
     @Override
-    public long getLong(FrameSlot slot) {
+    public long getLong(FrameSlot slot) throws FrameSlotTypeException {
         return wrapped.getLong(slot);
     }
 
     @Override
-    public void setLong(FrameSlot slot, long value) {
+    public void setLong(FrameSlot slot, long value) throws FrameSlotTypeException {
         wrapped.setLong(slot, value);
     }
 
     @Override
-    public float getFloat(FrameSlot slot) {
+    public float getFloat(FrameSlot slot) throws FrameSlotTypeException {
         return wrapped.getFloat(slot);
     }
 
     @Override
-    public void setFloat(FrameSlot slot, float value) {
+    public void setFloat(FrameSlot slot, float value) throws FrameSlotTypeException {
         wrapped.setFloat(slot, value);
     }
 
     @Override
-    public double getDouble(FrameSlot slot) {
+    public double getDouble(FrameSlot slot) throws FrameSlotTypeException {
         return wrapped.getDouble(slot);
     }
 
     @Override
-    public void setDouble(FrameSlot slot, double value) {
+    public void setDouble(FrameSlot slot, double value) throws FrameSlotTypeException {
         wrapped.setDouble(slot, value);
     }
 
     @Override
-    public void updateToLatestVersion() {
-        wrapped.updateToLatestVersion();
+    public Object getValue(FrameSlot slot) {
+        return wrapped.getValue(slot);
     }
 
     @Override
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Thu Apr 25 16:53:29 2013 +0200
@@ -38,13 +38,13 @@
     }
 
     @Override
-    public CallTarget createCallTarget(RootNode rootNode, FrameDescriptor frameDescriptor) {
-        return new DefaultCallTarget(rootNode, frameDescriptor);
+    public CallTarget createCallTarget(RootNode rootNode) {
+        return createCallTarget(rootNode, new FrameDescriptor());
     }
 
     @Override
-    public CallTarget createCallTarget(RootNode rootNode) {
-        return createCallTarget(rootNode, new FrameDescriptor());
+    public CallTarget createCallTarget(RootNode rootNode, FrameDescriptor frameDescriptor) {
+        return new DefaultCallTarget(rootNode, frameDescriptor);
     }
 
     @Override
@@ -56,4 +56,14 @@
     public MaterializedFrame createMaterializedFrame(Arguments arguments, FrameDescriptor frameDescriptor) {
         return new DefaultMaterializedFrame(new DefaultVirtualFrame(frameDescriptor, null, arguments));
     }
+
+    @Override
+    public Assumption createAssumption() {
+        return createAssumption(null);
+    }
+
+    @Override
+    public Assumption createAssumption(String name) {
+        return new DefaultAssumption(name);
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java	Thu Apr 25 16:53:29 2013 +0200
@@ -29,29 +29,18 @@
 
 public final class DefaultVirtualFrame implements VirtualFrame {
 
-    private static final Object UNDEFINED_OBJECT = null;
-    private static final Boolean UNDEFINED_BOOLEAN = false;
-    private static final Integer UNDEFINED_INTEGER = 0;
-    private static final Float UNDEFINED_FLOAT = 0.0f;
-    private static final Long UNDEFINED_LONG = 0L;
-    private static final Double UNDEFINED_DOUBLE = 0.0d;
-
     private final FrameDescriptor descriptor;
     private final PackedFrame caller;
     private final Arguments arguments;
-    private FrameVersion currentVersion;
-    protected Object[] locals;
-    protected Class[] tags;
+    private Object[] locals;
+    private Class[] tags;
 
     public DefaultVirtualFrame(FrameDescriptor descriptor, PackedFrame caller, Arguments arguments) {
         this.descriptor = descriptor;
         this.caller = caller;
         this.arguments = arguments;
-        this.currentVersion = descriptor.getCurrentVersion();
         this.locals = new Object[descriptor.getSize()];
-        // The tags are only needed for assertion checking, so initialize the field only when
-        // assertions are enabled
-        assert (this.tags = new Class[descriptor.getSize()]) != null;
+        this.tags = new Class[descriptor.getSize()];
     }
 
     @Override
@@ -75,126 +64,140 @@
     }
 
     @Override
-    public Object getObject(FrameSlot slot) {
-        return get(slot, Object.class, UNDEFINED_OBJECT);
-    }
-
-    @Override
-    public void setObject(FrameSlot slot, Object value) {
-        set(slot, Object.class, value);
+    public Object getObject(FrameSlot slot) throws FrameSlotTypeException {
+        verifyGet(slot, Object.class);
+        return locals[slot.getIndex()];
     }
 
     @Override
-    public boolean getBoolean(FrameSlot slot) {
-        return (Boolean) get(slot, Boolean.class, UNDEFINED_BOOLEAN);
-    }
-
-    @Override
-    public void setBoolean(FrameSlot slot, boolean value) {
-        set(slot, Boolean.class, value);
-    }
-
-    @Override
-    public int getInt(FrameSlot slot) {
-        return (Integer) get(slot, Integer.class, UNDEFINED_INTEGER);
+    public void setObject(FrameSlot slot, Object value) throws FrameSlotTypeException {
+        verifySet(slot, Object.class);
+        locals[slot.getIndex()] = value;
     }
 
     @Override
-    public void setInt(FrameSlot slot, int value) {
-        set(slot, Integer.class, value);
-    }
-
-    @Override
-    public long getLong(FrameSlot slot) {
-        return (Long) get(slot, Long.class, UNDEFINED_LONG);
+    public boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException {
+        verifyGet(slot, boolean.class);
+        return (boolean) locals[slot.getIndex()];
     }
 
     @Override
-    public void setLong(FrameSlot slot, long value) {
-        set(slot, Long.class, value);
+    public void setBoolean(FrameSlot slot, boolean value) throws FrameSlotTypeException {
+        verifySet(slot, boolean.class);
+        locals[slot.getIndex()] = value;
     }
 
     @Override
-    public float getFloat(FrameSlot slot) {
-        return (Float) get(slot, Float.class, UNDEFINED_FLOAT);
-    }
-
-    @Override
-    public void setFloat(FrameSlot slot, float value) {
-        set(slot, Float.class, value);
-    }
-
-    @Override
-    public double getDouble(FrameSlot slot) {
-        return (Double) get(slot, Double.class, UNDEFINED_DOUBLE);
+    public int getInt(FrameSlot slot) throws FrameSlotTypeException {
+        verifyGet(slot, int.class);
+        return (int) locals[slot.getIndex()];
     }
 
     @Override
-    public void setDouble(FrameSlot slot, double value) {
-        set(slot, Double.class, value);
-    }
-
-    private Object get(FrameSlot slot, Class<?> accessType, Object defaultValue) {
-        Object value = locals[slot.getIndex()];
-        assert verifyGet(slot, accessType, value);
-        if (value == null) {
-            return defaultValue;
-        } else {
-            return value;
-        }
+    public void setInt(FrameSlot slot, int value) throws FrameSlotTypeException {
+        verifySet(slot, int.class);
+        locals[slot.getIndex()] = value;
     }
 
-    private boolean verifyGet(FrameSlot slot, Class<?> accessType, Object value) {
-        assert descriptor.getSlots().get(slot.getIndex()) == slot;
-        Class<?> tag = tags[slot.getIndex()];
-        if (value == null) {
-            assert tag == null || tag == Object.class;
-        } else {
-            assert tag == accessType : "Local variable " + slot + " was written with set" + tag.getSimpleName() + ", but is read with get" + accessType.getSimpleName();
-        }
-        return true;
+    @Override
+    public long getLong(FrameSlot slot) throws FrameSlotTypeException {
+        verifyGet(slot, long.class);
+        return (long) locals[slot.getIndex()];
     }
 
-    private void set(FrameSlot slot, Class<?> accessType, Object value) {
-        assert verifySet(slot, accessType, value);
+    @Override
+    public void setLong(FrameSlot slot, long value) throws FrameSlotTypeException {
+        verifySet(slot, long.class);
         locals[slot.getIndex()] = value;
     }
 
-    private boolean verifySet(FrameSlot slot, Class<?> accessType, Object value) {
-        assert descriptor.getSlots().get(slot.getIndex()) == slot;
-        tags[slot.getIndex()] = accessType;
-        assert accessType.isAssignableFrom(slot.getType()) : "Local variable " + slot + ": " + accessType + " is not assignable from " + slot.getType();
-        if (value == null) {
-            assert accessType == Object.class;
-        } else {
-            assert slot.getType().isAssignableFrom(value.getClass()) : "Local variable " + slot + ": " + slot.getType() + " is not assignable from " + value.getClass();
-        }
-        return true;
+    @Override
+    public float getFloat(FrameSlot slot) throws FrameSlotTypeException {
+        verifyGet(slot, float.class);
+        return (float) locals[slot.getIndex()];
     }
 
     @Override
-    public void updateToLatestVersion() {
-        if (currentVersion.getNext() != null) {
-            doUpdateToLatestVersion();
-        }
+    public void setFloat(FrameSlot slot, float value) throws FrameSlotTypeException {
+        verifySet(slot, float.class);
+        locals[slot.getIndex()] = value;
     }
 
-    private void doUpdateToLatestVersion() {
-        FrameVersion version = currentVersion;
-        while (version.getNext() != null) {
-            version = version.getNext();
-            if (version instanceof FrameVersion.TypeChange) {
-                ((FrameVersion.TypeChange) version).applyTransformation(this);
-            } else if (version instanceof FrameVersion.Resize) {
-                int newSize = ((FrameVersion.Resize) version).getNewSize();
-                locals = Arrays.copyOf(locals, newSize);
-            }
-        }
-        currentVersion = version;
+    @Override
+    public double getDouble(FrameSlot slot) throws FrameSlotTypeException {
+        verifyGet(slot, double.class);
+        return (double) locals[slot.getIndex()];
+    }
+
+    @Override
+    public void setDouble(FrameSlot slot, double value) throws FrameSlotTypeException {
+        verifySet(slot, double.class);
+        locals[slot.getIndex()] = value;
     }
 
     @Override
     public FrameDescriptor getFrameDescriptor() {
         return this.descriptor;
     }
+
+    @Override
+    public Object getValue(FrameSlot slot) {
+        int index = slot.getIndex();
+        if (index >= tags.length) {
+            assert index >= 0 && index < descriptor.getSize();
+            return descriptor.getTypeConversion().getDefaultValue();
+        }
+        Class tag = tags[index];
+        if (tag == null) {
+            return descriptor.getTypeConversion().getDefaultValue();
+        } else {
+            return locals[index];
+        }
+    }
+
+    private void verifySet(FrameSlot slot, Class accessType) throws FrameSlotTypeException {
+        Class<?> slotType = slot.getType();
+        if (slotType != accessType) {
+            if (slotType == null) {
+                slot.setType(accessType);
+            } else {
+                throw new FrameSlotTypeException();
+            }
+        }
+        int slotIndex = slot.getIndex();
+        if (slotIndex >= tags.length) {
+            resize();
+        }
+        tags[slotIndex] = accessType;
+    }
+
+    private void verifyGet(FrameSlot slot, Class accessType) throws FrameSlotTypeException {
+        Class<?> slotType = slot.getType();
+        if (slotType != accessType) {
+            if (slotType == null && accessType == Object.class) {
+                slot.setType(Object.class);
+                this.setObject(slot, descriptor.getTypeConversion().getDefaultValue());
+            } else {
+                throw new FrameSlotTypeException();
+            }
+        }
+        int slotIndex = slot.getIndex();
+        if (slotIndex >= tags.length) {
+            resize();
+        }
+        if (tags[slotIndex] != accessType) {
+            descriptor.getTypeConversion().updateFrameSlot(this, slot, getValue(slot));
+            if (tags[slotIndex] != accessType) {
+                throw new FrameSlotTypeException();
+            }
+        }
+    }
+
+    private void resize() {
+        int newSize = descriptor.getSize();
+        if (newSize > tags.length) {
+            locals = Arrays.copyOf(locals, newSize);
+            tags = Arrays.copyOf(tags, newSize);
+        }
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/intrinsics/ExactMath.java	Mon Apr 22 18:30:33 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * 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.
- *
- * 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.intrinsics;
-
-/**
- * This class contains methods that will be part of java.lang.Math starting with JDK 8. Until JDK 8
- * is release, we duplicate them here because they are generally useful for dynamic language
- * implementations.
- */
-public class ExactMath {
-
-    public static int addExact(int x, int y) {
-        int r = x + y;
-        // HD 2-12 Overflow iff both arguments have the opposite sign of the result
-        if (((x ^ r) & (y ^ r)) < 0) {
-            throw new ArithmeticException("integer overflow");
-        }
-        return r;
-    }
-
-    public static long addExact(long x, long y) {
-        long r = x + y;
-        // HD 2-12 Overflow iff both arguments have the opposite sign of the result
-        if (((x ^ r) & (y ^ r)) < 0) {
-            throw new ArithmeticException("long overflow");
-        }
-        return r;
-    }
-
-    public static int subtractExact(int x, int y) {
-        int r = x - y;
-        // HD 2-12 Overflow iff the arguments have different signs and
-        // the sign of the result is different than the sign of x
-        if (((x ^ y) & (x ^ r)) < 0) {
-            throw new ArithmeticException("integer overflow");
-        }
-        return r;
-    }
-
-    public static long subtractExact(long x, long y) {
-        long r = x - y;
-        // HD 2-12 Overflow iff the arguments have different signs and
-        // the sign of the result is different than the sign of x
-        if (((x ^ y) & (x ^ r)) < 0) {
-            throw new ArithmeticException("long overflow");
-        }
-        return r;
-    }
-
-    public static int multiplyExact(int x, int y) {
-        long r = (long) x * (long) y;
-        if ((int) r != r) {
-            throw new ArithmeticException("long overflow");
-        }
-        return (int) r;
-    }
-
-    public static long multiplyExact(long x, long y) {
-        long r = x * y;
-        long ax = Math.abs(x);
-        long ay = Math.abs(y);
-        if (((ax | ay) >>> 31 != 0)) {
-            // Some bits greater than 2^31 that might cause overflow
-            // Check the result using the divide operator
-            // and check for the special case of Long.MIN_VALUE * -1
-            if (((y != 0) && (r / y != x)) || (x == Long.MIN_VALUE && y == -1)) {
-                throw new ArithmeticException("long overflow");
-            }
-        }
-        return r;
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/intrinsics/TruffleIntrinsics.java	Mon Apr 22 18:30:33 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * 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.
- *
- * 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.intrinsics;
-
-/**
- * Predefined Truffle intrinsics that allow direct influence of the generated machine code.
- */
-public final class TruffleIntrinsics {
-
-    /**
-     * Specifies that the compiler should put a deoptimization point at this position that will
-     * continue execution in the interpreter. Should be used to cut off cold paths that should not
-     * be part of the compiled machine code.
-     */
-    public static void deoptimize() {
-    }
-
-    /**
-     * Checks whether the Thread has been interrupted in the interpreter in order to avoid endless
-     * loops. The compiled code may choose a more efficient implementation.
-     */
-    public static void checkThreadInterrupted() {
-        if (Thread.currentThread().isInterrupted()) {
-            throw new RuntimeException("Timeout");
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/InvalidAssumptionException.java	Thu Apr 25 16:53:29 2013 +0200
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ *
+ * 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;
+
+/**
+ * An exception that should be thrown if an assumption is checked and the check fails. The Truffle
+ * optimizer has special knowledge of this exception class and will never compile a catch block that
+ * catches this exception type.
+ */
+public final class InvalidAssumptionException extends SlowPathException {
+
+    private static final long serialVersionUID = -6801338218909717979L;
+
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Thu Apr 25 16:53:29 2013 +0200
@@ -25,6 +25,8 @@
 import java.lang.annotation.*;
 import java.util.*;
 
+import com.oracle.truffle.api.*;
+
 /**
  * Abstract base class for all Truffle nodes.
  */
@@ -37,6 +39,8 @@
 
     private Node parent;
 
+    private SourceSection sourceSection;
+
     /**
      * Marks array fields that are children of this node.
      */
@@ -54,6 +58,34 @@
     }
 
     /**
+     * Assigns a link to a guest language source section to this node.
+     * 
+     * @param section the object representing a section in guest language source code
+     */
+    public final void assignSourceSection(SourceSection section) {
+        if (sourceSection != null) {
+            throw new IllegalStateException("Source section is already assigned.");
+        }
+        this.sourceSection = section;
+    }
+
+    /**
+     * Clears any previously assigned guest language source code from this node.
+     */
+    public final void clearSourceSection() {
+        this.sourceSection = null;
+    }
+
+    /**
+     * Retrieves the guest language source code section that is currently assigned to this node.
+     * 
+     * @return the assigned source code section
+     */
+    public final SourceSection getSourceSection() {
+        return sourceSection;
+    }
+
+    /**
      * Method that updates the link to the parent in the array of specified new child nodes to this
      * node.
      * 
@@ -103,38 +135,37 @@
     }
 
     /**
-     * Replaces one child of this node with another node.
+     * Replaces this node with another node. If there is a source section (see
+     * {@link #getSourceSection()}) associated with this node, it is transferred to the new node.
      * 
-     * @param oldChild the old child
-     * @param newChild the new child that should replace the old child
-     * @return the new child
+     * @param newNode the new node that is the replacement
+     * @param reason a description of the reason for the replacement
+     * @return the new node
      */
-    public final <T extends Node> T replaceChild(T oldChild, T newChild) {
+    @SuppressWarnings({"unchecked"})
+    public final <T extends Node> T replace(T newNode, String reason) {
+        assert this.getParent() != null;
+        if (sourceSection != null) {
+            // Pass on the source section to the new node.
+            newNode.assignSourceSection(sourceSection);
+        }
+        return (T) this.getParent().replaceChild(this, newNode);
+    }
+
+    private <T extends Node> T replaceChild(T oldChild, T newChild) {
         NodeUtil.replaceChild(this, oldChild, newChild);
         adoptChild(newChild);
         return newChild;
     }
 
     /**
-     * Replaces this node with another node.
-     * 
-     * @param newNode the new node that is the replacement
-     * @param reason a description of the reason for the replacement
-     * @return the new node
-     */
-    @SuppressWarnings({"unchecked"})
-    public <T extends Node> T replace(T newNode, String reason) {
-        assert this.getParent() != null;
-        return (T) this.getParent().replaceChild(this, newNode);
-    }
-
-    /**
-     * Replaces this node with another node.
+     * Replaces this node with another node. If there is a source section (see
+     * {@link #getSourceSection()}) associated with this node, it is transferred to the new node.
      * 
      * @param newNode the new node that is the replacement
      * @return the new node
      */
-    public <T extends Node> T replace(T newNode) {
+    public final <T extends Node> T replace(T newNode) {
         return replace(newNode, "");
     }
 
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Thu Apr 25 16:53:29 2013 +0200
@@ -99,6 +99,18 @@
 
             this.parentOffset = parentOffsetTemp;
         }
+
+        public long getParentOffset() {
+            return parentOffset;
+        }
+
+        public long[] getNodeFieldOffsets() {
+            return nodeFieldOffsets;
+        }
+
+        public long[] getNodeArrayFieldOffsets() {
+            return nodeArrayFieldOffsets;
+        }
     }
 
     public static class NodeIterator implements Iterator<Node> {
@@ -180,7 +192,7 @@
         return array;
     }
 
-    private static final Unsafe unsafe = getUnsafe();
+    protected static final Unsafe unsafe = getUnsafe();
 
     private static Unsafe getUnsafe() {
         try {
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -39,4 +39,14 @@
      * @return the value of the execution
      */
     public abstract Object execute(VirtualFrame frame);
+
+    private CallTarget callTarget;
+
+    public CallTarget getCallTarget() {
+        return callTarget;
+    }
+
+    public void setCallTarget(CallTarget callTarget) {
+        this.callTarget = callTarget;
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/SlowPathException.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/SlowPathException.java	Thu Apr 25 16:53:29 2013 +0200
@@ -33,7 +33,36 @@
     /**
      * Creates an exception thrown to enter a slow path.
      */
+    public SlowPathException() {
+    }
+
+    /**
+     * Creates an exception thrown to enter a slow path.
+     */
     public SlowPathException(String message, Throwable cause) {
         super(message, cause);
     }
+
+    /**
+     * Creates an exception thrown to enter a slow path.
+     */
+    public SlowPathException(String message) {
+        super(message);
+    }
+
+    /**
+     * Creates an exception thrown to enter a slow path.
+     */
+    public SlowPathException(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * For performance reasons, this exception does not record any stack trace information.
+     */
+    @SuppressWarnings("sync-override")
+    @Override
+    public Throwable fillInStackTrace() {
+        return null;
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java	Thu Apr 25 16:53:29 2013 +0200
@@ -39,7 +39,6 @@
      * @param result the alternative result
      */
     public UnexpectedResultException(Object result) {
-        super(null, null);
         assert !(result instanceof Throwable);
         this.result = result;
     }
@@ -50,13 +49,4 @@
     public Object getResult() {
         return result;
     }
-
-    /**
-     * For performance reasons, this exception does not record any stack trace information.
-     */
-    @SuppressWarnings("sync-override")
-    @Override
-    public Throwable fillInStackTrace() {
-        return null;
-    }
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java	Thu Apr 25 16:53:29 2013 +0200
@@ -28,8 +28,8 @@
 import javax.lang.model.type.*;
 import javax.tools.Diagnostic.*;
 
+import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.intrinsics.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.nodes.Node.Child;
 import com.oracle.truffle.api.nodes.Node.Children;
@@ -43,10 +43,11 @@
     private final TypeMirror nodeArray;
     private final TypeMirror unexpectedValueException;
     private final TypeMirror frame;
+    private final TypeMirror assumption;
+    private final TypeMirror invalidAssumption;
     private final DeclaredType childAnnotation;
     private final DeclaredType childrenAnnotation;
-    private final TypeMirror typeConversion;
-    private final TypeMirror truffleIntrinsics;
+    private final TypeMirror compilerDirectives;
 
     private final List<String> errors = new ArrayList<>();
 
@@ -57,8 +58,9 @@
         frame = getRequired(context, VirtualFrame.class);
         childAnnotation = getRequired(context, Child.class);
         childrenAnnotation = getRequired(context, Children.class);
-        typeConversion = getRequired(context, TypeConversion.class);
-        truffleIntrinsics = getRequired(context, TruffleIntrinsics.class);
+        compilerDirectives = getRequired(context, CompilerDirectives.class);
+        assumption = getRequired(context, Assumption.class);
+        invalidAssumption = getRequired(context, InvalidAssumptionException.class);
     }
 
     public boolean verify(ProcessorContext context, Element element, AnnotationMirror mirror) {
@@ -81,12 +83,16 @@
         return (DeclaredType) type;
     }
 
-    public TypeMirror getTruffleIntrinsics() {
-        return truffleIntrinsics;
+    public TypeMirror getInvalidAssumption() {
+        return invalidAssumption;
     }
 
-    public TypeMirror getTypeConversion() {
-        return typeConversion;
+    public TypeMirror getAssumption() {
+        return assumption;
+    }
+
+    public TypeMirror getCompilerDirectives() {
+        return compilerDirectives;
     }
 
     public TypeMirror getNode() {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java	Thu Apr 25 16:53:29 2013 +0200
@@ -44,8 +44,8 @@
     }
 
     @Override
-    protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData) {
-        List<ExecutableTypeData> execTypes = nodeData.findGenericExecutableTypes(getContext());
+    protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, int evaluatedCount) {
+        List<ExecutableTypeData> execTypes = nodeData.findGenericExecutableTypes(getContext(), evaluatedCount);
         List<TypeMirror> types = new ArrayList<>();
         for (ExecutableTypeData type : execTypes) {
             types.add(type.getType().getPrimitiveType());
@@ -57,7 +57,7 @@
 
     @Override
     protected ParameterSpec createReturnParameterSpec() {
-        return super.createValueParameterSpec("returnValue", getNode());
+        return super.createValueParameterSpec("returnValue", getNode(), 0);
     }
 
     @Override
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeChildData.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeChildData.java	Thu Apr 25 16:53:29 2013 +0200
@@ -22,10 +22,14 @@
  */
 package com.oracle.truffle.codegen.processor.node;
 
+import java.util.*;
+
 import javax.lang.model.element.*;
 import javax.lang.model.type.*;
 
+import com.oracle.truffle.codegen.processor.*;
 import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.typesystem.*;
 
 public class NodeChildData extends MessageContainer {
 
@@ -54,6 +58,9 @@
 
     private final Cardinality cardinality;
     private final ExecutionKind executionKind;
+
+    private List<NodeChildData> executeWith = Collections.emptyList();
+
     private NodeData nodeData;
 
     public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, Element accessElement, Cardinality cardinality, ExecutionKind executionKind) {
@@ -66,6 +73,34 @@
         this.executionKind = executionKind;
     }
 
+    public List<NodeChildData> getExecuteWith() {
+        return executeWith;
+    }
+
+    void setExecuteWith(List<NodeChildData> executeWith) {
+        this.executeWith = executeWith;
+    }
+
+    public ExecutableTypeData findExecutableType(ProcessorContext context, TypeData targetType) {
+        ExecutableTypeData executableType = nodeData.findExecutableType(targetType, getExecuteWith().size());
+        if (executableType == null) {
+            executableType = findAnyGenericExecutableType(context);
+        }
+        return executableType;
+    }
+
+    public List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context) {
+        return nodeData.findGenericExecutableTypes(context, getExecuteWith().size());
+    }
+
+    public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context) {
+        return nodeData.findAnyGenericExecutableType(context, getExecuteWith().size());
+    }
+
+    public List<ExecutableTypeData> findExecutableTypes() {
+        return nodeData.getExecutableTypes(getExecuteWith().size());
+    }
+
     @Override
     public Element getMessageElement() {
         return sourceElement;
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Thu Apr 25 16:53:29 2013 +0200
@@ -67,6 +67,10 @@
         return name;
     }
 
+    private static String valueNameEvaluated(ActualParameter targetParameter) {
+        return valueName(targetParameter) + "Evaluated";
+    }
+
     private static String valueName(ActualParameter param) {
         return param.getLocalName();
     }
@@ -137,7 +141,7 @@
         }
     }
 
-    private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName) {
+    private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName) {
         CodeTreeBuilder builder = parent.create();
 
         boolean castedValues = sourceMethod != targetMethod;
@@ -150,43 +154,47 @@
         TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement());
         NodeData node = (NodeData) targetMethod.getTemplate();
 
-        boolean accessible = targetMethod.canBeAccessedByInstanceOf(getContext(), node.getNodeType());
-        if (accessible) {
-            if (builder.findMethod().getModifiers().contains(STATIC)) {
+        if (target == null) {
+            boolean accessible = targetMethod.canBeAccessedByInstanceOf(getContext(), node.getNodeType());
+            if (accessible) {
+                if (builder.findMethod().getModifiers().contains(STATIC)) {
+                    if (method.getModifiers().contains(STATIC)) {
+                        builder.type(targetClass.asType());
+                    } else {
+                        builder.string(THIS_NODE_LOCAL_VAR_NAME);
+                    }
+                } else {
+                    if (targetMethod instanceof ExecutableTypeData) {
+                        builder.string("this");
+                    } else {
+                        builder.string("super");
+                    }
+                }
+            } else {
                 if (method.getModifiers().contains(STATIC)) {
                     builder.type(targetClass.asType());
                 } else {
-                    builder.string(THIS_NODE_LOCAL_VAR_NAME);
-                }
-            } else {
-                if (targetMethod instanceof ExecutableTypeData) {
-                    builder.string("this");
-                } else {
-                    builder.string("super");
+                    ActualParameter parameter = null;
+                    for (ActualParameter searchParameter : targetMethod.getParameters()) {
+                        if (searchParameter.getSpecification().isSignature()) {
+                            parameter = searchParameter;
+                            break;
+                        }
+                    }
+                    ActualParameter sourceParameter = sourceMethod.findParameter(parameter.getLocalName());
+                    assert parameter != null;
+
+                    if (castedValues && sourceParameter != null) {
+                        builder.string(valueName(sourceParameter, parameter));
+                    } else {
+                        builder.string(valueName(parameter));
+                    }
                 }
             }
+            builder.string(".");
         } else {
-            if (method.getModifiers().contains(STATIC)) {
-                builder.type(targetClass.asType());
-            } else {
-                ActualParameter parameter = null;
-                for (ActualParameter searchParameter : targetMethod.getParameters()) {
-                    if (searchParameter.getSpecification().isSignature()) {
-                        parameter = searchParameter;
-                        break;
-                    }
-                }
-                ActualParameter sourceParameter = sourceMethod.findParameter(parameter.getLocalName());
-                assert parameter != null;
-
-                if (castedValues && sourceParameter != null) {
-                    builder.string(valueName(sourceParameter, parameter));
-                } else {
-                    builder.string(valueName(parameter));
-                }
-            }
+            builder.tree(target);
         }
-        builder.string(".");
         builder.startCall(method.getSimpleName().toString());
 
         for (ActualParameter targetParameter : targetMethod.getParameters()) {
@@ -289,11 +297,11 @@
     }
 
     private CodeTree createGuardAndCast(CodeTreeBuilder parent, String conditionPrefix, SpecializationData sourceSpecialization, SpecializationData targetSpecialization, boolean castValues,
-                    CodeTree guardedStatements, CodeTree elseStatements) {
+                    CodeTree guardedStatements, CodeTree elseStatements, boolean emitAssumptions) {
 
         NodeData node = targetSpecialization.getNode();
         CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-        CodeTree implicitGuards = createImplicitGuards(parent, conditionPrefix, sourceSpecialization, targetSpecialization);
+        CodeTree implicitGuards = createImplicitGuards(parent, conditionPrefix, sourceSpecialization, targetSpecialization, emitAssumptions);
         CodeTree explicitGuards = createExplicitGuards(parent, implicitGuards == null ? conditionPrefix : null, sourceSpecialization, targetSpecialization);
 
         Set<String> valuesNeedsCast;
@@ -304,14 +312,20 @@
             // find out which values needs a cast
             valuesNeedsCast = new HashSet<>();
             for (GuardData guard : targetSpecialization.getGuards()) {
-                for (ActualParameter parameter : guard.getParameters()) {
-                    NodeChildData field = node.findChild(parameter.getSpecification().getName());
+                for (ActualParameter targetParameter : guard.getParameters()) {
+                    NodeChildData field = node.findChild(targetParameter.getSpecification().getName());
                     if (field == null) {
                         continue;
                     }
-                    TypeData typeData = parameter.getTypeSystemType();
-                    if (typeData != null && !typeData.isGeneric()) {
-                        valuesNeedsCast.add(parameter.getLocalName());
+                    TypeData targetType = targetParameter.getTypeSystemType();
+                    ActualParameter sourceParameter = sourceSpecialization.findParameter(targetParameter.getLocalName());
+                    if (sourceParameter == null) {
+                        sourceParameter = targetParameter;
+                    }
+                    TypeData sourceType = sourceParameter.getTypeSystemType();
+
+                    if (sourceType.needsCastTo(targetType)) {
+                        valuesNeedsCast.add(targetParameter.getLocalName());
                     }
                 }
             }
@@ -353,14 +367,14 @@
         return builder.getRoot();
     }
 
-    private CodeTree createExplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) {
+    private CodeTree createExplicitGuards(CodeTreeBuilder parent, String conditionPrefix, TemplateMethod valueSpecialization, SpecializationData guardedSpecialization) {
         CodeTreeBuilder builder = new CodeTreeBuilder(parent);
         String andOperator = conditionPrefix != null ? conditionPrefix + " && " : "";
         if (guardedSpecialization.getGuards().size() > 0) {
             // Explicitly specified guards
             for (GuardData guard : guardedSpecialization.getGuards()) {
                 builder.string(andOperator);
-                builder.tree(createTemplateMethodCall(parent, valueSpecialization, guard, null));
+                builder.tree(createTemplateMethodCall(parent, null, valueSpecialization, guard, null));
                 andOperator = " && ";
             }
         }
@@ -368,7 +382,7 @@
         return builder.isEmpty() ? null : builder.getRoot();
     }
 
-    private CodeTree createCasts(CodeTreeBuilder parent, Set<String> castWhiteList, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) {
+    private CodeTree createCasts(CodeTreeBuilder parent, Set<String> castWhiteList, TemplateMethod valueSpecialization, SpecializationData guardedSpecialization) {
         CodeTreeBuilder builder = new CodeTreeBuilder(parent);
         // Implict guards based on method signature
         for (ActualParameter guardedParam : guardedSpecialization.getParameters()) {
@@ -378,6 +392,14 @@
             }
             ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName());
 
+            if (valueParam == null) {
+                /*
+                 * If used inside a function execute method. The value param may not exist. In that
+                 * case it assumes that the value is already converted.
+                 */
+                valueParam = guardedParam;
+            }
+
             if (castWhiteList != null && !castWhiteList.contains(guardedParam.getLocalName())) {
                 continue;
             }
@@ -392,10 +414,26 @@
         return builder.getRoot();
     }
 
-    private CodeTree createImplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) {
+    private CodeTree createImplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, boolean emitAssumptions) {
         CodeTreeBuilder builder = new CodeTreeBuilder(parent);
         // Implict guards based on method signature
         String andOperator = conditionPrefix != null ? conditionPrefix + " && " : "";
+
+        if (emitAssumptions) {
+            boolean isStatic = parent.findMethod().getModifiers().contains(STATIC);
+
+            for (String assumption : guardedSpecialization.getAssumptions()) {
+                builder.string(andOperator);
+                if (isStatic) {
+                    builder.string(THIS_NODE_LOCAL_VAR_NAME);
+                } else {
+                    builder.string("this");
+                }
+                builder.string(".").string(assumption).string(".isValid()");
+                andOperator = " && ";
+            }
+        }
+
         for (ActualParameter guardedParam : guardedSpecialization.getParameters()) {
             NodeChildData field = guardedSpecialization.getNode().findChild(guardedParam.getSpecification().getName());
             if (field == null) {
@@ -403,6 +441,14 @@
             }
             ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName());
 
+            if (valueParam == null) {
+                /*
+                 * If used inside a function execute method. The value param may not exist. In that
+                 * case it assumes that the value is already converted.
+                 */
+                valueParam = guardedParam;
+            }
+
             CodeTree implicitGuard = createImplicitGuard(builder, field, valueParam, guardedParam);
             if (implicitGuard == null) {
                 continue;
@@ -423,7 +469,7 @@
         TypeData targetType = target.getTypeSystemType();
         TypeData sourceType = source.getTypeSystemType();
 
-        if (targetType.equalsType(sourceType) || targetType.isGeneric()) {
+        if (!sourceType.needsCastTo(targetType)) {
             return null;
         }
 
@@ -528,6 +574,19 @@
         return constructors;
     }
 
+    private static ExecutableElement findCopyConstructor(TypeMirror type) {
+        for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(type).getEnclosedElements())) {
+            if (constructor.getModifiers().contains(PRIVATE)) {
+                continue;
+            }
+            if (isCopyConstructor(constructor)) {
+                return constructor;
+            }
+        }
+
+        return null;
+    }
+
     private static boolean isCopyConstructor(ExecutableElement element) {
         if (element.getParameters().size() != 1) {
             return false;
@@ -578,6 +637,10 @@
                 }
             }
 
+            for (String assumption : node.getAssumptions()) {
+                clazz.add(createAssumptionField(assumption));
+            }
+
             createConstructors(node, clazz);
 
             if (node.getExtensionElements() != null) {
@@ -588,103 +651,102 @@
         }
 
         private void createConstructors(NodeData node, CodeTypeElement clazz) {
-            List<ExecutableElement> signatureConstructors = new ArrayList<>();
-            ExecutableElement copyConstructor = null;
-            List<? extends ExecutableElement> constructors = ElementFilter.constructorsIn(Utils.fromTypeMirror(node.getNodeType()).getEnclosedElements());
-            for (ExecutableElement constructor : constructors) {
-                if (constructor.getModifiers().contains(Modifier.PRIVATE) || constructor.getParameters().isEmpty()) {
-                    continue;
-                }
-
-                if (isCopyConstructor(constructor)) {
-                    assert copyConstructor == null;
-                    copyConstructor = createConstructor(clazz, constructor, true);
-                } else {
-                    signatureConstructors.add(createConstructor(clazz, constructor, false));
+            List<ExecutableElement> constructors = findUserConstructors(node.getNodeType());
+            if (constructors.isEmpty()) {
+                clazz.add(createUserConstructor(clazz, null));
+            } else {
+                for (ExecutableElement constructor : constructors) {
+                    clazz.add(createUserConstructor(clazz, constructor));
                 }
             }
-
-            if (copyConstructor == null && node.needsRewrites(getContext())) {
-                clazz.add(createConstructor(clazz, null, true));
-            } else if (copyConstructor != null) {
-                clazz.add(copyConstructor);
-            }
-
-            if (signatureConstructors.isEmpty() && !node.getChildren().isEmpty()) {
-                clazz.add(createConstructor(clazz, null, false));
-            } else {
-                clazz.getEnclosedElements().addAll(signatureConstructors);
+            if (node.needsRewrites(getContext())) {
+                clazz.add(createCopyConstructor(clazz, findCopyConstructor(node.getNodeType())));
             }
         }
 
-        private CodeExecutableElement createConstructor(CodeTypeElement type, ExecutableElement superConstructor, boolean copyConstructor) {
+        private CodeExecutableElement createUserConstructor(CodeTypeElement type, ExecutableElement superConstructor) {
             CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
             CodeTreeBuilder builder = method.createBuilder();
-            if (!copyConstructor) {
-                if (superConstructor != null) {
-                    for (VariableElement param : superConstructor.getParameters()) {
-                        method.getParameters().add(CodeVariableElement.clone(param));
-                    }
+
+            if (superConstructor != null) {
+                for (VariableElement param : superConstructor.getParameters()) {
+                    method.getParameters().add(CodeVariableElement.clone(param));
                 }
-                for (NodeChildData child : getModel().getChildren()) {
-                    method.getParameters().add(new CodeVariableElement(child.getNodeType(), child.getName()));
-                }
-            } else {
-                if (!(superConstructor == null && getModel().getChildren().isEmpty())) {
-                    method.getParameters().add(new CodeVariableElement(type.asType(), "copy"));
-                }
+            }
+
+            for (VariableElement var : type.getFields()) {
+                method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString()));
             }
 
             if (superConstructor != null) {
-                builder.startStatement();
-                builder.startSuperCall();
-                if (copyConstructor) {
-                    builder.string("copy");
-                } else {
-                    for (VariableElement param : superConstructor.getParameters()) {
-                        builder.string(param.getSimpleName().toString());
-                    }
+                builder.startStatement().startSuperCall();
+                for (VariableElement param : superConstructor.getParameters()) {
+                    builder.string(param.getSimpleName().toString());
                 }
-                builder.end();
-                builder.end();
+                builder.end().end();
             }
 
-            for (NodeChildData child : getModel().getChildren()) {
-
+            for (VariableElement var : type.getFields()) {
                 builder.startStatement();
-                builder.string("this.").string(child.getName()).string(" = ");
-
-                if (child.getCardinality() == Cardinality.MANY) {
-                    builder.startCall("adoptChildren");
+                String varName = var.getSimpleName().toString();
+                builder.string("this.").string(varName);
+                if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) {
+                    builder.string(" = adoptChild(").string(varName).string(")");
+                } else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) {
+                    builder.string(" = adoptChildren(").string(varName).string(")");
                 } else {
-                    builder.startCall("adoptChild");
+                    builder.string(" = ").string(varName);
                 }
-
-                builder.startGroup();
-                if (copyConstructor) {
-                    builder.string("copy.");
-                }
-                builder.string(child.getName());
                 builder.end();
-
-                builder.end();
-                builder.end();
-
             }
-
             return method;
         }
 
+        private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor) {
+            CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
+            CodeTreeBuilder builder = method.createBuilder();
+            if (!(superConstructor == null && type.getFields().isEmpty())) {
+                method.getParameters().add(new CodeVariableElement(type.asType(), "copy"));
+            }
+
+            if (superConstructor != null) {
+                builder.startStatement().startSuperCall().string("copy").end().end();
+            }
+
+            for (VariableElement var : type.getFields()) {
+                builder.startStatement();
+                String varName = var.getSimpleName().toString();
+                builder.string("this.").string(varName);
+                if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) {
+                    builder.string(" = adoptChild(copy.").string(varName).string(")");
+                } else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) {
+                    builder.string(" = adoptChildren(copy.").string(varName).string(")");
+                } else {
+                    builder.string(" = copy.").string(varName);
+                }
+                builder.end();
+            }
+            return method;
+        }
+
+        private CodeVariableElement createAssumptionField(String assumption) {
+            CodeVariableElement var = new CodeVariableElement(getContext().getTruffleTypes().getAssumption(), assumption);
+            var.getModifiers().add(Modifier.FINAL);
+            return var;
+        }
+
         private CodeVariableElement createChildField(NodeChildData child) {
+            CodeVariableElement var = new CodeVariableElement(child.getNodeType(), child.getName());
+            var.getModifiers().add(Modifier.PROTECTED);
+
             DeclaredType annotationType;
             if (child.getCardinality() == Cardinality.MANY) {
+                var.getModifiers().add(Modifier.FINAL);
                 annotationType = getContext().getTruffleTypes().getChildrenAnnotation();
             } else {
                 annotationType = getContext().getTruffleTypes().getChildAnnotation();
             }
 
-            CodeVariableElement var = new CodeVariableElement(child.getNodeType(), child.getName());
-            var.getModifiers().add(Modifier.PROTECTED);
             var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType));
             return var;
         }
@@ -726,11 +788,8 @@
 
                 createFactoryMethods(node, clazz, createVisibility);
 
-                if (node.getSpecializations().size() > 1) {
+                if (node.needsRewrites(context)) {
                     clazz.add(createCreateSpecializedMethod(node, createVisibility));
-                }
-
-                if (node.needsRewrites(context)) {
                     clazz.add(createSpecializeMethod(node));
                 }
 
@@ -910,7 +969,7 @@
 
         private CodeExecutableElement createCreateNodeSpecializedMethod(NodeData node) {
             CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNodeSpecialized");
-            CodeVariableElement nodeParam = new CodeVariableElement(node.getNodeType(), "thisNode");
+            CodeVariableElement nodeParam = new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME);
             CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Class.class), "types");
             method.addParameter(nodeParam);
             method.addParameter(arguments);
@@ -926,7 +985,9 @@
                 builder.startBlock();
 
                 builder.startReturn().startCall("createSpecialized");
-                builder.string("thisNode");
+                builder.startGroup();
+                builder.string(THIS_NODE_LOCAL_VAR_NAME);
+                builder.end();
                 builder.string("types[0]");
                 builder.end().end();
 
@@ -1083,10 +1144,16 @@
 
             CodeTreeBuilder body = method.createBuilder();
 
-            body.startStatement();
-            body.type(generatedNode.asType()).string(" ").string(THIS_NODE_LOCAL_VAR_NAME + "Cast");
-            body.string(" = ").string("(").type(generatedNode.asType()).string(") ").string(THIS_NODE_LOCAL_VAR_NAME);
-            body.end();
+            boolean hasCopyConstructor = findCopyConstructor(generatedNode.asType()) != null;
+
+            final String thisLocalVariableName = THIS_NODE_LOCAL_VAR_NAME + "Cast";
+
+            if (hasCopyConstructor) {
+                body.startStatement();
+                body.type(generatedNode.asType()).string(" ").string(thisLocalVariableName);
+                body.string(" = ").string("(").type(generatedNode.asType()).string(") ").string(THIS_NODE_LOCAL_VAR_NAME);
+                body.end();
+            }
 
             boolean first = true;
             for (TypeData type : node.getTypeSystem().getTypes()) {
@@ -1099,16 +1166,12 @@
                         body.startElseIf();
                     }
                     body.string("specializationClass == ").type(type.getBoxedType()).string(".class").end().startBlock();
-                    body.startReturn().startNew(nodeSpecializationClassName(specialization));
-                    body.string(THIS_NODE_LOCAL_VAR_NAME + "Cast");
-                    body.end().end(); // new, return
+                    body.tree(createReturnNewSpecialization(body, specialization, thisLocalVariableName, hasCopyConstructor));
 
                     body.end(); // if
                 }
             }
-            body.startReturn().startNew(nodeSpecializationClassName(node.getGenericSpecialization()));
-            body.string(THIS_NODE_LOCAL_VAR_NAME + "Cast");
-            body.end().end();
+            body.tree(createReturnNewSpecialization(body, node.getGenericSpecialization(), thisLocalVariableName, hasCopyConstructor));
             return method;
         }
 
@@ -1121,22 +1184,31 @@
             CodeTreeBuilder body = method.createBuilder();
             body.startStatement().string("boolean allowed = (minimumState == ").string(nodeSpecializationClassName(node.getSpecializations().get(0))).string(".class)").end();
 
+            boolean hasCopyConstructor = findCopyConstructor(generatedNode.asType()) != null;
+
             for (int i = 1; i < node.getSpecializations().size(); i++) {
                 SpecializationData specialization = node.getSpecializations().get(i);
                 body.startStatement().string("allowed = allowed || (minimumState == ").string(nodeSpecializationClassName(specialization)).string(".class)").end();
 
-                CodeTreeBuilder guarded = new CodeTreeBuilder(body);
-                guarded.startReturn().startNew(nodeSpecializationClassName(specialization));
-                guarded.string(THIS_NODE_LOCAL_VAR_NAME);
-                guarded.end().end();
+                CodeTree guarded = createReturnNewSpecialization(body, specialization, THIS_NODE_LOCAL_VAR_NAME, hasCopyConstructor);
 
-                body.tree(createGuardAndCast(body, "allowed", node.getGenericSpecialization(), specialization, false, guarded.getRoot(), null));
+                body.tree(createGuardAndCast(body, "allowed", node.getGenericSpecialization(), specialization, false, guarded, null, true));
             }
             body.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end();
 
             return method;
         }
 
+        private CodeTree createReturnNewSpecialization(CodeTreeBuilder parent, SpecializationData specialization, String thisLocalVariableName, boolean hasCopyConstructor) {
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            builder.startReturn().startNew(nodeSpecializationClassName(specialization));
+            if (hasCopyConstructor) {
+                builder.string(thisLocalVariableName);
+            }
+            builder.end().end();
+            return builder.getRoot();
+        }
+
         private List<CodeExecutableElement> createGeneratedGenericMethod(NodeData node) {
             TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType();
             if (node.needsRewrites(context)) {
@@ -1153,7 +1225,7 @@
                     } else {
                         String methodName = generatedGenericMethodName(current);
                         CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), genericReturnType, methodName);
-                        method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME));
+                        method.addParameter(new CodeVariableElement(generatedNode.asType(), THIS_NODE_LOCAL_VAR_NAME));
                         addInternalValueParameters(method, node.getGenericSpecialization(), true);
 
                         emitGeneratedGenericSpecialization(method.createBuilder(), current, next);
@@ -1166,7 +1238,7 @@
                 return methods;
             } else {
                 CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), genericReturnType, generatedGenericMethodName(null));
-                method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME));
+                method.addParameter(new CodeVariableElement(generatedNode.asType(), THIS_NODE_LOCAL_VAR_NAME));
                 addInternalValueParameters(method, node.getGenericSpecialization(), true);
                 emitInvokeDoMethod(method.createBuilder(), node.getGenericSpecialization(), 0);
                 return Arrays.asList(method);
@@ -1186,7 +1258,7 @@
                 addInternalValueParameterNames(nextBuilder, next, next, null, true, true);
                 nextBuilder.end().end();
 
-                invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, true, invokeMethod, nextBuilder.getRoot());
+                invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, true, invokeMethod, nextBuilder.getRoot(), true);
             }
 
             builder.tree(invokeMethod);
@@ -1205,7 +1277,7 @@
                 emitEncounteredSynthetic(builder);
             } else {
                 builder.startReturn();
-                builder.tree(createTemplateMethodCall(builder, specialization.getNode().getGenericSpecialization(), specialization, null));
+                builder.tree(createTemplateMethodCall(builder, null, specialization.getNode().getGenericSpecialization(), specialization, null));
                 builder.end(); // return
             }
 
@@ -1272,7 +1344,7 @@
                 }
             }
 
-            if (node.needsRewrites(getContext()) && !specialization.isGeneric() && !specialization.isUninitialized()) {
+            if (specialization.hasRewrite(getContext())) {
                 buildSpecializeAndExecute(clazz, specialization);
             }
         }
@@ -1301,7 +1373,12 @@
             int i = 0;
             for (VariableElement param : method.getParameters()) {
                 CodeVariableElement var = CodeVariableElement.clone(param);
-                var.setName(valueName(execType.getParameters().get(i)));
+                ActualParameter actualParameter = execType.getParameters().get(i);
+                if (actualParameter.getSpecification().isSignature()) {
+                    var.setName(valueNameEvaluated(actualParameter));
+                } else {
+                    var.setName(valueName(actualParameter));
+                }
                 method.getParameters().set(i, var);
                 i++;
             }
@@ -1356,7 +1433,7 @@
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
             NodeData node = specialization.getNode();
 
-            ExecutableTypeData castedType = node.findExecutableType(type);
+            ExecutableTypeData castedType = node.findExecutableType(type, 0);
             TypeData primaryType = castExecutable.getType();
 
             boolean needsTry = castExecutable.hasUnexpectedValue(getContext());
@@ -1371,17 +1448,13 @@
 
                 ActualParameter targetParameter = castExecutable.findParameter(sourceParameter.getLocalName());
                 if (targetParameter != null) {
-                    TypeData sourceType = sourceParameter.getTypeSystemType();
-                    TypeData targetType = targetParameter.getTypeSystemType();
-                    if (sourceType.needsCastTo(targetType)) {
-                        executeParameters.add(targetParameter);
-                    }
+                    executeParameters.add(targetParameter);
                 }
             }
 
             builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null, true));
 
-            CodeTree primaryExecuteCall = createTemplateMethodCall(builder, executable, castExecutable, null);
+            CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null);
             if (needsTry) {
                 if (!returnVoid) {
                     builder.declaration(primaryType.getPrimitiveType(), "value");
@@ -1448,6 +1521,24 @@
             return builder.getRoot();
         }
 
+        private CodeTree createExpectType(NodeData node, TypeData castedType, CodeTree value) {
+            if (castedType == null) {
+                return value;
+            } else if (castedType.isVoid()) {
+                return value;
+            } else if (castedType.isGeneric()) {
+                return value;
+            }
+
+            CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+            String targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(castedType);
+            startCallTypeSystemMethod(getContext(), builder, node, targetMethodName);
+
+            builder.tree(value);
+            builder.end().end();
+            return builder.getRoot();
+        }
+
         private CodeTree createFunctionalExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable) {
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
             if (specialization.isUninitialized()) {
@@ -1458,7 +1549,7 @@
 
             CodeTree executeNode;
             if (specialization.isUninitialized()) {
-                builder.tree(createSpecializeCall(builder, executable, specialization));
+                builder.tree(createSpecializeCall(builder, specialization));
             }
             executeNode = createExecute(builder, executable, specialization);
 
@@ -1467,7 +1558,7 @@
             if (next != null) {
                 returnSpecialized = createReturnSpecializeAndExecute(builder, executable, next, null);
             }
-            builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized));
+            builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized, false));
 
             return builder.getRoot();
         }
@@ -1475,12 +1566,12 @@
         private CodeTree createDeoptimize(CodeTreeBuilder parent) {
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
             builder.startStatement();
-            builder.startStaticCall(getContext().getTruffleTypes().getTruffleIntrinsics(), "deoptimize").end();
+            builder.startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end();
             builder.end();
             return builder.getRoot();
         }
 
-        private CodeTree createSpecializeCall(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) {
+        private CodeTree createSpecializeCall(CodeTreeBuilder parent, SpecializationData specialization) {
             NodeData node = specialization.getNode();
 
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
@@ -1492,28 +1583,35 @@
                 builder.startCall(factoryClassName(node), "specialize");
                 builder.string("this");
                 builder.typeLiteral(builder.findMethod().getEnclosingElement().asType());
-                addInternalValueParameterNames(builder, executable, specialization, null, true, true);
+                addInternalValueParameterNames(builder, specialization, specialization, null, true, true);
                 builder.end(); // call replace, call specialize
             } else {
                 builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end();
             }
             builder.end().end();
+            emitSpecializationListeners(builder, node);
             return builder.getRoot();
         }
 
         private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) {
             NodeData node = specialization.getNode();
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            if (!specialization.getExceptions().isEmpty()) {
+            if (!specialization.getExceptions().isEmpty() || !specialization.getAssumptions().isEmpty()) {
                 builder.startTryBlock();
             }
 
+            for (String assumption : specialization.getAssumptions()) {
+                builder.startStatement();
+                builder.string("this.").string(assumption).string(".check()");
+                builder.end();
+            }
+
             CodeTreeBuilder returnBuilder = new CodeTreeBuilder(parent);
             if (specialization.isUninitialized()) {
                 String genericMethodName = generatedGenericMethodName(null);
                 returnBuilder.startCall(factoryClassName(node), genericMethodName);
                 returnBuilder.string("this");
-                addInternalValueParameterNames(returnBuilder, executable, specialization, null, true, true);
+                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true);
                 returnBuilder.end();
             } else if (specialization.getMethod() == null && !node.needsRewrites(context)) {
                 emitEncounteredSynthetic(builder);
@@ -1527,10 +1625,10 @@
 
                 returnBuilder.startCall(factoryClassName(node), genericMethodName);
                 returnBuilder.string("this");
-                addInternalValueParameterNames(returnBuilder, executable, specialization, null, true, true);
+                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true);
                 returnBuilder.end();
             } else {
-                returnBuilder.tree(createTemplateMethodCall(returnBuilder, executable, specialization, null));
+                returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null));
             }
 
             if (!returnBuilder.isEmpty()) {
@@ -1556,6 +1654,12 @@
                 }
                 builder.end();
             }
+            if (!specialization.getAssumptions().isEmpty()) {
+                builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex");
+                builder.tree(createReturnSpecializeAndExecute(parent, executable, specialization.findNextSpecialization(), null));
+                builder.end();
+            }
+
             return builder.getRoot();
         }
 
@@ -1572,34 +1676,39 @@
                 }
                 TypeData targetType = targetParameter.getTypeSystemType();
 
-                ExecutableTypeData targetExecutable = field.getNodeData().findExecutableType(targetType);
+                ExecutableTypeData targetExecutable = field.findExecutableType(getContext(), targetType);
 
                 ActualParameter sourceParameter = sourceExecutable.findParameter(targetParameter.getLocalName());
 
-                String targetVariableName = null;
+                String targetVariableName = valueName(targetParameter);
                 CodeTree executionExpression = null;
                 if (cast || sourceParameter != null) {
                     TypeData sourceType = sourceParameter.getTypeSystemType();
                     if (!sourceType.needsCastTo(targetType)) {
                         if (field.isShortCircuit() && sourceParameter != null) {
-                            builder.tree(createShortCircuitValue(builder, sourceExecutable, specialization, field, targetParameter.getPreviousParameter(), unexpectedParameter));
+                            builder.tree(createShortCircuitValue(builder, specialization, field, targetParameter.getPreviousParameter(), unexpectedParameter));
                         }
-                        continue;
+                        builder.startStatement();
+                        builder.type(targetParameter.getType()).string(" ");
+                        builder.string(valueName(targetParameter)).string(" = ");
+                        builder.tree(CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter)));
+                        builder.end();
+                    } else {
+                        executionExpression = createExpectType(sourceNode, targetExecutable, CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter)));
                     }
-                    executionExpression = createExpectType(sourceNode, targetExecutable, CodeTreeBuilder.singleString(valueName(targetParameter)));
-                    targetVariableName = castValueName(targetParameter);
                 } else if (sourceParameter == null) {
-                    targetVariableName = valueName(targetParameter);
-                    executionExpression = createExecuteChildExpression(builder, field, targetParameter);
+                    executionExpression = createExecuteChildExpression(builder, field, targetParameter, unexpectedParameter);
                 }
 
-                CodeTreeVariable executionVar = new CodeTreeVariable();
-                CodeTree shortCircuitTree = createShortCircuitTree(builder, executionVar, targetVariableName, sourceExecutable, specialization, targetParameter, unexpectedParameter);
-                CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpression, targetVariableName, specialization, sourceExecutable, targetExecutable, targetParameter,
-                                shortCircuitTree != executionVar);
+                if (executionExpression != null) {
+                    CodeTreeVariable executionVar = new CodeTreeVariable();
+                    CodeTree shortCircuitTree = createShortCircuitTree(builder, executionVar, targetVariableName, specialization, targetParameter, unexpectedParameter);
+                    CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpression, targetVariableName, specialization, sourceExecutable, targetExecutable, targetParameter,
+                                    shortCircuitTree != executionVar);
 
-                executionVar.set(unexpectedTree);
-                builder.tree(shortCircuitTree);
+                    executionVar.set(unexpectedTree);
+                    builder.tree(shortCircuitTree);
+                }
             }
             return builder.getRoot();
         }
@@ -1607,7 +1716,7 @@
         private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) {
             for (TemplateMethod listener : node.getSpecializationListeners()) {
                 builder.startStatement();
-                builder.tree(createTemplateMethodCall(builder, listener, listener, null));
+                builder.tree(createTemplateMethodCall(builder, null, listener, listener, null));
                 builder.end(); // statement
             }
         }
@@ -1616,6 +1725,12 @@
                         ExecutableTypeData targetExecutable, ActualParameter param, boolean shortCircuit) {
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
             boolean unexpected = targetExecutable.hasUnexpectedValue(getContext());
+            boolean cast = false;
+            if (targetExecutable.getType().needsCastTo(param.getTypeSystemType())) {
+                unexpected = true;
+                cast = true;
+            }
+
             builder.startStatement();
 
             if (!shortCircuit) {
@@ -1634,7 +1749,11 @@
                 builder.string(targetVariableName);
             }
             builder.string(" = ");
-            builder.tree(body);
+            if (cast) {
+                builder.tree(createExpectType(specialization.getNode(), specialization.getReturnSignature(), body));
+            } else {
+                builder.tree(body);
+            }
             builder.end();
 
             if (unexpected) {
@@ -1651,9 +1770,9 @@
             return builder.getRoot();
         }
 
-        private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData targetField, ActualParameter sourceParameter) {
+        private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData targetField, ActualParameter sourceParameter, ActualParameter unexpectedParameter) {
             TypeData type = sourceParameter.getTypeSystemType();
-            ExecutableTypeData execType = targetField.getNodeData().findExecutableType(type);
+            ExecutableTypeData execType = targetField.findExecutableType(getContext(), type);
 
             /*
              * FIXME Temporary deactivated due to partial evaluation failure else if
@@ -1675,16 +1794,47 @@
                 }
                 builder.string(".");
             }
+
             builder.startCall(execType.getMethodName());
-            if (execType.getParameters().size() == 1) {
-                builder.string("frameValue");
+
+            List<ActualParameter> signatureParameters = getModel().getSignatureParameters();
+            int index = 0;
+            for (ActualParameter parameter : execType.getParameters()) {
+
+                if (!parameter.getSpecification().isSignature()) {
+                    builder.string(parameter.getLocalName());
+                } else {
+                    if (index < signatureParameters.size()) {
+                        ActualParameter specializationParam = signatureParameters.get(index);
+
+                        String localName = specializationParam.getLocalName();
+                        if (unexpectedParameter != null && unexpectedParameter.getLocalName().equals(specializationParam.getLocalName())) {
+                            localName = "ex.getResult()";
+                        }
+
+                        TypeData sourceType = specializationParam.getTypeSystemType();
+                        TypeData targetType = parameter.getTypeSystemType();
+
+                        CodeTree value = CodeTreeBuilder.singleString(localName);
+
+                        if (sourceType.needsCastTo(targetType)) {
+                            value = createCallTypeSystemMethod(getContext(), builder, getModel().getNode(), TypeSystemCodeGenerator.asTypeMethodName(targetType), value);
+                        }
+                        builder.tree(value);
+                    } else {
+                        builder.defaultValue(parameter.getType());
+                    }
+                    index++;
+                }
             }
+
             builder.end();
+
             return builder.getRoot();
         }
 
-        private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, ExecutableTypeData currentExecutable, SpecializationData specialization,
-                        ActualParameter parameter, ActualParameter exceptionParam) {
+        private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, String targetVariableName, SpecializationData specialization, ActualParameter parameter,
+                        ActualParameter exceptionParam) {
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
 
             NodeChildData forField = specialization.getNode().findChild(parameter.getSpecification().getName());
@@ -1698,7 +1848,7 @@
 
             ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter);
 
-            builder.tree(createShortCircuitValue(builder, currentExecutable, specialization, forField, shortCircuitParam, exceptionParam));
+            builder.tree(createShortCircuitValue(builder, specialization, forField, shortCircuitParam, exceptionParam));
 
             builder.declaration(parameter.getType(), targetVariableName, CodeTreeBuilder.createBuilder().defaultValue(parameter.getType()));
             builder.startIf().string(shortCircuitParam.getLocalName()).end();
@@ -1709,8 +1859,7 @@
             return builder.getRoot();
         }
 
-        private CodeTree createShortCircuitValue(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, NodeChildData forField,
-                        ActualParameter shortCircuitParam, ActualParameter exceptionParam) {
+        private CodeTree createShortCircuitValue(CodeTreeBuilder parent, SpecializationData specialization, NodeChildData forField, ActualParameter shortCircuitParam, ActualParameter exceptionParam) {
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
             int shortCircuitIndex = 0;
             for (NodeChildData field : specialization.getNode().getChildren()) {
@@ -1724,7 +1873,7 @@
 
             builder.startStatement().type(shortCircuitParam.getType()).string(" ").string(valueName(shortCircuitParam)).string(" = ");
             ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex);
-            builder.tree(createTemplateMethodCall(builder, currentExecutable, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null));
+            builder.tree(createTemplateMethodCall(builder, null, specialization, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null));
             builder.end(); // statement
 
             return builder.getRoot();
@@ -1734,8 +1883,8 @@
             CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent);
             specializeCall.startCall("specializeAndExecute");
             specializeCall.string(nodeSpecializationClassName(nextSpecialization) + ".class");
-            addInternalValueParameterNames(specializeCall, executable, nextSpecialization.getNode().getGenericSpecialization(), exceptionParam != null ? exceptionParam.getLocalName() : null, true,
-                            true);
+            addInternalValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), nextSpecialization.getNode().getGenericSpecialization(),
+                            exceptionParam != null ? exceptionParam.getLocalName() : null, true, true);
             specializeCall.end().end();
 
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java	Thu Apr 25 16:53:29 2013 +0200
@@ -49,6 +49,7 @@
     private List<SpecializationListenerData> specializationListeners;
     private Map<Integer, List<ExecutableTypeData>> executableTypes;
     private List<ShortCircuitData> shortCircuits;
+    private List<String> assumptions;
 
     public NodeData(TypeElement type, String id) {
         super(type, null, null);
@@ -68,6 +69,7 @@
         this.shortCircuits = splitSource.shortCircuits;
         this.fields = splitSource.fields;
         this.children = splitSource.children;
+        this.assumptions = splitSource.assumptions;
     }
 
     public boolean isSplitByMethodName() {
@@ -143,6 +145,14 @@
         return getTemplateType().asType();
     }
 
+    void setAssumptions(List<String> assumptions) {
+        this.assumptions = assumptions;
+    }
+
+    public List<String> getAssumptions() {
+        return assumptions;
+    }
+
     public boolean needsFactory() {
         if (specializations == null) {
             return false;
@@ -214,8 +224,8 @@
         return methods;
     }
 
-    public ExecutableTypeData findGenericExecutableType(ProcessorContext context, TypeData type) {
-        List<ExecutableTypeData> types = findGenericExecutableTypes(context);
+    public ExecutableTypeData findGenericExecutableType(ProcessorContext context, TypeData type, int evaluatedCount) {
+        List<ExecutableTypeData> types = findGenericExecutableTypes(context, evaluatedCount);
         for (ExecutableTypeData availableType : types) {
             if (Utils.typeEquals(availableType.getType().getBoxedType(), type.getBoxedType())) {
                 return availableType;
@@ -224,8 +234,8 @@
         return null;
     }
 
-    public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context) {
-        List<ExecutableTypeData> types = findGenericExecutableTypes(context);
+    public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context, int evaluatedCount) {
+        List<ExecutableTypeData> types = findGenericExecutableTypes(context, evaluatedCount);
         for (ExecutableTypeData type : types) {
             if (type.getType().isGeneric()) {
                 return type;
@@ -241,6 +251,9 @@
     }
 
     public List<ExecutableTypeData> getExecutableTypes(int evaluatedCount) {
+        if (executableTypes == null) {
+            return Collections.emptyList();
+        }
         if (evaluatedCount == -1) {
             List<ExecutableTypeData> typeData = new ArrayList<>();
             for (int currentEvaluationCount : executableTypes.keySet()) {
@@ -248,13 +261,17 @@
             }
             return typeData;
         } else {
-            return executableTypes.get(evaluatedCount);
+            List<ExecutableTypeData> types = executableTypes.get(evaluatedCount);
+            if (types == null) {
+                return Collections.emptyList();
+            }
+            return types;
         }
     }
 
-    public List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context) {
+    public List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context, int evaluatedCount) {
         List<ExecutableTypeData> types = new ArrayList<>();
-        for (ExecutableTypeData type : getExecutableTypes(0)) {
+        for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) {
             if (!type.hasUnexpectedValue(context)) {
                 types.add(type);
             }
@@ -262,8 +279,8 @@
         return types;
     }
 
-    public ExecutableTypeData findExecutableType(TypeData prmitiveType) {
-        for (ExecutableTypeData type : getExecutableTypes(0)) {
+    public ExecutableTypeData findExecutableType(TypeData prmitiveType, int evaluatedCount) {
+        for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) {
             if (Utils.typeEquals(type.getType().getPrimitiveType(), prmitiveType.getPrimitiveType())) {
                 return type;
             }
@@ -304,7 +321,7 @@
                 break;
             }
         }
-        return needsRewrites;
+        return needsRewrites || getSpecializations().size() > 1;
     }
 
     public SpecializationData getGenericSpecialization() {
@@ -339,6 +356,7 @@
         dumpProperty(builder, indent, "fields", getChildren());
         dumpProperty(builder, indent, "executableTypes", getExecutableTypes());
         dumpProperty(builder, indent, "specializations", getSpecializations());
+        dumpProperty(builder, indent, "assumptions", getAssumptions());
         dumpProperty(builder, indent, "messages", collectMessages());
         if (getDeclaredNodes().size() > 0) {
             builder.append(String.format("\n%s  children = [", indent));
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java	Thu Apr 25 16:53:29 2013 +0200
@@ -42,7 +42,8 @@
         return template;
     }
 
-    protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData) {
+    @SuppressWarnings("unused")
+    protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, int evaluatedCount) {
         ParameterSpec spec = new ParameterSpec(valueName, nodeTypeMirrors(nodeData));
         spec.setSignature(true);
         return spec;
@@ -61,7 +62,7 @@
     }
 
     protected ParameterSpec createReturnParameterSpec() {
-        return createValueParameterSpec("returnValue", getNode());
+        return createValueParameterSpec("returnValue", getNode(), 0);
     }
 
     @Override
@@ -95,7 +96,7 @@
         if (getNode().getChildren() != null) {
             for (NodeChildData child : getNode().getChildren()) {
                 if (child.getExecutionKind() == ExecutionKind.DEFAULT) {
-                    ParameterSpec spec = createValueParameterSpec(child.getName(), child.getNodeData());
+                    ParameterSpec spec = createValueParameterSpec(child.getName(), child.getNodeData(), child.getExecuteWith().size());
                     if (child.getCardinality().isMany()) {
                         spec.setCardinality(Cardinality.MANY);
                         spec.setIndexed(true);
@@ -110,7 +111,7 @@
                     if (shortCircuitsEnabled) {
                         methodSpec.addRequired(new ParameterSpec(shortCircuitValueName(valueName), getContext().getType(boolean.class)));
                     }
-                    methodSpec.addRequired(createValueParameterSpec(valueName, child.getNodeData()));
+                    methodSpec.addRequired(createValueParameterSpec(valueName, child.getNodeData(), child.getExecuteWith().size()));
                 } else {
                     assert false;
                 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Thu Apr 25 16:53:29 2013 +0200
@@ -310,7 +310,7 @@
             GenericParser parser = new GenericParser(context, node);
             MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, true, null);
 
-            ExecutableTypeData anyGenericReturnType = node.findAnyGenericExecutableType(context);
+            ExecutableTypeData anyGenericReturnType = node.findAnyGenericExecutableType(context, 0);
             assert anyGenericReturnType != null;
 
             ActualParameter returnType = new ActualParameter(specification.getReturnType(), anyGenericReturnType.getType(), 0, false);
@@ -322,7 +322,7 @@
                 if (child == null) {
                     actualType = specializationParameter.getTypeSystemType();
                 } else {
-                    ExecutableTypeData paramType = child.getNodeData().findAnyGenericExecutableType(context);
+                    ExecutableTypeData paramType = child.findAnyGenericExecutableType(context);
                     assert paramType != null;
                     actualType = paramType.getType();
                 }
@@ -562,15 +562,30 @@
             splitByMethodName = Utils.getAnnotationValue(Boolean.class, nodeClass, "splitByMethodName");
         }
 
+        List<String> assumptionsList = new ArrayList<>();
+
+        for (int i = lookupTypes.size() - 1; i >= 0; i--) {
+            TypeElement type = lookupTypes.get(i);
+            AnnotationMirror assumptions = Utils.findAnnotationMirror(context.getEnvironment(), type, NodeAssumptions.class);
+            if (assumptions != null) {
+                List<String> assumptionStrings = Utils.getAnnotationValueList(String.class, assumptions, "value");
+                for (String string : assumptionStrings) {
+                    if (assumptionsList.contains(string)) {
+                        assumptionsList.remove(string);
+                    }
+                    assumptionsList.add(string);
+                }
+            }
+        }
+        nodeData.setAssumptions(new ArrayList<>(assumptionsList));
         nodeData.setNodeType(nodeType);
         nodeData.setSplitByMethodName(splitByMethodName);
         nodeData.setTypeSystem(typeSystem);
         nodeData.setFields(parseFields(elements));
+        parsedNodes.put(Utils.getQualifiedName(templateType), nodeData);
+        // parseChildren invokes cyclic parsing.
+        nodeData.setChildren(parseChildren(elements, lookupTypes));
         nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)));
-        parsedNodes.put(Utils.getQualifiedName(templateType), nodeData);
-
-        // parseChildren invokes cyclic parsing.
-        nodeData.setChildren(parseChildren(templateType, elements, lookupTypes));
 
         return nodeData;
     }
@@ -707,7 +722,7 @@
         return fields;
     }
 
-    private List<NodeChildData> parseChildren(TypeElement templateType, List<? extends Element> elements, final List<TypeElement> typeHierarchy) {
+    private List<NodeChildData> parseChildren(List<? extends Element> elements, final List<TypeElement> typeHierarchy) {
         Set<String> shortCircuits = new HashSet<>();
         for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
             AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
@@ -750,7 +765,7 @@
                     kind = ExecutionKind.SHORT_CIRCUIT;
                 }
 
-                NodeChildData nodeChild = new NodeChildData(templateType, childMirror, name, childType, getter, cardinality, kind);
+                NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, getter, cardinality, kind);
 
                 parsedChildren.add(nodeChild);
 
@@ -763,8 +778,6 @@
                 nodeChild.setNode(fieldNodeData);
                 if (fieldNodeData == null) {
                     nodeChild.addError("Node type '%s' is invalid or not a valid Node.", Utils.getQualifiedName(childType));
-                } else if (fieldNodeData.findGenericExecutableTypes(context).isEmpty()) {
-                    nodeChild.addError("No executable generic types found for node '%s'.", Utils.getQualifiedName(type));
                 }
             }
         }
@@ -778,6 +791,53 @@
                 encounteredNames.add(child.getName());
             }
         }
+
+        for (NodeChildData child : filteredChildren) {
+            List<String> executeWithStrings = Utils.getAnnotationValueList(String.class, child.getMessageAnnotation(), "executeWith");
+            AnnotationValue executeWithValue = Utils.getAnnotationValue(child.getMessageAnnotation(), "executeWith");
+            List<NodeChildData> executeWith = new ArrayList<>();
+            for (String executeWithString : executeWithStrings) {
+
+                if (child.getName().equals(executeWithString)) {
+                    child.addError(executeWithValue, "The child node '%s' cannot be executed with itself.", executeWithString);
+                    continue;
+                }
+
+                NodeChildData found = null;
+                boolean before = true;
+                for (NodeChildData resolveChild : filteredChildren) {
+                    if (resolveChild == child) {
+                        before = false;
+                        continue;
+                    }
+                    if (resolveChild.getName().equals(executeWithString)) {
+                        found = resolveChild;
+                        break;
+                    }
+                }
+
+                if (found == null) {
+                    child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The child node was not found.", child.getName(), executeWithString);
+                    continue;
+                } else if (!before) {
+                    child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The node %s is executed after the current node.", child.getName(), executeWithString,
+                                    executeWithString);
+                    continue;
+                }
+                executeWith.add(found);
+            }
+            child.setExecuteWith(executeWith);
+            if (child.getNodeData() == null) {
+                continue;
+            }
+
+            List<ExecutableTypeData> types = child.findGenericExecutableTypes(context);
+            if (types.isEmpty()) {
+                child.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s.", executeWith.size(), Utils.getSimpleName(child.getNodeType()));
+                continue;
+            }
+        }
+
         return filteredChildren;
     }
 
@@ -915,7 +975,7 @@
                 continue;
             }
             ExecutableTypeData found = null;
-            List<ExecutableTypeData> executableElements = field.getNodeData().findGenericExecutableTypes(context);
+            List<ExecutableTypeData> executableElements = field.findGenericExecutableTypes(context);
             for (ExecutableTypeData executable : executableElements) {
                 if (executable.getType().equalsType(parameter.getTypeSystemType())) {
                     found = executable;
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java	Thu Apr 25 16:53:29 2013 +0200
@@ -36,8 +36,9 @@
     private final boolean uninitialized;
     private final List<SpecializationThrowsData> exceptions;
     private List<String> guardDefinitions = Collections.emptyList();
-    private List<GuardData> guards;
+    private List<GuardData> guards = Collections.emptyList();
     private List<ShortCircuitData> shortCircuits;
+    private List<String> assumptions = Collections.emptyList();
     private boolean useSpecializationsForGeneric = true;
     private NodeData node;
 
@@ -59,7 +60,6 @@
         this.generic = generic;
         this.uninitialized = uninitialized;
         this.exceptions = Collections.emptyList();
-        this.guards = new ArrayList<>();
     }
 
     @Override
@@ -81,12 +81,15 @@
         if (!getGuards().isEmpty()) {
             return true;
         }
+        if (!getAssumptions().isEmpty()) {
+            return true;
+        }
         for (ActualParameter parameter : getParameters()) {
-            NodeChildData field = getNode().findChild(parameter.getSpecification().getName());
-            if (field == null) {
+            NodeChildData child = getNode().findChild(parameter.getSpecification().getName());
+            if (child == null) {
                 continue;
             }
-            ExecutableTypeData type = field.getNodeData().findExecutableType(parameter.getTypeSystemType());
+            ExecutableTypeData type = child.findExecutableType(context, parameter.getTypeSystemType());
             if (type.hasUnexpectedValue(context)) {
                 return true;
             }
@@ -175,6 +178,14 @@
         return useSpecializationsForGeneric;
     }
 
+    public List<String> getAssumptions() {
+        return assumptions;
+    }
+
+    void setAssumptions(List<String> assumptions) {
+        this.assumptions = assumptions;
+    }
+
     public SpecializationData findNextSpecialization() {
         List<SpecializationData> specializations = node.getSpecializations();
         for (int i = 0; i < specializations.size() - 1; i++) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationMethodParser.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationMethodParser.java	Thu Apr 25 16:53:29 2013 +0200
@@ -53,7 +53,7 @@
         return Specialization.class;
     }
 
-    private static SpecializationData parseSpecialization(TemplateMethod method) {
+    private SpecializationData parseSpecialization(TemplateMethod method) {
         int order = Utils.getAnnotationValue(Integer.class, method.getMarkerAnnotation(), "order");
         if (order < 0 && order != Specialization.DEFAULT_ORDER) {
             method.addError("Invalid order attribute %d. The value must be >= 0 or the default value.");
@@ -82,7 +82,15 @@
         List<String> guardDefs = Utils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards");
         specialization.setGuardDefinitions(guardDefs);
 
+        List<String> assumptionDefs = Utils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "assumptions");
+        specialization.setAssumptions(assumptionDefs);
+
+        for (String assumption : assumptionDefs) {
+            if (!getNode().getAssumptions().contains(assumption)) {
+                specialization.addError("Undeclared assumption '%s' used. Use @NodeAssumptions to declare them.", assumption);
+            }
+        }
+
         return specialization;
     }
-
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MessageContainer.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MessageContainer.java	Thu Apr 25 16:53:29 2013 +0200
@@ -34,11 +34,15 @@
     private final List<Message> messages = new ArrayList<>();
 
     public final void addWarning(String text, Object... params) {
-        getMessages().add(new Message(this, String.format(text, params), Kind.WARNING));
+        getMessages().add(new Message(null, this, String.format(text, params), Kind.WARNING));
     }
 
     public final void addError(String text, Object... params) {
-        getMessages().add(new Message(this, String.format(text, params), Kind.ERROR));
+        addError(null, text, params);
+    }
+
+    public final void addError(AnnotationValue value, String text, Object... params) {
+        getMessages().add(new Message(value, this, String.format(text, params), Kind.ERROR));
     }
 
     protected List<MessageContainer> findChildContainers() {
@@ -150,15 +154,21 @@
     public static final class Message {
 
         private final MessageContainer originalContainer;
+        private final AnnotationValue annotationValue;
         private final String text;
         private final Kind kind;
 
-        public Message(MessageContainer originalContainer, String text, Kind kind) {
+        public Message(AnnotationValue annotationValue, MessageContainer originalContainer, String text, Kind kind) {
+            this.annotationValue = annotationValue;
             this.originalContainer = originalContainer;
             this.text = text;
             this.kind = kind;
         }
 
+        public AnnotationValue getAnnotationValue() {
+            return annotationValue;
+        }
+
         public MessageContainer getOriginalContainer() {
             return originalContainer;
         }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java	Thu Apr 25 16:53:29 2013 +0200
@@ -206,6 +206,17 @@
         return types;
     }
 
+    public List<ActualParameter> getSignatureParameters() {
+        List<ActualParameter> types = new ArrayList<>();
+        for (ActualParameter parameter : getParameters()) {
+            if (!parameter.getSpecification().isSignature()) {
+                continue;
+            }
+            types.add(parameter);
+        }
+        return types;
+    }
+
     @Override
     public int compareTo(TemplateMethod o) {
         if (this == o) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java	Thu Apr 25 16:53:29 2013 +0200
@@ -79,15 +79,10 @@
             String name = typeName(typeSystem);
             CodeTypeElement clazz = createClass(typeSystem, modifiers(PUBLIC), name, typeSystem.getTemplateType().asType(), false);
 
-            clazz.getImplements().add(getContext().getTruffleTypes().getTypeConversion());
-
             clazz.add(createConstructorUsingFields(modifiers(PROTECTED), clazz));
             CodeVariableElement singleton = createSingleton(clazz);
             clazz.add(singleton);
 
-            clazz.add(createGetTopType(typeSystem));
-            clazz.add(createConvertTo(typeSystem, singleton));
-
             for (TypeData type : typeSystem.getTypes()) {
                 if (!type.isGeneric()) {
                     CodeExecutableElement isType = createIsTypeMethod(type);
@@ -125,58 +120,6 @@
             return new ArrayList<>(sourceTypes);
         }
 
-        private CodeExecutableElement createConvertTo(TypeSystemData typeSystem, CodeVariableElement singleton) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(Object.class), "convertTo");
-            method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "targetType"));
-            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), "value"));
-
-            CodeTreeBuilder builder = method.createBuilder();
-
-            boolean first = true;
-            for (TypeData type : typeSystem.getTypes()) {
-                if (first) {
-                    builder.startIf();
-                    first = false;
-                } else {
-                    builder.startElseIf();
-                }
-                builder.string("targetType").string(" == ").typeLiteral(type.getBoxedType());
-                builder.end(); // if
-                builder.startBlock();
-
-                builder.startReturn();
-
-                if (typeEquals(type.getBoxedType(), getContext().getType(Object.class))) {
-                    builder.string("value");
-                } else {
-                    builder.string(singleton.getName()).string(".").startCall(asTypeMethodName(type)).string("value").end();
-                }
-
-                builder.end(); // return
-
-                builder.end(); // block
-            }
-
-            builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end();
-
-            return method;
-        }
-
-        private CodeExecutableElement createGetTopType(TypeSystemData typeSystem) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(Class.class), "getTopType");
-
-            CodeTreeBuilder builder = method.createBuilder();
-            builder.startReturn();
-            if (!typeSystem.getTypes().isEmpty()) {
-                builder.typeLiteral(typeSystem.getTypes().get(0).getBoxedType());
-            } else {
-                builder.null_();
-            }
-            builder.end(); // return
-
-            return method;
-        }
-
         private static String typeName(TypeSystemData typeSystem) {
             String name = getSimpleName(typeSystem.getTemplateType());
             return name + "Gen";
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/AbstractTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/AbstractTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -62,4 +62,5 @@
         System.setErr(origErr);
         Assert.assertEquals(repeat(concat(expectedOutput), REPEATS), new String(out.toByteArray()));
     }
+
 }
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/AddTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/AddTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -28,25 +28,25 @@
 public class AddTest extends AbstractTest {
 
     private static String[] INPUT = new String[] {
-"function main {  ",
-"  print 3 + 4;  ",
-"  print 3 + \"4\";  ",
-"  print \"3\" + 4;  ",
-"  print \"3\" + \"4\";  ",
-"  print 3 + 4000000000000;  ",
-"  print 3000000000000 + 4;  ",
-"  print 3000000000000 + 4000000000000;  ",
-"}  ",
+        "function main {  ",
+        "  print 3 + 4;  ",
+        "  print 3 + \"4\";  ",
+        "  print \"3\" + 4;  ",
+        "  print \"3\" + \"4\";  ",
+        "  print 3 + 4000000000000;  ",
+        "  print 3000000000000 + 4;  ",
+        "  print 3000000000000 + 4000000000000;  ",
+        "}  ",
     };
 
     private static String[] OUTPUT = new String[] {
-"7",
-"34",
-"34",
-"34",
-"4000000000003",
-"3000000000004",
-"7000000000000",
+        "7",
+        "34",
+        "34",
+        "34",
+        "4000000000003",
+        "3000000000004",
+        "7000000000000",
     };
 
     @Test
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/ComparisonTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/ComparisonTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -28,25 +28,25 @@
 public class ComparisonTest extends AbstractTest {
 
     private static String[] INPUT = new String[] {
-"function main {  ",
-"  print 4 < 20;  ",
-"  print 4 < \"20\";  ",
-"  print \"4\" < 20;  ",
-"  print \"4\" < \"20\";  ",
-"  print 4 < 20000000000000;  ",
-"  print 4000000000000 < 20;  ",
-"  print 4000000000000 < 20000000000000;  ",
-"}  ",
+        "function main {  ",
+        "  print 4 < 20;  ",
+        "  print 4 < \"20\";  ",
+        "  print \"4\" < 20;  ",
+        "  print \"4\" < \"20\";  ",
+        "  print 4 < 20000000000000;  ",
+        "  print 4000000000000 < 20;  ",
+        "  print 4000000000000 < 20000000000000;  ",
+        "}  ",
     };
 
     private static String[] OUTPUT = new String[] {
-"true",
-"false",
-"false",
-"false",
-"true",
-"false",
-"true",
+        "true",
+        "false",
+        "false",
+        "false",
+        "true",
+        "false",
+        "true",
     };
 
     @Test
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/DivTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/DivTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -28,19 +28,19 @@
 public class DivTest extends AbstractTest {
 
     private static String[] INPUT = new String[] {
-"function main {  ",
-"  print 4 / 2;  ",
-"  print 4 / 4000000000000;  ",
-"  print 3000000000000 / 3;  ",
-"  print 3000000000000 / 3000000000000;  ",
-"}  ",
+        "function main {  ",
+        "  print 4 / 2;  ",
+        "  print 4 / 4000000000000;  ",
+        "  print 3000000000000 / 3;  ",
+        "  print 3000000000000 / 3000000000000;  ",
+        "}  ",
     };
 
     private static String[] OUTPUT = new String[] {
-"2",
-"0",
-"1000000000000",
-"1",
+        "2",
+        "0",
+        "1000000000000",
+        "1",
     };
 
     @Test
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/LoopPrintTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/LoopPrintTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -28,17 +28,17 @@
 public class LoopPrintTest extends AbstractTest {
 
     private static String[] INPUT = new String[] {
-"function main {  ",
-"  i = 0;  ",
-"  while (i < 1000) {  ",
-"    i = i + 1;  ",
-"  }  ",
-"  print i;  ",
-"}  ",
+        "function main {  ",
+        "  i = 0;  ",
+        "  while (i < 1000) {  ",
+        "    i = i + 1;  ",
+        "  }  ",
+        "  print i;  ",
+        "}  ",
     };
 
     private static String[] OUTPUT = new String[] {
-"1000",
+        "1000",
     };
 
     @Test
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/LoopTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/LoopTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -28,17 +28,17 @@
 public class LoopTest extends AbstractTest {
 
     private static String[] INPUT = new String[] {
-"function main {  ",
-"  i = 0;  ",
-"  while (i < 1000) {  ",
-"    i = i + 1;  ",
-"  }  ",
-"  return i;  ",
-"}  ",
+        "function main {  ",
+        "  i = 0;  ",
+        "  while (i < 1000) {  ",
+        "    i = i + 1;  ",
+        "  }  ",
+        "  return i;  ",
+        "}  ",
     };
 
     private static String[] OUTPUT = new String[] {
-"1000",
+        "1000",
     };
 
     @Test
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/MulTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/MulTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -28,19 +28,19 @@
 public class MulTest extends AbstractTest {
 
     private static String[] INPUT = new String[] {
-"function main {  ",
-"  print 3 * 4;  ",
-"  print 3 * 4000000000000;  ",
-"  print 3000000000000 * 4;  ",
-"  print 3000000000000 * 4000000000000;  ",
-"}  ",
+        "function main {  ",
+        "  print 3 * 4;  ",
+        "  print 3 * 4000000000000;  ",
+        "  print 3000000000000 * 4;  ",
+        "  print 3000000000000 * 4000000000000;  ",
+        "}  ",
     };
 
     private static String[] OUTPUT = new String[] {
-"12",
-"12000000000000",
-"12000000000000",
-"12000000000000000000000000",
+        "12",
+        "12000000000000",
+        "12000000000000",
+        "12000000000000000000000000",
     };
 
     @Test
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SubTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SubTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -28,19 +28,19 @@
 public class SubTest extends AbstractTest {
 
     private static String[] INPUT = new String[] {
-"function main {  ",
-"  print 3 - 4;  ",
-"  print 3 - 4000000000000;  ",
-"  print 3000000000000 - 4;  ",
-"  print 3000000000000 - 4000000000000;  ",
-"}  ",
+        "function main {  ",
+        "  print 3 - 4;  ",
+        "  print 3 - 4000000000000;  ",
+        "  print 3000000000000 - 4;  ",
+        "  print 3000000000000 - 4000000000000;  ",
+        "}  ",
     };
 
     private static String[] OUTPUT = new String[] {
-"-1",
-"-3999999999997",
-"2999999999996",
-"-1000000000000",
+        "-1",
+        "-3999999999997",
+        "2999999999996",
+        "-1000000000000",
     };
 
     @Test
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SumTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SumTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -28,19 +28,19 @@
 public class SumTest extends AbstractTest {
 
     private static String[] INPUT = new String[] {
-"function main {  ",
-"  i = 0;  ",
-"  sum = 0;  ",
-"  while (i < 100000) {  ",
-"    sum = sum + 1000000;  ",
-"    i = i + 1;  ",
-"  }  ",
-"  return sum;  ",
-"}  ",
+        "function main {  ",
+        "  i = 0;  ",
+        "  sum = 0;  ",
+        "  while (i < 100000) {  ",
+        "    sum = sum + 1000000;  ",
+        "    i = i + 1;  ",
+        "  }  ",
+        "  return sum;  ",
+        "}  ",
     };
 
     private static String[] OUTPUT = new String[] {
-"100000000000",
+        "100000000000",
     };
 
     @Test
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/TernaryTest.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/TernaryTest.java	Thu Apr 25 16:53:29 2013 +0200
@@ -28,13 +28,13 @@
 public class TernaryTest extends AbstractTest {
 
     private static String[] INPUT = new String[] {
-"function main {  " +
-"  print #(1 < 2) ? 1 : 2;" +
-"  print #(2 < 1) ? 100000000000000 : 1;  ",
-"  print #(1 < 2) ? 100000000000000 : 1;  ",
-"  print #(2 < 1) ? \"wrong\" : \"true\";",
-"  print #(2 < 1) ? \"wrong\" : 1;",
-"}  ",
+        "function main {  " +
+        "  print #(1 < 2) ? 1 : 2;" +
+        "  print #(2 < 1) ? 100000000000000 : 1;  ",
+        "  print #(1 < 2) ? 100000000000000 : 1;  ",
+        "  print #(2 < 1) ? \"wrong\" : \"true\";",
+        "  print #(2 < 1) ? \"wrong\" : 1;",
+        "}  ",
     };
 
     private static String[] OUTPUT = new String[] {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java	Thu Apr 25 16:53:29 2013 +0200
@@ -51,7 +51,7 @@
     }
 
     public void startFunction() {
-        frameDescriptor = new FrameDescriptor(SLTypesGen.SLTYPES);
+        frameDescriptor = new FrameDescriptor();
     }
 
     public void createFunction(StatementNode body, String name) {
@@ -59,7 +59,7 @@
     }
 
     public TypedNode createLocal(String name) {
-        return ReadLocalNodeFactory.create(frameDescriptor.findOrAddFrameSlot(name));
+        return ReadLocalNodeFactory.create(frameDescriptor.findOrAddFrameSlot(name, int.class));
     }
 
     public TypedNode createStringLiteral(String value) {
@@ -67,7 +67,7 @@
     }
 
     public StatementNode createAssignment(String name, TypedNode right) {
-        return WriteLocalNodeFactory.create(frameDescriptor.findOrAddFrameSlot(name), right);
+        return WriteLocalNodeFactory.create(frameDescriptor.findOrAddFrameSlot(name, int.class), right);
     }
 
     public StatementNode createPrint(List<TypedNode> expressions) {
@@ -123,7 +123,7 @@
     }
 
     public StatementNode createReturn(TypedNode value) {
-        FrameSlot slot = frameDescriptor.findOrAddFrameSlot("<retval>");
+        FrameSlot slot = frameDescriptor.findOrAddFrameSlot("<retval>", int.class);
         if (returnValue == null) {
             returnValue = ReadLocalNodeFactory.create(slot);
         }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArithmeticNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -24,8 +24,8 @@
 
 import java.math.*;
 
+import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.codegen.*;
-import com.oracle.truffle.api.intrinsics.*;
 
 public abstract class ArithmeticNode extends BinaryNode {
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FrameSlotNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FrameSlotNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -24,20 +24,12 @@
 
 import com.oracle.truffle.api.frame.*;
 
-public abstract class FrameSlotNode extends TypedNode implements FrameSlotTypeListener {
+public abstract class FrameSlotNode extends TypedNode {
 
     protected final FrameSlot slot;
 
     public FrameSlotNode(FrameSlot slot) {
         this.slot = slot;
-        slot.registerOneShotTypeListener(this);
-    }
-
-    @Override
-    public void typeChanged(FrameSlot changedSlot, Class<?> oldType) {
-        if (getParent() != null) {
-            replace(specialize(changedSlot.getType()));
-        }
     }
 
     protected abstract FrameSlotNode specialize(Class<?> clazz);
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadLocalNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadLocalNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.truffle.sl.nodes;
 
-import java.math.*;
-
 import com.oracle.truffle.api.codegen.*;
 import com.oracle.truffle.api.frame.*;
 
@@ -37,29 +35,23 @@
         this(specialized.slot);
     }
 
-    @Specialization
-    public int doInteger(VirtualFrame frame) {
+    @Specialization(rewriteOn = {FrameSlotTypeException.class})
+    public int doInteger(VirtualFrame frame) throws FrameSlotTypeException {
         return frame.getInt(slot);
     }
 
-    @Specialization
-    public BigInteger doBigInteger(VirtualFrame frame) {
-        return (BigInteger) frame.getObject(slot);
-    }
-
-    @Specialization
-    public boolean doBoolean(VirtualFrame frame) {
+    @Specialization(rewriteOn = {FrameSlotTypeException.class})
+    public boolean doBoolean(VirtualFrame frame) throws FrameSlotTypeException {
         return frame.getBoolean(slot);
     }
 
-    @Specialization
-    public String doString(VirtualFrame frame) {
-        return (String) frame.getObject(slot);
-    }
-
-    @Generic
-    public Object doGeneric(VirtualFrame frame) {
-        return frame.getObject(slot);
+    @Generic(useSpecializations = false)
+    public Object doObject(VirtualFrame frame) {
+        try {
+            return frame.getObject(slot);
+        } catch (FrameSlotTypeException e) {
+            throw new RuntimeException("uninitialized variable " + slot.getIdentifier());
+        }
     }
 
     @Override
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WriteLocalNode.java	Mon Apr 22 18:30:33 2013 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WriteLocalNode.java	Thu Apr 25 16:53:29 2013 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.truffle.sl.nodes;
 
-import java.math.*;
-
 import com.oracle.truffle.api.codegen.*;
 import com.oracle.truffle.api.frame.*;
 
@@ -38,42 +36,28 @@
         this(node.slot);
     }
 
-    @Specialization
-    public int write(VirtualFrame frame, int right) {
+    @Specialization(rewriteOn = FrameSlotTypeException.class)
+    public int write(VirtualFrame frame, int right) throws FrameSlotTypeException {
         frame.setInt(slot, right);
         return right;
     }
 
-    @Specialization
-    public BigInteger write(VirtualFrame frame, BigInteger right) {
-        frame.setObject(slot, right);
-        return right;
-    }
-
-    @Specialization
-    public boolean write(VirtualFrame frame, boolean right) {
+    @Specialization(rewriteOn = FrameSlotTypeException.class)
+    public boolean write(VirtualFrame frame, boolean right) throws FrameSlotTypeException {
         frame.setBoolean(slot, right);
         return right;
     }
 
-    @Specialization
-    public String write(VirtualFrame frame, String right) {
-        frame.setObject(slot, right);
-        return right;
-    }
-
     @Generic(useSpecializations = false)
     public Object writeGeneric(VirtualFrame frame, Object right) {
-        frame.setObject(slot, right);
+        try {
+            frame.setObject(slot, right);
+        } catch (FrameSlotTypeException e) {
+            FrameUtil.setObjectSafe(frame, slot, right);
+        }
         return right;
     }
 
-    @SpecializationListener
-    protected void onSpecialize(VirtualFrame frame, Object value) {
-        slot.setType(value.getClass());
-        frame.updateToLatestVersion();
-    }
-
     @Override
     protected FrameSlotNode specialize(Class<?> clazz) {
         return WriteLocalNodeFactory.createSpecialized(this, clazz);
--- a/mx/commands.py	Mon Apr 22 18:30:33 2013 +0200
+++ b/mx/commands.py	Thu Apr 25 16:53:29 2013 +0200
@@ -812,6 +812,7 @@
     testfile = os.environ.get('MX_TESTFILE', None)
     if testfile is None:
         (_, testfile) = tempfile.mkstemp(".testclasses", "graal")
+        os.close(_)
 
     def harness(projectscp, vmArgs):
         if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource):
--- a/mxtool/mx.py	Mon Apr 22 18:30:33 2013 +0200
+++ b/mxtool/mx.py	Thu Apr 25 16:53:29 2013 +0200
@@ -980,11 +980,14 @@
     for arg in args:
         assert isinstance(arg, types.StringTypes), 'argument is not a string: ' + str(arg)
 
+    if env is None:
+        env = os.environ
+        
     if _opts.verbose:
         if _opts.very_verbose:
             log('Environment variables:')
-            for key in sorted(os.environ.keys()):
-                log('    ' + key + '=' + os.environ[key])
+            for key in sorted(env.keys()):
+                log('    ' + key + '=' + env[key])
         log(' '.join(args))
 
     if timeout is None and _opts.ptimeout != 0:
--- a/src/os/windows/vm/os_windows.cpp	Mon Apr 22 18:30:33 2013 +0200
+++ b/src/os/windows/vm/os_windows.cpp	Thu Apr 25 16:53:29 2013 +0200
@@ -2179,7 +2179,7 @@
       ctx->Rax = (DWORD64)min_jlong;     // result
     } else {
       ctx->Rip = (DWORD64)pc + 2;        // idiv reg, reg  is 2 bytes
-      ctx->Rax = (DWORD64)min_jint;      // result
+      ctx->Rax = (DWORD64)min_jlong;     // result
     }
     ctx->Rdx = (DWORD64)0;             // remainder
     // Continue the execution