changeset 16756:5148aab962af

Truffle-DSL: updated tests for the new generation layout.
author Christian Humer <christian.humer@gmail.com>
date Mon, 11 Aug 2014 15:53:05 +0200
parents bd28da642eea
children 0cd0bdedd4ad
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/CodeFormatTest.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/FallbackTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/InsertBeforeTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.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/SlowPathTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java
diffstat 18 files changed, 2255 insertions(+), 584 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.java	Mon Aug 11 15:53:05 2014 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.java	Mon Aug 11 15:53:05 2014 +0200
@@ -48,15 +48,16 @@
     @NodeAssumptions("assumption")
     abstract static class SingleAssumptionNode extends ValueNode {
 
-        @Specialization(order = 0, assumptions = "assumption")
-        int doInt() {
+        @Specialization(assumptions = "assumption")
+        int do2() {
             return 42;
         }
 
-        @Specialization
-        Object doObject() {
+        @Generic
+        Object doFallBack() {
             return "42";
         }
+
     }
 
     @Test
@@ -67,9 +68,9 @@
 
         Assert.assertEquals(42, TestHelper.executeWith(root));
         assumption2.invalidate();
-        Assert.assertEquals("42", TestHelper.executeWith(root));
+        Assert.assertEquals("41", TestHelper.executeWith(root));
         assumption1.invalidate();
-        Assert.assertEquals("43", TestHelper.executeWith(root));
+        Assert.assertEquals("42", TestHelper.executeWith(root));
     }
 
     @NodeAssumptions({"assumption1", "assumption2"})
@@ -82,12 +83,12 @@
 
         @Specialization(assumptions = "assumption1")
         Object doObject() {
-            return "42";
+            return "41";
         }
 
         @Generic
-        Object doGeneric() {
-            return "43";
+        Object doFallBack() {
+            return "42";
         }
     }
 
@@ -107,10 +108,11 @@
     @NodeAssumptions({"additionalAssumption"})
     abstract static class DerivedAssumptionNode extends SingleAssumptionNode {
 
-        @Specialization(order = 1, assumptions = "additionalAssumption")
+        @Specialization(assumptions = "additionalAssumption")
         int doIntDerived() {
             return 43;
         }
+
     }
 
     @Test
@@ -129,7 +131,7 @@
     @NodeAssumptions({"additionalAssumption", "assumption"})
     abstract static class DerivedAssumptionRedeclaredNode extends SingleAssumptionNode {
 
-        @Specialization(order = 1, assumptions = "additionalAssumption")
+        @Specialization(assumptions = "additionalAssumption")
         int doIntDerived() {
             return 43;
         }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java	Mon Aug 11 15:53:05 2014 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java	Mon Aug 11 15:53:05 2014 +0200
@@ -28,6 +28,9 @@
 import com.oracle.truffle.api.dsl.test.CodeFormatTestFactory.LineWrappingTestFactory;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
 
+/**
+ * Tests the generated code compiles without warnings for unusual large guard names.
+ */
 public class CodeFormatTest {
 
     @Test
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java	Mon Aug 11 15:53:05 2014 +0200
@@ -0,0 +1,603 @@
+/*
+ * 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.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.internal.*;
+import com.oracle.truffle.api.dsl.test.ContainsTestFactory.Contains1Factory;
+import com.oracle.truffle.api.dsl.test.ContainsTestFactory.Contains2Factory;
+import com.oracle.truffle.api.dsl.test.ContainsTestFactory.Contains3Factory;
+import com.oracle.truffle.api.dsl.test.ContainsTestFactory.Contains4Factory;
+import com.oracle.truffle.api.dsl.test.TestHelper.ExecutionListener;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+import com.oracle.truffle.api.nodes.*;
+
+@SuppressWarnings("unused")
+public class ContainsTest {
+
+    /*
+     * Tests a simple monomorphic inclusion.
+     */
+    @Test
+    public void testContains1() {
+        assertRuns(Contains1Factory.getInstance(), //
+                        array(1, "a", 2, "b"), //
+                        array(2, "aa", 3, "ba"),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (value instanceof String) {
+                                    // assert that the final specialization is always Object
+                                    Assert.assertEquals(Object.class, ((DSLNode) node.getNode()).getMetadata0().getSpecializedTypes()[0]);
+                                }
+                            }
+                        });
+    }
+
+    @NodeChild("a")
+    abstract static class Contains1 extends ValueNode {
+
+        @Specialization
+        int f1(int a) {
+            return a + 1;
+        }
+
+        @Specialization(contains = "f1")
+        Object f2(Object a) {
+            if (a instanceof Integer) {
+                return ((Integer) a) + 1;
+            }
+            return a + "a";
+        }
+    }
+
+    /*
+     * Tests an inclusion in within a polymorphic chain.
+     */
+    @Test
+    public void testContains2() {
+        assertRuns(Contains2Factory.getInstance(), //
+                        array(true, 1, 0, false), //
+                        array(false, -1, 1, true) //
+        );
+    }
+
+    @NodeChild("a")
+    abstract static class Contains2 extends ValueNode {
+
+        static boolean isZero(int a) {
+            return a == 0;
+        }
+
+        @Specialization(guards = "isZero")
+        int f1(int a) {
+            return a + 1;
+        }
+
+        @Specialization(contains = "f1")
+        int f2(int a) {
+            if (a == 0) {
+                return a + 1;
+            }
+            return -a;
+        }
+
+        @Specialization
+        boolean f3(boolean a) {
+            return !a;
+        }
+    }
+
+    /*
+     * Tests transitive monomorphic inclusion.
+     */
+    @Test
+    public void testContains3() {
+        assertRuns(Contains3Factory.getInstance(), //
+                        array(2, 1, 2, -3, -4), //
+                        array(-2, 2, -2, -3, -4),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                // assert that we are always monomorphic
+                                Assert.assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost());
+                            }
+                        });
+    }
+
+    @NodeChild("a")
+    abstract static class Contains3 extends ValueNode {
+
+        static boolean isGreaterZero(int a) {
+            return a > 0;
+        }
+
+        @Implies("isGreaterZero")
+        static boolean isOne(int a) {
+            return a == 1;
+        }
+
+        @Specialization(guards = {"isOne"})
+        int f1(int a) {
+            return a + 1;
+        }
+
+        @Specialization(contains = "f1", guards = {"isGreaterZero"})
+        int f2(int a) {
+            if (a == 1) {
+                return 2;
+            }
+            return -a;
+        }
+
+        @Specialization(contains = "f2")
+        int f3(int a) {
+            if (a > 0) {
+                return a == 1 ? 2 : -a;
+            } else {
+                return a;
+            }
+        }
+
+    }
+
+    /*
+     * Tests that if it can be derived that two specializations actually a as powerful as the latter
+     * we can combine them. Therefore operation should always become monomorphic in the end.
+     */
+    @Test
+    public void testContains4() {
+        assertRuns(Contains4Factory.getInstance(), //
+                        array(-1, 0, 1, 2), //
+                        array(1, 0, 1, 2),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                Assert.assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost());
+                            }
+                        });
+    }
+
+    @NodeChild("a")
+    abstract static class Contains4 extends ValueNode {
+
+        static boolean isGreaterEqualZero(int a) {
+            return a >= 0;
+        }
+
+        @Implies("isGreaterEqualZero")
+        static boolean isOne(int a) {
+            return a == 1;
+        }
+
+        @Specialization(guards = {"isOne"})
+        int f0(int a) {
+            return 1;
+        }
+
+        @Specialization(contains = "f0", guards = {"isGreaterEqualZero"})
+        int f1(int a) {
+            return a;
+        }
+
+        @Specialization(contains = {"f1"})
+        int f2(int a) {
+            return Math.abs(a);
+        }
+
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsError1 extends ValueNode {
+        @ExpectError("The contained specialization 'f1' must be declared before the containing specialization.")
+        @Specialization(contains = "f1")
+        int f0(int a) {
+            return a;
+        }
+
+        @Specialization
+        Object f1(String a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsError2 extends ValueNode {
+
+        @ExpectError("The referenced specialization 'does not exist' could not be found.")
+        @Specialization(contains = "does not exist")
+        int f0(int a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsError3 extends ValueNode {
+
+        @Specialization
+        int f0(int a) {
+            return a;
+        }
+
+        @ExpectError("Duplicate contains declaration 'f0'.")
+        @Specialization(contains = {"f0", "f0"})
+        Object f1(double a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsError4 extends ValueNode {
+
+        @ExpectError("Circular contained specialization 'f1(double)' found.")
+        @Specialization(contains = {"f1"})
+        Object f1(double a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsError5 extends ValueNode {
+
+        @ExpectError({"Circular contained specialization 'f0(int)' found.", "Circular contained specialization 'f1(double)' found.",
+                        "The contained specialization 'f1' must be declared before the containing specialization."})
+        @Specialization(contains = "f1")
+        int f0(int a) {
+            return a;
+        }
+
+        @ExpectError("Circular contained specialization 'f1(double)' found.")
+        @Specialization(contains = {"f0"})
+        Object f1(double a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsType1 extends ValueNode {
+        @Specialization
+        int f0(int a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by f0(int).")
+        @Specialization(contains = "f0")
+        Object f1(int a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsType2 extends ValueNode {
+        @Specialization
+        int f0(int a) {
+            return a;
+        }
+
+        @Specialization(contains = "f0")
+        Object f1(Object a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsType3 extends ValueNode {
+        @Specialization
+        int f0(int a) {
+            return a;
+        }
+
+        @Specialization(contains = "f0")
+        Object f1(double a) { // implicit type
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsType4 extends ValueNode {
+        @Specialization
+        double f0(double a) {
+            return a;
+        }
+
+        @ExpectError({"Specialization is not reachable. It is shadowed by f0(double).", "The contained specialization 'f0' is not fully compatible.%"})
+        @Specialization(contains = "f0")
+        int f1(int a) { // implicit type
+            return a;
+        }
+    }
+
+    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
+    abstract static class ContainsType5 extends ValueNode {
+        @Specialization
+        Object f0(Object a, int b) {
+            return a;
+        }
+
+        @ExpectError("The contained specialization 'f0' is not fully compatible.%")
+        @Specialization(contains = "f0")
+        Object f1(int a, Object b) {
+            return a;
+        }
+    }
+
+    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
+    abstract static class ContainsType6 extends ValueNode {
+        @Specialization
+        Object f0(double a, int b) {
+            return a;
+        }
+
+        @ExpectError("The contained specialization 'f0' is not fully compatible.%")
+        @Specialization(contains = "f0")
+        Object f1(int a, double b) { // implicit type
+            return a;
+        }
+    }
+
+    abstract static class ContainsGuard1 extends ValueNode {
+
+        boolean g1() {
+            return true;
+        }
+
+        @Specialization(guards = "g1")
+        Object f0() {
+            return null;
+        }
+
+        @Specialization(contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsGuard2 extends ValueNode {
+
+        boolean g1() {
+            return true;
+        }
+
+        @Specialization()
+        Object f0() {
+            return null;
+        }
+
+        @ExpectError({"Specialization is not reachable. It is shadowed by f0().", "The contained specialization 'f0' is not fully compatible.%"})
+        @Specialization(guards = "g1", contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsGuard3 extends ValueNode {
+
+        boolean g1() {
+            return true;
+        }
+
+        @Specialization(guards = "g1")
+        Object f0() {
+            return null;
+        }
+
+        @ExpectError({"The contained specialization 'f0' is not fully compatible.%"})
+        @Specialization(guards = "!g1", contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsGuard4 extends ValueNode {
+
+        boolean g1() {
+            return true;
+        }
+
+        boolean g2() {
+            return true;
+        }
+
+        @Specialization(guards = "g1")
+        Object f0() {
+            return null;
+        }
+
+        @ExpectError({"The contained specialization 'f0' is not fully compatible.%"})
+        @Specialization(guards = "g2", contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsGuard5 extends ValueNode {
+
+        @Implies("g2")
+        boolean g1() {
+            return true;
+        }
+
+        boolean g2() {
+            return true;
+        }
+
+        @Specialization(guards = "g1")
+        Object f0() {
+            return null;
+        }
+
+        @Specialization(guards = "g2", contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsGuard6 extends ValueNode {
+
+        @Implies("!g2")
+        boolean g1() {
+            return true;
+        }
+
+        boolean g2() {
+            return true;
+        }
+
+        @Specialization(guards = "g1")
+        Object f0() {
+            return null;
+        }
+
+        @Specialization(guards = "!g2", contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsGuard7 extends ValueNode {
+
+        boolean g1() {
+            return true;
+        }
+
+        boolean g2() {
+            return true;
+        }
+
+        @Specialization(guards = {"g1", "g2"})
+        Object f0() {
+            return null;
+        }
+
+        @Specialization(guards = "g2", contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    @NodeAssumptions("a1")
+    abstract static class ContainsAssumption1 extends ValueNode {
+
+        @Specialization(assumptions = "a1")
+        Object f0() {
+            return null;
+        }
+
+        @Specialization(contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    @NodeAssumptions("a1")
+    abstract static class ContainsAssumption2 extends ValueNode {
+
+        @Specialization
+        Object f0() {
+            return null;
+        }
+
+        @ExpectError({"Specialization is not reachable. It is shadowed by f0().", "The contained specialization 'f0' is not fully compatible.%"})
+        @Specialization(contains = "f0", assumptions = "a1")
+        Object f1() {
+            return null;
+        }
+    }
+
+    @NodeAssumptions({"a1", "a2"})
+    abstract static class ContainsAssumption3 extends ValueNode {
+
+        @Specialization(assumptions = "a1")
+        Object f0() {
+            return null;
+        }
+
+        @ExpectError({"The contained specialization 'f0' is not fully compatible.%"})
+        @Specialization(contains = "f0", assumptions = "a2")
+        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)
+        Object f0() throws RuntimeException {
+            throw new RuntimeException();
+        }
+
+        @Specialization(contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsThrowable2 extends ValueNode {
+
+        @Specialization(rewriteOn = RuntimeException.class)
+        Object f0() throws RuntimeException {
+            throw new RuntimeException();
+        }
+
+        @Specialization(contains = "f0", rewriteOn = RuntimeException.class)
+        Object f1() throws RuntimeException {
+            throw new RuntimeException();
+        }
+
+        @Specialization(contains = "f1")
+        Object f2() {
+            return null;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java	Mon Aug 11 15:53:05 2014 +0200
@@ -0,0 +1,186 @@
+/*
+ * 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.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.FallbackTestFactory.Fallback1Factory;
+import com.oracle.truffle.api.dsl.test.FallbackTestFactory.Fallback2Factory;
+import com.oracle.truffle.api.dsl.test.FallbackTestFactory.Fallback3Factory;
+import com.oracle.truffle.api.dsl.test.FallbackTestFactory.Fallback4Factory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.*;
+import com.oracle.truffle.api.nodes.*;
+
+public class FallbackTest {
+
+    private static final Object UNKNOWN_OBJECT = new Object() {
+    };
+
+    @Test
+    public void testFallback1() {
+        assertRuns(Fallback1Factory.getInstance(), //
+                        array(42, UNKNOWN_OBJECT), //
+                        array("(int)", "(fallback)"));
+    }
+
+    /**
+     * test with fallback handler defined
+     */
+    @SuppressWarnings("unused")
+    @NodeChild("a")
+    abstract static class Fallback1 extends ValueNode {
+
+        @Specialization
+        String f1(int a) {
+            return "(int)";
+        }
+
+        @Generic
+        String f2(Object a) {
+            return "(fallback)";
+        }
+    }
+
+    @Test
+    public void testFallback2() {
+        assertRuns(Fallback2Factory.getInstance(), //
+                        array(42, UNKNOWN_OBJECT), //
+                        array("(int)", UnsupportedSpecializationException.class));
+    }
+
+    /**
+     * test without fallback handler defined
+     */
+    @SuppressWarnings("unused")
+    @NodeChild("a")
+    abstract static class Fallback2 extends ValueNode {
+
+        @Specialization
+        String f1(int a) {
+            return "(int)";
+        }
+
+    }
+
+    @Test
+    public void testFallback3() {
+        assertRuns(Fallback3Factory.getInstance(), //
+                        array(42, 43, UNKNOWN_OBJECT, "somestring"), //
+                        array("(int)", "(int)", "(object)", "(object)"));
+    }
+
+    /**
+     * test without fallback handler and unreachable
+     */
+    @SuppressWarnings("unused")
+    @NodeChild("a")
+    abstract static class Fallback3 extends ValueNode {
+
+        @Specialization
+        String f1(int a) {
+            return "(int)";
+        }
+
+        @Specialization(guards = "notInt")
+        String f2(Object a) {
+            return "(object)";
+        }
+
+        boolean notInt(Object value) {
+            return !(value instanceof Integer);
+        }
+
+    }
+
+    /**
+     * Tests the contents of the {@link UnsupportedSpecializationException} contents in polymorphic
+     * nodes.
+     */
+    @Test
+    public void testFallback4() {
+        TestRootNode<Fallback4> node = createRoot(Fallback4Factory.getInstance());
+
+        Assert.assertEquals("(int)", executeWith(node, 1));
+        Assert.assertEquals("(boolean)", executeWith(node, true));
+        try {
+            executeWith(node, UNKNOWN_OBJECT);
+            Assert.fail();
+        } catch (UnsupportedSpecializationException e) {
+            Assert.assertEquals(node.getNode(), e.getNode());
+            Assert.assertArrayEquals(NodeUtil.findNodeChildren(node.getNode()).subList(0, 1).toArray(new Node[0]), e.getSuppliedNodes());
+            Assert.assertArrayEquals(new Object[]{UNKNOWN_OBJECT}, e.getSuppliedValues());
+        }
+    }
+
+    /**
+     * test without fallback handler and unreachable
+     */
+    @SuppressWarnings("unused")
+    @NodeChild("a")
+    abstract static class Fallback4 extends ValueNode {
+
+        @Specialization
+        String f1(int a) {
+            return "(int)";
+        }
+
+        @Specialization
+        String f2(boolean a) {
+            return "(boolean)";
+        }
+    }
+
+    /**
+     * Tests the contents of the {@link UnsupportedSpecializationException} contents in monomorphic
+     * nodes.
+     */
+    @Test
+    public void testFallback5() {
+        TestRootNode<Fallback4> node = createRoot(Fallback4Factory.getInstance());
+
+        Assert.assertEquals("(int)", executeWith(node, 1));
+        try {
+            executeWith(node, UNKNOWN_OBJECT);
+            Assert.fail();
+        } catch (UnsupportedSpecializationException e) {
+            Assert.assertEquals(node.getNode(), e.getNode());
+            Assert.assertArrayEquals(NodeUtil.findNodeChildren(node.getNode()).subList(0, 1).toArray(new Node[0]), e.getSuppliedNodes());
+            Assert.assertArrayEquals(new Object[]{UNKNOWN_OBJECT}, e.getSuppliedValues());
+        }
+    }
+
+    // test without fallback handler and unreachable
+    @SuppressWarnings("unused")
+    @NodeChild("a")
+    abstract static class Fallback5 extends ValueNode {
+
+        @Specialization
+        String f1(int a) {
+            return "(int)";
+        }
+    }
+
+}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/GuardsTest.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,315 +0,0 @@
-/*
- * 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.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GlobalFlagGuardFactory;
-import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GuardWithBaseClassFactory;
-import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GuardWithBaseInterfaceFactory;
-import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GuardWithBoxedPrimitiveFactory;
-import com.oracle.truffle.api.dsl.test.GuardsTestFactory.GuardWithObjectFactory;
-import com.oracle.truffle.api.dsl.test.GuardsTestFactory.InvocationGuardFactory;
-import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestAbstractGuard1Factory;
-import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve1Factory;
-import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve2Factory;
-import com.oracle.truffle.api.dsl.test.GuardsTestFactory.TestGuardResolve3Factory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.Abstract;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.BExtendsAbstract;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.CExtendsAbstract;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-@SuppressWarnings("unused")
-public class GuardsTest {
-
-    private static final Object NULL = new Object();
-
-    @Test
-    public void testGuardInvocations() {
-        TestRootNode<InvocationGuard> root = createRoot(InvocationGuardFactory.getInstance());
-
-        assertEquals(Integer.MAX_VALUE, executeWith(root, Integer.MAX_VALUE - 1, 1));
-        assertEquals(1, InvocationGuard.specializedInvocations);
-        assertEquals(0, InvocationGuard.genericInvocations);
-
-        assertEquals(42, executeWith(root, Integer.MAX_VALUE, 1));
-        assertEquals(1, InvocationGuard.specializedInvocations);
-        assertEquals(1, InvocationGuard.genericInvocations);
-    }
-
-    @NodeChildren({@NodeChild("value0"), @NodeChild("value1")})
-    public abstract static class InvocationGuard extends ValueNode {
-
-        static int specializedInvocations = 0;
-        static int genericInvocations = 0;
-
-        boolean guard(int value0, int value1) {
-            return value0 != Integer.MAX_VALUE;
-        }
-
-        @Specialization(guards = "guard")
-        int doSpecialized(int value0, int value1) {
-            specializedInvocations++;
-            return value0 + value1;
-        }
-
-        @Generic
-        int doGeneric(Object value0, Object value1) {
-            genericInvocations++;
-            return 42; // the generic answer to all questions
-        }
-    }
-
-    @Test
-    public void testGuardGlobal() {
-        TestRootNode<GlobalFlagGuard> root = createRoot(GlobalFlagGuardFactory.getInstance());
-
-        assertEquals(42, executeWith(root, NULL));
-
-        GlobalFlagGuard.globalFlag = true;
-        assertEquals(41, executeWith(root, NULL));
-
-        GlobalFlagGuard.globalFlag = false;
-        assertEquals(42, executeWith(root, NULL));
-    }
-
-    @NodeChild("expression")
-    public abstract static class GlobalFlagGuard extends ValueNode {
-
-        static boolean globalFlag = false;
-
-        static boolean globalFlagGuard() {
-            return globalFlag;
-        }
-
-        @Specialization(guards = "globalFlagGuard")
-        int doSpecialized(Object value0) {
-            return 41;
-        }
-
-        @Generic
-        int doGeneric(Object value0) {
-            return 42; // the generic answer to all questions
-        }
-    }
-
-    @Test
-    public void testGuardWithBaseClass() {
-        TestRootNode<?> root = createRoot(GuardWithBaseClassFactory.getInstance());
-
-        assertEquals(42, executeWith(root, new BExtendsAbstract()));
-    }
-
-    @NodeChild("expression")
-    public abstract static class GuardWithBaseClass extends ValueNode {
-
-        boolean baseGuard(Abstract base) {
-            return true;
-        }
-
-        @Specialization(guards = "baseGuard")
-        int doSpecialized(BExtendsAbstract value0) {
-            return 42;
-        }
-    }
-
-    @Test
-    public void testGuardWithBaseInterface() {
-        TestRootNode<?> root = createRoot(GuardWithBaseInterfaceFactory.getInstance());
-
-        assertEquals(42, executeWith(root, "anything"));
-    }
-
-    @NodeChild("expression")
-    public abstract static class GuardWithBaseInterface extends ValueNode {
-
-        boolean baseGuard(CharSequence base) {
-            return true;
-        }
-
-        @Specialization(guards = "baseGuard")
-        int doSpecialized(String value0) {
-            return 42;
-        }
-    }
-
-    @Test
-    public void testGuardWithPrimitive() {
-        TestRootNode<?> root = createRoot(GuardWithBoxedPrimitiveFactory.getInstance());
-
-        assertEquals(42, executeWith(root, 42));
-    }
-
-    @NodeChild("expression")
-    public abstract static class GuardWithBoxedPrimitive extends ValueNode {
-
-        boolean baseGuard(Integer primitive) {
-            return true;
-        }
-
-        @Specialization(guards = "baseGuard")
-        int doSpecialized(int value0) {
-            return value0;
-        }
-    }
-
-    @Test
-    public void testGuardWithObject() {
-        TestRootNode<?> root = createRoot(GuardWithObjectFactory.getInstance());
-
-        assertEquals(42, executeWith(root, 42));
-    }
-
-    @NodeChild("expression")
-    public abstract static class GuardWithObject extends ValueNode {
-
-        boolean baseGuard(Object primitive) {
-            return true;
-        }
-
-        @Specialization(guards = "baseGuard")
-        int doSpecialized(int value0) {
-            return value0;
-        }
-    }
-
-    @Test
-    public void testGuardResolve1() {
-        TestRootNode<?> root = createRoot(TestGuardResolve1Factory.getInstance());
-
-        assertEquals(42, executeWith(root, 42));
-    }
-
-    @NodeChild("expression")
-    public abstract static class TestGuardResolve1 extends ValueNode {
-
-        boolean guard(Object primitive) {
-            return false;
-        }
-
-        boolean guard(int primitive) {
-            return true;
-        }
-
-        @Specialization(guards = "guard")
-        int doSpecialized(int value0) {
-            return value0;
-        }
-    }
-
-    @Test
-    public void testGuardResolve2() {
-        TestRootNode<?> root = createRoot(TestGuardResolve2Factory.getInstance());
-        assertEquals(42, executeWith(root, new BExtendsAbstract()));
-    }
-
-    @NodeChild("expression")
-    public abstract static class TestGuardResolve2 extends ValueNode {
-
-        boolean guard(Object primitive) {
-            return false;
-        }
-
-        boolean guard(Abstract primitive) {
-            return true;
-        }
-
-        @Specialization(guards = "guard")
-        int doSpecialized(BExtendsAbstract value0) {
-            return 42;
-        }
-    }
-
-    @Test
-    public void testGuardResolve3() {
-        TestRootNode<?> root = createRoot(TestGuardResolve3Factory.getInstance());
-
-        assertEquals(42, executeWith(root, new BExtendsAbstract()));
-    }
-
-    @NodeChild("expression")
-    public abstract static class TestGuardResolve3 extends ValueNode {
-
-        boolean guard(Object primitive) {
-            return false;
-        }
-
-        boolean guard(Abstract primitive) {
-            return false;
-        }
-
-        boolean guard(BExtendsAbstract primitive) {
-            return true;
-        }
-
-        @Specialization(guards = "guard")
-        int doSpecialized(BExtendsAbstract value0) {
-            return 42;
-        }
-    }
-
-    @NodeChild("expression")
-    public abstract static class TestGuardResolve4 extends ValueNode {
-
-        boolean guard(Abstract primitive) {
-            return false;
-        }
-
-        @Specialization(guards = "guard")
-        int doSpecialized(BExtendsAbstract value0) {
-            return 42;
-        }
-    }
-
-    @Test
-    public void testAbstractGuard1() {
-        TestRootNode<?> root = createRoot(TestAbstractGuard1Factory.getInstance());
-
-        assertEquals(BExtendsAbstract.INSTANCE, executeWith(root, BExtendsAbstract.INSTANCE));
-        assertEquals(CExtendsAbstract.INSTANCE, executeWith(root, CExtendsAbstract.INSTANCE));
-    }
-
-    @NodeChild("expression")
-    public abstract static class TestAbstractGuard1 extends ValueNode {
-
-        boolean guard(Abstract value0) {
-            return true;
-        }
-
-        @Specialization(order = 1, guards = "guard")
-        BExtendsAbstract doSpecialized1(BExtendsAbstract value0) {
-            return value0;
-        }
-
-        @Specialization(order = 2, guards = "guard")
-        CExtendsAbstract doSpecialized2(CExtendsAbstract value0) {
-            return value0;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java	Mon Aug 11 15:53:05 2014 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java	Mon Aug 11 15:53:05 2014 +0200
@@ -34,7 +34,7 @@
 
 public class ImplicitCastTest {
 
-    @TypeSystem({int.class, boolean.class, String.class})
+    @TypeSystem({int.class, String.class, boolean.class})
     static class ImplicitCast0Types {
 
         @ImplicitCast
@@ -55,12 +55,12 @@
 
         public abstract Object executeEvaluated(VirtualFrame frame, Object value2);
 
-        @Specialization(order = 1)
+        @Specialization
         public String op1(String value) {
             return value;
         }
 
-        @Specialization(order = 2)
+        @Specialization
         public boolean op1(boolean value) {
             return value;
         }
@@ -81,22 +81,21 @@
 
     @TypeSystemReference(ImplicitCast0Types.class)
     @NodeChild(value = "operand", type = ImplicitCast1Node.class)
-    // TODO temporary workaround
     abstract static class ImplicitCast1Node extends ValueNode {
 
         public abstract Object executeEvaluated(VirtualFrame frame, Object operand);
 
-        @Specialization(order = 0)
+        @Specialization
         public String op0(String value) {
             return value;
         }
 
-        @Specialization(order = 1, rewriteOn = RuntimeException.class)
+        @Specialization(rewriteOn = RuntimeException.class)
         public boolean op1(@SuppressWarnings("unused") boolean value) throws RuntimeException {
             throw new RuntimeException();
         }
 
-        @Specialization(order = 2)
+        @Specialization(contains = "op1")
         public boolean op2(boolean value) {
             return value;
         }
@@ -120,18 +119,18 @@
     // TODO temporary workaround
     abstract static class ImplicitCast2Node extends ValueNode {
 
-        @Specialization(order = 0)
+        @Specialization
         public String op0(String v0, String v1) {
             return v0 + v1;
         }
 
         @SuppressWarnings("unused")
-        @Specialization(order = 1, rewriteOn = RuntimeException.class)
+        @Specialization(rewriteOn = RuntimeException.class)
         public boolean op1(boolean v0, boolean v1) throws RuntimeException {
             throw new RuntimeException();
         }
 
-        @Specialization(order = 2)
+        @Specialization(contains = "op1")
         public boolean op2(boolean v0, boolean v1) {
             return v0 && v1;
         }
@@ -156,4 +155,15 @@
         Assert.assertEquals(true, root.getNode().executeEvaluated(null, true, true));
     }
 
+    @TypeSystem({String.class, boolean.class})
+    static class ImplicitCastError1 {
+
+        @ImplicitCast
+        @ExpectError("Target type and source type of an @ImplicitCast must not be the same type.")
+        String castInvalid(@SuppressWarnings("unused") String value) {
+            throw new AssertionError();
+        }
+
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/InsertBeforeTest.java	Mon Aug 11 15:53:05 2014 +0200
@@ -0,0 +1,144 @@
+/*
+ * 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.dsl.test;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class InsertBeforeTest {
+
+    @NodeChild("a")
+    static class InsertBefore1Base extends ValueNode {
+
+        boolean g1(int a) {
+            return a == 1;
+        }
+
+        boolean g2(int a) {
+            return a == 2;
+        }
+
+        @Specialization(guards = "g1")
+        int f1(int a) {
+            return a;
+        }
+
+        @Specialization(guards = "g2")
+        int f3(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    static class InsertBefore1T1 extends InsertBefore1Base {
+
+        @Specialization
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    static class InsertBefore1T2 extends InsertBefore1Base {
+
+        boolean g0(int a) {
+            return a == 0;
+        }
+
+        @Specialization(guards = "g0", insertBefore = "f1")
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    static class InsertBefore1T3 extends InsertBefore1Base {
+
+        boolean g0(int a) {
+            return a == 0;
+        }
+
+        @Specialization(guards = "g0", insertBefore = "f3")
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    @ExpectError({"Element int f3(int)  at annotation @Specialization is erroneous: Specialization is not reachable. It is shadowed by f0(int).",
+                    "Element int f1(int)  at annotation @Specialization is erroneous: Specialization is not reachable. It is shadowed by f0(int)."})
+    static class InsertBefore1T4 extends InsertBefore1Base {
+
+        boolean g0(int a) {
+            return a == 0;
+        }
+
+        @Specialization(insertBefore = "f1")
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    @ExpectError({"Element int f3(int)  at annotation @Specialization is erroneous: Specialization is not reachable. It is shadowed by f0(int)."})
+    static class InsertBefore1T5 extends InsertBefore1Base {
+
+        boolean g0(int a) {
+            return a == 0;
+        }
+
+        @Specialization(insertBefore = "f3")
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    static class InsertBefore1Error1 extends InsertBefore1Base {
+
+        @ExpectError("Specializations can only be inserted before specializations in superclasses.")
+        @Specialization(insertBefore = "f0")
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    static class InsertBefore1Error2 extends InsertBefore1Base {
+
+        @ExpectError("The referenced specialization 'asdf' could not be found.")
+        @Specialization(insertBefore = "asdf")
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java	Mon Aug 11 15:53:05 2014 +0200
@@ -0,0 +1,308 @@
+/*
+ * 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.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GlobalFlagGuardFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardWithBaseClassFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardWithBoxedPrimitiveFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardWithObjectFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.InvocationGuardFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.TestAbstractGuard1Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.TestGuardResolve1Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.TestGuardResolve2Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.TestGuardResolve3Factory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.Abstract;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.BExtendsAbstract;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.CExtendsAbstract;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+@SuppressWarnings("unused")
+public class MethodGuardsTest {
+
+    private static final Object NULL = new Object();
+
+    @Test
+    public void testGuardInvocations() {
+        TestRootNode<InvocationGuard> root = createRoot(InvocationGuardFactory.getInstance());
+
+        assertEquals(Integer.MAX_VALUE, executeWith(root, Integer.MAX_VALUE - 1, 1));
+        assertEquals(1, InvocationGuard.specializedInvocations);
+        assertEquals(0, InvocationGuard.genericInvocations);
+
+        assertEquals(42, executeWith(root, Integer.MAX_VALUE, 1));
+        assertEquals(1, InvocationGuard.specializedInvocations);
+        assertEquals(1, InvocationGuard.genericInvocations);
+    }
+
+    @NodeChildren({@NodeChild("value0"), @NodeChild("value1")})
+    public abstract static class InvocationGuard extends ValueNode {
+
+        static int specializedInvocations = 0;
+        static int genericInvocations = 0;
+
+        boolean guard(int value0, int value1) {
+            return value0 != Integer.MAX_VALUE;
+        }
+
+        @Specialization(guards = "guard")
+        int doSpecialized(int value0, int value1) {
+            specializedInvocations++;
+            return value0 + value1;
+        }
+
+        @Generic
+        int doGeneric(Object value0, Object value1) {
+            genericInvocations++;
+            return 42; // the generic answer to all questions
+        }
+    }
+
+    @Test
+    public void testGuardGlobal() {
+        TestRootNode<GlobalFlagGuard> root = createRoot(GlobalFlagGuardFactory.getInstance());
+
+        assertEquals(42, executeWith(root, NULL));
+
+        GlobalFlagGuard.globalFlag = true;
+        assertEquals(41, executeWith(root, NULL));
+
+        GlobalFlagGuard.globalFlag = false;
+        assertEquals(42, executeWith(root, NULL));
+    }
+
+    @NodeChild("expression")
+    public abstract static class GlobalFlagGuard extends ValueNode {
+
+        static boolean globalFlag = false;
+
+        static boolean globalFlagGuard() {
+            return globalFlag;
+        }
+
+        @Specialization(guards = "globalFlagGuard")
+        int doSpecialized(Object value0) {
+            return 41;
+        }
+
+        @Generic
+        int doGeneric(Object value0) {
+            return 42; // the generic answer to all questions
+        }
+    }
+
+    @Test
+    public void testGuardWithBaseClass() {
+        TestRootNode<?> root = createRoot(GuardWithBaseClassFactory.getInstance());
+
+        assertEquals(42, executeWith(root, new BExtendsAbstract()));
+    }
+
+    @NodeChild("expression")
+    public abstract static class GuardWithBaseClass extends ValueNode {
+
+        boolean baseGuard(Abstract base) {
+            return true;
+        }
+
+        @Specialization(guards = "baseGuard")
+        int doSpecialized(BExtendsAbstract value0) {
+            return 42;
+        }
+    }
+
+    @NodeChild("expression")
+    public abstract static class GuardWithBaseInterface extends ValueNode {
+
+        boolean baseGuard(CharSequence base) {
+            return true;
+        }
+
+        @Specialization(guards = "baseGuard")
+        @ExpectError("No compatible guard with method name 'baseGuard' found. Please note that all signature types of the method guard must be declared in the type system.")
+        int doSpecialized(String value0) {
+            return 42;
+        }
+    }
+
+    @Test
+    public void testGuardWithPrimitive() {
+        TestRootNode<?> root = createRoot(GuardWithBoxedPrimitiveFactory.getInstance());
+
+        assertEquals(42, executeWith(root, 42));
+    }
+
+    @NodeChild("expression")
+    public abstract static class GuardWithBoxedPrimitive extends ValueNode {
+
+        boolean baseGuard(Integer primitive) {
+            return true;
+        }
+
+        @Specialization(guards = "baseGuard")
+        int doSpecialized(int value0) {
+            return value0;
+        }
+    }
+
+    @Test
+    public void testGuardWithObject() {
+        TestRootNode<?> root = createRoot(GuardWithObjectFactory.getInstance());
+
+        assertEquals(42, executeWith(root, 42));
+    }
+
+    @NodeChild("expression")
+    public abstract static class GuardWithObject extends ValueNode {
+
+        boolean baseGuard(Object primitive) {
+            return true;
+        }
+
+        @Specialization(guards = "baseGuard")
+        int doSpecialized(int value0) {
+            return value0;
+        }
+    }
+
+    @Test
+    public void testGuardResolve1() {
+        TestRootNode<?> root = createRoot(TestGuardResolve1Factory.getInstance());
+
+        assertEquals(42, executeWith(root, 42));
+    }
+
+    @NodeChild("expression")
+    public abstract static class TestGuardResolve1 extends ValueNode {
+
+        boolean guard(Object primitive) {
+            return false;
+        }
+
+        boolean guard(int primitive) {
+            return true;
+        }
+
+        @Specialization(guards = "guard")
+        int doSpecialized(int value0) {
+            return value0;
+        }
+    }
+
+    @Test
+    public void testGuardResolve2() {
+        TestRootNode<?> root = createRoot(TestGuardResolve2Factory.getInstance());
+        assertEquals(42, executeWith(root, new BExtendsAbstract()));
+    }
+
+    @NodeChild("expression")
+    public abstract static class TestGuardResolve2 extends ValueNode {
+
+        boolean guard(Object primitive) {
+            return false;
+        }
+
+        boolean guard(Abstract primitive) {
+            return true;
+        }
+
+        @Specialization(guards = "guard")
+        int doSpecialized(BExtendsAbstract value0) {
+            return 42;
+        }
+    }
+
+    @Test
+    public void testGuardResolve3() {
+        TestRootNode<?> root = createRoot(TestGuardResolve3Factory.getInstance());
+
+        assertEquals(42, executeWith(root, new BExtendsAbstract()));
+    }
+
+    @NodeChild("expression")
+    public abstract static class TestGuardResolve3 extends ValueNode {
+
+        boolean guard(Object primitive) {
+            return false;
+        }
+
+        boolean guard(Abstract primitive) {
+            return false;
+        }
+
+        boolean guard(BExtendsAbstract primitive) {
+            return true;
+        }
+
+        @Specialization(guards = "guard")
+        int doSpecialized(BExtendsAbstract value0) {
+            return 42;
+        }
+    }
+
+    @NodeChild("expression")
+    public abstract static class TestGuardResolve4 extends ValueNode {
+
+        boolean guard(Abstract primitive) {
+            return false;
+        }
+
+        @Specialization(guards = "guard")
+        int doSpecialized(BExtendsAbstract value0) {
+            return 42;
+        }
+    }
+
+    @Test
+    public void testAbstractGuard1() {
+        TestRootNode<?> root = createRoot(TestAbstractGuard1Factory.getInstance());
+
+        assertEquals(BExtendsAbstract.INSTANCE, executeWith(root, BExtendsAbstract.INSTANCE));
+        assertEquals(CExtendsAbstract.INSTANCE, executeWith(root, CExtendsAbstract.INSTANCE));
+    }
+
+    @NodeChild("expression")
+    public abstract static class TestAbstractGuard1 extends ValueNode {
+
+        boolean guard(Abstract value0) {
+            return true;
+        }
+
+        @Specialization(guards = "guard")
+        BExtendsAbstract do1(BExtendsAbstract value0) {
+            return value0;
+        }
+
+        @Specialization(guards = "guard")
+        CExtendsAbstract do2(CExtendsAbstract value0) {
+            return value0;
+        }
+    }
+
+}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java	Mon Aug 11 15:53:05 2014 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java	Mon Aug 11 15:53:05 2014 +0200
@@ -45,12 +45,12 @@
             return true;
         }
 
-        @Specialization(order = 1, guards = "!guard")
+        @Specialization(guards = "!guard")
         int do1() {
             throw new AssertionError();
         }
 
-        @Specialization(order = 2)
+        @Specialization()
         int do2() {
             return 42; // the generic answer to all questions
         }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java	Mon Aug 11 15:53:05 2014 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java	Mon Aug 11 15:53:05 2014 +0200
@@ -117,12 +117,12 @@
 
         public abstract String getField();
 
-        @Specialization(order = 1, rewriteOn = RuntimeException.class)
+        @Specialization(rewriteOn = RuntimeException.class)
         String alwaysRewrite() {
             throw new RuntimeException();
         }
 
-        @Specialization(order = 2)
+        @Specialization(contains = "alwaysRewrite")
         String returnField() {
             return getField();
         }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java	Mon Aug 11 15:53:05 2014 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java	Mon Aug 11 15:53:05 2014 +0200
@@ -25,11 +25,15 @@
 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.dsl.*;
-import com.oracle.truffle.api.dsl.test.BinaryNodeTest.BinaryNode;
-import com.oracle.truffle.api.dsl.test.PolymorphicTestFactory.Node1Factory;
+import com.oracle.truffle.api.dsl.test.PolymorphicTestFactory.Polymorphic1Factory;
+import com.oracle.truffle.api.dsl.test.PolymorphicTestFactory.Polymorphic2Factory;
+import com.oracle.truffle.api.dsl.test.PolymorphicTestFactory.Polymorphic3Factory;
+import com.oracle.truffle.api.dsl.test.TestHelper.ExecutionListener;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
 import com.oracle.truffle.api.nodes.*;
@@ -47,103 +51,155 @@
         }
     }
 
+    public static void assertNoDuplicates(Node node, Node... ignored) {
+        assertNoDuplicatesRec(new HashSet<>(Arrays.asList(ignored)), new HashSet<Class<?>>(), node);
+    }
+
+    private static void assertNoDuplicatesRec(Set<Node> ignored, Set<Class<?>> seenClasses, Node current) {
+        if (!ignored.contains(current)) {
+            if (seenClasses.contains(current.getClass())) {
+                Assert.fail(String.format("Multiple occurences of the same class %s. %nTree: %s", current.getClass().getSimpleName(), NodeUtil.printCompactTreeToString(current.getRootNode())));
+            } else {
+                seenClasses.add(current.getClass());
+            }
+        }
+
+        for (Node child : current.getChildren()) {
+            if (child != null) {
+                assertNoDuplicatesRec(ignored, seenClasses, child);
+            }
+        }
+    }
+
     @Test
-    public void testJustSpecialize() {
-        TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
-        assertEquals("(int,int)", executeWith(node, 42, 42));
-        assertEquals("(boolean,boolean)", executeWith(node, false, false));
-        assertEquals("(int,boolean)", executeWith(node, 42, false));
-        assertEquals("(boolean,int)", executeWith(node, false, 42));
-        assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost());
-        assertParent(node.getNode(), node.getNode().getLeft());
-        assertParent(node.getNode(), node.getNode().getRight());
+    public void testPolymorphic1() {
+        assertRuns(Polymorphic1Factory.getInstance(), //
+                        array(42, 43, true, false, "a", "b"), //
+                        array(42, 43, true, false, "a", "b"),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                Polymorphic1 polymorphic = ((Polymorphic1) node.getNode());
+                                assertParent(node.getNode(), polymorphic.getA());
+                                assertNoDuplicates(polymorphic, polymorphic.getA());
+                                if (index == 0) {
+                                    assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost());
+                                }
+                            }
+                        });
+    }
+
+    @NodeChild("a")
+    abstract static class Polymorphic1 extends ValueNode {
+
+        public abstract ValueNode getA();
+
+        @Specialization
+        int add(int a) {
+            return a;
+        }
+
+        @Specialization
+        boolean add(boolean a) {
+            return a;
+        }
+
+        @Specialization
+        String add(String a) {
+            return a;
+        }
+
+        @Generic
+        String add(Object left) {
+            throw new AssertionError(left.toString());
+        }
+
     }
 
     @Test
     public void testPolymorphic2() {
-        TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
-        assertEquals("(int,boolean)", executeWith(node, 42, false));
-        assertEquals("(int,int)", executeWith(node, 42, 42));
-        assertEquals(NodeCost.POLYMORPHIC, node.getNode().getCost());
-        assertParent(node.getNode(), node.getNode().getLeft());
-        assertParent(node.getNode(), node.getNode().getRight());
+        assertRuns(Polymorphic2Factory.getInstance(), //
+                        array(0, 1, 1, "1", "2", 2, 3), //
+                        array(0, 1, 1, "1", "2", 2, 3),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                Polymorphic2 polymorphic = ((Polymorphic2) node.getNode());
+                                assertParent(node.getNode(), polymorphic.getA());
+                                assertNoDuplicates(polymorphic, polymorphic.getA());
+                                if (index == 0) {
+                                    assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost());
+                                }
+                            }
+                        });
+    }
+
+    @NodeChild("a")
+    abstract static class Polymorphic2 extends ValueNode {
+
+        public abstract ValueNode getA();
+
+        @Specialization
+        String s2(String a) {
+            return a;
+        }
+
+        @Specialization(rewriteOn = RuntimeException.class)
+        int s0(int a) {
+            if (a == 1) {
+                throw new RuntimeException();
+            }
+            return a;
+        }
+
+        @Specialization
+        int s1(int a) {
+            return a;
+        }
+
     }
 
     @Test
     public void testPolymorphic3() {
-        TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
-        assertEquals("(int,boolean)", executeWith(node, 42, false));
-        assertEquals("(boolean,boolean)", executeWith(node, true, false));
-        assertEquals("(int,int)", executeWith(node, 42, 42));
-        assertEquals(NodeCost.POLYMORPHIC, node.getNode().getCost());
-        assertParent(node.getNode(), node.getNode().getLeft());
-        assertParent(node.getNode(), node.getNode().getRight());
-    }
-
-    @Test
-    public void testGenericLimitReached() {
-        TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
-        assertEquals("(boolean,int)", executeWith(node, false, 42));
-        assertEquals("(int,boolean)", executeWith(node, 42, false));
-        assertEquals("(boolean,boolean)", executeWith(node, true, false));
-        assertEquals("(int,int)", executeWith(node, 42, 42));
-        assertEquals(NodeCost.MEGAMORPHIC, node.getNode().getCost());
-        assertParent(node.getNode(), node.getNode().getLeft());
-        assertParent(node.getNode(), node.getNode().getRight());
-    }
-
-    @Test
-    public void testGenericInitial() {
-        TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
-        assertEquals("(generic,generic)", executeWith(node, "1", "1"));
-        assertEquals(NodeCost.MEGAMORPHIC, node.getNode().getCost());
-        assertParent(node.getNode(), node.getNode().getLeft());
-        assertParent(node.getNode(), node.getNode().getRight());
+        assertRuns(Polymorphic3Factory.getInstance(), //
+                        array("0", "1", 1, 1, 2, 2, 3, 3), //
+                        array("0", "1", 1, 1, 2, 2, 3, 3),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                Polymorphic3 polymorphic = ((Polymorphic3) node.getNode());
+                                assertParent(node.getNode(), polymorphic.getA());
+                                assertNoDuplicates(polymorphic, polymorphic.getA());
+                            }
+                        });
     }
 
-    @Test
-    public void testGenericPolymorphic1() {
-        TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
-        assertEquals("(boolean,int)", executeWith(node, false, 42));
-        assertEquals("(boolean,boolean)", executeWith(node, false, false));
-        assertEquals("(generic,generic)", executeWith(node, "", ""));
-        assertEquals(NodeCost.MEGAMORPHIC, node.getNode().getCost());
-        /* Assertions for bug GRAAL-425 */
-        assertParent(node.getNode(), node.getNode().getLeft());
-        assertParent(node.getNode(), node.getNode().getRight());
-    }
+    @NodeChild("a")
+    abstract static class Polymorphic3 extends ValueNode {
 
-    @SuppressWarnings("unused")
-    @PolymorphicLimit(3)
-    abstract static class Node1 extends BinaryNode {
-
-        public abstract ValueNode getLeft();
+        public abstract ValueNode getA();
 
-        public abstract ValueNode getRight();
-
-        @Specialization(order = 1)
-        String add(int left, int right) {
-            return "(int,int)";
+        @Specialization
+        String s2(String a) {
+            return a;
         }
 
-        @Specialization(order = 2)
-        String add(boolean left, boolean right) {
-            return "(boolean,boolean)";
+        @Specialization(rewriteOn = RuntimeException.class)
+        int s0(int a) {
+            if (a == 1) {
+                throw new RuntimeException();
+            }
+            return a;
         }
 
-        @Specialization(order = 3)
-        String add(int left, boolean right) {
-            return "(int,boolean)";
+        @Specialization(rewriteOn = RuntimeException.class)
+        int s1(int a) {
+            if (a == 1) {
+                throw new RuntimeException();
+            }
+            return a;
         }
 
-        @Specialization(order = 4)
-        String add(boolean left, int right) {
-            return "(boolean,int)";
-        }
-
-        @Generic
-        String add(Object left, Object right) {
-            return "(generic,generic)";
+        @Specialization
+        int s2(int a) {
+            return a;
         }
 
     }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java	Mon Aug 11 15:53:05 2014 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java	Mon Aug 11 15:53:05 2014 +0200
@@ -29,7 +29,7 @@
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.dsl.test.BinaryNodeTest.BinaryNode;
-import com.oracle.truffle.api.dsl.test.PolymorphicTest2Factory.Node1Factory;
+import com.oracle.truffle.api.dsl.test.PolymorphicTest2Factory.Polymorphic1Factory;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
 import com.oracle.truffle.api.nodes.*;
 
@@ -38,7 +38,7 @@
     @Test
     public void testMultipleTypes() {
         /* Tests the unexpected polymorphic case. */
-        TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
+        TestRootNode<Polymorphic1> node = TestHelper.createRoot(Polymorphic1Factory.getInstance());
         assertEquals(21, executeWith(node, false, false));
         assertEquals(42, executeWith(node, 21, 21));
         assertEquals("(boolean,int)", executeWith(node, false, 42));
@@ -46,8 +46,7 @@
     }
 
     @SuppressWarnings("unused")
-    @PolymorphicLimit(3)
-    abstract static class Node1 extends BinaryNode {
+    abstract static class Polymorphic1 extends BinaryNode {
 
         @Specialization(order = 1)
         int add(int left, int right) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java	Mon Aug 11 15:53:05 2014 +0200
@@ -0,0 +1,353 @@
+package com.oracle.truffle.api.dsl.test;
+
+import java.math.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.*;
+
+public class ReachabilityTest {
+
+    static class Reachability1 extends ValueNode {
+        @Specialization
+        int do2() {
+            return 2;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
+        @Specialization
+        int do1() {
+            return 2;
+        }
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType1 extends ValueNode {
+        @Specialization
+        int do2(int a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2(int).")
+        @Specialization
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType2 extends ValueNode {
+        @Specialization
+        BExtendsAbstract do2(BExtendsAbstract a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2(BExtendsAbstract).")
+        @Specialization
+        BExtendsAbstract do1(BExtendsAbstract a) {
+            return a;
+        }
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType3 extends ValueNode {
+        @Specialization
+        Abstract do2(Abstract a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2(Abstract).")
+        @Specialization
+        BExtendsAbstract do1(BExtendsAbstract a) {
+            return a;
+        }
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType4 extends ValueNode {
+
+        @Specialization
+        BExtendsAbstract do2(BExtendsAbstract a) {
+            return a;
+        }
+
+        @Specialization
+        Abstract do1(Abstract a) {
+            return a;
+        }
+
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType5 extends ValueNode {
+
+        @Specialization
+        double do2(double a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2(double).")
+        @Specialization
+        int do1(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType6 extends ValueNode {
+
+        @Specialization
+        BigInteger do2(BigInteger a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2(BigInteger).")
+        @Specialization
+        int do1(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType7 extends ValueNode {
+
+        @Specialization
+        int do2(int a) {
+            return a;
+        }
+
+        @Specialization
+        BigInteger do1(BigInteger a) {
+            return a;
+        }
+
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType8 extends ValueNode {
+
+        @Specialization
+        int do2(int a) {
+            return a;
+        }
+
+        @Specialization
+        Object do1(Object a) {
+            return a;
+        }
+
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType9 extends ValueNode {
+
+        @Specialization
+        Object do2(Object a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2(Object).")
+        @Specialization
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    static class ReachabilityGuard1 extends ValueNode {
+
+        boolean foo() {
+            return false;
+        }
+
+        @Specialization(guards = "foo")
+        int do2() {
+            return 1;
+        }
+
+        @Specialization
+        int do1() {
+            return 2;
+        }
+
+    }
+
+    static class ReachabilityGuard2 extends ValueNode {
+
+        boolean foo() {
+            return false;
+        }
+
+        @Specialization
+        int do2() {
+            return 2;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
+        @Specialization(guards = "foo")
+        int do1() {
+            return 1;
+        }
+
+    }
+
+    static class ReachabilityGuard3 extends ValueNode {
+
+        boolean foo() {
+            return false;
+        }
+
+        @Specialization(guards = "foo")
+        int do2() {
+            return 1;
+        }
+
+        @Specialization
+        int do1() {
+            return 2;
+        }
+
+    }
+
+    static class ReachabilityGuard4 extends ValueNode {
+
+        boolean foo() {
+            return false;
+        }
+
+        @Specialization(guards = "foo")
+        int do2() {
+            return 1;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
+        @Specialization(guards = "foo")
+        int do1() {
+            return 2;
+        }
+
+    }
+
+    @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)
+        int do2() throws RuntimeException {
+            return 1;
+        }
+
+        @Specialization
+        int do1() {
+            return 2;
+        }
+
+    }
+
+    static class ReachabilityThrowable2 extends ValueNode {
+
+        @Specialization
+        int do2() {
+            return 1;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
+        @Specialization(rewriteOn = RuntimeException.class)
+        int do1() throws RuntimeException {
+            return 2;
+        }
+
+    }
+
+}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SlowPathTest.java	Mon Aug 11 15:53:05 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * 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.dsl.test;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.CompilerDirectives.SlowPath;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.SlowPathTestFactory.SlowPathOnGeneric0Factory;
-import com.oracle.truffle.api.dsl.test.SlowPathTestFactory.SlowPathOnGeneric1Factory;
-import com.oracle.truffle.api.dsl.test.SlowPathTestFactory.SlowPathOnGeneric2Factory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/** Tests the generated placement of {@link SlowPath} in generated methods. */
-public class SlowPathTest {
-
-    @Test
-    public void testSlowPathOnGeneric0() throws NoSuchMethodException, SecurityException {
-        Node node = SlowPathOnGeneric0Factory.create(null);
-        Assert.assertNull(node.getClass().getSuperclass().getDeclaredMethod("executeGeneric0", VirtualFrame.class, Object.class).getAnnotation(SlowPath.class));
-    }
-
-    @NodeChild
-    abstract static class SlowPathOnGeneric0 extends ValueNode {
-
-        @Specialization
-        @SuppressWarnings("unused")
-        Object doObject0(VirtualFrame frame, int value0) {
-            throw new AssertionError();
-        }
-
-    }
-
-    @Test
-    public void testSlowPathOnGeneric1() throws NoSuchMethodException, SecurityException {
-        Node node = SlowPathOnGeneric1Factory.create(null);
-        Assert.assertNotNull(node.getClass().getSuperclass().getDeclaredMethod("executeGeneric0", Object.class).getAnnotation(SlowPath.class));
-    }
-
-    @NodeChild
-    abstract static class SlowPathOnGeneric1 extends ValueNode {
-
-        @Specialization
-        @SuppressWarnings("unused")
-        Object doObject0(int value0) {
-            throw new AssertionError();
-        }
-
-    }
-
-    @Test
-    public void testSlowPathOnGeneric2() throws NoSuchMethodException, SecurityException {
-        Node node = SlowPathOnGeneric2Factory.create(null);
-        Assert.assertNull(node.getClass().getSuperclass().getDeclaredMethod("executeGeneric0", VirtualFrame.class, Object.class).getAnnotation(SlowPath.class));
-    }
-
-    @NodeChild
-    abstract static class SlowPathOnGeneric2 extends ValueNode {
-
-        @Specialization(order = 0)
-        @SuppressWarnings("unused")
-        Object doObject0(int value0) {
-            throw new AssertionError();
-        }
-
-        @Specialization(order = 1)
-        @SuppressWarnings("unused")
-        Object doObject1(VirtualFrame frame, String value0) {
-            throw new AssertionError();
-        }
-
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java	Mon Aug 11 15:53:05 2014 +0200
@@ -0,0 +1,350 @@
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest0Factory;
+import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest1Factory;
+import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest2Factory;
+import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest3Factory;
+import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest4Factory;
+import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest5Factory;
+import com.oracle.truffle.api.dsl.test.TestHelper.ExecutionListener;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class SpecializationFallthroughTest {
+
+    @Test
+    public void testFallthrough0() {
+        assertRuns(FallthroughTest0Factory.getInstance(), //
+                        array(0, 0, 1, 2), //
+                        array(0, 0, 1, 2),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (!last) {
+                                    return;
+                                }
+                                if (FallthroughTest0.fallthroughCount > 1) {
+                                    Assert.fail("The fallthrough case must never be triggered twice. Therfore count must be <= 1, but is not.");
+                                }
+                            }
+                        });
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughTest0 extends ValueNode {
+
+        static int fallthroughCount = 0;
+
+        public FallthroughTest0() {
+            fallthroughCount = 0;
+        }
+
+        @Specialization(rewriteOn = ArithmeticException.class)
+        int do1(int a) throws ArithmeticException {
+            if (a == 0) {
+                fallthroughCount++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Generic
+        Object doFallback(Object a) {
+            return a;
+        }
+    }
+
+    /*
+     * Tests that the fall through is never triggered twice for monomorphic cases.
+     */
+    @Test
+    public void testFallthrough1() {
+        assertRuns(FallthroughTest1Factory.getInstance(), //
+                        array(0, 0, 0, 1, 2), //
+                        array(0, 0, 0, 1, 2),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (!last) {
+                                    return;
+                                }
+                                if (FallthroughTest1.fallthroughCount > 1) {
+                                    Assert.fail("The fallthrough case must never be triggered twice. Therfore count must be <= 1, but is not.");
+                                }
+                            }
+                        });
+    }
+
+    /* TODO assert falltrough do1 before do2 */
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughTest1 extends ValueNode {
+
+        static int fallthroughCount;
+
+        public FallthroughTest1() {
+            fallthroughCount = 0;
+        }
+
+        @Specialization(rewriteOn = ArithmeticException.class)
+        int do1(int a) throws ArithmeticException {
+            if (a == 0) {
+                fallthroughCount++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Specialization
+        int do2(int a) {
+            return a;
+        }
+
+    }
+
+    /*
+     * Tests that the fall through is never triggered twice with two falltrhoughs in one operation.
+     */
+    @Test
+    public void testFallthrough2() {
+        assertRuns(FallthroughTest2Factory.getInstance(), //
+                        array(0, 0, 1, 1, 2, 2), //
+                        array(0, 0, 1, 1, 2, 2),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (!last) {
+                                    return;
+                                }
+                                if (FallthroughTest2.fallthrough1 > 1) {
+                                    Assert.fail();
+                                }
+                                if (FallthroughTest2.fallthrough2 > 1) {
+                                    Assert.fail();
+                                }
+                                FallthroughTest2.fallthrough1 = 0;
+                                FallthroughTest2.fallthrough2 = 0;
+                            }
+                        });
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughTest2 extends ValueNode {
+
+        static int fallthrough1;
+        static int fallthrough2;
+
+        @Specialization(order = 1, rewriteOn = ArithmeticException.class)
+        int do1(int a) throws ArithmeticException {
+            if (a == 0) {
+                fallthrough1++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Specialization(order = 2, rewriteOn = ArithmeticException.class)
+        int do2(int a) throws ArithmeticException {
+            if (a == 1) {
+                fallthrough2++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Specialization
+        int do3(int a) {
+            return a;
+        }
+    }
+
+    /*
+     * Tests that the fall through is never triggered twice. In this case mixed fallthrough with
+     * normal specializations.
+     */
+    @Test
+    public void testFallthrough3() {
+        assertRuns(FallthroughTest3Factory.getInstance(), //
+                        array(0, 0, 1, 1, 2, 2), //
+                        array(0, 0, 1, 1, 2, 2),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (!last) {
+                                    return;
+                                }
+                                if (FallthroughTest3.fallthrough1 > 1) {
+                                    Assert.fail(String.valueOf(FallthroughTest3.fallthrough1));
+                                }
+                                FallthroughTest3.fallthrough1 = 0;
+                            }
+                        });
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughTest3 extends ValueNode {
+
+        static int fallthrough1;
+
+        boolean guard0(int a) {
+            return a == 1;
+        }
+
+        @Specialization(guards = "guard0")
+        int do2(int a) {
+            return a;
+        }
+
+        @Specialization(rewriteOn = ArithmeticException.class)
+        int do1(int a) throws ArithmeticException {
+            if (a == 0) {
+                fallthrough1++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Specialization
+        int do3(int a) {
+            return a;
+        }
+
+    }
+
+    @Test
+    public void testFallthrough4() {
+        assertRuns(FallthroughTest4Factory.getInstance(), //
+                        array(0, 0, 1, 1, 2, 2), //
+                        array(0, 0, 1, 1, 2, 2),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (!last) {
+                                    return;
+                                }
+                                if (FallthroughTest4.fallthrough1 > 1) {
+                                    Assert.fail(String.valueOf(FallthroughTest4.fallthrough1));
+                                }
+                                if (FallthroughTest4.fallthrough2 > 1) {
+                                    Assert.fail(String.valueOf(FallthroughTest4.fallthrough1));
+                                }
+                                FallthroughTest4.fallthrough1 = 0;
+                                FallthroughTest4.fallthrough2 = 0;
+                            }
+                        });
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughTest4 extends ValueNode {
+
+        static int fallthrough1;
+        static int fallthrough2;
+
+        @Specialization(order = 1, rewriteOn = ArithmeticException.class)
+        int do1(int a) throws ArithmeticException {
+            if (a == 0) {
+                fallthrough1++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Specialization(order = 2, rewriteOn = ArithmeticException.class)
+        int do2(int a) throws ArithmeticException {
+            if (a == 1) {
+                fallthrough2++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Specialization
+        int do3(int a) {
+            return a;
+        }
+
+    }
+
+    @Test
+    public void testFallthrough5() {
+        assertRuns(FallthroughTest5Factory.getInstance(), //
+                        array(0, 0, 1, 1, 2, 2), //
+                        array(0, 0, 1, 1, 2, 2),//
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (!last) {
+                                    return;
+                                }
+                                if (FallthroughTest5.fallthrough1 > 1) {
+                                    Assert.fail(String.valueOf(FallthroughTest5.fallthrough1));
+                                }
+                                FallthroughTest5.fallthrough1 = 0;
+                            }
+                        });
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughTest5 extends ValueNode {
+
+        static int fallthrough1;
+
+        @Specialization(guards = "isDo1", rewriteOn = ArithmeticException.class)
+        int do1(int a) throws ArithmeticException {
+            if (a == 0) {
+                fallthrough1++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        protected static boolean isDo1(int a) {
+            return a == 0 || a == 1;
+        }
+
+        @Specialization(guards = "isDo1")
+        int do2(int a) {
+            return a;
+        }
+
+        @Specialization
+        int do3(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughTest6 extends ValueNode {
+
+        static int fallthrough1;
+        static int fallthrough2;
+        static int fallthrough3;
+        static int fallthrough4;
+
+        @Specialization(order = 1, rewriteOn = ArithmeticException.class)
+        int do4(int a) throws ArithmeticException {
+            return a;
+        }
+
+        @Specialization(order = 2, rewriteOn = ArithmeticException.class)
+        int do2(int a) throws ArithmeticException {
+            return a;
+        }
+
+        @Specialization(order = 3, rewriteOn = ArithmeticException.class)
+        int do3(int a) throws ArithmeticException {
+            return a;
+        }
+
+        @Specialization(order = 4, rewriteOn = ArithmeticException.class)
+        int do1(int a) throws ArithmeticException {
+            return a;
+        }
+
+        @Specialization
+        double do5(double a) {
+            return a;
+        }
+
+    }
+
+}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java	Mon Aug 11 15:53:05 2014 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java	Mon Aug 11 15:53:05 2014 +0200
@@ -48,7 +48,7 @@
         MockAssumption a2 = new MockAssumption(false);
         MockAssumption a3 = new MockAssumption(true);
 
-        TestRootNode<TestGrouping> root = TestHelper.createGenericRoot(TestGroupingFactory.getInstance(), a1, a2, a3);
+        TestRootNode<TestGrouping> root = TestHelper.createRoot(TestGroupingFactory.getInstance(), a1, a2, a3);
 
         SimpleTypes.intCast = 0;
         SimpleTypes.intCheck = 0;
@@ -59,29 +59,29 @@
         TestGrouping.true3 = 0;
 
         Assert.assertEquals(42, TestHelper.executeWith(root, 21, 21));
-        Assert.assertEquals(1, TestGrouping.true1);
-        Assert.assertEquals(1, TestGrouping.false1);
-        Assert.assertEquals(1, TestGrouping.true2);
-        Assert.assertEquals(1, TestGrouping.false2);
-        Assert.assertEquals(1, TestGrouping.true3);
-        Assert.assertEquals(2, SimpleTypes.intCheck);
-        Assert.assertEquals(2, SimpleTypes.intCast);
-        Assert.assertEquals(1, a1.checked);
-        Assert.assertEquals(1, a2.checked);
-        Assert.assertEquals(1, a3.checked);
+        Assert.assertEquals(4, TestGrouping.true1);
+        Assert.assertEquals(0, TestGrouping.false1);
+        Assert.assertEquals(4, TestGrouping.true2);
+        Assert.assertEquals(5, TestGrouping.false2);
+        Assert.assertEquals(5, TestGrouping.true3);
+        Assert.assertEquals(8, SimpleTypes.intCheck);
+        Assert.assertEquals(8, SimpleTypes.intCast);
+        Assert.assertEquals(4, a1.checked);
+        Assert.assertEquals(0, a2.checked);
+        Assert.assertEquals(4, a3.checked);
 
         Assert.assertEquals(42, TestHelper.executeWith(root, 21, 21));
-        Assert.assertEquals(2, TestGrouping.true1);
-        Assert.assertEquals(2, TestGrouping.false1);
-        Assert.assertEquals(2, TestGrouping.true2);
-        Assert.assertEquals(2, TestGrouping.false2);
-        Assert.assertEquals(2, TestGrouping.true3);
+        Assert.assertEquals(5, TestGrouping.true1);
+        Assert.assertEquals(0, TestGrouping.false1);
+        Assert.assertEquals(5, TestGrouping.true2);
+        Assert.assertEquals(6, TestGrouping.false2);
+        Assert.assertEquals(6, TestGrouping.true3);
 
-        Assert.assertEquals(2, a1.checked);
-        Assert.assertEquals(2, a2.checked);
-        Assert.assertEquals(2, a3.checked);
-        Assert.assertEquals(4, SimpleTypes.intCheck);
-        Assert.assertEquals(4, SimpleTypes.intCast);
+        Assert.assertEquals(5, a1.checked);
+        Assert.assertEquals(0, a2.checked);
+        Assert.assertEquals(5, a3.checked);
+        Assert.assertEquals(8, SimpleTypes.intCheck);
+        Assert.assertEquals(8, SimpleTypes.intCast);
 
     }
 
@@ -121,39 +121,39 @@
             return true;
         }
 
-        @Specialization(order = 1)
+        @Specialization
         public int fail(int value1, String value2) {
             throw new AssertionError();
         }
 
-        @Specialization(order = 2, guards = {"true1", "false1"})
-        public int fail1(int value1, int value2) {
-            throw new AssertionError();
-        }
-
-        @Specialization(order = 3, guards = {"true1", "true2"}, assumptions = {"a1", "a2"})
-        public int fail2(int value1, int value2) {
-            throw new AssertionError();
-        }
-
-        @Specialization(order = 4, guards = {"true1", "true2"}, assumptions = {"a1", "a3"}, rewriteOn = RuntimeException.class)
+        @Specialization(guards = {"true1", "true2", "!false2", "true3"}, assumptions = {"a1", "a3"}, rewriteOn = RuntimeException.class)
         public int throwRewrite(int value1, int value2) {
             throw new RuntimeException();
         }
 
-        @Specialization(order = 5, guards = {"true1", "true2", "false2"}, assumptions = {"a1", "a3"})
+        @Specialization(guards = {"true1", "true2", "!false2", "true3"}, contains = "throwRewrite", assumptions = {"a1", "a3"})
+        public int success(int value1, int value2) {
+            return value1 + value2;
+        }
+
+        @Specialization(guards = {"true1", "true2", "!false2", "!true3"}, assumptions = {"a1", "a3"})
+        public int fail5(int value1, int value2) {
+            throw new AssertionError();
+        }
+
+        @Specialization(guards = {"true1", "true2", "false2"}, assumptions = {"a1", "a3"})
         public int fail4(int value1, int value2) {
             throw new AssertionError();
         }
 
-        @Specialization(order = 6, guards = {"true1", "true2", "!false2", "!true3"}, assumptions = {"a1", "a3"})
-        public int fail5(int value1, int value2) {
+        @Specialization(guards = {"true1", "true2"}, assumptions = {"a1", "a3"})
+        public int fail2break(int value1, int value2) {
             throw new AssertionError();
         }
 
-        @Specialization(order = 7, guards = {"true1", "true2", "!false2", "true3"}, assumptions = {"a1", "a3"})
-        public int success(int value1, int value2) {
-            return value1 + value2;
+        @Specialization(guards = {"true1", "false1"})
+        public int fail1(int value1, int value2) {
+            throw new AssertionError();
         }
 
     }
@@ -168,18 +168,18 @@
     @NodeChild(value = "genericChild", type = GenericInt.class)
     public abstract static class TestElseConnectionBug1 extends ValueNode {
 
-        @Specialization(order = 1, rewriteOn = {SlowPathException.class}, guards = "isInitialized")
-        public int doInteger(int value) throws SlowPathException {
+        @Specialization(rewriteOn = {SlowPathException.class}, guards = "isInitialized")
+        public int do1(int value) throws SlowPathException {
             throw new SlowPathException();
         }
 
-        @Specialization(order = 3, guards = "isInitialized")
-        public int doObject(int value) {
+        @Specialization(contains = "do1", guards = "isInitialized")
+        public int do2(int value) {
             return value == 42 ? value : 0;
         }
 
-        @Specialization(order = 4, guards = "!isInitialized")
-        public Object doUninitialized(int value) {
+        @Specialization(guards = "!isInitialized")
+        public Object do3(int value) {
             throw new AssertionError();
         }
 
@@ -204,25 +204,25 @@
 
     @Test
     public void testElseConnectionBug2() {
-        TestHelper.assertRuns(TestElseConnectionBug2Factory.getInstance(), 42, 42);
+        TestHelper.assertRuns(TestElseConnectionBug2Factory.getInstance(), new Object[]{42}, new Object[]{42});
     }
 
     @SuppressWarnings("unused")
     @NodeChild
     public abstract static class TestElseConnectionBug2 extends ValueNode {
 
-        @Specialization(order = 2, guards = "guard0")
-        public int doGuard0(int value) {
+        @Specialization(guards = "guard0")
+        public int do1(int value) {
             throw new AssertionError();
         }
 
-        @Specialization(order = 3, guards = "guard1")
-        public int doGuard1(int value) {
+        @Specialization(guards = "guard1")
+        public int do2(int value) {
             throw new AssertionError();
         }
 
-        @Specialization(order = 4, guards = "!guard0")
-        public int doUninitialized(int value) {
+        @Specialization(guards = "!guard0")
+        public int do3(int value) {
             return value;
         }
 
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java	Mon Aug 11 15:53:05 2014 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java	Mon Aug 11 15:53:05 2014 +0200
@@ -98,7 +98,7 @@
         return createCallTarget(node).call(values);
     }
 
-    static Object array(Object... val) {
+    static Object[] array(Object... val) {
         return val;
     }
 
@@ -138,29 +138,71 @@
         return output;
     }
 
+    static void assertRuns(NodeFactory<? extends ValueNode> factory, Object[] testValues, Object[] result) {
+        assertRuns(factory, testValues, result, null);
+    }
+
     /* Methods tests all test values in combinational order. */
-    static void assertRuns(NodeFactory<? extends ValueNode> factory, Object result, Object... testValues) {
+    static void assertRuns(NodeFactory<? extends ValueNode> factory, Object[] testValues, Object[] result, ExecutionListener listener) {
         // test each run by its own.
         for (int i = 0; i < testValues.length; i++) {
-            assertValue(createRoot(factory), result, testValues);
+            assertValue(createRoot(factory), 0, testValues[i], result[i], listener, true);
         }
 
         // test all combinations of the test values
-        List<List<Object>> permuts = permutations(Arrays.asList(testValues));
+        List<Object> testValuesList = Arrays.asList(testValues);
+        List<List<Object>> permuts = permutations(testValuesList);
         for (List<Object> list : permuts) {
             TestRootNode<?> root = createRoot(factory);
+            int index = 0;
             for (Object object : list) {
-                assertValue(root, result, object);
+                assertValue(root, index, object, result[testValuesList.indexOf(object)], listener, index == list.size() - 1);
+                index++;
             }
         }
     }
 
-    static void assertValue(TestRootNode<? extends ValueNode> root, Object result, Object testValues) {
-        if (testValues instanceof Object[]) {
-            assertEquals(result, executeWith(root, (Object[]) testValues));
+    static void assertValue(TestRootNode<? extends ValueNode> root, int index, Object value, Object result, ExecutionListener listener, boolean last) {
+        Object actualResult = null;
+        if (result instanceof Class && Throwable.class.isAssignableFrom((Class<?>) result)) {
+            try {
+                if (value instanceof Object[]) {
+                    actualResult = executeWith(root, (Object[]) value);
+                } else {
+                    actualResult = executeWith(root, value);
+                }
+                fail(String.format("Exception %s  expected but not occured.", result.getClass()));
+            } catch (Throwable e) {
+                actualResult = e;
+                if (!e.getClass().isAssignableFrom(((Class<?>) result))) {
+                    e.printStackTrace();
+                    fail(String.format("Incompatible exception class thrown. Expected %s but was %s.", result.toString(), e.getClass()));
+                }
+            }
+        } else if (value instanceof Object[]) {
+            actualResult = executeWith(root, (Object[]) value);
+            assertEquals(result, actualResult);
         } else {
-            assertEquals(result, executeWith(root, testValues));
+            actualResult = executeWith(root, value);
+            assertEquals(result, actualResult);
+        }
+        if (listener != null) {
+            listener.afterExecution(root, index, value, result, actualResult, last);
         }
     }
 
+    public static final class LogListener implements ExecutionListener {
+
+        public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+            System.out.printf("Run %3d Node:%-20s Parameters: %10s Expected: %10s Result %10s%n", index, node.getNode().getClass().getSimpleName(), value, expectedResult, actualResult);
+        }
+
+    }
+
+    interface ExecutionListener {
+
+        void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last);
+
+    }
+
 }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java	Mon Aug 11 15:53:05 2014 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java	Mon Aug 11 15:53:05 2014 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.truffle.api.dsl.test;
 
+import java.math.*;
+
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
@@ -29,7 +31,7 @@
 
 public class TypeSystemTest {
 
-    @TypeSystem({int.class, boolean.class, String.class, CallTarget.class, BExtendsAbstract.class, CExtendsAbstract.class, Abstract.class, Object[].class})
+    @TypeSystem({int.class, double.class, boolean.class, BigInteger.class, String.class, CallTarget.class, BExtendsAbstract.class, CExtendsAbstract.class, Abstract.class, Object[].class})
     static class SimpleTypes {
 
         static int intCheck;
@@ -47,10 +49,20 @@
             return (int) value;
         }
 
+        @ImplicitCast
+        public double castDouble(int value) {
+            return value;
+        }
+
+        @ImplicitCast
+        public BigInteger castBigInteger(int value) {
+            return BigInteger.valueOf(value);
+        }
+
     }
 
     @TypeSystemReference(SimpleTypes.class)
-    public abstract static class ValueNode extends Node {
+    public static class ValueNode extends Node {
 
         public ValueNode() {
             super(null);
@@ -72,6 +84,10 @@
             return SimpleTypesGen.SIMPLETYPES.expectObjectArray(execute(frame));
         }
 
+        public BigInteger executeBigInteger(VirtualFrame frame) throws UnexpectedResultException {
+            return SimpleTypesGen.SIMPLETYPES.expectBigInteger(execute(frame));
+        }
+
         public BExtendsAbstract executeBExtendsAbstract(VirtualFrame frame) throws UnexpectedResultException {
             return SimpleTypesGen.SIMPLETYPES.expectBExtendsAbstract(execute(frame));
         }
@@ -80,7 +96,17 @@
             return SimpleTypesGen.SIMPLETYPES.expectCExtendsAbstract(execute(frame));
         }
 
-        public abstract Object execute(VirtualFrame frame);
+        public Abstract executeAbstract(VirtualFrame frame) throws UnexpectedResultException {
+            return SimpleTypesGen.SIMPLETYPES.expectAbstract(execute(frame));
+        }
+
+        public double executeDouble(VirtualFrame frame) throws UnexpectedResultException {
+            return SimpleTypesGen.SIMPLETYPES.expectDouble(execute(frame));
+        }
+
+        public Object execute(@SuppressWarnings("unused") VirtualFrame frame) {
+            throw new UnsupportedOperationException();
+        }
 
         @Override
         public ValueNode copy() {