changeset 19291:f4792a544170

Truffle-DSL: implement new assumptions semantics.
author Christian Humer <christian.humer@gmail.com>
date Wed, 11 Feb 2015 12:13:44 +0100
parents bf166845c7d8
children 906367e494ca
files graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AssumptionExpression.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java
diffstat 13 files changed, 460 insertions(+), 533 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.java	Wed Feb 11 12:13:44 2015 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.java	Wed Feb 11 12:13:44 2015 +0100
@@ -22,120 +22,236 @@
  */
 package com.oracle.truffle.api.dsl.test;
 
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+
 import org.junit.*;
 
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.DerivedAssumptionNodeFactory;
-import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.DerivedAssumptionRedeclaredNodeFactory;
-import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.MultipleAssumptionsNodeFactory;
-import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.SingleAssumptionNodeFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.AssumptionArrayTestFactory;
+import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.CacheAssumptionTestFactory;
+import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.FieldTestFactory;
+import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.MethodTestFactory;
+import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.NodeFieldTest2Factory;
+import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.StaticFieldTestFactory;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
 
 public class AssumptionsTest {
 
     @Test
-    public void testSingleAssumption() {
+    public void testField() {
+        CallTarget root = createCallTarget(FieldTestFactory.getInstance());
+        FieldTest node = getNode(root);
+        assertEquals(42, root.call(42));
+        assertEquals(42, root.call(42));
+        node.field.invalidate();
+        try {
+            root.call(45);
+            fail();
+        } catch (UnsupportedSpecializationException e) {
+        }
+    }
+
+    @NodeChild
+    static class FieldTest extends ValueNode {
+
+        protected final Assumption field = Truffle.getRuntime().createAssumption();
+
+        @Specialization(assumptions = "field")
+        static int do1(int value) {
+            return value;
+        }
+    }
+
+    @Test
+    public void testNodeField() {
         Assumption assumption = Truffle.getRuntime().createAssumption();
-        TestRootNode<?> root = TestHelper.createRoot(SingleAssumptionNodeFactory.getInstance(), assumption);
+        CallTarget root = createCallTarget(NodeFieldTest2Factory.getInstance(), assumption);
+        assertEquals(42, root.call(42));
+        assertEquals(42, root.call(42));
+        assumption.invalidate();
+        try {
+            root.call(45);
+            fail();
+        } catch (UnsupportedSpecializationException e) {
+        }
+    }
+
+    @NodeChild
+    @NodeField(name = "field", type = Assumption.class)
+    static class NodeFieldTest2 extends ValueNode {
 
-        Assert.assertEquals(42, TestHelper.executeWith(root));
-        assumption.invalidate();
-        Assert.assertEquals("42", TestHelper.executeWith(root));
+        @Specialization(assumptions = "field")
+        static int do1(int value) {
+            return value;
+        }
+    }
+
+    @Test
+    public void testStaticField() {
+        CallTarget root = createCallTarget(StaticFieldTestFactory.getInstance());
+        assertEquals(42, root.call(42));
+        assertEquals(42, root.call(42));
+        StaticFieldTest.FIELD.invalidate();
+        try {
+            root.call(45);
+            fail();
+        } catch (UnsupportedSpecializationException e) {
+        }
+    }
+
+    @NodeChild
+    static class StaticFieldTest extends ValueNode {
+
+        static final Assumption FIELD = Truffle.getRuntime().createAssumption();
+
+        @Specialization(assumptions = "FIELD")
+        static int do1(int value) {
+            return value;
+        }
+    }
+
+    @Test
+    public void testMethod() {
+        CallTarget root = createCallTarget(MethodTestFactory.getInstance());
+        MethodTest node = getNode(root);
+        assertEquals(42, root.call(42));
+        assertEquals(42, root.call(42));
+        node.hiddenAssumption.invalidate();
+        try {
+            root.call(45);
+            fail();
+        } catch (UnsupportedSpecializationException e) {
+        }
     }
 
-    @NodeAssumptions("assumption")
-    abstract static class SingleAssumptionNode extends ValueNode {
+    @NodeChild
+    static class MethodTest extends ValueNode {
 
-        @Specialization(assumptions = "assumption")
-        int do2() {
-            return 42;
+        private final Assumption hiddenAssumption = Truffle.getRuntime().createAssumption();
+
+        @Specialization(assumptions = "getAssumption()")
+        static int do1(int value) {
+            return value;
         }
 
-        @Fallback
-        Object doFallBack() {
-            return "42";
+        Assumption getAssumption() {
+            return hiddenAssumption;
+        }
+    }
+
+    @Test
+    public void testCacheAssumption() {
+        CallTarget root = createCallTarget(CacheAssumptionTestFactory.getInstance());
+        CacheAssumptionTest node = getNode(root);
+        assertEquals("do1", root.call(42));
+        assertEquals("do1", root.call(43));
+        assertEquals("do1", root.call(44));
+        node.assumptions.get(42).invalidate();
+        node.assumptions.put(42, null); // clear 42
+        node.assumptions.get(43).invalidate();
+        node.assumptions.get(44).invalidate();
+        assertEquals("do1", root.call(42)); // recreates 42
+        assertEquals("do2", root.call(43)); // invalid 43 -> remove -> insert do2
+        assertEquals("do2", root.call(46)); // no more lines can be created.
+    }
+
+    @Test
+    public void testCacheAssumptionLimit() {
+        CallTarget root = createCallTarget(CacheAssumptionTestFactory.getInstance());
+        assertEquals("do1", root.call(42));
+        assertEquals("do1", root.call(43));
+        assertEquals("do1", root.call(44));
+        assertEquals("do2", root.call(45));
+        assertEquals("do1", root.call(43));
+        assertEquals("do1", root.call(44));
+    }
+
+    @NodeChild
+    @SuppressWarnings("unused")
+    static class CacheAssumptionTest extends ValueNode {
+
+        private final Map<Integer, Assumption> assumptions = new HashMap<>();
+
+        @Specialization(guards = "value == cachedValue", assumptions = "getAssumption(cachedValue)")
+        static String do1(int value, @Cached("value") int cachedValue) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+
+        Assumption getAssumption(int value) {
+            Assumption assumption = assumptions.get(value);
+            if (assumption == null) {
+                assumption = Truffle.getRuntime().createAssumption();
+                assumptions.put(value, assumption);
+            }
+            return assumption;
+        }
+    }
+
+    @Test
+    public void testAssumptionArrays() {
+        CallTarget root = createCallTarget(AssumptionArrayTestFactory.getInstance());
+        AssumptionArrayTest node = getNode(root);
+
+        Assumption a1 = Truffle.getRuntime().createAssumption();
+        Assumption a2 = Truffle.getRuntime().createAssumption();
+
+        node.assumptions = new Assumption[]{a1, a2};
+
+        assertEquals("do1", root.call(42));
+
+        a2.invalidate();
+
+        assertEquals("do2", root.call(42));
+    }
+
+    @NodeChild
+    @SuppressWarnings("unused")
+    static class AssumptionArrayTest extends ValueNode {
+
+        Assumption[] assumptions;
+
+        @Specialization(assumptions = "assumptions")
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
         }
 
     }
 
-    @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("41", TestHelper.executeWith(root));
-        assumption1.invalidate();
-        Assert.assertEquals("42", 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 "41";
-        }
-
-        @Fallback
-        Object doFallBack() {
-            return "42";
+    @NodeChild
+    static class ErrorIncompatibleReturnType extends ValueNode {
+        @ExpectError("Incompatible return type int. Assumptions must be assignable to Assumption or Assumption[].")
+        @Specialization(assumptions = "3")
+        static int do1(int value) {
+            return value;
         }
     }
 
-    @Test
-    public void testDerivedAssumption() {
-        Assumption additionalAssumption = Truffle.getRuntime().createAssumption();
-        Assumption assumption = Truffle.getRuntime().createAssumption();
-        TestRootNode<?> root = TestHelper.createRoot(DerivedAssumptionNodeFactory.getInstance(), assumption, additionalAssumption);
+    @NodeChild
+    static class ErrorBoundDynamicValue extends ValueNode {
 
-        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(assumptions = "additionalAssumption")
-        int doIntDerived() {
-            return 43;
+        @ExpectError("Assumption expressions must not bind dynamic parameter values.")
+        @Specialization(assumptions = "createAssumption(value)")
+        static int do1(int value) {
+            return value;
         }
 
-    }
-
-    @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(assumptions = "additionalAssumption")
-        int doIntDerived() {
-            return 43;
+        Assumption createAssumption(int value) {
+            return Truffle.getRuntime().createAssumption(String.valueOf(value));
         }
-
     }
 
 }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java	Wed Feb 11 12:13:44 2015 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java	Wed Feb 11 12:13:44 2015 +0100
@@ -142,7 +142,6 @@
             return a > 0;
         }
 
-        @Implies("isGreaterZero(a)")
         static boolean isOne(int a) {
             return a == 1;
         }
@@ -190,7 +189,6 @@
     @NodeChild("a")
     abstract static class Contains4 extends ValueNode {
 
-        @Implies("isGreaterEqualZero")
         static boolean isOne(int a) {
             return a == 1;
         }
@@ -433,7 +431,6 @@
 
     abstract static class ContainsGuard5 extends ValueNode {
 
-        @Implies("g2")
         boolean g1() {
             return true;
         }
@@ -455,7 +452,6 @@
 
     abstract static class ContainsGuard6 extends ValueNode {
 
-        @Implies("!g2")
         boolean g1() {
             return true;
         }
@@ -496,48 +492,6 @@
         }
     }
 
-    @NodeAssumptions("a1")
-    abstract static class ContainsAssumption1 extends ValueNode {
-
-        @Specialization(assumptions = "a1")
-        Object f0() {
-            return null;
-        }
-
-        @Specialization(contains = "f0")
-        Object f1() {
-            return null;
-        }
-    }
-
-    @NodeAssumptions({"a1", "a2"})
-    abstract static class ContainsAssumption4 extends ValueNode {
-
-        @Specialization(assumptions = {"a1", "a2"})
-        Object f0() {
-            return null;
-        }
-
-        @Specialization(contains = "f0", assumptions = "a1")
-        Object f1() {
-            return null;
-        }
-    }
-
-    @NodeAssumptions({"a1", "a2"})
-    abstract static class ContainsAssumption5 extends ValueNode {
-
-        @Specialization(assumptions = {"a2", "a1"})
-        Object f0() {
-            return null;
-        }
-
-        @Specialization(contains = "f0", assumptions = "a1")
-        Object f1() {
-            return null;
-        }
-    }
-
     abstract static class ContainsThrowable1 extends ValueNode {
 
         @Specialization(rewriteOn = RuntimeException.class)
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java	Wed Feb 11 12:13:44 2015 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java	Wed Feb 11 12:13:44 2015 +0100
@@ -319,7 +319,6 @@
 
     @TypeSystemReference(ExecuteMethodTypes.class)
     @NodeChild(value = "a", type = ChildNoFrame.class)
-    @ExpectError("Invalid inconsistent frame types [MaterializedFrame, void] found for the declared execute methods.%")
     abstract static class ExecuteWithFrameError5 extends Node {
 
         abstract Object execute();
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java	Wed Feb 11 12:13:44 2015 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java	Wed Feb 11 12:13:44 2015 +0100
@@ -250,99 +250,6 @@
 
     }
 
-    @NodeAssumptions({"a1"})
-    static class ReachabilityAssumption1 extends ValueNode {
-
-        @Specialization(assumptions = "a1")
-        int do2() {
-            return 1;
-        }
-
-        @Specialization
-        int do1() {
-            return 2;
-        }
-
-    }
-
-    @NodeAssumptions({"a1"})
-    static class ReachabilityAssumption2 extends ValueNode {
-
-        @Specialization(assumptions = "a1")
-        int do2() {
-            return 1;
-        }
-
-        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
-        @Specialization(assumptions = "a1")
-        int do1() {
-            return 2;
-        }
-
-    }
-
-    @NodeAssumptions({"a1", "a2"})
-    static class ReachabilityAssumption3 extends ValueNode {
-
-        @Specialization(assumptions = {"a1", "a2"})
-        int do2() {
-            return 1;
-        }
-
-        @Specialization(assumptions = "a1")
-        int do1() {
-            return 2;
-        }
-
-    }
-
-    @NodeAssumptions({"a1", "a2"})
-    static class ReachabilityAssumption4 extends ValueNode {
-
-        @Specialization(assumptions = "a1")
-        int do2() {
-            return 1;
-        }
-
-        @Specialization(assumptions = "a2")
-        int do1() {
-            return 2;
-        }
-
-    }
-
-    @NodeAssumptions({"a1", "a2"})
-    static class ReachabilityAssumption5 extends ValueNode {
-
-        @Specialization
-        int do2() {
-            return 1;
-        }
-
-        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
-        @Specialization(assumptions = "a2")
-        int do1() {
-            return 2;
-        }
-
-    }
-
-    @NodeAssumptions({"a1", "a2"})
-    static class ReachabilityAssumption6 extends ValueNode {
-
-        @Specialization(assumptions = {"a1"})
-        int do2() {
-            return 1;
-        }
-
-        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
-        @Specialization(assumptions = {"a1", "a2"})
-        int do1() {
-            return 2;
-        }
-
-    }
-
     static class ReachabilityThrowable1 extends ValueNode {
 
         @Specialization(rewriteOn = RuntimeException.class)
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java	Wed Feb 11 12:13:44 2015 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java	Wed Feb 11 12:13:44 2015 +0100
@@ -28,9 +28,6 @@
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.dsl.test.SpecializationGroupingTestFactory.TestElseConnectionBug1Factory;
 import com.oracle.truffle.api.dsl.test.SpecializationGroupingTestFactory.TestElseConnectionBug2Factory;
-import com.oracle.truffle.api.dsl.test.SpecializationGroupingTestFactory.TestGroupingFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.SimpleTypes;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
@@ -43,119 +40,6 @@
 public class SpecializationGroupingTest {
 
     @Test
-    public void testGrouping() {
-        MockAssumption a1 = new MockAssumption(true);
-        MockAssumption a3 = new MockAssumption(true);
-
-        TestRootNode<TestGrouping> root = TestHelper.createRoot(TestGroupingFactory.getInstance(), a1, a3);
-
-        SimpleTypes.intCast = 0;
-        SimpleTypes.intCheck = 0;
-        TestGrouping.true1 = 0;
-        TestGrouping.false1 = 0;
-        TestGrouping.true2 = 0;
-        TestGrouping.false2 = 0;
-        TestGrouping.true3 = 0;
-
-        Assert.assertEquals(42, TestHelper.executeWith(root, 21, 21));
-        Assert.assertEquals(5, TestGrouping.true1);
-        Assert.assertEquals(0, TestGrouping.false1);
-        Assert.assertEquals(5, TestGrouping.true2);
-        Assert.assertEquals(5, TestGrouping.false2);
-        Assert.assertEquals(5, TestGrouping.true3);
-        Assert.assertEquals(10, SimpleTypes.intCheck);
-        Assert.assertEquals(8, SimpleTypes.intCast);
-        Assert.assertEquals(4, a1.checked);
-        Assert.assertEquals(4, a3.checked);
-
-        Assert.assertEquals(42, TestHelper.executeWith(root, 21, 21));
-        Assert.assertEquals(6, TestGrouping.true1);
-        Assert.assertEquals(0, TestGrouping.false1);
-        Assert.assertEquals(6, TestGrouping.true2);
-        Assert.assertEquals(6, TestGrouping.false2);
-        Assert.assertEquals(6, TestGrouping.true3);
-
-        Assert.assertEquals(5, a1.checked);
-        Assert.assertEquals(5, a3.checked);
-        Assert.assertEquals(10, SimpleTypes.intCheck);
-        Assert.assertEquals(8, SimpleTypes.intCast);
-
-    }
-
-    @SuppressWarnings("unused")
-    @NodeChildren({@NodeChild, @NodeChild})
-    @NodeAssumptions({"a1", "a3"})
-    public abstract static class TestGrouping extends ValueNode {
-
-        private static int true1;
-        private static int false1;
-        private static int true2;
-        private static int false2;
-        private static int true3;
-
-        protected boolean true1(int value) {
-            true1++;
-            return true;
-        }
-
-        protected boolean false1(int value, int value2) {
-            false1++;
-            return false;
-        }
-
-        protected boolean true2(int value) {
-            true2++;
-            return true;
-        }
-
-        protected boolean false2(int value) {
-            false2++;
-            return false;
-        }
-
-        protected boolean true3(int value) {
-            true3++;
-            return true;
-        }
-
-        @Specialization
-        public int fail(int value1, String value2) {
-            throw new AssertionError();
-        }
-
-        @Specialization(guards = {"true1(value1)", "true2(value1)", "!false2(value1)", "true3(value1)"}, assumptions = {"a1", "a3"}, rewriteOn = RuntimeException.class)
-        public int throwRewrite(int value1, int value2) {
-            throw new RuntimeException();
-        }
-
-        @Specialization(guards = {"true1(value1)", "true2(value1)", "!false2(value1)", "true3(value1)"}, contains = "throwRewrite", assumptions = {"a1", "a3"})
-        public int success(int value1, int value2) {
-            return value1 + value2;
-        }
-
-        @Specialization(guards = {"true1(value1)", "true2(value1)", "!false2(value1)", "!true3(value1)"}, assumptions = {"a1", "a3"})
-        public int fail5(int value1, int value2) {
-            throw new AssertionError();
-        }
-
-        @Specialization(guards = {"true1(value1)", "true2(value1)", "false2(value1)"}, assumptions = {"a1", "a3"})
-        public int fail4(int value1, int value2) {
-            throw new AssertionError();
-        }
-
-        @Specialization(guards = {"true1(value1)", "true2(value1)"}, assumptions = {"a1", "a3"})
-        public int fail2break(int value1, int value2) {
-            throw new AssertionError();
-        }
-
-        @Specialization(guards = {"true1(value1)", "false1(value1, value2)"})
-        public int fail1(int value1, int value2) {
-            throw new AssertionError();
-        }
-
-    }
-
-    @Test
     public void testElseConnectionBug1() {
         CallTarget target = TestHelper.createCallTarget(TestElseConnectionBug1Factory.create(new GenericInt()));
         Assert.assertEquals(42, target.call());
@@ -232,36 +116,4 @@
         }
     }
 
-    private static class MockAssumption implements Assumption {
-
-        int checked;
-
-        private final boolean valid;
-
-        public MockAssumption(boolean valid) {
-            this.valid = valid;
-        }
-
-        public void check() throws InvalidAssumptionException {
-            checked++;
-            if (!valid) {
-                throw new InvalidAssumptionException();
-            }
-        }
-
-        public boolean isValid() {
-            checked++;
-            return valid;
-        }
-
-        public void invalidate() {
-            throw new UnsupportedOperationException();
-        }
-
-        public String getName() {
-            throw new UnsupportedOperationException();
-        }
-
-    }
-
 }
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java	Wed Feb 11 12:13:44 2015 +0100
+++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java	Wed Feb 11 12:13:44 2015 +0100
@@ -25,6 +25,7 @@
 package com.oracle.truffle.api.dsl.internal;
 
 import java.lang.reflect.*;
+import java.util.*;
 import java.util.concurrent.*;
 
 import com.oracle.truffle.api.*;
@@ -165,10 +166,43 @@
         return node;
     }
 
+    protected final Object removeThis(final CharSequence reason, Frame frame) {
+        return removeThisImpl(reason).acceptAndExecute(frame);
+    }
+
+    protected final Object removeThis(final CharSequence reason, Frame frame, Object o1) {
+        return removeThisImpl(reason).acceptAndExecute(frame, o1);
+    }
+
+    protected final Object removeThis(final CharSequence reason, Frame frame, Object o1, Object o2) {
+        return removeThisImpl(reason).acceptAndExecute(frame, o1, o2);
+    }
+
+    protected final Object removeThis(final CharSequence reason, Frame frame, Object o1, Object o2, Object o3) {
+        return removeThisImpl(reason).acceptAndExecute(frame, o1, o2, o3);
+    }
+
+    protected final Object removeThis(final CharSequence reason, Frame frame, Object o1, Object o2, Object o3, Object o4) {
+        return removeThisImpl(reason).acceptAndExecute(frame, o1, o2, o3, o4);
+    }
+
+    protected final Object removeThis(final CharSequence reason, Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
+        return removeThisImpl(reason).acceptAndExecute(frame, o1, o2, o3, o4, o5);
+    }
+
+    protected final Object removeThis(final CharSequence reason, Frame frame, Object... args) {
+        return removeThisImpl(reason).acceptAndExecute(frame, args);
+    }
+
+    private SpecializationNode removeThisImpl(final CharSequence reason) {
+        this.replace(this.next, reason);
+        return findEnd().findStart();
+    }
+
     protected final SpecializationNode removeSame(final CharSequence reason) {
         return atomic(new Callable<SpecializationNode>() {
             public SpecializationNode call() throws Exception {
-                return removeImpl(SpecializationNode.this, reason);
+                return removeSameImpl(SpecializationNode.this, reason);
             }
         });
     }
@@ -192,7 +226,7 @@
         return findStart().getParent();
     }
 
-    private SpecializationNode removeImpl(SpecializationNode toRemove, CharSequence reason) {
+    private SpecializationNode removeSameImpl(SpecializationNode toRemove, CharSequence reason) {
         SpecializationNode start = findStart();
         SpecializationNode current = start;
         while (current != null) {
@@ -470,7 +504,7 @@
 
         appendFields(b, clazz);
         if (next != null) {
-            b.append(" -> ").append(next.toString());
+            b.append("\n -> ").append(next.toString());
         }
         return b.toString();
     }
@@ -481,25 +515,69 @@
             return;
         }
         b.append("(");
+        String sep = "";
         for (Field field : fields) {
             if (Modifier.isStatic(field.getModifiers())) {
                 continue;
             }
+            b.append(sep);
             String name = field.getName();
             if (name.equals("root")) {
                 continue;
             }
             b.append(field.getName());
+            b.append(" = ");
             try {
                 field.setAccessible(true);
-                b.append(field.get(this));
+                Object value = field.get(this);
+                if (value instanceof Object[]) {
+                    b.append(Arrays.toString((Object[]) field.get(this)));
+                } else {
+                    b.append(field.get(this));
+                }
             } catch (IllegalArgumentException e) {
                 b.append(e.toString());
             } catch (IllegalAccessException e) {
                 b.append(e.toString());
             }
+            sep = ", ";
         }
         b.append(")");
     }
 
+    // utilities for generated code
+    protected static void check(Assumption assumption) throws InvalidAssumptionException {
+        if (assumption != null) {
+            assumption.check();
+        }
+    }
+
+    @ExplodeLoop
+    protected static void check(Assumption[] assumptions) throws InvalidAssumptionException {
+        if (assumptions != null) {
+            CompilerAsserts.compilationConstant(assumptions.length);
+            for (Assumption assumption : assumptions) {
+                check(assumption);
+            }
+        }
+    }
+
+    protected static boolean isValid(Assumption assumption) {
+        if (assumption != null) {
+            return assumption.isValid();
+        }
+        return true;
+    }
+
+    protected static boolean isValid(Assumption[] assumptions) {
+        if (assumptions != null) {
+            for (Assumption assumption : assumptions) {
+                if (!isValid(assumption)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java	Wed Feb 11 12:13:44 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java	Wed Feb 11 12:13:44 2015 +0100
@@ -32,7 +32,6 @@
 import javax.lang.model.type.*;
 import javax.lang.model.util.*;
 
-import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.*;
@@ -74,11 +73,10 @@
         this.genericType = typeSystem.getGenericTypeData();
         this.options = typeSystem.getOptions();
         this.singleSpecializable = isSingleSpecializableImpl();
-        this.varArgsThreshold = calculateVarArgsThresHold();
-
+        this.varArgsThreshold = calculateVarArgsThreshold();
     }
 
-    private int calculateVarArgsThresHold() {
+    private int calculateVarArgsThreshold() {
         TypeMirror specialization = context.getType(SpecializationNode.class);
         TypeElement specializationType = fromTypeMirror(specialization);
 
@@ -95,6 +93,10 @@
         return resolveNodeId(node) + NODE_SUFFIX;
     }
 
+    private static String assumptionName(AssumptionExpression assumption) {
+        return assumption.getId() + NAME_SUFFIX;
+    }
+
     private static String resolveNodeId(NodeData node) {
         String nodeid = node.getNodeId();
         if (nodeid.endsWith("Node") && !nodeid.equals("Node")) {
@@ -157,18 +159,10 @@
         }
     }
 
-    private static String assumptionName(String assumption) {
-        return assumption + "_";
-    }
-
     public CodeTypeElement create() {
         CodeTypeElement clazz = GeneratorUtils.createClass(node, null, modifiers(FINAL), nodeTypeName(node), node.getTemplateType().asType());
         ElementUtils.setVisibility(clazz.getModifiers(), ElementUtils.getVisibility(node.getTemplateType().getModifiers()));
 
-        for (String assumption : node.getAssumptions()) {
-            clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getType(Assumption.class), assumptionName(assumption)));
-        }
-
         for (NodeChildData child : node.getChildren()) {
             clazz.addOptional(createAccessChildMethod(child));
         }
@@ -757,6 +751,11 @@
                 return false;
             }
         }
+
+        if (!specialization.getAssumptionExpressions().isEmpty()) {
+            return false;
+        }
+
         if (specialization.getCaches().size() > 0) {
             // TODO chumer: caches do not yet support single specialization.
             // it could be worthwhile to explore if this is possible
@@ -830,7 +829,7 @@
             if (wrappedExecutableType != null) {
                 builder.startReturn().tree(callTemplateMethod(null, wrappedExecutableType, locals)).end();
             } else {
-                builder.tree(createFastPathExecute(builder, specialization, execType.getType(), locals));
+                builder.tree(createFastPath(builder, specialization, execType.getType(), locals));
             }
         } else {
             // create acceptAndExecute
@@ -988,7 +987,8 @@
                     continue;
                 }
             }
-            builder.string(parameter.getLocalName());
+
+            builder.defaultValue(parameter.getType());
         }
         builder.end();
         return builder.build();
@@ -1036,6 +1036,35 @@
         if (node.isFrameUsedByAnyGuard()) {
             builder.tree(createTransferToInterpreterAndInvalidate());
         }
+
+        boolean hasAssumptions = !specialization.getAssumptionExpressions().isEmpty();
+        if (hasAssumptions) {
+            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
+                CodeTree assumptions = DSLExpressionGenerator.write(assumption.getExpression(), accessParent(null),
+                                castBoundTypes(bindExpressionValues(assumption.getExpression(), specialization, currentValues)));
+                String name = assumptionName(assumption);
+                // needs specialization index for assumption to make unique
+                String varName = name + specialization.getIndex();
+                TypeMirror type = assumption.getExpression().getResolvedType();
+                builder.declaration(type, varName, assumptions);
+                currentValues.set(name, new LocalVariable(null, type, varName, null));
+            }
+
+            builder.startIf();
+            String sep = "";
+            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
+                LocalVariable assumptionVar = currentValues.get(assumptionName(assumption));
+                if (assumptionVar == null) {
+                    throw new AssertionError("assumption var not resolved");
+                }
+                builder.string(sep);
+                builder.startCall("isValid").tree(assumptionVar.createReference()).end();
+                sep = " && ";
+            }
+            builder.end();
+            builder.startBlock();
+        }
+
         for (SpecializationData otherSpeciailzation : node.getSpecializations()) {
             if (otherSpeciailzation == specialization) {
                 continue;
@@ -1052,7 +1081,6 @@
 
         if (specialization.hasMultipleInstances()) {
             builder.declaration(getType(SpecializationNode.class), "s", create);
-
             DSLExpression limitExpression = specialization.getLimitExpression();
             CodeTree limitExpressionTree;
             if (limitExpression == null) {
@@ -1065,11 +1093,14 @@
             builder.startIf().string("countSame(s) < ").tree(limitExpressionTree).end().startBlock();
             builder.statement("return s");
             builder.end();
-
         } else {
             builder.startReturn().tree(create).end();
         }
 
+        if (hasAssumptions) {
+            builder.end();
+        }
+
         if (mayBeExcluded(specialization)) {
             CodeTreeBuilder checkHasSeenBuilder = builder.create();
             checkHasSeenBuilder.startIf().string("!").tree(accessParent(excludedFieldName(specialization))).end().startBlock();
@@ -1112,7 +1143,7 @@
             return true;
         }
 
-        if ((!fastPath || forType.isGeneric()) && !group.getAssumptions().isEmpty()) {
+        if (!fastPath && specialization != null && !specialization.getAssumptionExpressions().isEmpty()) {
             return true;
         }
 
@@ -1193,7 +1224,13 @@
                 }
                 builder.tree(variable.createReference());
             }
-
+            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
+                LocalVariable variable = currentValues.get(assumptionName(assumption));
+                if (variable == null) {
+                    throw new AssertionError("Could not bind assumption value " + assumption.getId() + ": " + currentValues);
+                }
+                builder.tree(variable.createReference());
+            }
         }
         builder.end();
 
@@ -1287,6 +1324,13 @@
                 builder.startStatement().string("this.").string(name).string(" = ").string(name).end();
             }
 
+            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
+                String name = assumptionName(assumption);
+                TypeMirror type = assumption.getExpression().getResolvedType();
+                clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), type, name));
+                constructor.addParameter(new CodeVariableElement(type, name));
+                builder.startStatement().string("this.").string(name).string(" = ").string(name).end();
+            }
         }
 
         if (constructor.getParameters().isEmpty()) {
@@ -1346,9 +1390,12 @@
         return builder.build();
     }
 
-    private static CodeTree createCallDelegate(String methodName, TypeData forType, LocalContext currentValues) {
+    private static CodeTree createCallDelegate(String methodName, String reason, TypeData forType, LocalContext currentValues) {
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
         builder.startCall(methodName);
+        if (reason != null) {
+            builder.doubleQuote(reason);
+        }
         currentValues.addReferencesTo(builder, FRAME_VALUE);
         builder.end();
 
@@ -1389,7 +1436,7 @@
         LocalContext currentLocals = LocalContext.load(this, evaluatedArguments, varArgsThreshold);
 
         if (specialization != null) {
-            currentLocals.loadFastPathCachedValues(specialization);
+            currentLocals.loadFastPathState(specialization);
         }
 
         CodeExecutableElement executable = currentLocals.createMethod(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemNodeFactory.executeName(forType), FRAME_VALUE);
@@ -1400,12 +1447,12 @@
         }
 
         CodeTreeBuilder builder = executable.createBuilder();
-        builder.tree(createFastPathExecute(builder, specialization, type, currentLocals));
+        builder.tree(createFastPath(builder, specialization, type, currentLocals));
 
         return executable;
     }
 
-    private CodeTree createFastPathExecute(CodeTreeBuilder parent, SpecializationData specialization, TypeData type, LocalContext currentLocals) {
+    private CodeTree createFastPath(CodeTreeBuilder parent, SpecializationData specialization, TypeData type, LocalContext currentLocals) {
         final CodeTreeBuilder builder = parent.create();
 
         for (NodeExecutionData execution : node.getChildExecutions()) {
@@ -1426,11 +1473,11 @@
 
         LocalContext originalValues = currentLocals.copy();
         if (specialization == null) {
-            builder.startReturn().tree(createCallDelegate("acceptAndExecute", type, currentLocals)).end();
+            builder.startReturn().tree(createCallDelegate("acceptAndExecute", null, type, currentLocals)).end();
         } else if (specialization.isPolymorphic()) {
             builder.tree(createCallNext(type, currentLocals));
         } else if (specialization.isUninitialized()) {
-            builder.startReturn().tree(createCallDelegate("uninitialized", type, currentLocals)).end();
+            builder.startReturn().tree(createCallDelegate("uninitialized", null, type, currentLocals)).end();
         } else {
             final TypeData finalType = type;
             SpecializationGroup group = SpecializationGroup.create(specialization);
@@ -1495,6 +1542,27 @@
             ifCount++;
         }
         CodeTreeBuilder execute = builder.create();
+
+        if (!specialization.getAssumptionExpressions().isEmpty()) {
+            builder.startTryBlock();
+            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
+                LocalVariable assumptionVar = currentValues.get(assumptionName(assumption));
+                if (assumptionVar == null) {
+                    throw new AssertionError("Could not resolve assumption var " + currentValues);
+                }
+                builder.startStatement().startCall("check").tree(assumptionVar.createReference()).end().end();
+            }
+            builder.end().startCatchBlock(getType(InvalidAssumptionException.class), "ae");
+            builder.startReturn();
+            List<String> assumptionIds = new ArrayList<>();
+            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
+                assumptionIds.add(assumption.getId());
+            }
+            builder.tree(createCallDelegate("removeThis", String.format("Assumption %s invalidated", assumptionIds), forType, currentValues));
+            builder.end();
+            builder.end();
+        }
+
         execute.startReturn();
         if (specialization.getMethod() == null) {
             execute.startCall("unsupported");
@@ -1525,7 +1593,7 @@
         }
 
         SpecializationData specialization = group.getSpecialization();
-        CodeTree[] checkAndCast = createTypeCheckCastAndCaches(specialization, group.getTypeGuards(), castGuards, currentValues, execution);
+        CodeTree[] checkAndCast = createTypeCheckAndLocals(specialization, group.getTypeGuards(), castGuards, currentValues, execution);
 
         CodeTree check = checkAndCast[0];
         CodeTree cast = checkAndCast[1];
@@ -1537,14 +1605,6 @@
         CodeTree methodGuards = methodGuardAndAssertions[0];
         CodeTree guardAssertions = methodGuardAndAssertions[1];
 
-        if (!group.getAssumptions().isEmpty()) {
-            if (execution.isFastPath() && !forType.isGeneric()) {
-                cast = appendAssumptionFastPath(cast, group.getAssumptions(), forType, currentValues);
-            } else {
-                methodGuards = appendAssumptionSlowPath(methodGuards, group.getAssumptions());
-            }
-        }
-
         int ifCount = 0;
         if (!check.isEmpty()) {
             builder.startIf();
@@ -1583,33 +1643,6 @@
         return builder.build();
     }
 
-    private CodeTree appendAssumptionSlowPath(CodeTree methodGuards, List<String> assumptions) {
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-
-        builder.tree(methodGuards);
-        String connect = methodGuards.isEmpty() ? "" : " && ";
-        for (String assumption : assumptions) {
-            builder.string(connect);
-            builder.startCall(accessParent(assumptionName(assumption)), "isValid").end();
-            connect = " && ";
-        }
-
-        return builder.build();
-    }
-
-    private CodeTree appendAssumptionFastPath(CodeTree casts, List<String> assumptions, TypeData forType, LocalContext currentValues) {
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        builder.tree(casts);
-        builder.startTryBlock();
-        for (String assumption : assumptions) {
-            builder.startStatement().startCall(accessParent(assumptionName(assumption)), "check").end().end();
-        }
-        builder.end().startCatchBlock(getType(InvalidAssumptionException.class), "ae");
-        builder.tree(createCallNext(forType, currentValues));
-        builder.end();
-        return builder.build();
-    }
-
     private static boolean isReachableGroup(SpecializationGroup group, int ifCount) {
         if (ifCount != 0) {
             return true;
@@ -1623,7 +1656,7 @@
          * Hacky else case. In this case the specialization is not reachable due to previous else
          * branch. This is only true if the minimum state is not checked.
          */
-        if (previous.getGuards().size() == 1 && previous.getTypeGuards().isEmpty() && previous.getAssumptions().isEmpty() &&
+        if (previous.getGuards().size() == 1 && previous.getTypeGuards().isEmpty() &&
                         (previous.getParent() == null || previous.getMaxSpecializationIndex() != previous.getParent().getMaxSpecializationIndex())) {
             return false;
         }
@@ -2124,10 +2157,10 @@
         return bindings;
     }
 
-    private CodeTree[] createTypeCheckCastAndCaches(SpecializationData specialization, List<TypeGuard> typeGuards, Set<TypeGuard> castGuards, LocalContext currentValues,
+    private CodeTree[] createTypeCheckAndLocals(SpecializationData specialization, List<TypeGuard> typeGuards, Set<TypeGuard> castGuards, LocalContext currentValues,
                     SpecializationExecution specializationExecution) {
         CodeTreeBuilder checksBuilder = CodeTreeBuilder.createBuilder();
-        CodeTreeBuilder castsAndCaches = CodeTreeBuilder.createBuilder();
+        CodeTreeBuilder localsBuilder = CodeTreeBuilder.createBuilder();
         for (TypeGuard typeGuard : typeGuards) {
             int signatureIndex = typeGuard.getSignatureIndex();
             LocalVariable value = currentValues.getValue(signatureIndex);
@@ -2188,7 +2221,7 @@
             if (castGuards == null || castGuards.contains(typeGuard)) {
                 LocalVariable castVariable = currentValues.getValue(execution).nextName().newType(typeGuard.getType()).accessWith(null);
                 currentValues.setValue(execution, castVariable);
-                castsAndCaches.tree(castVariable.createDeclaration(castBuilder.build()));
+                localsBuilder.tree(castVariable.createDeclaration(castBuilder.build()));
             }
 
             checksBuilder.tree(checkBuilder.build());
@@ -2202,12 +2235,12 @@
                 // multiple specializations might use the same name
                 String varName = name + specialization.getIndex();
                 TypeMirror type = cache.getParameter().getType();
-                castsAndCaches.declaration(type, varName, initializer);
+                localsBuilder.declaration(type, varName, initializer);
                 currentValues.set(name, new LocalVariable(null, type, varName, null));
             }
         }
 
-        return new CodeTree[]{checksBuilder.build(), castsAndCaches.build()};
+        return new CodeTree[]{checksBuilder.build(), localsBuilder.build()};
     }
 
     public static final class LocalContext {
@@ -2219,12 +2252,18 @@
             this.factory = factory;
         }
 
-        public void loadFastPathCachedValues(SpecializationData specialization) {
+        public void loadFastPathState(SpecializationData specialization) {
             for (CacheExpression cache : specialization.getCaches()) {
                 Parameter cacheParameter = cache.getParameter();
                 String name = cacheParameter.getVariableElement().getSimpleName().toString();
                 set(cacheParameter.getLocalName(), new LocalVariable(cacheParameter.getTypeSystemType(), cacheParameter.getType(), name, CodeTreeBuilder.singleString("this." + name)));
             }
+
+            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
+                String name = assumptionName(assumption);
+                TypeMirror type = assumption.getExpression().getResolvedType();
+                set(name, new LocalVariable(null, type, name, CodeTreeBuilder.singleString("this." + name)));
+            }
         }
 
         public CodeExecutableElement createMethod(Set<Modifier> modifiers, TypeMirror returnType, String name, String... optionalArguments) {
@@ -2425,6 +2464,11 @@
             return values.get(shortCircuitName(execution));
         }
 
+        @Override
+        public String toString() {
+            return "LocalContext [values=" + values + "]";
+        }
+
     }
 
     public static final class LocalVariable {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AssumptionExpression.java	Wed Feb 11 12:13:44 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AssumptionExpression.java	Wed Feb 11 12:13:44 2015 +0100
@@ -31,10 +31,16 @@
 
     private final TemplateMethod source;
     private final DSLExpression expression;
+    private final String id;
 
-    public AssumptionExpression(TemplateMethod source, DSLExpression expression) {
+    public AssumptionExpression(TemplateMethod source, DSLExpression expression, String id) {
         this.source = source;
         this.expression = expression;
+        this.id = id;
+    }
+
+    public String getId() {
+        return id;
     }
 
     @Override
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java	Wed Feb 11 12:13:44 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java	Wed Feb 11 12:13:44 2015 +0100
@@ -42,7 +42,6 @@
     private final List<NodeChildData> children;
     private final List<NodeExecutionData> childExecutions;
     private final List<NodeFieldData> fields;
-    private final List<String> assumptions;
 
     private ParameterSpec instanceParameterSpec;
 
@@ -64,7 +63,6 @@
         this.fields = new ArrayList<>();
         this.children = new ArrayList<>();
         this.childExecutions = new ArrayList<>();
-        this.assumptions = new ArrayList<>();
         this.thisExecution = new NodeExecutionData(new NodeChildData(null, null, "this", getNodeType(), getNodeType(), null, Cardinality.ONE), -1, false);
         this.thisExecution.getChild().setNode(this);
         this.generateFactory = generateFactory;
@@ -217,10 +215,6 @@
         return getTemplateType().asType();
     }
 
-    public List<String> getAssumptions() {
-        return assumptions;
-    }
-
     public boolean needsFactory() {
         if (specializations == null) {
             return false;
@@ -427,7 +421,6 @@
         dumpProperty(builder, indent, "fields", getChildren());
         dumpProperty(builder, indent, "executableTypes", getExecutableTypes());
         dumpProperty(builder, indent, "specializations", getSpecializations());
-        dumpProperty(builder, indent, "assumptions", getAssumptions());
         dumpProperty(builder, indent, "casts", getCasts());
         dumpProperty(builder, indent, "messages", collectMessages());
         if (getEnclosingNodes().size() > 0) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java	Wed Feb 11 12:13:44 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java	Wed Feb 11 12:13:44 2015 +0100
@@ -46,7 +46,6 @@
     private List<CacheExpression> caches = Collections.emptyList();
     private List<AssumptionExpression> assumptionExpressions = Collections.emptyList();
     private List<ShortCircuitData> shortCircuits;
-    private List<String> assumptions = Collections.emptyList();
     private final Set<SpecializationData> contains = new TreeSet<>();
     private final Set<String> containsNames = new TreeSet<>();
     private final Set<SpecializationData> excludedBy = new TreeSet<>();
@@ -159,6 +158,9 @@
         if (caches != null) {
             sinks.addAll(caches);
         }
+        if (assumptionExpressions != null) {
+            sinks.addAll(assumptionExpressions);
+        }
         return sinks;
     }
 
@@ -169,7 +171,7 @@
         if (!getGuards().isEmpty()) {
             return true;
         }
-        if (!getAssumptions().isEmpty()) {
+        if (!getAssumptionExpressions().isEmpty()) {
             return true;
         }
 
@@ -260,14 +262,6 @@
         return shortCircuits;
     }
 
-    public List<String> getAssumptions() {
-        return assumptions;
-    }
-
-    public 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++) {
@@ -317,9 +311,7 @@
                 }
             }
         }
-
         return false;
-
     }
 
     public boolean isReachableAfter(SpecializationData prev) {
@@ -349,10 +341,10 @@
             }
         }
 
-        for (String prevAssumption : prev.getAssumptions()) {
-            if (!getAssumptions().contains(prevAssumption)) {
-                return true;
-            }
+        if (!prev.getAssumptionExpressions().isEmpty()) {
+            // TODO: chumer: we could at least check reachability after trivial assumptions
+            // not sure if this is worth it.
+            return true;
         }
 
         Iterator<GuardExpression> prevGuards = prev.getGuards().iterator();
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java	Wed Feb 11 12:13:44 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java	Wed Feb 11 12:13:44 2015 +0100
@@ -30,12 +30,14 @@
 import javax.lang.model.util.*;
 import javax.tools.Diagnostic.Kind;
 
+import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.expression.*;
 import com.oracle.truffle.dsl.processor.java.*;
 import com.oracle.truffle.dsl.processor.java.compiler.*;
+import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror;
 import com.oracle.truffle.dsl.processor.java.model.*;
 import com.oracle.truffle.dsl.processor.model.*;
 import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality;
@@ -136,8 +138,10 @@
         }
 
         NodeData node = parseNodeData(templateType, lookupTypes);
+        if (node.hasErrors()) {
+            return node;
+        }
 
-        node.getAssumptions().addAll(parseAssumptions(lookupTypes));
         node.getFields().addAll(parseFields(lookupTypes, members));
         node.getChildren().addAll(parseChildren(lookupTypes, members));
         node.getChildExecutions().addAll(parseExecutions(node.getChildren(), members));
@@ -275,24 +279,6 @@
 
     }
 
-    private List<String> parseAssumptions(List<TypeElement> typeHierarchy) {
-        List<String> assumptionsList = new ArrayList<>();
-        for (int i = typeHierarchy.size() - 1; i >= 0; i--) {
-            TypeElement type = typeHierarchy.get(i);
-            AnnotationMirror assumptions = ElementUtils.findAnnotationMirror(context.getEnvironment(), type, NodeAssumptions.class);
-            if (assumptions != null) {
-                List<String> assumptionStrings = ElementUtils.getAnnotationValueList(String.class, assumptions, "value");
-                for (String string : assumptionStrings) {
-                    if (assumptionsList.contains(string)) {
-                        assumptionsList.remove(string);
-                    }
-                    assumptionsList.add(string);
-                }
-            }
-        }
-        return assumptionsList;
-    }
-
     private List<NodeFieldData> parseFields(List<TypeElement> typeHierarchy, List<? extends Element> elements) {
         Set<String> names = new HashSet<>();
 
@@ -562,16 +548,11 @@
 
             Parameter frame = execute.getFrame();
             TypeMirror resolvedFrameType;
-            if (frame == null) {
-                resolvedFrameType = node.getTypeSystem().getVoidType().getPrimitiveType();
-            } else {
+            if (frame != null) {
                 resolvedFrameType = frame.getType();
-            }
-
-            if (frameType == null) {
-                frameType = resolvedFrameType;
-            } else {
-                if (!ElementUtils.typeEquals(frameType, resolvedFrameType)) {
+                if (frameType == null) {
+                    frameType = resolvedFrameType;
+                } else if (!ElementUtils.typeEquals(frameType, resolvedFrameType)) {
                     // found inconsistent frame types
                     inconsistentFrameTypes.add(ElementUtils.getSimpleName(frameType));
                     inconsistentFrameTypes.add(ElementUtils.getSimpleName(resolvedFrameType));
@@ -584,6 +565,10 @@
             Collections.sort(inconsistentFrameTypesList);
             node.addError("Invalid inconsistent frame types %s found for the declared execute methods. The frame type must be identical for all execute methods.", inconsistentFrameTypesList);
         }
+        if (frameType == null) {
+            frameType = context.getType(void.class);
+        }
+
         node.setFrameType(frameType);
 
         int totalGenericCount = 0;
@@ -979,9 +964,39 @@
                 continue;
             }
             initializeLimit(specialization, resolver);
+            initializeAssumptions(specialization, resolver);
         }
     }
 
+    private void initializeAssumptions(SpecializationData specialization, DSLExpressionResolver resolver) {
+        final DeclaredType assumptionType = context.getDeclaredType(Assumption.class);
+        final TypeMirror assumptionArrayType = new ArrayCodeTypeMirror(assumptionType);
+        final List<String> assumptionDefinitions = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "assumptions");
+        List<AssumptionExpression> assumptionExpressions = new ArrayList<>();
+        int assumptionId = 0;
+        for (String assumption : assumptionDefinitions) {
+            AssumptionExpression assumptionExpression;
+            DSLExpression expression = null;
+            try {
+                expression = DSLExpression.parse(assumption);
+                expression.accept(resolver);
+                assumptionExpression = new AssumptionExpression(specialization, expression, "assumption" + assumptionId);
+                if (!ElementUtils.isAssignable(expression.getResolvedType(), assumptionType) && !ElementUtils.isAssignable(expression.getResolvedType(), assumptionArrayType)) {
+                    assumptionExpression.addError("Incompatible return type %s. Assumptions must be assignable to %s or %s.", ElementUtils.getSimpleName(expression.getResolvedType()),
+                                    ElementUtils.getSimpleName(assumptionType), ElementUtils.getSimpleName(assumptionArrayType));
+                }
+                if (specialization.isDynamicParameterBound(expression)) {
+                    specialization.addError("Assumption expressions must not bind dynamic parameter values.");
+                }
+            } catch (InvalidExpressionException e) {
+                assumptionExpression = new AssumptionExpression(specialization, null, "assumption" + assumptionId);
+                assumptionExpression.addError("Error parsing expression '%s': %s", assumption, e.getMessage());
+            }
+            assumptionExpressions.add(assumptionExpression);
+        }
+        specialization.setAssumptionExpressions(assumptionExpressions);
+    }
+
     private void initializeLimit(SpecializationData specialization, DSLExpressionResolver resolver) {
         AnnotationValue annotationValue = ElementUtils.getAnnotationValue(specialization.getMessageAnnotation(), "limit");
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java	Wed Feb 11 12:13:44 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java	Wed Feb 11 12:13:44 2015 +0100
@@ -33,7 +33,6 @@
  */
 public final class SpecializationGroup {
 
-    private final List<String> assumptions;
     private final List<TypeGuard> typeGuards;
     private final List<GuardExpression> guards;
 
@@ -45,12 +44,10 @@
 
     private SpecializationGroup(SpecializationData data) {
         this.node = data.getNode();
-        this.assumptions = new ArrayList<>();
         this.typeGuards = new ArrayList<>();
         this.guards = new ArrayList<>();
         this.specialization = data;
 
-        this.assumptions.addAll(data.getAssumptions());
         TypeSignature sig = data.getTypeSignature();
         for (int i = 1; i < sig.size(); i++) {
             typeGuards.add(new TypeGuard(sig.get(i), i - 1));
@@ -58,9 +55,8 @@
         this.guards.addAll(data.getGuards());
     }
 
-    public SpecializationGroup(List<SpecializationGroup> children, List<String> assumptionMatches, List<TypeGuard> typeGuardsMatches, List<GuardExpression> guardMatches) {
+    public SpecializationGroup(List<SpecializationGroup> children, List<TypeGuard> typeGuardsMatches, List<GuardExpression> guardMatches) {
         assert !children.isEmpty() : "children must not be empty";
-        this.assumptions = assumptionMatches;
         this.typeGuards = typeGuardsMatches;
         this.guards = guardMatches;
         this.node = children.get(0).node;
@@ -78,7 +74,7 @@
     }
 
     public List<GuardExpression> findElseConnectableGuards() {
-        if (!getTypeGuards().isEmpty() || !getAssumptions().isEmpty()) {
+        if (!getTypeGuards().isEmpty()) {
             return Collections.emptyList();
         }
 
@@ -133,10 +129,6 @@
         return parent;
     }
 
-    public List<String> getAssumptions() {
-        return assumptions;
-    }
-
     public List<TypeGuard> getTypeGuards() {
         return typeGuards;
     }
@@ -161,23 +153,12 @@
             return null;
         }
 
-        List<String> assumptionMatches = new ArrayList<>();
         List<TypeGuard> typeGuardsMatches = new ArrayList<>();
         List<GuardExpression> guardMatches = new ArrayList<>();
 
         SpecializationGroup first = groups.get(0);
         List<SpecializationGroup> others = groups.subList(1, groups.size());
 
-        outer: for (String assumption : first.assumptions) {
-            for (SpecializationGroup other : others) {
-                if (!other.assumptions.contains(assumption)) {
-                    // assumptions can be combined unordered
-                    continue outer;
-                }
-            }
-            assumptionMatches.add(assumption);
-        }
-
         outer: for (TypeGuard typeGuard : first.typeGuards) {
             for (SpecializationGroup other : others) {
                 if (!other.typeGuards.contains(typeGuard)) {
@@ -207,18 +188,17 @@
             // TODO we need to be smarter here with bound parameters.
         }
 
-        if (assumptionMatches.isEmpty() && typeGuardsMatches.isEmpty() && guardMatches.isEmpty()) {
+        if (typeGuardsMatches.isEmpty() && guardMatches.isEmpty()) {
             return null;
         }
 
         for (SpecializationGroup group : groups) {
-            group.assumptions.removeAll(assumptionMatches);
             group.typeGuards.removeAll(typeGuardsMatches);
             group.guards.removeAll(guardMatches);
         }
 
         List<SpecializationGroup> newChildren = new ArrayList<>(groups);
-        return new SpecializationGroup(newChildren, assumptionMatches, typeGuardsMatches, guardMatches);
+        return new SpecializationGroup(newChildren, typeGuardsMatches, guardMatches);
     }
 
     public static SpecializationGroup create(SpecializationData specialization) {
@@ -230,12 +210,12 @@
         for (SpecializationData specialization : specializations) {
             groups.add(new SpecializationGroup(specialization));
         }
-        return new SpecializationGroup(createCombinationalGroups(groups), Collections.<String> emptyList(), Collections.<TypeGuard> emptyList(), Collections.<GuardExpression> emptyList());
+        return new SpecializationGroup(createCombinationalGroups(groups), Collections.<TypeGuard> emptyList(), Collections.<GuardExpression> emptyList());
     }
 
     @Override
     public String toString() {
-        return "SpecializationGroup [assumptions=" + assumptions + ", typeGuards=" + typeGuards + ", guards=" + guards + "]";
+        return "SpecializationGroup [typeGuards=" + typeGuards + ", guards=" + guards + "]";
     }
 
     private static List<SpecializationGroup> createCombinationalGroups(List<SpecializationGroup> groups) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java	Wed Feb 11 12:13:44 2015 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java	Wed Feb 11 12:13:44 2015 +0100
@@ -109,15 +109,6 @@
 
         }
 
-        List<String> assumptionDefs = ElementUtils.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;
     }
 }