changeset 20938:18c0f02fa4d2

Truffle-DSL: make type systems optional.
author Christian Humer <christian.humer@gmail.com>
date Tue, 14 Apr 2015 15:12:48 +0200
parents 37ea76052733
children f83fd99b2962
files CHANGELOG.md graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ArrayTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NoTypeSystemTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeChildTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemErrorsTest.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/ImplicitCastNodeFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemNodeFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeExecutableElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ImplicitCastData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCastData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCheckData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GenericParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ImplicitCastParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCastParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCheckParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java
diffstat 40 files changed, 1484 insertions(+), 1384 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGELOG.md	Tue Apr 14 22:12:03 2015 +0200
+++ b/CHANGELOG.md	Tue Apr 14 15:12:48 2015 +0200
@@ -36,6 +36,10 @@
 * Changed syntax and semantics of Specialization#assumptions and Specialization#guards. They now use a Java like expression syntax.
 * Changed guard expressions that do not bind any dynamic parameter are invoked just once per specialization instantiation. They are now asserted to be true on the fast path.
 * Renamed @ImportGuards to @ImportStatic.
+* Changed declaring a @TypeSystemReference for a node that contains specializations is not mandatory anymore.
+* Changed types used in specializations are not restricted on types declared in the type system anymore.
+* Changed nodes that declare all execute methods with the same number of evaluated arguments as specialization arguments do not require @NodeChild annotations anymore.
+* Changed types used in checks and casts are not mandatory to be declared in the type system.
 
 ## Version 0.6
 19-Dec-2014, [Repository Revision](http://hg.openjdk.java.net/graal/graal/shortlog/graal-0.6)
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ArrayTest.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ArrayTest.java	Tue Apr 14 15:12:48 2015 +0200
@@ -26,7 +26,6 @@
 
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.internal.*;
 import com.oracle.truffle.api.dsl.test.ArrayTestFactory.TestNode1NodeGen;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
@@ -97,7 +96,6 @@
     }
 
     @TypeSystem({int.class, int[].class, double[].class, String[].class, Object[].class})
-    @DSLOptions(useNewLayout = true)
     public static class ArrayTypeSystem {
 
         @ImplicitCast
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java	Tue Apr 14 15:12:48 2015 +0200
@@ -175,8 +175,7 @@
         abstract void executeVoid();
 
         @Specialization
-        int doInt(int a) {
-            return a;
+        void doInt(@SuppressWarnings("unused") int 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/NoTypeSystemTest.java	Tue Apr 14 15:12:48 2015 +0200
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2015, 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.dsl.*;
+import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.JustFrameTestNodeGen;
+import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.NoParameterTestNodeGen;
+import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.ObjectInterfaceNodeGen;
+import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.ObjectPrimitiveTestNodeGen;
+import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.ObjectStringTestNodeGen;
+import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.PrimitiveTestNodeGen;
+import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.TypesNotInTypeSystemTestNodeGen;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+public class NoTypeSystemTest {
+
+    abstract static class NoParameterTestNode extends Node {
+        abstract void execute();
+
+        @Specialization
+        void s1() {
+        }
+    }
+
+    @Test
+    public void testNoParameter() {
+        NoParameterTestNodeGen.create().execute();
+    }
+
+    abstract static class JustFrameTestNode extends Node {
+
+        abstract void execute(VirtualFrame frames);
+
+        @Specialization
+        void s1(@SuppressWarnings("unused") VirtualFrame frame) {
+        }
+    }
+
+    @Test
+    public void testJustFrame() {
+        JustFrameTestNodeGen.create().execute(null);
+    }
+
+    abstract static class PrimitiveTestNode extends Node {
+
+        abstract int execute(int primitive);
+
+        @Specialization
+        int test(int primitive) {
+            return primitive;
+        }
+
+    }
+
+    @Test
+    public void testPrimitive() {
+        Assert.assertEquals(42, PrimitiveTestNodeGen.create().execute(42));
+    }
+
+    abstract static class ObjectInterfaceNode extends Node {
+
+        abstract CharSequence execute(Object operand);
+
+        @Specialization
+        CharSequence s1(CharSequence operandSpecial) {
+            return operandSpecial;
+        }
+    }
+
+    @Test
+    public void testObjectInterface() {
+        Assert.assertEquals("42", ObjectInterfaceNodeGen.create().execute("42"));
+    }
+
+    abstract static class ObjectPrimitiveTestNode extends Node {
+
+        abstract int execute(Object primitive);
+
+        @Specialization
+        int s1(int primitive) {
+            return primitive;
+        }
+
+    }
+
+    @Test
+    public void testObjectPrimitiveTest() {
+        Assert.assertEquals(42, ObjectPrimitiveTestNodeGen.create().execute(42));
+    }
+
+    abstract static class ObjectStringTestNode extends Node {
+
+        abstract String execute(Object operand);
+
+        @Specialization
+        String s1(String operand) {
+            return operand;
+        }
+    }
+
+    @Test
+    public void testObjectStringTest() {
+        Assert.assertEquals("42", ObjectStringTestNodeGen.create().execute("42"));
+    }
+
+    abstract static class TypesNotInTypeSystemTest extends Node {
+
+        abstract Object execute(Object primitive);
+
+        abstract int executeInt(Object primitive) throws UnexpectedResultException;
+
+        abstract double executeDouble(Object primitive) throws UnexpectedResultException;
+
+        abstract String executeString(Object primitive) throws UnexpectedResultException;
+
+        abstract int[] executeIntArray(Object primitive) throws UnexpectedResultException;
+
+        abstract void executeVoid(Object primitive) throws UnexpectedResultException;
+
+        abstract void executeChar(Object primitive) throws UnexpectedResultException;
+
+        abstract int executeInt(int primitive) throws UnexpectedResultException;
+
+        abstract double executeDouble(double primitive) throws UnexpectedResultException;
+
+        abstract String executeString(String primitive) throws UnexpectedResultException;
+
+        abstract int[] executeIntArray(int[] primitive) throws UnexpectedResultException;
+
+        abstract void executeChar(char primitive) throws UnexpectedResultException;
+
+        @Specialization
+        int s1(int primitive) {
+            return primitive;
+        }
+
+        @Specialization
+        double s2(double primitive) {
+            return (int) primitive;
+        }
+
+        @Specialization
+        String s3(String object) {
+            return object;
+        }
+
+        @Specialization
+        int[] s4(int[] object) {
+            return object;
+        }
+
+        @Specialization
+        void s5(@SuppressWarnings("unused") char object) {
+        }
+
+    }
+
+    // make nodes replacable
+    private static <T extends Node> T createRoot(final T node) {
+        new RootNode() {
+            @Child T child = node;
+
+            @Override
+            public Object execute(VirtualFrame frame) {
+                return null;
+            }
+        }.adoptChildren();
+        return node;
+    }
+
+    @Test
+    public void testTypesNotInTypeSystem() throws UnexpectedResultException {
+        int[] someArray = {1, 2, 3};
+        Assert.assertEquals(42, createTypesNotInTypeSystem().execute(42));
+        Assert.assertEquals(42d, createTypesNotInTypeSystem().execute(42d));
+        Assert.assertEquals(someArray, createTypesNotInTypeSystem().execute(someArray));
+        Assert.assertNull(createTypesNotInTypeSystem().execute((char) 42));
+
+        Assert.assertEquals(42, createTypesNotInTypeSystem().executeInt((Object) 42));
+        Assert.assertEquals(42d, createTypesNotInTypeSystem().executeDouble((Object) 42d), 0d);
+        Assert.assertEquals(someArray, createTypesNotInTypeSystem().executeIntArray((Object) someArray));
+        createTypesNotInTypeSystem().executeChar((Object) (char) 42);
+
+        Assert.assertEquals(42, createTypesNotInTypeSystem().executeInt(42));
+        Assert.assertEquals(42d, createTypesNotInTypeSystem().executeDouble(42d), 0d);
+        Assert.assertEquals(someArray, createTypesNotInTypeSystem().executeIntArray(someArray));
+        createTypesNotInTypeSystem().executeChar((char) 42);
+
+        try {
+            createTypesNotInTypeSystem().executeInt("a");
+            Assert.fail();
+        } catch (UnexpectedResultException e) {
+        }
+
+        try {
+            createTypesNotInTypeSystem().executeDouble("a");
+            Assert.fail();
+        } catch (UnexpectedResultException e) {
+        }
+
+        try {
+            createTypesNotInTypeSystem().executeIntArray("a");
+            Assert.fail();
+        } catch (UnexpectedResultException e) {
+        }
+
+        createTypesNotInTypeSystem().executeChar("a");
+
+    }
+
+    private static TypesNotInTypeSystemTest createTypesNotInTypeSystem() {
+        return createRoot(TypesNotInTypeSystemTestNodeGen.create());
+    }
+
+    abstract static class ErrorImpossibleTypes1 extends Node {
+
+        abstract int execute(int primitive);
+
+        @Specialization
+        int test(int primitive) {
+            return primitive;
+        }
+
+        @ExpectError("The provided return type \"Object\" does not match expected return type \"int\".%")
+        @Specialization
+        Object s2(int arg0) {
+            return arg0;
+        }
+    }
+
+    abstract static class ErrorImpossibleTypes2 extends Node {
+
+        abstract int execute(int primitive);
+
+        @Specialization
+        int test(int primitive) {
+            return primitive;
+        }
+
+        @ExpectError("Method signature (Object) does not match to the expected signature: %")
+        @Specialization
+        int s2(Object arg0) {
+            return (int) arg0;
+        }
+    }
+
+    @ExpectError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. "
+                    + "The following execute methods do not provide all evaluated values for the expected signature size 1: [execute()].")
+    abstract static class ErrorMissingNodeChild1 extends Node {
+
+        abstract int execute();
+
+        @Specialization
+        int s1(int arg0) {
+            return arg0;
+        }
+    }
+
+    @ExpectError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. "
+                    + "The following execute methods do not provide all evaluated values for the expected signature size 2: [execute(int)].")
+    @NodeChild
+    abstract static class ErrorMissingNodeChild2 extends Node {
+
+        abstract int execute(int arg0);
+
+        @Specialization
+        int s1(int arg0, int arg1) {
+            return arg0 + arg1;
+        }
+    }
+
+    @ExpectError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. "
+                    + "The following execute methods do not provide all evaluated values for the expected signature size 1: [execute()].")
+    abstract static class ErrorMissingNodeChild3 extends Node {
+
+        abstract int execute();
+
+        abstract int execute(int arg0);
+
+        @Specialization
+        int s1(int arg0) {
+            return arg0;
+        }
+
+    }
+
+    @ExpectError("Unnecessary @NodeChild declaration. All evaluated child values are provided as parameters in execute methods.")
+    @NodeChild
+    abstract static class ErrorAdditionalNodeChild1 extends Node {
+
+        abstract int execute(int arg0);
+
+        @Specialization
+        int s1(int arg0) {
+            return arg0;
+        }
+    }
+
+    @NodeChild
+    @ExpectError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. "
+                    + "The following execute methods do not provide all evaluated values for the expected signature size 2: [execute(int)].")
+    abstract static class ErrorAdditionalNodeChild2 extends Node {
+
+        abstract int execute(int arg0);
+
+        @Specialization
+        int s1(int arg0, int arg1) {
+            return arg0 + arg1;
+        }
+    }
+
+}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeChildTest.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeChildTest.java	Tue Apr 14 15:12:48 2015 +0200
@@ -71,10 +71,11 @@
 
     }
 
+    @ExpectError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. "
+                    + "The following execute methods do not provide all evaluated values for the expected signature size 3:%")
     @NodeChildren({@NodeChild(value = "child2", type = ValueNode.class)})
     abstract static class Child2Node extends Base1Node {
 
-        // TODO this is an error to fix
         @ExpectError("Method signature (int, int, int) does not match to the expected signature:%")
         @Specialization
         int intField(int child0, int child1, int child2) {
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemErrorsTest.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemErrorsTest.java	Tue Apr 14 15:12:48 2015 +0200
@@ -102,15 +102,6 @@
         }
     }
 
-    @TypeSystem({boolean.class})
-    public static class CastError3 {
-        @ExpectError("The type 'int' is not declared in the @TypeSystem.")
-        @TypeCast(int.class)
-        public static int asInt(Object value) {
-            return (int) value;
-        }
-    }
-
     @TypeSystem({int.class})
     public static class CastError4 {
         @ExpectError("@TypeCast annotated method asInt must be public and static.")
@@ -129,15 +120,6 @@
         }
     }
 
-    @TypeSystem({boolean.class})
-    public static class CheckError1 {
-        @ExpectError("The type 'int' is not declared in the @TypeSystem.")
-        @TypeCheck(int.class)
-        public static boolean isInt(Object value) {
-            return value instanceof Integer;
-        }
-    }
-
     @TypeSystem({int.class})
     public static class CheckError2 {
         @ExpectError("@TypeCheck annotated method isInt must be public and static.")
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java	Tue Apr 14 15:12:48 2015 +0200
@@ -88,6 +88,10 @@
         return (DeclaredType) ElementUtils.getType(environment, element);
     }
 
+    public boolean isType(TypeMirror type, Class<?> clazz) {
+        return ElementUtils.typeEquals(type, getType(clazz));
+    }
+
     public TypeMirror getType(Class<?> element) {
         return ElementUtils.getType(environment, element);
     }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java	Tue Apr 14 15:12:48 2015 +0200
@@ -85,14 +85,14 @@
         return method;
     }
 
-    public static boolean isTypeBoxingOptimized(TypeBoxingOptimization boxing, TypeData type) {
+    public static boolean isTypeBoxingOptimized(TypeBoxingOptimization boxing, TypeMirror type) {
         switch (boxing) {
             case NONE:
                 return false;
             case ALWAYS:
-                return !type.isGeneric() && !type.isVoid();
+                return !ElementUtils.isObject(type) && !ElementUtils.isVoid(type);
             case PRIMITIVE:
-                return type.isPrimitive();
+                return ElementUtils.isPrimitive(type);
             default:
                 throw new AssertionError();
         }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/ImplicitCastNodeFactory.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/ImplicitCastNodeFactory.java	Tue Apr 14 15:12:48 2015 +0200
@@ -44,31 +44,30 @@
 public class ImplicitCastNodeFactory {
 
     private final ProcessorContext context;
-    private final TypeData forType;
+    private final TypeMirror forType;
     private final TypeSystemData typeSystem;
     private final DSLOptions options;
-    private final List<TypeData> sourceTypes;
+    private final List<TypeMirror> sourceTypes;
 
-    public ImplicitCastNodeFactory(ProcessorContext context, TypeData forType) {
+    public ImplicitCastNodeFactory(ProcessorContext context, TypeSystemData typeSystem, TypeMirror forType) {
         this.context = context;
         this.forType = forType;
-        this.typeSystem = forType.getTypeSystem();
+        this.typeSystem = typeSystem;
         this.options = typeSystem.getOptions();
         this.sourceTypes = typeSystem.lookupSourceTypes(forType);
     }
 
-    public static String typeName(TypeData type) {
-        return "Implicit" + getTypeId(type.getBoxedType()) + "Cast";
+    public static String typeName(TypeMirror type) {
+        return "Implicit" + getTypeId(type) + "Cast";
     }
 
-    public static TypeMirror type(TypeData type) {
-        TypeSystemData typeSystem = type.getTypeSystem();
+    public static TypeMirror type(TypeSystemData typeSystem, TypeMirror type) {
         String typeSystemName = TypeSystemCodeGenerator.typeName(typeSystem);
         return new GeneratedTypeMirror(ElementUtils.getPackageName(typeSystem.getTemplateType()) + "." + typeSystemName, typeName(type));
     }
 
-    public static CodeTree create(TypeData type, CodeTree value) {
-        return CodeTreeBuilder.createBuilder().startStaticCall(type(type), "create").tree(value).end().build();
+    public static CodeTree create(TypeSystemData typeSystem, TypeMirror type, CodeTree value) {
+        return CodeTreeBuilder.createBuilder().startStaticCall(type(typeSystem, type), "create").tree(value).end().build();
     }
 
     public static CodeTree cast(String nodeName, CodeTree value) {
@@ -79,8 +78,8 @@
         return CodeTreeBuilder.createBuilder().startCall(nodeName, "check").tree(value).end().build();
     }
 
-    private static String seenFieldName(TypeData type) {
-        return "seen" + getTypeId(type.getBoxedType());
+    private static String seenFieldName(TypeMirror type) {
+        return "seen" + getTypeId(type);
     }
 
     public CodeTypeElement create() {
@@ -88,7 +87,7 @@
         TypeMirror baseType = context.getType(Object.class);
         CodeTypeElement clazz = GeneratorUtils.createClass(typeSystem, null, modifiers(PUBLIC, FINAL, STATIC), typeName, baseType);
 
-        for (TypeData sourceType : sourceTypes) {
+        for (TypeMirror sourceType : sourceTypes) {
             CodeVariableElement hasSeen = new CodeVariableElement(modifiers(PUBLIC), context.getType(boolean.class), seenFieldName(sourceType));
             hasSeen.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(CompilationFinal.class)));
             clazz.add(hasSeen);
@@ -113,7 +112,7 @@
         CodeTreeBuilder builder = method.createBuilder();
         builder.startReturn();
         String operator = "";
-        for (TypeData sourceType : sourceTypes) {
+        for (TypeMirror sourceType : sourceTypes) {
             builder.string(operator);
             builder.string(seenFieldName(sourceType));
             operator = " ^ ";
@@ -129,15 +128,15 @@
     private Element createCreate(CodeTypeElement clazz) {
         String methodName = "create";
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), clazz.asType(), methodName);
-        method.addParameter(new CodeVariableElement(typeSystem.getGenericType(), "value"));
+        method.addParameter(new CodeVariableElement(context.getType(Object.class), "value"));
         CodeTreeBuilder builder = method.createBuilder();
 
         builder.declaration(clazz.asType(), "newCast", builder.create().startNew(clazz.asType()).end());
 
-        for (TypeData sourceType : sourceTypes) {
+        for (TypeMirror sourceType : sourceTypes) {
             String seenField = seenFieldName(sourceType);
             builder.startStatement();
-            builder.string("newCast.").string(seenField).string(" = ").tree(TypeSystemCodeGenerator.check(sourceType, "value"));
+            builder.string("newCast.").string(seenField).string(" = ").tree(TypeSystemCodeGenerator.check(typeSystem, sourceType, "value"));
             builder.end();
         }
         builder.startReturn().string("newCast").end();
@@ -150,7 +149,7 @@
         method.addParameter(new CodeVariableElement(clazz.asType(), "otherCast"));
         CodeTreeBuilder builder = method.createBuilder();
 
-        for (TypeData sourceType : sourceTypes) {
+        for (TypeMirror sourceType : sourceTypes) {
             String seenField = seenFieldName(sourceType);
             builder.startStatement();
             builder.string("this.").string(seenField).string(" |= ").string("otherCast.").string(seenField);
@@ -162,13 +161,13 @@
     private Element createCheck() {
         String methodName = "check";
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(boolean.class), methodName);
-        method.addParameter(new CodeVariableElement(typeSystem.getGenericType(), "value"));
+        method.addParameter(new CodeVariableElement(context.getType(Object.class), "value"));
         CodeTreeBuilder builder = method.createBuilder();
 
         boolean elseIf = false;
-        for (TypeData sourceType : sourceTypes) {
+        for (TypeMirror sourceType : sourceTypes) {
             elseIf = builder.startIf(elseIf);
-            builder.string(seenFieldName(sourceType)).string(" && ").tree(TypeSystemCodeGenerator.check(sourceType, "value"));
+            builder.string(seenFieldName(sourceType)).string(" && ").tree(TypeSystemCodeGenerator.check(typeSystem, sourceType, "value"));
             builder.end();
             builder.startBlock().returnTrue().end();
         }
@@ -178,8 +177,8 @@
 
     private Element createCast(boolean expect) {
         String methodName = expect ? "expect" : "cast";
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), forType.getPrimitiveType(), methodName);
-        method.addParameter(new CodeVariableElement(typeSystem.getGenericType(), "value"));
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), forType, methodName);
+        method.addParameter(new CodeVariableElement(context.getType(Object.class), "value"));
         if (expect) {
             method.getThrownTypes().add(context.getType(UnexpectedResultException.class));
         }
@@ -187,16 +186,16 @@
         CodeTreeBuilder builder = method.createBuilder();
 
         boolean elseIf = false;
-        for (TypeData sourceType : sourceTypes) {
+        for (TypeMirror sourceType : sourceTypes) {
             elseIf = builder.startIf(elseIf);
-            builder.string(seenFieldName(sourceType)).string(" && ").tree(TypeSystemCodeGenerator.check(sourceType, "value"));
+            builder.string(seenFieldName(sourceType)).string(" && ").tree(TypeSystemCodeGenerator.check(typeSystem, sourceType, "value"));
             builder.end();
             builder.startBlock();
             builder.startReturn();
-            CodeTree castTree = TypeSystemCodeGenerator.cast(sourceType, "value");
+            CodeTree castTree = TypeSystemCodeGenerator.cast(typeSystem, sourceType, "value");
             ImplicitCastData cast = typeSystem.lookupCast(sourceType, forType);
             if (cast != null) {
-                builder.tree(TypeSystemCodeGenerator.invokeImplicitCast(cast, castTree));
+                builder.tree(TypeSystemCodeGenerator.invokeImplicitCast(typeSystem, cast, castTree));
             } else {
                 builder.tree(castTree);
             }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java	Tue Apr 14 15:12:48 2015 +0200
@@ -61,16 +61,19 @@
     private final ProcessorContext context;
     private final NodeData node;
     private final TypeSystemData typeSystem;
-    private final TypeData genericType;
+    private final TypeMirror genericType;
+    private final TypeMirror voidType;
     private final DSLOptions options;
     private final boolean singleSpecializable;
     private final int varArgsThreshold;
+    private final Set<TypeMirror> expectedTypes = new HashSet<>();
 
     public NodeGenFactory(ProcessorContext context, NodeData node) {
         this.context = context;
         this.node = node;
         this.typeSystem = node.getTypeSystem();
-        this.genericType = typeSystem.getGenericTypeData();
+        this.genericType = context.getType(Object.class);
+        this.voidType = context.getType(void.class);
         this.options = typeSystem.getOptions();
         this.singleSpecializable = isSingleSpecializableImpl();
         this.varArgsThreshold = calculateVarArgsThreshold();
@@ -139,8 +142,8 @@
         return "exclude" + specialization.getId() + NAME_SUFFIX;
     }
 
-    private static String executeChildMethodName(NodeExecutionData execution, TypeData type) {
-        return "execute" + ElementUtils.firstLetterUpperCase(execution.getName()) + (type.isGeneric() ? "" : getTypeId(type.getBoxedType())) + NAME_SUFFIX;
+    private static String executeChildMethodName(NodeExecutionData execution, TypeMirror type) {
+        return "execute" + ElementUtils.firstLetterUpperCase(execution.getName()) + (ElementUtils.isObject(type) ? "" : getTypeId(type)) + NAME_SUFFIX;
     }
 
     private CodeTree accessParent(String name) {
@@ -186,7 +189,9 @@
         }
 
         for (NodeExecutionData execution : node.getChildExecutions()) {
-            clazz.add(createNodeField(PRIVATE, execution.getNodeType(), nodeFieldName(execution), Child.class));
+            if (execution.getChild() != null) {
+                clazz.add(createNodeField(PRIVATE, execution.getNodeType(), nodeFieldName(execution), Child.class));
+            }
         }
 
         for (NodeExecutionData execution : node.getChildExecutions()) {
@@ -201,7 +206,7 @@
             }
         }
 
-        Collection<TypeData> specializedTypes = node.findSpecializedReturnTypes();
+        Collection<TypeMirror> specializedTypes = node.findSpecializedReturnTypes();
         List<ExecutableTypeData> implementedExecutables = new ArrayList<>();
         for (ExecutableTypeData execType : node.getExecutableTypes()) {
             if (shouldImplementExecutableType(specializedTypes, execType)) {
@@ -235,6 +240,12 @@
             }
         }
 
+        for (TypeMirror type : ElementUtils.uniqueSortedTypes(expectedTypes)) {
+            if (!typeSystem.hasType(type)) {
+                clazz.addOptional(TypeSystemCodeGenerator.createExpectMethod(PRIVATE, typeSystem, context.getType(Object.class), type));
+            }
+        }
+
         return clazz;
     }
 
@@ -295,7 +306,7 @@
                     CodeTree nameTree = CodeTreeBuilder.singleString(name);
                     CodeTreeBuilder callBuilder = builder.create();
                     callBuilder.string(name).string(" != null ? ");
-                    callBuilder.tree(callTemplateMethod(null, createCast, nameTree));
+                    callBuilder.tree(callMethod(null, createCast.getMethod(), nameTree));
                     callBuilder.string(" : null");
                     name += "_";
                     builder.declaration(child.getNodeType(), name, callBuilder.build());
@@ -305,6 +316,9 @@
         }
 
         for (NodeExecutionData execution : node.getChildExecutions()) {
+            if (execution.getChild() == null) {
+                continue;
+            }
             CreateCastData createCast = node.findCast(execution.getChild().getName());
 
             builder.startStatement();
@@ -315,18 +329,18 @@
             accessorBuilder.string(name);
 
             if (execution.isIndexed()) {
-                accessorBuilder.string("[").string(String.valueOf(execution.getIndex())).string("]");
+                accessorBuilder.string("[").string(String.valueOf(execution.getChildIndex())).string("]");
             }
 
             CodeTree accessor = accessorBuilder.build();
 
             if (createCast != null && execution.getChild().getCardinality().isOne()) {
-                accessor = callTemplateMethod(null, createCast, accessor);
+                accessor = callMethod(null, createCast.getMethod(), accessor);
             }
 
             if (execution.isIndexed()) {
                 CodeTreeBuilder nullCheck = builder.create();
-                nullCheck.string(name).string(" != null && ").string(String.valueOf(execution.getIndex())).string(" < ").string(name).string(".length").string(" ? ");
+                nullCheck.string(name).string(" != null && ").string(String.valueOf(execution.getChildIndex())).string(" < ").string(name).string(".length").string(" ? ");
                 nullCheck.tree(accessor);
                 nullCheck.string(" : null");
                 accessor = nullCheck.build();
@@ -378,8 +392,8 @@
 
         SpecializationData specialization = reachableSpecializations.get(0);
         for (Parameter parameter : specialization.getSignatureParameters()) {
-            TypeData type = parameter.getTypeSystemType();
-            if (type != null && type.hasImplicitSourceTypes()) {
+            TypeMirror type = parameter.getType();
+            if (type != null && typeSystem.hasImplicitSourceTypes(type)) {
                 return true;
             }
         }
@@ -410,9 +424,9 @@
         }
 
         for (NodeExecutionData execution : node.getChildExecutions()) {
-            Collection<TypeData> specializedTypes = node.findSpecializedTypes(execution);
+            Collection<TypeMirror> specializedTypes = node.findSpecializedTypes(execution);
             specializedTypes.add(genericType);
-            for (TypeData specializedType : specializedTypes) {
+            for (TypeMirror specializedType : specializedTypes) {
                 if (isExecuteChildShared(execution, specializedType)) {
                     clazz.add(createExecuteChildMethod(execution, specializedType));
                 }
@@ -428,10 +442,10 @@
         CodeExecutableElement constructor = clazz.addOptional(createSpecializationConstructor(clazz, specialization, null));
 
         for (Parameter p : specialization.getSignatureParameters()) {
-            TypeData targetType = p.getTypeSystemType();
-            if (targetType.hasImplicitSourceTypes()) {
+            TypeMirror targetType = p.getType();
+            if (typeSystem.hasImplicitSourceTypes(targetType)) {
                 NodeExecutionData execution = p.getSpecification().getExecution();
-                CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, p.getTypeSystemType());
+                CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, p.getType());
                 if (implicitProfile != null) {
                     implicitProfile.getModifiers().add(PRIVATE);
                     implicitProfile.getModifiers().add(FINAL);
@@ -449,21 +463,21 @@
         clazz.addOptional(createIsSameMethod(specialization));
         clazz.addOptional(createIsIdenticalMethod(specialization));
 
-        TypeData returnType = specialization.getReturnType().getTypeSystemType();
+        TypeMirror returnType = specialization.getReturnType().getType();
         int signatureSize = specialization.getSignatureSize();
 
         clazz.add(createFastPathExecuteMethod(specialization, null, signatureSize));
 
         if (isTypeBoxingEliminated(specialization)) {
-            clazz.add(createFastPathExecuteMethod(specialization, returnType, 0));
-
-            if (signatureSize > 0 && !returnType.isGeneric()) {
-                clazz.add(createFastPathWrapExecuteMethod(genericType, returnType));
-            }
-
-            ExecutableTypeData voidExecutableType = node.findExecutableType(typeSystem.getVoidType(), 0);
-            if (voidExecutableType != null && isTypeBoxingOptimized(options.voidBoxingOptimization(), returnType)) {
-                clazz.add(createFastPathWrapVoidMethod(returnType));
+            if (node.getMinimalEvaluatedParameters() == 0 || signatureSize == 0) {
+                clazz.add(createFastPathExecuteMethod(specialization, returnType, 0));
+                if (signatureSize > 0 && !isObject(returnType)) {
+                    clazz.add(createFastPathWrapExecuteMethod(genericType, returnType));
+                }
+                ExecutableTypeData voidExecutableType = node.findExecutableType(voidType, 0);
+                if (voidExecutableType != null && isTypeBoxingOptimized(options.voidBoxingOptimization(), returnType)) {
+                    clazz.add(createFastPathWrapVoidMethod(returnType));
+                }
             }
         }
 
@@ -517,7 +531,7 @@
             }
         };
 
-        builder.tree(createGuardAndCast(group, typeSystem.getGenericTypeData(), currentLocals, executionFactory));
+        builder.tree(createGuardAndCast(group, genericType, currentLocals, executionFactory));
         builder.returnFalse();
         return method;
     }
@@ -533,7 +547,7 @@
             if (execution == null) {
                 continue;
             }
-            CodeVariableElement var = createImplicitProfileParameter(execution, parameter.getTypeSystemType());
+            CodeVariableElement var = createImplicitProfileParameter(execution, parameter.getType());
             if (var != null) {
                 profiles.add(var);
             }
@@ -605,8 +619,9 @@
         return executable;
     }
 
-    private Element createFastPathWrapVoidMethod(TypeData wrap) {
-        CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), typeSystem.getVoidType().getPrimitiveType(), TypeSystemNodeFactory.executeName(typeSystem.getVoidType()));
+    private Element createFastPathWrapVoidMethod(TypeMirror wrap) {
+
+        CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), voidType, TypeSystemNodeFactory.executeName(voidType));
         executable.addParameter(new CodeVariableElement(getType(Frame.class), FRAME_VALUE));
         executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
         CodeTreeBuilder builder = executable.createBuilder();
@@ -619,8 +634,8 @@
         return executable;
     }
 
-    private Element createFastPathWrapExecuteMethod(TypeData override, TypeData wrap) {
-        CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), override.getPrimitiveType(), TypeSystemNodeFactory.executeName(override));
+    private Element createFastPathWrapExecuteMethod(TypeMirror override, TypeMirror wrap) {
+        CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), override, TypeSystemNodeFactory.executeName(override));
         executable.addParameter(new CodeVariableElement(getType(Frame.class), FRAME_VALUE));
         executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
         CodeTreeBuilder builder = executable.createBuilder();
@@ -758,11 +773,11 @@
         }
 
         TypeBoxingOptimization optimization = options.monomorphicTypeBoxingOptimization();
-        if (isTypeBoxingOptimized(optimization, specialization.getReturnType().getTypeSystemType())) {
+        if (isTypeBoxingOptimized(optimization, specialization.getReturnType().getType())) {
             return true;
         }
         for (Parameter p : specialization.getSignatureParameters()) {
-            if (isTypeBoxingOptimized(optimization, p.getTypeSystemType())) {
+            if (isTypeBoxingOptimized(optimization, p.getType())) {
                 return true;
             }
         }
@@ -772,7 +787,7 @@
 
     private Set<Integer> getEvaluatedCounts() {
         Set<Integer> evaluatedCount = new TreeSet<>();
-        Collection<TypeData> returnSpecializedTypes = node.findSpecializedReturnTypes();
+        Collection<TypeMirror> returnSpecializedTypes = node.findSpecializedReturnTypes();
         for (ExecutableTypeData execType : node.getExecutableTypes()) {
             if (shouldImplementExecutableType(returnSpecializedTypes, execType)) {
                 evaluatedCount.add(execType.getEvaluatedCount());
@@ -788,7 +803,7 @@
         }
         LocalContext locals = LocalContext.load(this);
 
-        CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), genericType.getPrimitiveType(), "unsupported", FRAME_VALUE);
+        CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), genericType, "unsupported", FRAME_VALUE);
         method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
 
         CodeTreeBuilder builder = method.createBuilder();
@@ -808,8 +823,8 @@
         SpecializationData specialization = reachableSpecializations.get(0);
 
         for (Parameter parameter : specialization.getSignatureParameters()) {
-            TypeData type = parameter.getTypeSystemType();
-            if (type != null && type.hasImplicitSourceTypes()) {
+            TypeMirror type = parameter.getType();
+            if (type != null && typeSystem.hasImplicitSourceTypes(type)) {
                 return false;
             }
         }
@@ -853,22 +868,23 @@
 
     private CodeExecutableElement createExecutableTypeOverride(List<ExecutableTypeData> implementedExecutables, ExecutableTypeData execType) {
         final String varArgsName = "args";
-        final TypeData returnType = execType.getType();
-        final TypeData executedType = execType.getEvaluatedCount() > 0 ? null : returnType;
-
-        CodeExecutableElement method = cloneExecutableTypeOverride(execType, varArgsName);
-        LocalContext locals = LocalContext.load(this, execType.getSignatureSize(), Integer.MAX_VALUE);
+        final TypeMirror returnType = execType.getReturnType();
+        final TypeMirror executedType = execType.getEvaluatedCount() > 0 ? null : returnType;
+
+        LocalContext locals = LocalContext.load(this, execType.getEvaluatedCount(), Integer.MAX_VALUE);
+        CodeExecutableElement method = cloneExecutableTypeOverride(locals, execType, varArgsName);
 
         // rename varargs parameter
         int signatureIndex = 0;
-        for (Parameter parameter : execType.getSignatureParameters()) {
-            LocalVariable var = locals.get(parameter, signatureIndex);
+        for (TypeMirror parameter : execType.getEvaluatedParameters()) {
+            LocalVariable var = locals.getValue(signatureIndex);
             if (var != null) {
-                if (parameter.isTypeVarArgs()) {
-                    var = var.accessWith(CodeTreeBuilder.singleString(varArgsName + "[" + parameter.getTypeVarArgsIndex() + "]"));
+                int varArgsIndex = execType.getVarArgsIndex(execType.getParameterIndex(signatureIndex));
+                if (varArgsIndex >= 0) {
+                    var = var.accessWith(CodeTreeBuilder.singleString(varArgsName + "[" + varArgsIndex + "]"));
                 }
-                if (!parameter.getTypeSystemType().isGeneric()) {
-                    var = var.newType(parameter.getTypeSystemType());
+                if (!isObject(parameter)) {
+                    var = var.newType(parameter);
                 }
                 locals.setValue(node.getChildExecutions().get(signatureIndex), var);
             }
@@ -876,12 +892,12 @@
             signatureIndex++;
         }
 
-        Parameter frame = execType.getFrame();
+        TypeMirror frame = execType.getFrameParameter();
         CodeTreeBuilder builder = method.createBuilder();
         if (singleSpecializable) {
             LocalVariable frameVar = null;
             if (frame != null) {
-                frameVar = locals.get(FRAME_VALUE).newType(frame.getType());
+                frameVar = locals.get(FRAME_VALUE).newType(frame);
             }
             method.getThrownTypes().clear();
             locals.set(FRAME_VALUE, frameVar);
@@ -889,9 +905,9 @@
             SpecializationData specialization = getReachableSpecializations().iterator().next();
             ExecutableTypeData wrappedExecutableType = findWrappedExecutable(specialization, implementedExecutables, execType);
             if (wrappedExecutableType != null) {
-                builder.startReturn().tree(callTemplateMethod(null, wrappedExecutableType, locals)).end();
+                builder.startReturn().tree(callExecuteMethod(null, wrappedExecutableType, locals)).end();
             } else {
-                builder.tree(createFastPath(builder, specialization, execType.getType(), locals));
+                builder.tree(createFastPath(builder, specialization, execType.getReturnType(), locals));
             }
         } else {
             // create acceptAndExecute
@@ -900,23 +916,23 @@
             if (frame == null) {
                 executeBuilder.nullLiteral();
             } else {
-                executeBuilder.string(frame.getLocalName());
+                executeBuilder.string(locals.get(FRAME_VALUE).getName());
             }
             locals.addReferencesTo(executeBuilder);
             executeBuilder.end();
 
-            boolean hasExecutedUnexpected = executedType != null && !executedType.isGeneric() && !executedType.isVoid();
+            boolean hasExecutedUnexpected = executedType != null && !isObject(executedType) && !isVoid(executedType);
 
             CodeTreeBuilder contentBuilder = builder.create();
             contentBuilder.startReturn();
             if (!hasExecutedUnexpected && !execType.hasUnexpectedValue(context)) {
-                if (executedType == null || executedType.needsCastTo(returnType)) {
-                    contentBuilder.cast(returnType.getPrimitiveType(), executeBuilder.build());
+                if (executedType == null || needsCastTo(executedType, returnType)) {
+                    contentBuilder.cast(returnType, executeBuilder.build());
                 } else {
                     contentBuilder.tree(executeBuilder.build());
                 }
             } else {
-                contentBuilder.tree(TypeSystemCodeGenerator.expect(executedType, returnType, executeBuilder.build()));
+                contentBuilder.tree(expect(executedType, returnType, executeBuilder.build()));
             }
             contentBuilder.end();
             // try catch assert if unexpected value is not expected
@@ -940,12 +956,12 @@
     }
 
     private static ExecutableTypeData findWrappedExecutable(SpecializationData specialization, List<ExecutableTypeData> implementedExecutables, ExecutableTypeData executedType) {
-        if (specialization.getReturnType().getTypeSystemType() == executedType.getType()) {
+        if (specialization.getReturnType().getType() == executedType.getReturnType()) {
             return null;
         }
         for (ExecutableTypeData otherType : implementedExecutables) {
             if (otherType != executedType && //
-                            otherType.getType() == specialization.getReturnType().getTypeSystemType() && //
+                            otherType.getReturnType() == specialization.getReturnType().getType() && //
                             otherType.getEvaluatedCount() == executedType.getEvaluatedCount()) {
                 return otherType;
             }
@@ -953,43 +969,50 @@
         return null;
     }
 
-    private CodeExecutableElement cloneExecutableTypeOverride(ExecutableTypeData execType, final String varArgsName) throws AssertionError {
+    private CodeExecutableElement cloneExecutableTypeOverride(LocalContext locals, ExecutableTypeData execType, final String varArgsName) throws AssertionError {
         CodeExecutableElement method = CodeExecutableElement.clone(context.getEnvironment(), execType.getMethod());
 
         method.getAnnotationMirrors().clear();
         method.getModifiers().remove(Modifier.ABSTRACT);
 
-        if (!execType.getMethod().isVarArgs() && execType.getParameters().size() != method.getParameters().size()) {
-            throw new AssertionError("Should be verified in the parser");
+        // align argument names
+        int parameterIndex = 0;
+        if (execType.getFrameParameter() != null) {
+            CodeVariableElement frameParameter = (CodeVariableElement) method.getParameters().get(0);
+            frameParameter.setName(FRAME_VALUE);
+            frameParameter.getAnnotationMirrors().clear();
+            parameterIndex++;
         }
 
-        // align argument names
-        int index = 0;
-        for (Parameter parameter : execType.getParameters()) {
-            CodeVariableElement var = (CodeVariableElement) method.getParameters().get(index);
-            if (parameter.isTypeVarArgs()) {
+        for (int signatureIndex = 0; signatureIndex < execType.getEvaluatedCount(); signatureIndex++) {
+            CodeVariableElement var = (CodeVariableElement) method.getParameters().get(parameterIndex);
+            if (signatureIndex < node.getSignatureSize()) {
+                if (execType.getVarArgsIndex(parameterIndex) >= 0) {
+                    var.getAnnotationMirrors().clear();
+                    var.setName(varArgsName);
+                    break;
+                }
+                var.setName(locals.getValue(signatureIndex).getName());
                 var.getAnnotationMirrors().clear();
-                var.setName(varArgsName);
-                break;
+            } else {
+                var.setName("other" + signatureIndex);
             }
-            var.setName(LocalVariable.fromParameter(parameter).createParameter().getName());
-            var.getAnnotationMirrors().clear();
-            index++;
+            parameterIndex++;
         }
         return method;
     }
 
-    private boolean shouldImplementExecutableType(Collection<TypeData> specializedTypes, ExecutableTypeData execType) {
-        TypeData type = execType.getType();
+    private boolean shouldImplementExecutableType(Collection<TypeMirror> specializedTypes, ExecutableTypeData execType) {
+        TypeMirror type = execType.getReturnType();
         Set<Modifier> modifiers = execType.getMethod().getModifiers();
         if (modifiers.contains(FINAL) || modifiers.contains(STATIC) || modifiers.contains(PRIVATE)) {
             return false;
         } else if (execType.isAbstract()) {
             return true;
-        } else if (type.isGeneric()) {
+        } else if (ElementUtils.isObject(type)) {
             return true;
-        } else if (type.isVoid()) {
-            for (TypeData specializedType : specializedTypes) {
+        } else if (ElementUtils.isVoid(type)) {
+            for (TypeMirror specializedType : specializedTypes) {
                 if (isTypeBoxingOptimized(options.voidBoxingOptimization(), specializedType)) {
                     return true;
                 }
@@ -1021,7 +1044,7 @@
         return childField;
     }
 
-    private static List<ExecutableTypeData> resolveSpecializedExecutables(NodeExecutionData execution, Collection<TypeData> types, TypeBoxingOptimization optimization) {
+    private static List<ExecutableTypeData> resolveSpecializedExecutables(NodeExecutionData execution, Collection<TypeMirror> types, TypeBoxingOptimization optimization) {
         if (optimization == TypeBoxingOptimization.NONE) {
             return Collections.emptyList();
         } else if (types.isEmpty()) {
@@ -1029,10 +1052,13 @@
         }
 
         List<ExecutableTypeData> executables = new ArrayList<>();
-        for (TypeData type : types) {
+        for (TypeMirror type : types) {
             if (!isTypeBoxingOptimized(optimization, type)) {
                 continue;
             }
+            if (execution.getChild() == null) {
+                continue;
+            }
             ExecutableTypeData foundType = execution.getChild().getNodeData().findExecutableType(type, execution.getChild().getExecuteWith().size());
             if (foundType != null) {
                 executables.add(foundType);
@@ -1041,15 +1067,15 @@
         return executables;
     }
 
-    private static CodeTree callTemplateMethod(CodeTree receiver, TemplateMethod method, CodeTree... boundValues) {
+    private static CodeTree callMethod(CodeTree receiver, ExecutableElement method, CodeTree... boundValues) {
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        if (method.getMethod().getModifiers().contains(STATIC)) {
-            builder.startStaticCall(method.getMethod().getEnclosingElement().asType(), method.getMethodName());
+        if (method.getModifiers().contains(STATIC)) {
+            builder.startStaticCall(method.getEnclosingElement().asType(), method.getSimpleName().toString());
         } else {
-            builder.startCall(receiver, method.getMethodName());
+            builder.startCall(receiver, method.getSimpleName().toString());
         }
         int index = -1;
-        for (Parameter parameter : method.getParameters()) {
+        for (VariableElement parameter : method.getParameters()) {
             index++;
             if (index < boundValues.length) {
                 CodeTree tree = boundValues[index];
@@ -1059,13 +1085,39 @@
                 }
             }
 
-            builder.defaultValue(parameter.getType());
+            builder.defaultValue(parameter.asType());
         }
         builder.end();
         return builder.build();
     }
 
-    private static CodeTree callTemplateMethod(CodeTree receiver, TemplateMethod method, LocalContext currentValues) {
+    private CodeTree callExecuteMethod(NodeExecutionData execution, ExecutableTypeData method, LocalContext currentValues) {
+        CodeTree receiver = execution != null ? accessParent(nodeFieldName(execution)) : null;
+        List<NodeExecutionData> executeWith = execution != null ? execution.getChild().getExecuteWith() : null;
+
+        List<CodeTree> values = new ArrayList<>();
+        if (method.getFrameParameter() != null) {
+            LocalVariable frameLocal = currentValues.get(FRAME_VALUE);
+            if (frameLocal == null) {
+                values.add(CodeTreeBuilder.singleString("null"));
+            } else {
+                values.add(createTypeSafeReference(frameLocal, method.getFrameParameter()));
+            }
+        }
+        for (int parameterIndex = 0; parameterIndex < method.getEvaluatedCount(); parameterIndex++) {
+            TypeMirror targetParameter = method.getEvaluatedParameters().get(parameterIndex);
+            LocalVariable variable;
+            if (executeWith != null && parameterIndex < executeWith.size()) {
+                variable = currentValues.getValue(executeWith.get(parameterIndex));
+            } else {
+                variable = currentValues.getValue(parameterIndex);
+            }
+            values.add(createTypeSafeReference(variable, targetParameter));
+        }
+        return callMethod(receiver, method.getMethod(), values.toArray(new CodeTree[values.size()]));
+    }
+
+    private CodeTree callTemplateMethod(CodeTree receiver, TemplateMethod method, LocalContext currentValues) {
         CodeTree[] bindings = new CodeTree[method.getParameters().size()];
 
         int signatureIndex = 0;
@@ -1078,20 +1130,28 @@
             }
 
             if (var != null) {
-                CodeTree valueReference = var.createReference();
-                if (parameter.getTypeSystemType() != null && var.getType() != null && var.getType().needsCastTo(parameter.getTypeSystemType())) {
-                    valueReference = TypeSystemCodeGenerator.cast(parameter.getTypeSystemType(), valueReference);
-                } else if (ElementUtils.needsCastTo(var.getTypeMirror(), parameter.getType())) {
-                    valueReference = CodeTreeBuilder.createBuilder().cast(parameter.getType(), valueReference).build();
-                }
-                bindings[i] = valueReference;
+                bindings[i] = createTypeSafeReference(var, parameter.getType());
             }
 
             if (parameter.getSpecification().isSignature()) {
                 signatureIndex++;
             }
         }
-        return callTemplateMethod(receiver, method, bindings);
+        return callMethod(receiver, method.getMethod(), bindings);
+    }
+
+    private CodeTree createTypeSafeReference(LocalVariable var, TypeMirror targetType) {
+        CodeTree valueReference = var.createReference();
+        TypeMirror sourceType = var.getTypeMirror();
+        if (targetType == null || sourceType == null) {
+            return valueReference;
+        }
+        if (needsCastTo(sourceType, targetType)) {
+            valueReference = TypeSystemCodeGenerator.cast(typeSystem, targetType, valueReference);
+        } else if (ElementUtils.needsCastTo(sourceType, targetType)) {
+            valueReference = CodeTreeBuilder.createBuilder().cast(targetType, valueReference).build();
+        }
+        return valueReference;
     }
 
     private SpecializationGroup createSpecializationGroups() {
@@ -1125,7 +1185,7 @@
                 String varName = name + specialization.getIndex();
                 TypeMirror type = assumption.getExpression().getResolvedType();
                 builder.declaration(type, varName, assumptions);
-                currentValues.set(name, new LocalVariable(null, type, varName, null, null));
+                currentValues.set(name, new LocalVariable(type, varName, null, null));
             }
 
             builder.startIf();
@@ -1189,14 +1249,14 @@
         return builder.build();
     }
 
-    private boolean hasFallthrough(SpecializationGroup group, TypeData forType, LocalContext currentValues, boolean fastPath, List<GuardExpression> ignoreGuards) {
+    private boolean hasFallthrough(SpecializationGroup group, TypeMirror forType, LocalContext currentValues, boolean fastPath, List<GuardExpression> ignoreGuards) {
         for (TypeGuard guard : group.getTypeGuards()) {
             if (currentValues.getValue(guard.getSignatureIndex()) == null) {
                 // not evaluated
                 return true;
             }
             LocalVariable value = currentValues.getValue(guard.getSignatureIndex());
-            if (value.getType().needsCastTo(guard.getType())) {
+            if (needsCastTo(value.getTypeMirror(), guard.getType())) {
                 return true;
             }
         }
@@ -1265,7 +1325,11 @@
             if (execution.isShortCircuit()) {
                 builder.nullLiteral();
             }
-            builder.tree(accessParent(nodeFieldName(execution)));
+            if (execution.getChild() == null) {
+                builder.nullLiteral();
+            } else {
+                builder.tree(accessParent(nodeFieldName(execution)));
+            }
         }
         builder.end();
         return builder.build();
@@ -1289,7 +1353,7 @@
         }
         if (currentValues != null) {
             for (Parameter p : specialization.getSignatureParameters()) {
-                CodeVariableElement var = createImplicitProfileParameter(p.getSpecification().getExecution(), p.getTypeSystemType());
+                CodeVariableElement var = createImplicitProfileParameter(p.getSpecification().getExecution(), p.getType());
                 if (var != null) {
                     LocalVariable variable = currentValues.get(p.getLocalName());
                     if (variable == null) {
@@ -1370,19 +1434,19 @@
             for (Parameter p : specialization.getSignatureParameters()) {
                 NodeExecutionData execution = p.getSpecification().getExecution();
 
-                CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, p.getTypeSystemType());
+                CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, p.getType());
                 if (implicitProfile != null) {
-                    LocalVariable var = LocalVariable.fromParameter(p).makeGeneric();
+                    LocalVariable var = LocalVariable.fromParameter(p).makeGeneric(context);
 
                     String implicitFieldName = implicitProfile.getName();
                     if (options.implicitCastOptimization().isDuplicateTail()) {
                         constructor.addParameter(var.createParameter());
-                        CodeTree implicitType = TypeSystemCodeGenerator.implicitType(p.getTypeSystemType(), var.createReference());
+                        CodeTree implicitType = TypeSystemCodeGenerator.implicitType(typeSystem, p.getType(), var.createReference());
                         builder.startStatement().string("this.").string(implicitFieldName).string(" = ").tree(implicitType).end();
                     } else if (options.implicitCastOptimization().isMergeCasts()) {
                         // use node that supports polymorphism
                         constructor.addParameter(var.createParameter());
-                        builder.startStatement().string("this.").string(implicitFieldName).string(" = ").tree(ImplicitCastNodeFactory.create(p.getTypeSystemType(), var.createReference())).end();
+                        builder.startStatement().string("this.").string(implicitFieldName).string(" = ").tree(ImplicitCastNodeFactory.create(typeSystem, p.getType(), var.createReference())).end();
                     } else {
                         throw new AssertionError();
                     }
@@ -1443,7 +1507,7 @@
         return builder.build();
     }
 
-    private CodeTree createCallNext(TypeData forType, LocalContext currentValues) {
+    private CodeTree createCallNext(TypeMirror forType, LocalContext currentValues) {
         if (singleSpecializable) {
             return createThrowUnsupported(currentValues);
         }
@@ -1451,10 +1515,10 @@
         callBuilder.startCall("next", TypeSystemNodeFactory.executeName(null));
         currentValues.addReferencesTo(callBuilder, FRAME_VALUE);
         callBuilder.end();
-        return CodeTreeBuilder.createBuilder().startReturn().tree(TypeSystemCodeGenerator.expect(genericType, forType, callBuilder.build())).end().build();
+        return CodeTreeBuilder.createBuilder().startReturn().tree(expect(genericType, forType, callBuilder.build())).end().build();
     }
 
-    private CodeTree createCallRemove(String reason, TypeData forType, LocalContext currentValues) {
+    private CodeTree createCallRemove(String reason, TypeMirror forType, LocalContext currentValues) {
         if (singleSpecializable) {
             return createThrowUnsupported(currentValues);
         }
@@ -1467,12 +1531,12 @@
 
         builder = builder.create();
         builder.startReturn();
-        builder.tree(TypeSystemCodeGenerator.expect(genericType, forType, call));
+        builder.tree(expect(genericType, forType, call));
         builder.end();
         return builder.build();
     }
 
-    private static CodeTree createCallDelegate(String methodName, String reason, TypeData forType, LocalContext currentValues) {
+    private CodeTree createCallDelegate(String methodName, String reason, TypeMirror forType, LocalContext currentValues) {
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
         builder.startCall(methodName);
         if (reason != null) {
@@ -1481,21 +1545,28 @@
         currentValues.addReferencesTo(builder, FRAME_VALUE);
         builder.end();
 
-        TypeData executedType = forType.getTypeSystem().getGenericTypeData();
-        return TypeSystemCodeGenerator.expect(executedType, forType, builder.build());
+        return expect(genericType, forType, builder.build());
     }
 
-    private Set<ExecutableTypeData> findSpecializedExecutableTypes(NodeExecutionData execution, TypeData type) {
+    private CodeTree expect(TypeMirror sourceType, TypeMirror forType, CodeTree tree) {
+        expectedTypes.add(forType);
+        return TypeSystemCodeGenerator.expect(typeSystem, sourceType, forType, tree);
+    }
+
+    private Set<ExecutableTypeData> findSpecializedExecutableTypes(NodeExecutionData execution, TypeMirror type) {
+        if (execution.getChild() == null) {
+            return Collections.emptySet();
+        }
         ExecutableTypeData executableType = resolveExecutableType(execution.getChild(), type);
         Set<ExecutableTypeData> executedTypes = new HashSet<>();
         executedTypes.add(executableType);
-        if (type.hasImplicitSourceTypes()) {
-            executedTypes.addAll(resolveSpecializedExecutables(execution, type.getImplicitSourceTypes(), options.implicitTypeBoxingOptimization()));
+        if (typeSystem.hasImplicitSourceTypes(type)) {
+            executedTypes.addAll(resolveSpecializedExecutables(execution, typeSystem.lookupSourceTypes(type), options.implicitTypeBoxingOptimization()));
         }
         return executedTypes;
     }
 
-    private ExecutableTypeData resolveExecutableType(NodeChildData child, TypeData type) {
+    private ExecutableTypeData resolveExecutableType(NodeChildData child, TypeMirror type) {
         int executeWithCount = child.getExecuteWith().size();
         ExecutableTypeData executableType = child.getNodeData().findExecutableType(type, executeWithCount);
         if (executableType == null) {
@@ -1504,27 +1575,27 @@
         return executableType;
     }
 
-    private boolean hasUnexpectedResult(NodeExecutionData execution, TypeData type) {
+    private boolean hasUnexpectedResult(NodeExecutionData execution, TypeMirror type) {
         for (ExecutableTypeData executableType : findSpecializedExecutableTypes(execution, type)) {
-            if (executableType != null && (executableType.hasUnexpectedValue(context) || executableType.getType().needsCastTo(type))) {
+            if (executableType != null && (executableType.hasUnexpectedValue(context) || needsCastTo(executableType.getReturnType(), type))) {
                 return true;
             }
         }
         return false;
     }
 
-    private Element createFastPathExecuteMethod(SpecializationData specialization, final TypeData forType, int evaluatedArguments) {
-        TypeData type = forType == null ? genericType : forType;
+    private Element createFastPathExecuteMethod(SpecializationData specialization, final TypeMirror forType, int evaluatedArguments) {
+        TypeMirror type = forType == null ? genericType : forType;
         LocalContext currentLocals = LocalContext.load(this, evaluatedArguments, varArgsThreshold);
 
         if (specialization != null) {
             currentLocals.loadFastPathState(specialization);
         }
 
-        CodeExecutableElement executable = currentLocals.createMethod(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemNodeFactory.executeName(forType), FRAME_VALUE);
+        CodeExecutableElement executable = currentLocals.createMethod(modifiers(PUBLIC), type, TypeSystemNodeFactory.executeName(forType), FRAME_VALUE);
         executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
 
-        if (!type.isGeneric()) {
+        if (!isObject(type)) {
             executable.getThrownTypes().add(getType(UnexpectedResultException.class));
         }
 
@@ -1534,17 +1605,17 @@
         return executable;
     }
 
-    private CodeTree createFastPath(CodeTreeBuilder parent, SpecializationData specialization, TypeData type, LocalContext currentLocals) {
+    private CodeTree createFastPath(CodeTreeBuilder parent, SpecializationData specialization, TypeMirror type, LocalContext currentLocals) {
         final CodeTreeBuilder builder = parent.create();
 
         for (NodeExecutionData execution : node.getChildExecutions()) {
             LocalVariable var = currentLocals.getValue(execution);
             if (var == null) {
-                TypeData targetType;
+                TypeMirror targetType;
                 if (specialization == null) {
                     targetType = genericType;
                 } else {
-                    targetType = specialization.findParameterOrDie(execution).getTypeSystemType();
+                    targetType = specialization.findParameterOrDie(execution).getType();
                 }
                 LocalVariable shortCircuit = resolveShortCircuit(specialization, execution, currentLocals);
                 LocalVariable value = currentLocals.createValue(execution, targetType).nextName();
@@ -1561,7 +1632,7 @@
         } else if (specialization.isUninitialized()) {
             builder.startReturn().tree(createCallDelegate("uninitialized", null, type, currentLocals)).end();
         } else {
-            final TypeData finalType = type;
+            final TypeMirror finalType = type;
             SpecializationGroup group = SpecializationGroup.create(specialization);
             SpecializationBody executionFactory = new SpecializationBody(true, true) {
                 @Override
@@ -1605,7 +1676,7 @@
         return shortCircuitIndex;
     }
 
-    private CodeTree createFastPathExecute(CodeTreeBuilder parent, final TypeData forType, SpecializationData specialization, LocalContext currentValues) {
+    private CodeTree createFastPathExecute(CodeTreeBuilder parent, final TypeMirror forType, SpecializationData specialization, LocalContext currentValues) {
         CodeTreeBuilder builder = parent.create();
         int ifCount = 0;
         if (specialization.isFallback()) {
@@ -1642,21 +1713,37 @@
             builder.end();
         }
 
-        execute.startReturn();
         if (specialization.getMethod() == null) {
+            execute.startReturn();
             execute.startCall("unsupported");
             currentValues.addReferencesTo(execute, FRAME_VALUE);
             execute.end();
+            execute.end();
         } else {
+            boolean doReturn = !isVoid(specialization.getMethod().getReturnType());
+            if (doReturn) {
+                execute.startReturn();
+            } else {
+                execute.startStatement();
+            }
             execute.tree(callTemplateMethod(accessParent(null), specialization, currentValues));
+            execute.end();
+            if (!doReturn) {
+                if (isVoid(forType)) {
+                    execute.returnStatement();
+                } else {
+                    execute.startReturn();
+                    execute.defaultValue(forType);
+                    execute.end();
+                }
+            }
         }
-        execute.end();
         builder.tree(createFastPathTryCatchRewriteException(specialization, forType, currentValues, execute.build()));
         builder.end(ifCount);
         return builder.build();
     }
 
-    private CodeTree createGuardAndCast(SpecializationGroup group, TypeData forType, LocalContext currentValues, SpecializationBody execution) {
+    private CodeTree createGuardAndCast(SpecializationGroup group, TypeMirror forType, LocalContext currentValues, SpecializationBody execution) {
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
 
         Set<TypeGuard> castGuards;
@@ -1780,10 +1867,10 @@
         return false;
     }
 
-    private CodeExecutableElement createExecuteChildMethod(NodeExecutionData execution, TypeData targetType) {
+    private CodeExecutableElement createExecuteChildMethod(NodeExecutionData execution, TypeMirror targetType) {
         LocalContext locals = LocalContext.load(this, 0, varArgsThreshold);
 
-        CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), targetType.getPrimitiveType(), executeChildMethodName(execution, targetType), FRAME_VALUE);
+        CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), targetType, executeChildMethodName(execution, targetType), FRAME_VALUE);
         if (hasUnexpectedResult(execution, targetType)) {
             method.getThrownTypes().add(getType(UnexpectedResultException.class));
         }
@@ -1810,30 +1897,30 @@
         return method;
     }
 
-    private CodeVariableElement createImplicitProfileParameter(NodeExecutionData execution, TypeData targetType) {
-        if (targetType.hasImplicitSourceTypes()) {
+    private CodeVariableElement createImplicitProfileParameter(NodeExecutionData execution, TypeMirror targetType) {
+        if (typeSystem.hasImplicitSourceTypes(targetType)) {
             switch (options.implicitCastOptimization()) {
                 case NONE:
                     return null;
                 case DUPLICATE_TAIL:
                     return new CodeVariableElement(getType(Class.class), implicitClassFieldName(execution));
                 case MERGE_CASTS:
-                    return new CodeVariableElement(ImplicitCastNodeFactory.type(targetType), implicitNodeFieldName(execution));
+                    return new CodeVariableElement(ImplicitCastNodeFactory.type(typeSystem, targetType), implicitNodeFieldName(execution));
             }
         }
         return null;
     }
 
-    private boolean isExecuteChildShared(NodeExecutionData execution, TypeData targetType) {
-        if (targetType.isVoid()) {
+    private boolean isExecuteChildShared(NodeExecutionData execution, TypeMirror targetType) {
+        if (isVoid(targetType)) {
             return false;
-        } else if (targetType.isGeneric()) {
+        } else if (isObject(targetType)) {
             return resolvePolymorphicExecutables(execution).size() >= 1;
         } else {
             if (!isTypeBoxingOptimized(options.monomorphicTypeBoxingOptimization(), targetType)) {
                 return false;
             }
-            if (!targetType.hasImplicitSourceTypes()) {
+            if (!typeSystem.hasImplicitSourceTypes(targetType)) {
                 return false;
             }
 
@@ -1841,25 +1928,25 @@
             for (SpecializationData specialization : node.getSpecializations()) {
                 List<Parameter> parameters = specialization.findByExecutionData(execution);
                 for (Parameter parameter : parameters) {
-                    if (targetType.equals(parameter.getTypeSystemType())) {
+                    if (targetType.equals(parameter.getType())) {
                         uses++;
                     }
                 }
             }
             if (uses > 1) {
-                return resolveSpecializedExecutables(execution, targetType.getImplicitSourceTypes(), options.implicitTypeBoxingOptimization()).size() > 1;
+                return resolveSpecializedExecutables(execution, typeSystem.lookupSourceTypes(targetType), options.implicitTypeBoxingOptimization()).size() > 1;
             } else {
                 return false;
             }
         }
     }
 
-    private CodeTree createAssignExecuteChild(NodeExecutionData execution, TypeData returnType, LocalVariable targetValue, LocalVariable shortCircuit, LocalContext currentValues) {
+    private CodeTree createAssignExecuteChild(NodeExecutionData execution, TypeMirror returnType, LocalVariable targetValue, LocalVariable shortCircuit, LocalContext currentValues) {
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        boolean hasUnexpected = hasUnexpectedResult(execution, targetValue.getType());
+        boolean hasUnexpected = hasUnexpectedResult(execution, targetValue.getTypeMirror());
 
         CodeTree executeChild;
-        if (isExecuteChildShared(execution, targetValue.getType())) {
+        if (isExecuteChildShared(execution, targetValue.getTypeMirror())) {
             executeChild = createCallSharedExecuteChild(execution, targetValue, currentValues);
         } else {
             executeChild = createExecuteChild(execution, targetValue, currentValues, false);
@@ -1876,7 +1963,7 @@
             builder.startCatchBlock(getType(UnexpectedResultException.class), "ex");
             LocalContext slowPathValues = currentValues.copy();
 
-            slowPathValues.setValue(execution, targetValue.makeGeneric().accessWith(CodeTreeBuilder.singleString("ex.getResult()")));
+            slowPathValues.setValue(execution, targetValue.makeGeneric(context).accessWith(CodeTreeBuilder.singleString("ex.getResult()")));
             boolean found = false;
             for (NodeExecutionData otherExecution : node.getChildExecutions()) {
                 if (found) {
@@ -1945,16 +2032,16 @@
     }
 
     private CodeTree createCallSharedExecuteChild(NodeExecutionData execution, LocalVariable targetValue, LocalContext currentValues) {
-        if (!isExecuteChildShared(execution, targetValue.getType())) {
+        if (!isExecuteChildShared(execution, targetValue.getTypeMirror())) {
             throw new AssertionError("Execute child not shared with method but called.");
         }
 
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
         builder.tree(targetValue.createReference()).string(" = ");
-        builder.startCall(executeChildMethodName(execution, targetValue.getType()));
+        builder.startCall(executeChildMethodName(execution, targetValue.getTypeMirror()));
         builder.string(FRAME_VALUE);
 
-        CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, targetValue.getType());
+        CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, targetValue.getTypeMirror());
         if (implicitProfile != null) {
             builder.string(implicitProfile.getName());
         }
@@ -1970,12 +2057,12 @@
 
         CodeTree assignment = createAssignmentStart(target, shared);
 
-        final Set<ExecutableTypeData> executableTypes = findSpecializedExecutableTypes(execution, target.getType());
+        final Set<ExecutableTypeData> executableTypes = findSpecializedExecutableTypes(execution, target.getTypeMirror());
         if (executableTypes.isEmpty()) {
             throw new AssertionError(); // cannot execute child
-        } else if (executableTypes.size() == 1 && !target.getType().hasImplicitSourceTypes()) {
+        } else if (executableTypes.size() == 1 && !typeSystem.hasImplicitSourceTypes(target.getTypeMirror())) {
             ExecutableTypeData executableType = executableTypes.iterator().next();
-            if (target.getType().isGeneric() && executableType.getEvaluatedCount() == 0) {
+            if (isObject(target.getTypeMirror()) && executableType.getEvaluatedCount() == 0) {
                 return createPolymorphicExecuteChild(execution, target, currentValues, shared);
             } else {
                 builder.tree(assignment);
@@ -1997,9 +2084,8 @@
     }
 
     private CodeTree createSingleExecute(NodeExecutionData execution, LocalVariable target, LocalContext currentValues, ExecutableTypeData executableType) {
-        CodeTree accessChild = accessParent(nodeFieldName(execution));
-        CodeTree execute = callTemplateMethod(accessChild, executableType, currentValues);
-        return TypeSystemCodeGenerator.expect(executableType.getType(), target.getType(), execute);
+        CodeTree execute = callExecuteMethod(execution, executableType, currentValues);
+        return expect(executableType.getReturnType(), target.getTypeMirror(), execute);
     }
 
     private CodeTree createPolymorphicExecuteChild(NodeExecutionData execution, LocalVariable target, LocalContext currentValues, boolean shared) throws AssertionError {
@@ -2011,7 +2097,7 @@
         List<ExecutableTypeData> specializedExecutables = resolvePolymorphicExecutables(execution);
         Collections.sort(specializedExecutables, new Comparator<ExecutableTypeData>() {
             public int compare(ExecutableTypeData o1, ExecutableTypeData o2) {
-                return o1.getType().compareTo(o2.getType());
+                return compareType(o1.getReturnType(), o2.getReturnType());
             }
         });
 
@@ -2034,7 +2120,7 @@
             for (ExecutableTypeData executableType : specializedExecutables) {
                 hasSpecializedTypes = polyChainBuilder.startIf(hasSpecializedTypes);
                 polyChainBuilder.string(profileField);
-                polyChainBuilder.string(" == ").typeLiteral(executableType.getType().getPrimitiveType());
+                polyChainBuilder.string(" == ").typeLiteral(executableType.getReturnType());
                 polyChainBuilder.end();
                 polyChainBuilder.startBlock();
                 polyChainBuilder.startStatement();
@@ -2048,20 +2134,20 @@
             polyChainBuilder.startElseIf().string(profileField).string(" == null").end();
             polyChainBuilder.startBlock();
             polyChainBuilder.tree(createTransferToInterpreterAndInvalidate());
-            polyChainBuilder.declaration(genericExecutableType.getType().getPrimitiveType(), valueFieldName, executeGeneric);
+            polyChainBuilder.declaration(genericExecutableType.getReturnType(), valueFieldName, executeGeneric);
 
             hasSpecializedTypes = false;
             for (ExecutableTypeData executableType : specializedExecutables) {
                 hasSpecializedTypes = polyChainBuilder.startIf(hasSpecializedTypes);
-                polyChainBuilder.tree(TypeSystemCodeGenerator.check(executableType.getType(), CodeTreeBuilder.singleString(valueFieldName)));
+                polyChainBuilder.tree(TypeSystemCodeGenerator.check(typeSystem, executableType.getReturnType(), CodeTreeBuilder.singleString(valueFieldName)));
                 polyChainBuilder.end();
                 polyChainBuilder.startBlock();
-                polyChainBuilder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(executableType.getType().getPrimitiveType()).end();
+                polyChainBuilder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(executableType.getReturnType()).end();
                 polyChainBuilder.end();
             }
 
             polyChainBuilder.startElseBlock();
-            polyChainBuilder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(genericType.getPrimitiveType()).end();
+            polyChainBuilder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(genericType).end();
             polyChainBuilder.end();
             polyChainBuilder.startReturn().string(valueFieldName).end();
             polyChainBuilder.end();
@@ -2077,7 +2163,7 @@
                 builder.tree(executePolymorphic);
                 builder.end();
                 builder.startCatchBlock(getType(UnexpectedResultException.class), "ex");
-                builder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(genericType.getPrimitiveType()).end();
+                builder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(genericType).end();
                 builder.startReturn().string("ex.getResult()").end();
                 builder.end();
             } else {
@@ -2091,9 +2177,9 @@
         if (singleSpecializable) {
             return Collections.emptyList();
         }
-        Set<TypeData> specializedTypes = new HashSet<>();
-        for (TypeData type : node.findSpecializedTypes(execution)) {
-            specializedTypes.addAll(type.getImplicitSourceTypes());
+        Set<TypeMirror> specializedTypes = new HashSet<>();
+        for (TypeMirror type : node.findSpecializedTypes(execution)) {
+            specializedTypes.addAll(typeSystem.lookupSourceTypes(type));
         }
         return resolveSpecializedExecutables(execution, specializedTypes, options.polymorphicTypeBoxingElimination());
     }
@@ -2110,23 +2196,22 @@
 
     private CodeTree createExecuteChildDuplicateTail(CodeTreeBuilder parent, NodeExecutionData execution, CodeTree assignment, LocalVariable target, LocalContext currentValues) {
         CodeTreeBuilder builder = parent.create();
-        List<TypeData> sourceTypes = target.getType().getImplicitSourceTypes();
+        List<TypeMirror> sourceTypes = typeSystem.lookupSourceTypes(target.getTypeMirror());
         String implicitClassFieldName = implicitClassFieldName(execution);
-        String nodeFieldName = nodeFieldName(execution);
         List<ExecutableTypeData> executableTypes = resolveSpecializedExecutables(execution, sourceTypes, options.implicitTypeBoxingOptimization());
 
         boolean elseIf = false;
         for (ExecutableTypeData executableType : executableTypes) {
             elseIf = builder.startIf(elseIf);
-            builder.string(implicitClassFieldName).string(" == ").typeLiteral(executableType.getType().getPrimitiveType());
+            builder.string(implicitClassFieldName).string(" == ").typeLiteral(executableType.getReturnType());
             builder.end();
             builder.startBlock();
             builder.startStatement().tree(assignment);
 
-            CodeTree execute = callTemplateMethod(accessParent(nodeFieldName), executableType, currentValues);
-            ImplicitCastData cast = typeSystem.lookupCast(executableType.getType(), target.getType());
+            CodeTree execute = callExecuteMethod(execution, executableType, currentValues);
+            ImplicitCastData cast = typeSystem.lookupCast(executableType.getReturnType(), target.getTypeMirror());
             if (cast != null) {
-                execute = callTemplateMethod(null, cast, execute);
+                execute = callMethod(null, cast.getMethod(), execute);
             }
             builder.tree(execute);
             builder.end();
@@ -2137,13 +2222,13 @@
             builder.startElseBlock();
         }
 
-        LocalVariable genericValue = target.makeGeneric().nextName();
-        builder.tree(createAssignExecuteChild(execution, genericValue.getType(), genericValue, null, currentValues));
+        LocalVariable genericValue = target.makeGeneric(context).nextName();
+        builder.tree(createAssignExecuteChild(execution, genericValue.getTypeMirror(), genericValue, null, currentValues));
         if (executableTypes.size() == sourceTypes.size()) {
             builder.startThrow().startNew(getType(UnexpectedResultException.class)).tree(genericValue.createReference()).end().end();
         } else {
             builder.startStatement().tree(assignment);
-            builder.tree(TypeSystemCodeGenerator.implicitExpect(target.getType(), genericValue.createReference(), implicitClassFieldName));
+            builder.tree(TypeSystemCodeGenerator.implicitExpect(typeSystem, target.getTypeMirror(), genericValue.createReference(), implicitClassFieldName));
             builder.end();
         }
 
@@ -2153,7 +2238,7 @@
         return builder.build();
     }
 
-    private CodeTree createFastPathTryCatchRewriteException(SpecializationData specialization, TypeData forType, LocalContext currentValues, CodeTree execution) {
+    private CodeTree createFastPathTryCatchRewriteException(SpecializationData specialization, TypeMirror forType, LocalContext currentValues, CodeTree execution) {
         if (specialization.getExceptions().isEmpty()) {
             return execution;
         }
@@ -2248,8 +2333,8 @@
         for (TypeGuard typeGuard : typeGuards) {
             int signatureIndex = typeGuard.getSignatureIndex();
             LocalVariable value = currentValues.getValue(signatureIndex);
-            TypeData targetType = typeGuard.getType();
-            if (!value.getType().needsCastTo(targetType)) {
+            TypeMirror targetType = typeGuard.getType();
+            if (!ElementUtils.needsCastTo(value.getTypeMirror(), targetType)) {
                 continue;
             }
             NodeExecutionData execution = node.getChildExecutions().get(signatureIndex);
@@ -2264,7 +2349,7 @@
             if (shortCircuit != null) {
                 checkBuilder.string("(");
                 CodeTreeBuilder referenceBuilder = checkBuilder.create();
-                if (!shortCircuit.getType().isPrimitive()) {
+                if (!ElementUtils.isPrimitive(shortCircuit.getTypeMirror())) {
                     referenceBuilder.string("(boolean) ");
                 }
                 referenceBuilder.tree(shortCircuit.createReference());
@@ -2276,15 +2361,15 @@
             List<ImplicitCastData> sourceTypes = typeSystem.lookupByTargetType(targetType);
             CodeTree valueReference = value.createReference();
             if (sourceTypes.isEmpty()) {
-                checkBuilder.tree(TypeSystemCodeGenerator.check(targetType, value.createReference()));
-                castBuilder.tree(TypeSystemCodeGenerator.cast(targetType, valueReference));
+                checkBuilder.tree(TypeSystemCodeGenerator.check(typeSystem, targetType, value.createReference()));
+                castBuilder.tree(TypeSystemCodeGenerator.cast(typeSystem, targetType, valueReference));
             } else {
                 ImplicitCastOptimization opt = options.implicitCastOptimization();
                 if (specializationExecution.isFastPath() && !opt.isNone()) {
                     if (opt.isDuplicateTail()) {
                         String typeHintField = implicitClassFieldName(execution);
-                        checkBuilder.tree(TypeSystemCodeGenerator.implicitCheck(targetType, valueReference, typeHintField));
-                        castBuilder.tree(TypeSystemCodeGenerator.implicitCast(targetType, valueReference, typeHintField));
+                        checkBuilder.tree(TypeSystemCodeGenerator.implicitCheck(typeSystem, targetType, valueReference, typeHintField));
+                        castBuilder.tree(TypeSystemCodeGenerator.implicitCast(typeSystem, targetType, valueReference, typeHintField));
                     } else if (opt.isMergeCasts()) {
                         checkBuilder.tree(ImplicitCastNodeFactory.check(implicitNodeFieldName(execution), valueReference));
                         castBuilder.tree(ImplicitCastNodeFactory.cast(implicitNodeFieldName(execution), valueReference));
@@ -2292,14 +2377,14 @@
                         throw new AssertionError("implicit cast opt");
                     }
                 } else {
-                    checkBuilder.tree(TypeSystemCodeGenerator.implicitCheck(targetType, valueReference, null));
-                    castBuilder.tree(TypeSystemCodeGenerator.implicitCast(targetType, valueReference, null));
+                    checkBuilder.tree(TypeSystemCodeGenerator.implicitCheck(typeSystem, targetType, valueReference, null));
+                    castBuilder.tree(TypeSystemCodeGenerator.implicitCast(typeSystem, targetType, valueReference, null));
                 }
             }
 
             if (shortCircuit != null) {
                 checkBuilder.string(")");
-                castBuilder.string(" : ").defaultValue(targetType.getPrimitiveType());
+                castBuilder.string(" : ").defaultValue(targetType);
             }
 
             if (castGuards == null || castGuards.contains(typeGuard)) {
@@ -2329,7 +2414,7 @@
         String varName = name + specialization.getIndex();
         TypeMirror type = cache.getParameter().getType();
         builder.declaration(type, varName, initializer);
-        currentValues.set(name, new LocalVariable(null, type, varName, null, null));
+        currentValues.set(name, new LocalVariable(type, varName, null, null));
     }
 
     public static final class LocalContext {
@@ -2345,13 +2430,13 @@
             for (CacheExpression cache : specialization.getCaches()) {
                 Parameter cacheParameter = cache.getParameter();
                 String name = cacheParameter.getVariableElement().getSimpleName().toString();
-                set(cacheParameter.getLocalName(), new LocalVariable(cacheParameter.getTypeSystemType(), cacheParameter.getType(), name, CodeTreeBuilder.singleString("this." + name), null));
+                set(cacheParameter.getLocalName(), new LocalVariable(cacheParameter.getType(), name, CodeTreeBuilder.singleString("this." + name), null));
             }
 
             for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
                 String name = assumptionName(assumption);
                 TypeMirror type = assumption.getExpression().getResolvedType();
-                set(name, new LocalVariable(null, type, name, CodeTreeBuilder.singleString("this." + name), null));
+                set(name, new LocalVariable(type, name, CodeTreeBuilder.singleString("this." + name), null));
             }
         }
 
@@ -2382,12 +2467,12 @@
         }
 
         @SuppressWarnings("static-method")
-        public LocalVariable createValue(NodeExecutionData execution, TypeData type) {
-            return new LocalVariable(type, type.getPrimitiveType(), valueName(execution), null, null);
+        public LocalVariable createValue(NodeExecutionData execution, TypeMirror type) {
+            return new LocalVariable(type, valueName(execution), null, null);
         }
 
         public LocalVariable createShortCircuitValue(NodeExecutionData execution) {
-            return new LocalVariable(factory.typeSystem.getBooleanType(), factory.getType(boolean.class), shortCircuitName(execution), null, null);
+            return new LocalVariable(factory.getType(boolean.class), shortCircuitName(execution), null, null);
         }
 
         private static String valueName(NodeExecutionData execution) {
@@ -2424,7 +2509,12 @@
         }
 
         public LocalVariable getValue(int signatureIndex) {
-            return getValue(factory.node.getChildExecutions().get(signatureIndex));
+            List<NodeExecutionData> childExecutions = factory.node.getChildExecutions();
+            if (signatureIndex < childExecutions.size()) {
+                return getValue(childExecutions.get(signatureIndex));
+            } else {
+                return null;
+            }
         }
 
         public void removeValue(String id) {
@@ -2458,11 +2548,11 @@
         }
 
         private void loadValues(int evaluatedArguments, int varargsThreshold) {
-            values.put(FRAME_VALUE, new LocalVariable(null, factory.getType(Frame.class), FRAME_VALUE, null, null));
+            values.put(FRAME_VALUE, new LocalVariable(factory.getType(Frame.class), FRAME_VALUE, null, null));
 
             for (NodeFieldData field : factory.node.getFields()) {
                 String fieldName = fieldValueName(field);
-                values.put(fieldName, new LocalVariable(null, field.getType(), fieldName, factory.accessParent(field.getName()), null));
+                values.put(fieldName, new LocalVariable(field.getType(), fieldName, factory.accessParent(field.getName()), null));
             }
 
             boolean varargs = needsVarargs(false, varargsThreshold);
@@ -2473,7 +2563,7 @@
                 }
                 NodeExecutionData execution = childExecutions.get(i);
                 if (execution.isShortCircuit()) {
-                    LocalVariable shortCircuit = createShortCircuitValue(execution).makeGeneric();
+                    LocalVariable shortCircuit = createShortCircuitValue(execution).makeGeneric(factory.context);
                     if (varargs) {
                         shortCircuit = shortCircuit.accessWith(createReadVarargs(i));
                     }
@@ -2562,7 +2652,6 @@
 
     public static final class LocalVariable {
 
-        private final TypeData type;
         private final TypeMirror typeMirror;
         private final CodeTree accessorTree;
         private final String name;
@@ -2576,22 +2665,17 @@
             } else {
                 name = createName(execution);
             }
-            return new LocalVariable(parameter.getTypeSystemType(), parameter.getType(), name, null, null);
+            return new LocalVariable(parameter.getType(), name, null, null);
         }
 
-        private LocalVariable(TypeData type, TypeMirror typeMirror, String name, CodeTree accessorTree, LocalVariable previous) {
+        private LocalVariable(TypeMirror typeMirror, String name, CodeTree accessorTree, LocalVariable previous) {
             Objects.requireNonNull(typeMirror);
             this.typeMirror = typeMirror;
             this.accessorTree = accessorTree;
-            this.type = type;
             this.name = name;
             this.previous = previous;
         }
 
-        public TypeData getType() {
-            return type;
-        }
-
         public String getShortCircuitName() {
             return "has" + ElementUtils.firstLetterUpperCase(getName());
         }
@@ -2631,24 +2715,20 @@
             }
         }
 
-        public LocalVariable newType(TypeData newType) {
-            return new LocalVariable(newType, newType.getPrimitiveType(), name, accessorTree, this);
-        }
-
         public LocalVariable newType(TypeMirror newType) {
-            return new LocalVariable(type, newType, name, accessorTree, this);
+            return new LocalVariable(newType, name, accessorTree, this);
         }
 
         public LocalVariable accessWith(CodeTree tree) {
-            return new LocalVariable(type, typeMirror, name, tree, this);
+            return new LocalVariable(typeMirror, name, tree, this);
         }
 
         public LocalVariable nextName() {
-            return new LocalVariable(type, typeMirror, createNextName(name), accessorTree, this);
+            return new LocalVariable(typeMirror, createNextName(name), accessorTree, this);
         }
 
         public LocalVariable makeOriginal() {
-            return new LocalVariable(type, typeMirror, name, accessorTree, null);
+            return new LocalVariable(typeMirror, name, accessorTree, null);
         }
 
         public LocalVariable original() {
@@ -2659,8 +2739,8 @@
             return variable;
         }
 
-        public LocalVariable makeGeneric() {
-            return newType(type.getTypeSystem().getGenericTypeData());
+        public LocalVariable makeGeneric(ProcessorContext context) {
+            return newType(context.getType(Object.class));
         }
 
         @Override
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java	Tue Apr 14 15:12:48 2015 +0200
@@ -22,12 +22,13 @@
  */
 package com.oracle.truffle.dsl.processor.generator;
 
+import static com.oracle.truffle.dsl.processor.generator.GeneratorUtils.*;
 import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
-import static com.oracle.truffle.dsl.processor.generator.GeneratorUtils.*;
 import static javax.lang.model.element.Modifier.*;
 
 import java.util.*;
 
+import javax.lang.model.element.*;
 import javax.lang.model.type.*;
 
 import com.oracle.truffle.api.nodes.*;
@@ -38,64 +39,47 @@
 
 public class TypeSystemCodeGenerator extends CodeTypeElementFactory<TypeSystemData> {
 
-    public static CodeTree cast(TypeData type, String content) {
-        return cast(type, CodeTreeBuilder.singleString(content));
+    private static final String LOCAL_VALUE = "value";
+
+    public static CodeTree cast(TypeSystemData typeSystem, TypeMirror type, String content) {
+        return cast(typeSystem, type, CodeTreeBuilder.singleString(content));
     }
 
-    public static CodeTree implicitType(TypeData type, CodeTree value) {
-        if (type.isGeneric()) {
+    public static CodeTree implicitType(TypeSystemData typeSystem, TypeMirror type, CodeTree value) {
+        if (ElementUtils.isObject(type)) {
             return value;
         }
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        TypeSystemData typeSystem = type.getTypeSystem();
-        builder.startStaticCall(createTypeSystemGen(typeSystem), getImplicitClass(type)).tree(value);
+        builder.startStaticCall(createTypeSystemGen(typeSystem), getImplicitClass(typeSystem, type)).tree(value);
         builder.end();
         return builder.build();
     }
 
-    public static CodeTree invokeImplicitCast(ImplicitCastData cast, CodeTree expression) {
+    public static CodeTree invokeImplicitCast(TypeSystemData typeSystem, ImplicitCastData cast, CodeTree expression) {
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        TypeSystemData typeSystem = cast.getTargetType().getTypeSystem();
         builder.startStaticCall(createTypeSystemGen(typeSystem), cast.getMethodName()).tree(expression);
         builder.end();
         return builder.build();
     }
 
-    public static CodeTree implicitCheck(TypeData type, CodeTree value, String typeHint) {
-        if (type.isGeneric()) {
+    public static CodeTree implicitCheck(TypeSystemData typeSystem, TypeMirror type, CodeTree value, String typeHint) {
+        return callImplictMethod(typeSystem, type, isImplicitTypeMethodName(typeSystem, type), value, typeHint);
+    }
+
+    public static CodeTree implicitExpect(TypeSystemData typeSystem, TypeMirror type, CodeTree value, String typeHint) {
+        return callImplictMethod(typeSystem, type, expectImplicitTypeMethodName(typeSystem, type), value, typeHint);
+    }
+
+    public static CodeTree implicitCast(TypeSystemData typeSystem, TypeMirror type, CodeTree value, String typeHint) {
+        return callImplictMethod(typeSystem, type, asImplicitTypeMethodName(typeSystem, type), value, typeHint);
+    }
+
+    private static CodeTree callImplictMethod(TypeSystemData typeSystem, TypeMirror type, String methodName, CodeTree value, String typeHint) {
+        if (ElementUtils.isObject(type)) {
             return value;
         }
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        TypeSystemData typeSystem = type.getTypeSystem();
-        builder.startStaticCall(createTypeSystemGen(typeSystem), isImplicitTypeMethodName(type)).tree(value);
-        if (typeHint != null) {
-            builder.string(typeHint);
-        }
-        builder.end();
-        return builder.build();
-    }
-
-    public static CodeTree implicitExpect(TypeData type, CodeTree value, String typeHint) {
-        if (type.isGeneric()) {
-            return value;
-        }
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        TypeSystemData typeSystem = type.getTypeSystem();
-        builder.startStaticCall(createTypeSystemGen(typeSystem), expectImplicitTypeMethodName(type)).tree(value);
-        if (typeHint != null) {
-            builder.string(typeHint);
-        }
-        builder.end();
-        return builder.build();
-    }
-
-    public static CodeTree implicitCast(TypeData type, CodeTree value, String typeHint) {
-        if (type.isGeneric()) {
-            return value;
-        }
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        TypeSystemData typeSystem = type.getTypeSystem();
-        builder.startStaticCall(createTypeSystemGen(typeSystem), asImplicitTypeMethodName(type)).tree(value);
+        builder.startStaticCall(createTypeSystemGen(typeSystem), methodName).tree(value);
         if (typeHint != null) {
             builder.string(typeHint);
         }
@@ -103,36 +87,57 @@
         return builder.build();
     }
 
-    public static CodeTree cast(TypeData type, CodeTree content) {
-        if (type.isGeneric()) {
+    public static CodeTree cast(TypeSystemData typeSystem, TypeMirror type, CodeTree content) {
+        if (ElementUtils.isObject(type)) {
             return content;
         }
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        TypeSystemData typeSystem = type.getTypeSystem();
 
-        if (type.isDefaultCast()) {
-            builder.cast(type.getPrimitiveType(), content);
+        TypeCastData cast = typeSystem.getCast(type);
+        if (cast == null) {
+            builder.cast(type, content);
         } else {
-            builder.startStaticCall(typeSystem.getTemplateType().asType(), type.getTypeCasts().get(0).getMethodName()).tree(content).end();
+            builder.startStaticCall(typeSystem.getTemplateType().asType(), cast.getMethodName()).tree(content).end();
         }
         return builder.build();
     }
 
-    public static CodeTree expect(TypeData type, CodeTree content) {
-        if (type.isGeneric() || type.isVoid()) {
+    public static CodeTree expect(TypeSystemData typeSystem, TypeMirror type, CodeTree content) {
+        if (ElementUtils.isObject(type) || ElementUtils.isVoid(type)) {
             return content;
         }
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        TypeSystemData typeSystem = type.getTypeSystem();
-        builder.startStaticCall(createTypeSystemGen(typeSystem), expectTypeMethodName(type)).tree(content).end();
+        if (typeSystem.hasType(type)) {
+            builder.startStaticCall(createTypeSystemGen(typeSystem), expectTypeMethodName(typeSystem, type)).tree(content).end();
+        } else {
+            builder.startCall(expectTypeMethodName(typeSystem, type)).tree(content).end();
+        }
+
         return builder.build();
     }
 
-    public static CodeTree expect(TypeData sourceType, TypeData targetType, CodeTree content) {
-        if (sourceType != null && !sourceType.needsCastTo(targetType)) {
+    public static CodeExecutableElement createExpectMethod(Modifier visibility, TypeSystemData typeSystem, TypeMirror sourceType, TypeMirror expectedType) {
+        if (ElementUtils.isObject(expectedType) || ElementUtils.isVoid(expectedType)) {
+            return null;
+        }
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), expectedType, TypeSystemCodeGenerator.expectTypeMethodName(typeSystem, expectedType));
+        method.setVisibility(visibility);
+        method.addParameter(new CodeVariableElement(sourceType, LOCAL_VALUE));
+        method.addThrownType(typeSystem.getContext().getTruffleTypes().getUnexpectedValueException());
+
+        CodeTreeBuilder body = method.createBuilder();
+        body.startIf().tree(check(typeSystem, expectedType, LOCAL_VALUE)).end().startBlock();
+        body.startReturn().tree(cast(typeSystem, expectedType, LOCAL_VALUE)).end();
+        body.end();
+        body.startThrow().startNew(typeSystem.getContext().getTruffleTypes().getUnexpectedValueException()).string(LOCAL_VALUE).end().end();
+        return method;
+    }
+
+    public static CodeTree expect(TypeSystemData typeSystem, TypeMirror sourceType, TypeMirror targetType, CodeTree content) {
+        if (sourceType != null && !ElementUtils.needsCastTo(sourceType, targetType)) {
             return content;
         } else {
-            return expect(targetType, content);
+            return expect(typeSystem, targetType, content);
         }
     }
 
@@ -140,51 +145,55 @@
         return new GeneratedTypeMirror(ElementUtils.getPackageName(typeSystem.getTemplateType()), typeName(typeSystem));
     }
 
-    public static CodeTree check(TypeData type, String content) {
-        return check(type, CodeTreeBuilder.singleString(content));
+    public static CodeTree check(TypeSystemData typeSystem, TypeMirror type, String content) {
+        return check(typeSystem, type, CodeTreeBuilder.singleString(content));
     }
 
-    public static CodeTree check(TypeData type, CodeTree content) {
-        if (type.isGeneric()) {
+    public static CodeTree check(TypeSystemData typeSystem, TypeMirror type, CodeTree content) {
+        if (ElementUtils.isObject(type)) {
             return content;
         }
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        TypeSystemData typeSystem = type.getTypeSystem();
 
-        if (type.isDefaultCheck()) {
-            builder.instanceOf(content, type.getBoxedType());
+        TypeCheckData check = typeSystem.getCheck(type);
+        if (check == null) {
+            builder.instanceOf(content, ElementUtils.boxType(typeSystem.getContext(), type));
         } else {
-            builder.startStaticCall(typeSystem.getTemplateType().asType(), type.getTypeChecks().get(0).getMethodName()).tree(content).end();
+            builder.startStaticCall(typeSystem.getTemplateType().asType(), check.getMethodName()).tree(content).end();
         }
         return builder.build();
     }
 
-    public static String isTypeMethodName(TypeData type) {
-        return "is" + ElementUtils.getTypeId(type.getBoxedType());
+    public static String isTypeMethodName(TypeSystemData typeSystem, TypeMirror type) {
+        return "is" + getTypeId(typeSystem, type);
     }
 
-    static String isImplicitTypeMethodName(TypeData type) {
-        return "isImplicit" + ElementUtils.getTypeId(type.getBoxedType());
+    private static String getTypeId(TypeSystemData typeSystem, TypeMirror type) {
+        return ElementUtils.getTypeId(typeSystem.boxType(type));
     }
 
-    public static String asTypeMethodName(TypeData type) {
-        return "as" + ElementUtils.getTypeId(type.getBoxedType());
+    static String isImplicitTypeMethodName(TypeSystemData typeSystem, TypeMirror type) {
+        return "isImplicit" + getTypeId(typeSystem, type);
     }
 
-    static String asImplicitTypeMethodName(TypeData type) {
-        return "asImplicit" + ElementUtils.getTypeId(type.getBoxedType());
+    public static String asTypeMethodName(TypeSystemData typeSystem, TypeMirror type) {
+        return "as" + getTypeId(typeSystem, type);
+    }
+
+    static String asImplicitTypeMethodName(TypeSystemData typeSystem, TypeMirror type) {
+        return "asImplicit" + getTypeId(typeSystem, type);
     }
 
-    static String expectImplicitTypeMethodName(TypeData type) {
-        return "expectImplicit" + ElementUtils.getTypeId(type.getBoxedType());
+    static String expectImplicitTypeMethodName(TypeSystemData typeSystem, TypeMirror type) {
+        return "expectImplicit" + getTypeId(typeSystem, type);
     }
 
-    static String getImplicitClass(TypeData type) {
-        return "getImplicit" + ElementUtils.getTypeId(type.getBoxedType()) + "Class";
+    static String getImplicitClass(TypeSystemData typeSystem, TypeMirror type) {
+        return "getImplicit" + getTypeId(typeSystem, type) + "Class";
     }
 
-    public static String expectTypeMethodName(TypeData type) {
-        return "expect" + ElementUtils.getTypeId(type.getBoxedType());
+    public static String expectTypeMethodName(TypeSystemData typeSystem, TypeMirror type) {
+        return "expect" + getTypeId(typeSystem, type);
     }
 
     static String typeName(TypeSystemData typeSystem) {
@@ -203,11 +212,8 @@
         clazz.add(new TypeSystemNodeFactory(context, typeSystem).create());
 
         if (typeSystem.getOptions().implicitCastOptimization().isMergeCasts()) {
-            for (TypeData type : typeSystem.getTypes()) {
-                List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
-                if (sourceTypes.size() > 1) {
-                    clazz.add(new ImplicitCastNodeFactory(context, type).create());
-                }
+            for (TypeMirror type : typeSystem.lookupTargetTypes()) {
+                clazz.add(new ImplicitCastNodeFactory(context, typeSystem, type).create());
             }
         }
         return clazz;
@@ -215,8 +221,6 @@
 
     private static class TypeClassFactory {
 
-        private static final String LOCAL_VALUE = "value";
-
         private final ProcessorContext context;
         private final TypeSystemData typeSystem;
 
@@ -233,50 +237,35 @@
             CodeVariableElement singleton = createSingleton(clazz);
             clazz.add(singleton);
 
-            for (TypeData type : typeSystem.getTypes()) {
-                if (type.isVoid() || type.isGeneric()) {
+            for (TypeMirror type : typeSystem.getLegacyTypes()) {
+                if (ElementUtils.isVoid(type) || ElementUtils.isObject(type)) {
                     continue;
                 }
 
                 clazz.addOptional(createIsTypeMethod(type));
                 clazz.addOptional(createAsTypeMethod(type));
+                clazz.addOptional(createExpectTypeMethod(type, context.getType(Object.class)));
 
-                for (TypeData sourceType : collectExpectSourceTypes(type)) {
-                    clazz.addOptional(createExpectTypeMethod(type, sourceType));
-                }
+            }
 
-                if (type.hasImplicitSourceTypes()) {
-                    clazz.add(createAsImplicitTypeMethod(type, false));
-                    if (typeSystem.getOptions().implicitCastOptimization().isNone()) {
-                        clazz.add(createExpectImplicitTypeMethod(type, false));
-                    }
-                    clazz.add(createIsImplicitTypeMethod(type, false));
+            List<TypeMirror> lookupTargetTypes = typeSystem.lookupTargetTypes();
+            for (TypeMirror type : lookupTargetTypes) {
+                clazz.add(createAsImplicitTypeMethod(type, false));
+                if (typeSystem.getOptions().implicitCastOptimization().isNone()) {
+                    clazz.add(createExpectImplicitTypeMethod(type, false));
+                }
+                clazz.add(createIsImplicitTypeMethod(type, false));
 
-                    if (typeSystem.getOptions().implicitCastOptimization().isDuplicateTail()) {
-                        clazz.add(createAsImplicitTypeMethod(type, true));
-                        clazz.add(createExpectImplicitTypeMethod(type, true));
-                        clazz.add(createIsImplicitTypeMethod(type, true));
-                        clazz.add(createGetImplicitClass(type));
-                    }
+                if (typeSystem.getOptions().implicitCastOptimization().isDuplicateTail()) {
+                    clazz.add(createAsImplicitTypeMethod(type, true));
+                    clazz.add(createExpectImplicitTypeMethod(type, true));
+                    clazz.add(createIsImplicitTypeMethod(type, true));
+                    clazz.add(createGetImplicitClass(type));
                 }
             }
-
             return clazz;
         }
 
-        private static List<TypeData> collectExpectSourceTypes(TypeData type) {
-            Set<TypeData> sourceTypes = new HashSet<>();
-            sourceTypes.add(type.getTypeSystem().getGenericTypeData());
-            for (TypeCastData cast : type.getTypeCasts()) {
-                sourceTypes.add(cast.getSourceType());
-            }
-            for (TypeCheckData cast : type.getTypeChecks()) {
-                sourceTypes.add(cast.getCheckedType());
-            }
-            sourceTypes.remove(type);
-            return new ArrayList<>(sourceTypes);
-        }
-
         private CodeVariableElement createSingleton(CodeTypeElement clazz) {
             CodeVariableElement field = new CodeVariableElement(modifiers(PUBLIC, STATIC, FINAL), clazz.asType(), singletonName(typeSystem));
             field.createInitBuilder().startNew(clazz.asType()).end();
@@ -287,24 +276,24 @@
             return field;
         }
 
-        private CodeExecutableElement createIsImplicitTypeMethod(TypeData type, boolean typed) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(boolean.class), TypeSystemCodeGenerator.isImplicitTypeMethodName(type));
+        private CodeExecutableElement createIsImplicitTypeMethod(TypeMirror type, boolean typed) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(boolean.class), TypeSystemCodeGenerator.isImplicitTypeMethodName(typeSystem, type));
             method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
             if (typed) {
                 method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint"));
             }
             CodeTreeBuilder builder = method.createBuilder();
 
-            List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
+            List<TypeMirror> sourceTypes = typeSystem.lookupSourceTypes(type);
 
             builder.startReturn();
             String sep = "";
-            for (TypeData sourceType : sourceTypes) {
+            for (TypeMirror sourceType : sourceTypes) {
                 builder.string(sep);
                 if (typed) {
-                    builder.string("(typeHint == ").typeLiteral(sourceType.getPrimitiveType()).string(" && ");
+                    builder.string("(typeHint == ").typeLiteral(sourceType).string(" && ");
                 }
-                builder.tree(check(sourceType, LOCAL_VALUE));
+                builder.tree(check(typeSystem, sourceType, LOCAL_VALUE));
                 if (typed) {
                     builder.string(")");
                 }
@@ -321,24 +310,24 @@
             return method;
         }
 
-        private CodeExecutableElement createAsImplicitTypeMethod(TypeData type, boolean useTypeHint) {
-            String name = asImplicitTypeMethodName(type);
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type.getPrimitiveType(), name);
+        private CodeExecutableElement createAsImplicitTypeMethod(TypeMirror type, boolean useTypeHint) {
+            String name = asImplicitTypeMethodName(typeSystem, type);
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type, name);
             method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
             if (useTypeHint) {
                 method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint"));
             }
 
-            List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
+            List<TypeMirror> sourceTypes = typeSystem.lookupSourceTypes(type);
 
             CodeTreeBuilder builder = method.createBuilder();
             boolean elseIf = false;
-            for (TypeData sourceType : sourceTypes) {
+            for (TypeMirror sourceType : sourceTypes) {
                 elseIf = builder.startIf(elseIf);
                 if (useTypeHint) {
-                    builder.string("typeHint == ").typeLiteral(sourceType.getPrimitiveType());
+                    builder.string("typeHint == ").typeLiteral(sourceType);
                 } else {
-                    builder.tree(check(sourceType, LOCAL_VALUE));
+                    builder.tree(check(typeSystem, sourceType, LOCAL_VALUE));
                 }
 
                 builder.end().startBlock();
@@ -348,7 +337,7 @@
                 if (cast != null) {
                     builder.startCall(cast.getMethodName());
                 }
-                builder.tree(cast(sourceType, LOCAL_VALUE)).end();
+                builder.tree(cast(typeSystem, sourceType, LOCAL_VALUE)).end();
                 if (cast != null) {
                     builder.end();
                 }
@@ -363,26 +352,26 @@
             return method;
         }
 
-        private CodeExecutableElement createExpectImplicitTypeMethod(TypeData type, boolean useTypeHint) {
-            String name = expectImplicitTypeMethodName(type);
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type.getPrimitiveType(), name);
+        private CodeExecutableElement createExpectImplicitTypeMethod(TypeMirror type, boolean useTypeHint) {
+            String name = expectImplicitTypeMethodName(typeSystem, type);
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type, name);
             method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
             if (useTypeHint) {
                 method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint"));
             }
             method.getThrownTypes().add(context.getType(UnexpectedResultException.class));
 
-            List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
+            List<TypeMirror> sourceTypes = typeSystem.lookupSourceTypes(type);
 
             CodeTreeBuilder builder = method.createBuilder();
             boolean elseIf = false;
-            for (TypeData sourceType : sourceTypes) {
+            for (TypeMirror sourceType : sourceTypes) {
                 elseIf = builder.startIf(elseIf);
                 if (useTypeHint) {
-                    builder.string("typeHint == ").typeLiteral(sourceType.getPrimitiveType());
+                    builder.string("typeHint == ").typeLiteral(sourceType);
                     builder.string(" && ");
                 }
-                builder.tree(check(sourceType, LOCAL_VALUE));
+                builder.tree(check(typeSystem, sourceType, LOCAL_VALUE));
 
                 builder.end().startBlock();
 
@@ -391,7 +380,7 @@
                 if (cast != null) {
                     builder.startCall(cast.getMethodName());
                 }
-                builder.tree(cast(sourceType, LOCAL_VALUE)).end();
+                builder.tree(cast(typeSystem, sourceType, LOCAL_VALUE)).end();
                 if (cast != null) {
                     builder.end();
                 }
@@ -405,18 +394,18 @@
             return method;
         }
 
-        private CodeExecutableElement createGetImplicitClass(TypeData type) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(Class.class), TypeSystemCodeGenerator.getImplicitClass(type));
+        private CodeExecutableElement createGetImplicitClass(TypeMirror type) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(Class.class), TypeSystemCodeGenerator.getImplicitClass(typeSystem, type));
             method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
 
-            List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
+            List<TypeMirror> sourceTypes = typeSystem.lookupSourceTypes(type);
             CodeTreeBuilder builder = method.createBuilder();
             boolean elseIf = false;
-            for (TypeData sourceType : sourceTypes) {
+            for (TypeMirror sourceType : sourceTypes) {
                 elseIf = builder.startIf(elseIf);
-                builder.tree(check(sourceType, LOCAL_VALUE)).end();
+                builder.tree(check(typeSystem, sourceType, LOCAL_VALUE)).end();
                 builder.end().startBlock();
-                builder.startReturn().typeLiteral(sourceType.getPrimitiveType()).end();
+                builder.startReturn().typeLiteral(sourceType).end();
                 builder.end();
             }
 
@@ -428,50 +417,39 @@
             return method;
         }
 
-        private CodeExecutableElement createIsTypeMethod(TypeData type) {
-            if (!type.getTypeChecks().isEmpty()) {
+        private CodeExecutableElement createIsTypeMethod(TypeMirror type) {
+            if (typeSystem.getCheck(type) != null) {
                 return null;
             }
 
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(boolean.class), TypeSystemCodeGenerator.isTypeMethodName(type));
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(boolean.class), TypeSystemCodeGenerator.isTypeMethodName(typeSystem, type));
             method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
 
             CodeTreeBuilder body = method.createBuilder();
-            body.startReturn().tree(check(type, LOCAL_VALUE)).end();
+            body.startReturn().tree(check(typeSystem, type, LOCAL_VALUE)).end();
 
             return method;
         }
 
-        private CodeExecutableElement createAsTypeMethod(TypeData type) {
-            if (!type.getTypeCasts().isEmpty()) {
+        private CodeExecutableElement createAsTypeMethod(TypeMirror type) {
+            if (typeSystem.getCast(type) != null) {
                 return null;
             }
 
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asTypeMethodName(type));
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type, TypeSystemCodeGenerator.asTypeMethodName(typeSystem, type));
             method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
 
             CodeTreeBuilder body = method.createBuilder();
-            String assertMessage = typeName(typeSystem) + "." + asTypeMethodName(type) + ": " + ElementUtils.getSimpleName(type.getBoxedType()) + " expected";
-            body.startAssert().tree(check(type, LOCAL_VALUE)).string(" : ").doubleQuote(assertMessage).end();
-            body.startReturn().tree(cast(type, LOCAL_VALUE)).end();
+            String assertMessage = typeName(typeSystem) + "." + asTypeMethodName(typeSystem, type) + ": " + ElementUtils.getSimpleName(type) + " expected";
+            body.startAssert().tree(check(typeSystem, type, LOCAL_VALUE)).string(" : ").doubleQuote(assertMessage).end();
+            body.startReturn().tree(cast(typeSystem, type, LOCAL_VALUE)).end();
 
             return method;
         }
 
-        private CodeExecutableElement createExpectTypeMethod(TypeData expectedType, TypeData sourceType) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), expectedType.getPrimitiveType(), TypeSystemCodeGenerator.expectTypeMethodName(expectedType));
-            method.addParameter(new CodeVariableElement(sourceType.getPrimitiveType(), LOCAL_VALUE));
-            method.addThrownType(context.getTruffleTypes().getUnexpectedValueException());
-
-            CodeTreeBuilder body = method.createBuilder();
-            body.startIf().tree(check(expectedType, LOCAL_VALUE)).end().startBlock();
-            body.startReturn().tree(cast(expectedType, LOCAL_VALUE)).end().end();
-            body.end(); // if-block
-            body.startThrow().startNew(context.getTruffleTypes().getUnexpectedValueException()).string(LOCAL_VALUE).end().end();
-
-            return method;
+        private CodeExecutableElement createExpectTypeMethod(TypeMirror expectedType, TypeMirror sourceType) {
+            return createExpectMethod(Modifier.PUBLIC, typeSystem, sourceType, expectedType);
         }
-
     }
 
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemNodeFactory.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemNodeFactory.java	Tue Apr 14 15:12:48 2015 +0200
@@ -50,8 +50,12 @@
     }
 
     public static TypeMirror nodeType(TypeSystemData typeSystem) {
-        TypeMirror parentType = TypeSystemCodeGenerator.createTypeSystemGen(typeSystem);
-        return new GeneratedTypeMirror(getQualifiedName(parentType), typeName(typeSystem));
+        if (typeSystem.isDefault()) {
+            return typeSystem.getContext().getType(SpecializationNode.class);
+        } else {
+            TypeMirror parentType = TypeSystemCodeGenerator.createTypeSystemGen(typeSystem);
+            return new GeneratedTypeMirror(getQualifiedName(parentType), typeName(typeSystem));
+        }
     }
 
     public static String typeName(TypeSystemData typeSystem) {
@@ -62,17 +66,17 @@
         return "acceptAndExecute";
     }
 
-    public static String executeName(TypeData type) {
+    public static String executeName(TypeMirror type) {
         if (type == null) {
             return acceptAndExecuteName();
-        } else if (type.isGeneric()) {
+        } else if (ElementUtils.isObject(type)) {
             return "executeGeneric";
         } else {
-            return "execute" + getTypeId(type.getBoxedType());
+            return "execute" + getTypeId(type);
         }
     }
 
-    public static String voidBoxingExecuteName(TypeData type) {
+    public static String voidBoxingExecuteName(TypeMirror type) {
         return executeName(type) + "Void";
     }
 
@@ -85,7 +89,7 @@
             clazz.add(GeneratorUtils.createSuperConstructor(context, clazz, constructor));
         }
 
-        for (TypeData type : typeSystem.getTypes()) {
+        for (TypeMirror type : typeSystem.getLegacyTypes()) {
             clazz.add(createExecuteMethod(type));
             if (GeneratorUtils.isTypeBoxingOptimized(options.voidBoxingOptimization(), type)) {
                 clazz.add(createVoidBoxingExecuteMethod(type));
@@ -94,10 +98,10 @@
         return clazz;
     }
 
-    private Element createVoidBoxingExecuteMethod(TypeData type) {
-        TypeData voidType = typeSystem.getVoidType();
+    private Element createVoidBoxingExecuteMethod(TypeMirror type) {
+        TypeMirror voidType = context.getType(void.class);
         String methodName = voidBoxingExecuteName(type);
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), voidType.getPrimitiveType(), methodName);
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), voidType, methodName);
         method.addParameter(new CodeVariableElement(context.getType(Frame.class), "frame"));
 
         CodeTreeBuilder builder = method.createBuilder();
@@ -110,21 +114,21 @@
         return method;
     }
 
-    private Element createExecuteMethod(TypeData type) {
-        TypeData genericType = typeSystem.getGenericTypeData();
+    private Element createExecuteMethod(TypeMirror type) {
+        TypeMirror genericType = context.getType(Object.class);
         String methodName = executeName(type);
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), methodName);
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type, methodName);
         method.addParameter(new CodeVariableElement(context.getType(Frame.class), "frame"));
 
-        if (type.isGeneric()) {
+        if (ElementUtils.isObject(type)) {
             method.getModifiers().add(ABSTRACT);
         } else {
             CodeTreeBuilder builder = method.createBuilder();
             CodeTree executeGeneric = builder.create().startCall(executeName(genericType)).string("frame").end().build();
-            if (!type.isVoid()) {
+            if (!ElementUtils.isVoid(type)) {
                 method.getThrownTypes().add(context.getType(UnexpectedResultException.class));
             }
-            builder.startReturn().tree(TypeSystemCodeGenerator.expect(type, executeGeneric)).end();
+            builder.startReturn().tree(TypeSystemCodeGenerator.expect(typeSystem, type, executeGeneric)).end();
         }
 
         return method;
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java	Tue Apr 14 15:12:48 2015 +0200
@@ -225,8 +225,14 @@
     }
 
     public static boolean isAssignable(TypeMirror from, TypeMirror to) {
+        if (typeEquals(from, to)) {
+            return true;
+        } else if (isVoid(to)) {
+            return true;
+        } else if (isObject(to)) {
+            return true;
+        }
         ProcessorContext context = ProcessorContext.getInstance();
-
         if (!(from instanceof CodeTypeMirror) && !(to instanceof CodeTypeMirror)) {
             return context.getEnvironment().getTypeUtils().isAssignable(context.reloadType(from), context.reloadType(to));
         } else {
@@ -1122,4 +1128,82 @@
             throw new AssertionError("unsupported element type");
         }
     }
+
+    public static List<TypeMirror> sortTypes(List<TypeMirror> list) {
+        Collections.sort(list, new Comparator<TypeMirror>() {
+            public int compare(TypeMirror o1, TypeMirror o2) {
+                return compareType(o1, o2);
+            }
+        });
+        return list;
+    }
+
+    public static int compareType(TypeMirror signature1, TypeMirror signature2) {
+        if (signature1 == null) {
+            return 1;
+        } else if (signature2 == null) {
+            return -1;
+        }
+
+        if (ElementUtils.typeEquals(signature1, signature2)) {
+            return 0;
+        }
+
+        if (signature1.getKind() == TypeKind.DECLARED && signature2.getKind() == TypeKind.DECLARED) {
+            TypeElement element1 = ElementUtils.fromTypeMirror(signature1);
+            TypeElement element2 = ElementUtils.fromTypeMirror(signature2);
+
+            if (ElementUtils.getDirectSuperTypes(element1).contains(element2)) {
+                return -1;
+            } else if (ElementUtils.getDirectSuperTypes(element2).contains(element1)) {
+                return 1;
+            }
+        }
+        return ElementUtils.getSimpleName(signature1).compareTo(ElementUtils.getSimpleName(signature2));
+    }
+
+    public static List<TypeMirror> uniqueSortedTypes(Collection<TypeMirror> types) {
+        if (types.isEmpty()) {
+            return Collections.emptyList();
+        } else if (types.size() <= 1) {
+            if (types instanceof List) {
+                return (List<TypeMirror>) types;
+            } else {
+                return new ArrayList<>(types);
+            }
+        }
+        Map<String, TypeMirror> sourceTypes = new HashMap<>();
+        for (TypeMirror type : types) {
+            sourceTypes.put(ElementUtils.getTypeId(type), type);
+        }
+        return sortTypes(new ArrayList<>(sourceTypes.values()));
+    }
+
+    public static int compareMethod(ExecutableElement method1, ExecutableElement method2) {
+        List<? extends VariableElement> parameters1 = method1.getParameters();
+        List<? extends VariableElement> parameters2 = method2.getParameters();
+        if (parameters1.size() != parameters2.size()) {
+            return Integer.compare(parameters1.size(), parameters2.size());
+        }
+
+        int result = 0;
+        for (int i = 0; i < parameters1.size(); i++) {
+            VariableElement var1 = parameters1.get(i);
+            VariableElement var2 = parameters2.get(i);
+            result = compareType(var1.asType(), var2.asType());
+            if (result != 0) {
+                return result;
+            }
+        }
+
+        result = method1.getSimpleName().toString().compareTo(method2.getSimpleName().toString());
+        if (result == 0) {
+            // if still no difference sort by enclosing type name
+            TypeElement enclosingType1 = ElementUtils.findNearestEnclosingType(method1);
+            TypeElement enclosingType2 = ElementUtils.findNearestEnclosingType(method2);
+            result = enclosingType1.getQualifiedName().toString().compareTo(enclosingType2.getQualifiedName().toString());
+        }
+        return result;
+    }
+
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeExecutableElement.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeExecutableElement.java	Tue Apr 14 15:12:48 2015 +0200
@@ -58,6 +58,14 @@
         }
     }
 
+    public void setVisibility(Modifier visibility) {
+        ElementUtils.setVisibility(getModifiers(), visibility);
+    }
+
+    public Modifier getVisibility() {
+        return ElementUtils.getVisibility(getModifiers());
+    }
+
     /* Support JDK8 langtools. */
     public boolean isDefault() {
         return false;
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java	Tue Apr 14 15:12:48 2015 +0200
@@ -22,67 +22,111 @@
  */
 package com.oracle.truffle.dsl.processor.model;
 
+import java.util.*;
+
 import javax.lang.model.element.*;
+import javax.lang.model.type.*;
 
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.java.*;
 
-public class ExecutableTypeData extends TemplateMethod {
+public class ExecutableTypeData extends MessageContainer implements Comparable<ExecutableTypeData> {
 
-    private final TypeSystemData typeSystem;
-    private final TypeData type;
+    private final ExecutableElement method;
+    private final TypeMirror frameParameter;
+    private final List<TypeMirror> evaluatedParameters;
+
+    public ExecutableTypeData(ExecutableElement method, int signatureSize, List<TypeMirror> frameTypes) {
+        this.method = method;
+        TypeMirror foundFrameParameter = null;
+        List<? extends VariableElement> parameters = method.getParameters();
 
-    public ExecutableTypeData(TemplateMethod method, ExecutableElement executable, TypeSystemData typeSystem, TypeData type) {
-        super(method, executable);
-        this.typeSystem = typeSystem;
-        this.type = type;
-        if (executable.getParameters().size() < method.getMethod().getParameters().size()) {
-            throw new IllegalArgumentException(String.format("Method parameter count mismatch %s != %s.", executable.getParameters(), method.getMethod().getParameters()));
+        int parameterIndex = 0;
+        evaluatedParameters = new ArrayList<>();
+        if (!parameters.isEmpty()) {
+            TypeMirror firstParameter = parameters.get(0).asType();
+            for (TypeMirror frameType : frameTypes) {
+                if (ElementUtils.typeEquals(firstParameter, frameType)) {
+                    foundFrameParameter = firstParameter;
+                    parameterIndex++;
+                    break;
+                }
+            }
         }
+
+        int numberParameters = Math.max(parameters.size() - parameterIndex, signatureSize);
+        for (int i = 0; i < numberParameters; i++) {
+            TypeMirror parameter;
+            if (method.isVarArgs() && parameterIndex >= parameters.size() - 1) {
+                ArrayType varArgsArray = (ArrayType) parameters.get(parameters.size() - 1).asType();
+                parameter = varArgsArray.getComponentType();
+            } else if (parameterIndex < parameters.size()) {
+                parameter = parameters.get(parameterIndex).asType();
+            } else {
+                break;
+            }
+            parameterIndex++;
+            evaluatedParameters.add(parameter);
+        }
+        this.frameParameter = foundFrameParameter;
     }
 
-    public TypeData getType() {
-        return type;
+    public ExecutableElement getMethod() {
+        return method;
+    }
+
+    public String getName() {
+        return method.getSimpleName().toString();
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return method;
+    }
+
+    public List<TypeMirror> getEvaluatedParameters() {
+        return evaluatedParameters;
     }
 
-    public TypeSystemData getTypeSystem() {
-        return typeSystem;
+    public int getVarArgsIndex(int parameterIndex) {
+        if (method.isVarArgs()) {
+            int index = parameterIndex - (method.getParameters().size() - 1);
+            return index;
+        }
+        return -1;
+    }
+
+    public int getParameterIndex(int signatureIndex) {
+        return frameParameter != null ? signatureIndex + 1 : signatureIndex;
+    }
+
+    public TypeMirror getFrameParameter() {
+        return frameParameter;
+    }
+
+    public TypeMirror getReturnType() {
+        return method.getReturnType();
     }
 
     public boolean hasUnexpectedValue(ProcessorContext context) {
-        return ElementUtils.canThrowType(getMethod().getThrownTypes(), context.getType(UnexpectedResultException.class));
+        return ElementUtils.canThrowType(method.getThrownTypes(), context.getType(UnexpectedResultException.class));
     }
 
     public boolean isFinal() {
-        return getMethod().getModifiers().contains(Modifier.FINAL);
+        return method.getModifiers().contains(Modifier.FINAL);
     }
 
     public boolean isAbstract() {
-        return getMethod().getModifiers().contains(Modifier.ABSTRACT);
+        return method.getModifiers().contains(Modifier.ABSTRACT);
     }
 
     public int getEvaluatedCount() {
-        int count = 0;
-        for (Parameter parameter : getParameters()) {
-            if (parameter.getSpecification().isSignature()) {
-                count++;
-            }
-        }
-        return count;
+        return evaluatedParameters.size();
     }
 
-    @Override
-    public int hashCode() {
-        return type.hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof ExecutableTypeData) {
-            return type.equals(((ExecutableTypeData) obj).type);
-        }
-        return super.equals(obj);
+    public int compareTo(ExecutableTypeData o) {
+        return ElementUtils.compareMethod(method, o.getMethod());
     }
 
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ImplicitCastData.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ImplicitCastData.java	Tue Apr 14 15:12:48 2015 +0200
@@ -22,35 +22,29 @@
  */
 package com.oracle.truffle.dsl.processor.model;
 
+import javax.lang.model.type.*;
+
 public class ImplicitCastData extends TemplateMethod {
 
-    private final TypeData sourceType;
-    private final TypeData targetType;
+    private final TypeMirror sourceType;
+    private final TypeMirror targetType;
 
-    public ImplicitCastData(TemplateMethod method, TypeData sourceType, TypeData targetType) {
+    public ImplicitCastData(TemplateMethod method, TypeMirror sourceType, TypeMirror targetType) {
         super(method);
         this.sourceType = sourceType;
         this.targetType = targetType;
     }
 
-    public TypeData getSourceType() {
+    public TypeMirror getSourceType() {
         return sourceType;
     }
 
-    public TypeData getTargetType() {
+    public TypeMirror getTargetType() {
         return targetType;
     }
 
     @Override
     public int compareTo(TemplateMethod o) {
-        if (o instanceof ImplicitCastData && sourceType != null) {
-            // implicit casts are ordered by source type since
-            // its also the order in which they are checked.
-            TypeData otherSourceType = ((ImplicitCastData) o).getSourceType();
-            if (otherSourceType != null) {
-                return this.sourceType.compareTo(otherSourceType);
-            }
-        }
         return super.compareTo(o);
     }
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java	Tue Apr 14 15:12:48 2015 +0200
@@ -103,8 +103,8 @@
 
         int defIndex = 0;
         for (ParameterSpec spec : getAll()) {
-            List<TypeMirror> allowedTypes = spec.getAllowedTypes();
-            List<TypeMirror> types = spec.getAllowedTypes();
+            Collection<TypeMirror> allowedTypes = spec.getAllowedTypes();
+            Collection<TypeMirror> types = spec.getAllowedTypes();
             if (types != null && allowedTypes.size() > 1) {
                 TypeDef foundDef = null;
                 for (TypeDef def : typeDefs) {
@@ -189,7 +189,7 @@
         if (foundTypeDef != null) {
             builder.append("<" + foundTypeDef.getName() + ">");
         } else if (spec.getAllowedTypes().size() >= 1) {
-            builder.append(ElementUtils.getSimpleName(spec.getAllowedTypes().get(0)));
+            builder.append(ElementUtils.getSimpleName(spec.getAllowedTypes().iterator().next()));
         } else {
             builder.append("void");
         }
@@ -207,15 +207,15 @@
 
     static final class TypeDef {
 
-        private final List<TypeMirror> types;
+        private final Collection<TypeMirror> types;
         private final String name;
 
-        private TypeDef(List<TypeMirror> types, String name) {
+        private TypeDef(Collection<TypeMirror> types, String name) {
             this.types = types;
             this.name = name;
         }
 
-        public List<TypeMirror> getTypes() {
+        public Collection<TypeMirror> getTypes() {
             return types;
         }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java	Tue Apr 14 15:12:48 2015 +0200
@@ -74,7 +74,7 @@
         this.executeWith = executeWith;
     }
 
-    public ExecutableTypeData findExecutableType(TypeData targetType) {
+    public ExecutableTypeData findExecutableType(TypeMirror targetType) {
         return childNode.findExecutableType(targetType, getExecuteWith().size());
     }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java	Tue Apr 14 15:12:48 2015 +0200
@@ -63,7 +63,7 @@
         this.fields = new ArrayList<>();
         this.children = new ArrayList<>();
         this.childExecutions = new ArrayList<>();
-        this.thisExecution = new NodeExecutionData(new NodeChildData(null, null, "this", getNodeType(), getNodeType(), null, Cardinality.ONE), -1, false);
+        this.thisExecution = new NodeExecutionData(new NodeChildData(null, null, "this", getNodeType(), getNodeType(), null, Cardinality.ONE), -1, -1, false);
         this.thisExecution.getChild().setNode(this);
         this.generateFactory = generateFactory;
     }
@@ -105,15 +105,15 @@
         return childExecutions;
     }
 
-    public Set<TypeData> findSpecializedTypes(NodeExecutionData execution) {
-        Set<TypeData> types = new HashSet<>();
+    public Set<TypeMirror> findSpecializedTypes(NodeExecutionData execution) {
+        Set<TypeMirror> types = new HashSet<>();
         for (SpecializationData specialization : getSpecializations()) {
             if (!specialization.isSpecialized()) {
                 continue;
             }
             List<Parameter> parameters = specialization.findByExecutionData(execution);
             for (Parameter parameter : parameters) {
-                TypeData type = parameter.getTypeSystemType();
+                TypeMirror type = parameter.getType();
                 if (type == null) {
                     throw new AssertionError();
                 }
@@ -123,13 +123,13 @@
         return types;
     }
 
-    public Collection<TypeData> findSpecializedReturnTypes() {
-        Set<TypeData> types = new HashSet<>();
+    public Collection<TypeMirror> findSpecializedReturnTypes() {
+        Set<TypeMirror> types = new HashSet<>();
         for (SpecializationData specialization : getSpecializations()) {
             if (!specialization.isSpecialized()) {
                 continue;
             }
-            types.add(specialization.getReturnType().getTypeSystemType());
+            types.add(specialization.getReturnType().getType());
         }
         return types;
     }
@@ -233,7 +233,7 @@
     public boolean supportsFrame() {
         if (executableTypes != null) {
             for (ExecutableTypeData execType : getExecutableTypes(-1)) {
-                if (execType.findParameter(TemplateMethod.FRAME_NAME) == null) {
+                if (execType.getFrameParameter() == null) {
                     return false;
                 }
             }
@@ -258,7 +258,7 @@
         }
 
         for (NodeExecutionData execution : childExecutions) {
-            if (execution.getName().equals(childName) && (execution.getIndex() == -1 || execution.getIndex() == index)) {
+            if (execution.getName().equals(childName) && (execution.getChildIndex() == -1 || execution.getChildIndex() == index)) {
                 return execution;
             }
         }
@@ -284,17 +284,25 @@
         return enclosingNodes;
     }
 
-    public List<TemplateMethod> getAllTemplateMethods() {
-        List<TemplateMethod> methods = new ArrayList<>();
+    public List<ExecutableElement> getAllTemplateMethods() {
+        List<ExecutableElement> methods = new ArrayList<>();
 
         for (SpecializationData specialization : getSpecializations()) {
-            methods.add(specialization);
+            methods.add(specialization.getMethod());
+        }
+
+        for (ExecutableTypeData execType : getExecutableTypes()) {
+            methods.add(execType.getMethod());
         }
 
-        methods.addAll(getExecutableTypes());
-        methods.addAll(getShortCircuits());
+        for (ShortCircuitData shortcircuit : getShortCircuits()) {
+            methods.add(shortcircuit.getMethod());
+        }
+
         if (getCasts() != null) {
-            methods.addAll(getCasts());
+            for (CreateCastData castData : getCasts()) {
+                methods.add(castData.getMethod());
+            }
         }
 
         return methods;
@@ -303,13 +311,13 @@
     public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context, int evaluatedCount) {
         List<ExecutableTypeData> types = findGenericExecutableTypes(context, evaluatedCount);
         for (ExecutableTypeData type : types) {
-            if (type.getType().isGeneric()) {
+            if (context.isType(type.getReturnType(), Object.class)) {
                 return type;
             }
         }
 
         for (ExecutableTypeData type : types) {
-            if (!type.getType().isVoid()) {
+            if (!context.isType(type.getReturnType(), void.class)) {
                 return type;
             }
         }
@@ -349,9 +357,9 @@
         return types;
     }
 
-    public ExecutableTypeData findExecutableType(TypeData prmitiveType, int evaluatedCount) {
+    public ExecutableTypeData findExecutableType(TypeMirror primitiveType, int evaluatedCount) {
         for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) {
-            if (ElementUtils.typeEquals(type.getType().getPrimitiveType(), prmitiveType.getPrimitiveType())) {
+            if (ElementUtils.typeEquals(type.getReturnType(), primitiveType)) {
                 return type;
             }
         }
@@ -496,6 +504,14 @@
         return shortCircuits;
     }
 
+    public int getMinimalEvaluatedParameters() {
+        int minimalEvaluatedParameters = Integer.MAX_VALUE;
+        for (ExecutableTypeData type : getExecutableTypes()) {
+            minimalEvaluatedParameters = Math.min(minimalEvaluatedParameters, type.getEvaluatedCount());
+        }
+        return minimalEvaluatedParameters;
+    }
+
     public void setExecutableTypes(Map<Integer, List<ExecutableTypeData>> executableTypes) {
         this.executableTypes = executableTypes;
     }
@@ -520,4 +536,29 @@
         return getNodeId().compareTo(o.getNodeId());
     }
 
+    public List<TypeMirror> getPossibleTypes(NodeExecutionData execution) {
+        List<TypeMirror> types = new ArrayList<>();
+
+        // add types possible through return types and evaluated parameters in execute methods
+        if (execution.getChild() != null) {
+            for (ExecutableTypeData executable : execution.getChild().getNodeData().getExecutableTypes()) {
+                if (executable.hasUnexpectedValue(getContext())) {
+                    continue;
+                }
+                types.add(executable.getReturnType());
+            }
+        }
+
+        int executionIndex = execution.getIndex();
+        if (executionIndex >= 0) {
+            for (ExecutableTypeData typeData : getExecutableTypes()) {
+                if (executionIndex < typeData.getEvaluatedCount()) {
+                    types.add(typeData.getEvaluatedParameters().get(executionIndex));
+                }
+            }
+        }
+
+        return ElementUtils.uniqueSortedTypes(types);
+    }
+
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java	Tue Apr 14 15:12:48 2015 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.truffle.dsl.processor.model;
 
+import java.util.*;
+
 import javax.lang.model.type.*;
 
 import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality;
@@ -31,17 +33,28 @@
     private final NodeChildData child;
     private final String name;
     private final int index;
+    private final int childIndex;
     private final boolean shortCircuit;
+    private final List<TypeMirror> typeRestrictions = new ArrayList<>();
 
-    public NodeExecutionData(NodeChildData child, int index, boolean shortCircuit) {
+    public NodeExecutionData(NodeChildData child, int index, int childIndex, boolean shortCircuit) {
         this.child = child;
         this.index = index;
+        this.childIndex = childIndex;
         this.shortCircuit = shortCircuit;
         this.name = createName();
     }
 
     private String createName() {
-        return createName(child.getName(), index);
+        return child != null ? createName(child.getName(), childIndex) : ("arg" + index);
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public List<TypeMirror> getTypeRestrictions() {
+        return typeRestrictions;
     }
 
     public TypeMirror getNodeType() {
@@ -62,12 +75,12 @@
         return child;
     }
 
-    public int getIndex() {
-        return index;
+    public int getChildIndex() {
+        return childIndex;
     }
 
     public boolean isIndexed() {
-        return index > -1;
+        return childIndex > -1;
     }
 
     public boolean isShortCircuit() {
@@ -75,7 +88,7 @@
     }
 
     public String getIndexedName() {
-        return createIndexedName(child, index);
+        return createIndexedName(child, childIndex);
     }
 
     public static String createIndexedName(NodeChildData child, int varArgsIndex) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java	Tue Apr 14 15:12:48 2015 +0200
@@ -28,19 +28,17 @@
 public final class Parameter {
 
     private final ParameterSpec specification;
-    private TypeData typeSystemType;
     private TemplateMethod method;
     private String localName;
     private final int specificationVarArgsIndex;
     private final int typeVarArgsIndex;
-
     private final VariableElement variableElement;
+    private final TypeMirror type;
 
     public Parameter(ParameterSpec specification, VariableElement variableElement, int specificationVarArgsIndex, int typeVarArgsIndex) {
         this.specification = specification;
         this.variableElement = variableElement;
-        this.typeSystemType = null;
-
+        this.type = variableElement.asType();
         this.specificationVarArgsIndex = specificationVarArgsIndex;
 
         String valueName = specification.getName() + "Value";
@@ -51,22 +49,22 @@
         this.localName = valueName;
     }
 
-    public Parameter(ParameterSpec specification, TypeData actualType, VariableElement variableElement, int specificationIndex, int varArgsIndex) {
-        this(specification, variableElement, specificationIndex, varArgsIndex);
-        this.typeSystemType = actualType;
-    }
-
-    public Parameter(Parameter parameter, TypeData otherType) {
-        this(parameter.specification, otherType, parameter.variableElement, parameter.specificationVarArgsIndex, parameter.typeVarArgsIndex);
-    }
-
     public Parameter(Parameter parameter) {
         this.specification = parameter.specification;
-        this.typeSystemType = parameter.typeSystemType;
         this.specificationVarArgsIndex = parameter.specificationVarArgsIndex;
         this.localName = parameter.localName;
         this.typeVarArgsIndex = parameter.typeVarArgsIndex;
         this.variableElement = parameter.variableElement;
+        this.type = parameter.type;
+    }
+
+    public Parameter(Parameter parameter, TypeMirror newType) {
+        this.specification = parameter.specification;
+        this.specificationVarArgsIndex = parameter.specificationVarArgsIndex;
+        this.localName = parameter.localName;
+        this.typeVarArgsIndex = parameter.typeVarArgsIndex;
+        this.variableElement = parameter.variableElement;
+        this.type = newType;
     }
 
     public void setLocalName(String localName) {
@@ -102,11 +100,7 @@
     }
 
     public TypeMirror getType() {
-        return variableElement.asType();
-    }
-
-    public TypeData getTypeSystemType() {
-        return typeSystemType;
+        return type;
     }
 
     public boolean isTypeVarArgs() {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java	Tue Apr 14 15:12:48 2015 +0200
@@ -33,45 +33,46 @@
 public class ParameterSpec {
 
     private final String name;
-    private final List<TypeMirror> allowedTypes;
-    private final Set<String> allowedTypesIdentifier;
+    private final Collection<TypeMirror> allowedTypes;
+    private final boolean anyType;
 
     /** Type is bound to local final variable. */
     private boolean local;
     private boolean signature;
+    private boolean allowSubclasses = true;
 
     /** Optional bound execution of node. */
     private NodeExecutionData execution;
     private TypeDef typeDefinition;
 
-    public ParameterSpec(String name, List<TypeMirror> allowedTypes, Set<String> typeIdentifiers) {
+    public ParameterSpec(String name, Collection<TypeMirror> allowedTypes) {
         this.name = name;
         this.allowedTypes = allowedTypes;
-        this.allowedTypesIdentifier = typeIdentifiers;
+        boolean anyTypeTemp = false;
+        for (TypeMirror type : allowedTypes) {
+            if (ElementUtils.isObject(type)) {
+                anyTypeTemp = true;
+                break;
+            }
+        }
+        this.anyType = anyTypeTemp;
     }
 
-    public ParameterSpec(String name, List<TypeMirror> allowedTypes) {
-        this.name = name;
-        this.allowedTypes = allowedTypes;
-        Set<String> typeIdentifiers = new HashSet<>();
-        for (TypeMirror type : allowedTypes) {
-            typeIdentifiers.add(ElementUtils.getUniqueIdentifier(type));
-        }
-        this.allowedTypesIdentifier = typeIdentifiers;
+    public ParameterSpec(ParameterSpec original, TypeMirror newType) {
+        this(original.name, newType);
+        this.local = original.local;
+        this.signature = original.signature;
+        this.execution = original.execution;
+        this.typeDefinition = original.typeDefinition;
+        this.allowSubclasses = original.allowSubclasses;
     }
 
     public ParameterSpec(String name, TypeMirror type) {
-        this(name, Arrays.asList(type), new HashSet<>(Arrays.asList(ElementUtils.getUniqueIdentifier(type))));
+        this(name, Arrays.asList(type));
     }
 
-    public ParameterSpec(ParameterSpec o, List<TypeMirror> allowedTypes, Set<String> typeIdentifiers) {
-        this.name = o.name;
-        this.local = o.local;
-        this.typeDefinition = o.typeDefinition;
-        this.execution = o.execution;
-        this.signature = o.signature;
-        this.allowedTypes = allowedTypes;
-        this.allowedTypesIdentifier = typeIdentifiers;
+    public void setAllowSubclasses(boolean allowSubclasses) {
+        this.allowSubclasses = allowSubclasses;
     }
 
     public NodeExecutionData getExecution() {
@@ -111,15 +112,28 @@
         return name;
     }
 
-    public List<TypeMirror> getAllowedTypes() {
+    public Collection<TypeMirror> getAllowedTypes() {
         return allowedTypes;
     }
 
     public boolean matches(VariableElement variable) {
-        if (allowedTypesIdentifier != null) {
-            return allowedTypesIdentifier.contains(ElementUtils.getUniqueIdentifier(variable.asType()));
+        if (anyType) {
+            return true;
+        } else {
+            for (TypeMirror type : allowedTypes) {
+                if (ElementUtils.typeEquals(variable.asType(), type)) {
+                    return true;
+                }
+            }
+            if (allowSubclasses) {
+                for (TypeMirror type : allowedTypes) {
+                    if (ElementUtils.isAssignable(variable.asType(), type)) {
+                        return true;
+                    }
+                }
+            }
         }
-        return true;
+        return false;
     }
 
     @Override
@@ -132,7 +146,7 @@
         if (typeDefinition != null) {
             builder.append("<" + typeDefinition.getName() + ">");
         } else if (getAllowedTypes().size() >= 1) {
-            builder.append(ElementUtils.getSimpleName(getAllowedTypes().get(0)));
+            builder.append(ElementUtils.getSimpleName(getAllowedTypes().iterator().next()));
         } else {
             builder.append("void");
         }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java	Tue Apr 14 15:12:48 2015 +0200
@@ -25,6 +25,7 @@
 import java.util.*;
 
 import javax.lang.model.element.*;
+import javax.lang.model.type.*;
 
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.expression.*;
@@ -201,17 +202,18 @@
 
         for (Parameter parameter : getSignatureParameters()) {
             NodeChildData child = parameter.getSpecification().getExecution().getChild();
-            ExecutableTypeData type = child.findExecutableType(parameter.getTypeSystemType());
-            if (type == null) {
-                type = child.findAnyGenericExecutableType(context);
+            if (child != null) {
+                ExecutableTypeData type = child.findExecutableType(parameter.getType());
+                if (type == null) {
+                    type = child.findAnyGenericExecutableType(context);
+                }
+                if (type.hasUnexpectedValue(context)) {
+                    return true;
+                }
+                if (ElementUtils.needsCastTo(type.getReturnType(), parameter.getType())) {
+                    return true;
+                }
             }
-            if (type.hasUnexpectedValue(context)) {
-                return true;
-            }
-            if (type.getReturnType().getTypeSystemType().needsCastTo(parameter.getTypeSystemType())) {
-                return true;
-            }
-
         }
         return false;
     }
@@ -356,11 +358,12 @@
         Iterator<Parameter> currentSignature = getSignatureParameters().iterator();
         Iterator<Parameter> prevSignature = prev.getSignatureParameters().iterator();
 
+        TypeSystemData typeSystem = prev.getNode().getTypeSystem();
         while (currentSignature.hasNext() && prevSignature.hasNext()) {
-            TypeData currentType = currentSignature.next().getTypeSystemType();
-            TypeData prevType = prevSignature.next().getTypeSystemType();
+            TypeMirror currentType = currentSignature.next().getType();
+            TypeMirror prevType = prevSignature.next().getType();
 
-            if (!currentType.isImplicitSubtypeOf(prevType)) {
+            if (!typeSystem.isImplicitSubtypeOf(currentType, prevType)) {
                 return true;
             }
         }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java	Tue Apr 14 15:12:48 2015 +0200
@@ -228,9 +228,9 @@
 
     public TypeSignature getTypeSignature() {
         TypeSignature signature = new TypeSignature();
-        signature.types.add(getReturnType().getTypeSystemType());
+        signature.types.add(getReturnType().getType());
         for (Parameter parameter : getSignatureParameters()) {
-            TypeData typeData = parameter.getTypeSystemType();
+            TypeMirror typeData = parameter.getType();
             if (typeData != null) {
                 signature.types.add(typeData);
             }
@@ -250,8 +250,8 @@
             if (signatureIndex >= signature.size()) {
                 break;
             }
-            TypeData newType = signature.get(signatureIndex++);
-            if (!parameter.getTypeSystemType().equals(newType)) {
+            TypeMirror newType = signature.get(signatureIndex++);
+            if (!ElementUtils.typeEquals(newType, parameter.getType())) {
                 replaceParameter(parameter.getLocalName(), new Parameter(parameter, newType));
             }
         }
@@ -278,11 +278,6 @@
     }
 
     public int compareBySignature(TemplateMethod compareMethod) {
-        final TypeSystemData typeSystem = getTemplate().getTypeSystem();
-        if (typeSystem != compareMethod.getTemplate().getTypeSystem()) {
-            throw new IllegalStateException("Cannot compare two methods with different type systems.");
-        }
-
         List<TypeMirror> signature1 = getSignatureTypes(this);
         List<TypeMirror> signature2 = getSignatureTypes(compareMethod);
 
@@ -290,7 +285,7 @@
         for (int i = 0; i < Math.max(signature1.size(), signature2.size()); i++) {
             TypeMirror t1 = i < signature1.size() ? signature1.get(i) : null;
             TypeMirror t2 = i < signature2.size() ? signature2.get(i) : null;
-            result = compareParameter(typeSystem, t1, t2);
+            result = ElementUtils.compareType(t1, t2);
             if (result != 0) {
                 break;
             }
@@ -299,37 +294,6 @@
         return result;
     }
 
-    protected static int compareParameter(TypeSystemData data, TypeMirror signature1, TypeMirror signature2) {
-        if (signature1 == null) {
-            return 1;
-        } else if (signature2 == null) {
-            return -1;
-        }
-
-        if (ElementUtils.typeEquals(signature1, signature2)) {
-            return 0;
-        }
-
-        int index1 = data.findType(signature1);
-        int index2 = data.findType(signature2);
-        if (index1 != -1 && index2 != -1) {
-            return index1 - index2;
-        }
-
-        // TODO this version if subclass of should be improved.
-        if (signature1.getKind() == TypeKind.DECLARED && signature2.getKind() == TypeKind.DECLARED) {
-            TypeElement element1 = ElementUtils.fromTypeMirror(signature1);
-            TypeElement element2 = ElementUtils.fromTypeMirror(signature2);
-
-            if (ElementUtils.getDirectSuperTypes(element1).contains(element2)) {
-                return -1;
-            } else if (ElementUtils.getDirectSuperTypes(element2).contains(element1)) {
-                return 1;
-            }
-        }
-        return ElementUtils.getSimpleName(signature1).compareTo(ElementUtils.getSimpleName(signature2));
-    }
-
     public static List<TypeMirror> getSignatureTypes(TemplateMethod method) {
         List<TypeMirror> types = new ArrayList<>();
         for (Parameter param : method.getSignatureParameters()) {
@@ -338,15 +302,15 @@
         return types;
     }
 
-    public static class TypeSignature implements Iterable<TypeData>, Comparable<TypeSignature> {
+    public static class TypeSignature implements Iterable<TypeMirror> {
 
-        private final List<TypeData> types;
+        private final List<TypeMirror> types;
 
         public TypeSignature() {
             this.types = new ArrayList<>();
         }
 
-        public TypeSignature(List<TypeData> signature) {
+        public TypeSignature(List<TypeMirror> signature) {
             this.types = signature;
         }
 
@@ -359,32 +323,10 @@
             return types.size();
         }
 
-        public TypeData get(int index) {
+        public TypeMirror get(int index) {
             return types.get(index);
         }
 
-        public int compareTo(TypeSignature other) {
-            if (this == other) {
-                return 0;
-            } else if (types.size() != other.types.size()) {
-                return types.size() - other.types.size();
-            } else if (types.isEmpty()) {
-                return 0;
-            }
-
-            for (int i = 0; i < types.size(); i++) {
-                TypeData type1 = types.get(i);
-                TypeData type2 = other.types.get(i);
-
-                int comparison = type1.compareTo(type2);
-                if (comparison != 0) {
-                    return comparison;
-                }
-            }
-
-            return 0;
-        }
-
         @Override
         public boolean equals(Object obj) {
             if (obj instanceof TypeSignature) {
@@ -393,7 +335,7 @@
             return super.equals(obj);
         }
 
-        public Iterator<TypeData> iterator() {
+        public Iterator<TypeMirror> iterator() {
             return types.iterator();
         }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCastData.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCastData.java	Tue Apr 14 15:12:48 2015 +0200
@@ -22,26 +22,24 @@
  */
 package com.oracle.truffle.dsl.processor.model;
 
+import javax.lang.model.type.*;
+
 public class TypeCastData extends TemplateMethod {
 
-    private final TypeData targetType;
-    private final TypeData sourceType;
+    private final TypeMirror targetType;
+    private final TypeMirror sourceType;
 
-    public TypeCastData(TemplateMethod method, TypeData sourceType, TypeData targetType) {
+    public TypeCastData(TemplateMethod method, TypeMirror sourceType, TypeMirror targetType) {
         super(method);
         this.sourceType = sourceType;
         this.targetType = targetType;
     }
 
-    public boolean isGeneric() {
-        return sourceType.isGeneric();
-    }
-
-    public TypeData getSourceType() {
+    public TypeMirror getSourceType() {
         return sourceType;
     }
 
-    public TypeData getTargetType() {
+    public TypeMirror getTargetType() {
         return targetType;
     }
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCheckData.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCheckData.java	Tue Apr 14 15:12:48 2015 +0200
@@ -22,26 +22,24 @@
  */
 package com.oracle.truffle.dsl.processor.model;
 
+import javax.lang.model.type.*;
+
 public class TypeCheckData extends TemplateMethod {
 
-    private final TypeData checkedType;
-    private final TypeData valueType;
+    private final TypeMirror checkedType;
+    private final TypeMirror valueType;
 
-    public TypeCheckData(TemplateMethod method, TypeData checkedType, TypeData valueType) {
+    public TypeCheckData(TemplateMethod method, TypeMirror checkedType, TypeMirror valueType) {
         super(method);
         this.checkedType = checkedType;
         this.valueType = valueType;
     }
 
-    public boolean isGeneric() {
-        return valueType.isGeneric();
-    }
-
-    public TypeData getCheckedType() {
+    public TypeMirror getCheckedType() {
         return checkedType;
     }
 
-    public TypeData getValueType() {
+    public TypeMirror getValueType() {
         return valueType;
     }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeData.java	Tue Apr 14 22:12:03 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,181 +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.dsl.processor.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.java.*;
-
-public class TypeData extends MessageContainer implements Comparable<TypeData> {
-
-    private final TypeSystemData typeSystem;
-    private final AnnotationValue annotationValue;
-    private final TypeMirror primitiveType;
-    private final TypeMirror boxedType;
-
-    private final int index;
-    private final List<TypeCastData> typeCasts = new ArrayList<>();
-    private final List<TypeCheckData> typeChecks = new ArrayList<>();
-
-    public TypeData(TypeSystemData typeSystem, int index, AnnotationValue value, TypeMirror primitiveType, TypeMirror boxedType) {
-        this.index = index;
-        this.typeSystem = typeSystem;
-        this.annotationValue = value;
-        this.primitiveType = primitiveType;
-        this.boxedType = boxedType;
-    }
-
-    public int getIndex() {
-        return index;
-    }
-
-    public boolean isDefaultCast() {
-        return getTypeCasts().isEmpty();
-    }
-
-    public boolean isDefaultCheck() {
-        return getTypeChecks().isEmpty();
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return typeSystem.getMessageElement();
-    }
-
-    @Override
-    public AnnotationMirror getMessageAnnotation() {
-        return typeSystem.getMessageAnnotation();
-    }
-
-    @Override
-    public AnnotationValue getMessageAnnotationValue() {
-        return annotationValue;
-    }
-
-    public void addTypeCast(TypeCastData typeCast) {
-        this.typeCasts.add(typeCast);
-    }
-
-    public void addTypeCheck(TypeCheckData typeCheck) {
-        this.typeChecks.add(typeCheck);
-    }
-
-    public List<TypeCastData> getTypeCasts() {
-        return typeCasts;
-    }
-
-    public List<TypeCheckData> getTypeChecks() {
-        return typeChecks;
-    }
-
-    public TypeSystemData getTypeSystem() {
-        return typeSystem;
-    }
-
-    public TypeMirror getPrimitiveType() {
-        return primitiveType;
-    }
-
-    public TypeMirror getBoxedType() {
-        return boxedType;
-    }
-
-    public boolean isGeneric() {
-        return ElementUtils.typeEquals(boxedType, getTypeSystem().getGenericType());
-    }
-
-    public boolean isVoid() {
-        if (getTypeSystem().getVoidType() == null) {
-            return false;
-        }
-        return ElementUtils.typeEquals(boxedType, getTypeSystem().getVoidType().getBoxedType());
-    }
-
-    public int compareTo(TypeData o) {
-        if (this.equals(o)) {
-            return 0;
-        }
-        return index - o.index;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(index, primitiveType);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (!(obj instanceof TypeData)) {
-            return false;
-        }
-        TypeData otherType = (TypeData) obj;
-        return index == otherType.index && ElementUtils.typeEquals(primitiveType, otherType.primitiveType);
-    }
-
-    @Override
-    public String toString() {
-        return getClass().getSimpleName() + "[" + ElementUtils.getSimpleName(primitiveType) + "]";
-    }
-
-    public boolean equalsType(TypeData actualTypeData) {
-        return ElementUtils.typeEquals(boxedType, actualTypeData.boxedType);
-    }
-
-    public boolean needsCastTo(TypeData targetType) {
-        return ElementUtils.needsCastTo(getPrimitiveType(), targetType.getPrimitiveType());
-    }
-
-    public boolean needsCastTo(TypeMirror targetType) {
-        return ElementUtils.needsCastTo(getPrimitiveType(), targetType);
-    }
-
-    public boolean isPrimitive() {
-        return ElementUtils.isPrimitive(getPrimitiveType());
-    }
-
-    public List<TypeData> getImplicitSourceTypes() {
-        return getTypeSystem().lookupSourceTypes(this);
-    }
-
-    public boolean hasImplicitSourceTypes() {
-        return getTypeSystem().hasImplicitSourceTypes(this);
-    }
-
-    public boolean isImplicitSubtypeOf(TypeData other) {
-        List<ImplicitCastData> casts = other.getTypeSystem().lookupByTargetType(other);
-        for (ImplicitCastData cast : casts) {
-            if (isSubtypeOf(cast.getSourceType())) {
-                return true;
-            }
-        }
-        return isSubtypeOf(other);
-    }
-
-    public boolean isSubtypeOf(TypeData other) {
-        return ElementUtils.isSubtype(boxedType, other.boxedType);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java	Tue Apr 14 15:12:48 2015 +0200
@@ -33,24 +33,24 @@
 
 public class TypeSystemData extends Template {
 
-    private List<TypeData> types;
-    private List<TypeMirror> primitiveTypeMirrors = new ArrayList<>();
-    private List<TypeMirror> boxedTypeMirrors = new ArrayList<>();
-    private Map<String, TypeData> cachedTypes = new HashMap<>();
+    private final List<ImplicitCastData> implicitCasts = new ArrayList<>();
+    private final List<TypeCastData> casts = new ArrayList<>();
+    private final List<TypeCheckData> checks = new ArrayList<>();
+    private final List<TypeMirror> legacyTypes = new ArrayList<>();
 
-    private List<ImplicitCastData> implicitCasts;
-    private List<TypeCastData> casts;
-    private List<TypeCheckData> checks;
+    private Set<String> legacyTypeIds;
 
-    private TypeMirror genericType;
-    private TypeData booleanType;
-    private TypeData voidType;
+    private final boolean isDefault;
+    private final DSLOptions options;
 
-    private DSLOptions options;
-
-    public TypeSystemData(ProcessorContext context, TypeElement templateType, AnnotationMirror annotation, DSLOptions options) {
+    public TypeSystemData(ProcessorContext context, TypeElement templateType, AnnotationMirror annotation, DSLOptions options, boolean isDefault) {
         super(context, templateType, annotation);
         this.options = options;
+        this.isDefault = isDefault;
+    }
+
+    public boolean isDefault() {
+        return isDefault;
     }
 
     public DSLOptions getOptions() {
@@ -62,48 +62,43 @@
         return this;
     }
 
-    public void setTypes(List<TypeData> types) {
-        this.types = types;
-        if (types != null) {
-            for (TypeData typeData : types) {
-                primitiveTypeMirrors.add(typeData.getPrimitiveType());
-                boxedTypeMirrors.add(typeData.getBoxedType());
-                cachedTypes.put(ElementUtils.getUniqueIdentifier(typeData.getPrimitiveType()), typeData);
-                cachedTypes.put(ElementUtils.getUniqueIdentifier(typeData.getBoxedType()), typeData);
+    public List<TypeMirror> getLegacyTypes() {
+        return legacyTypes;
+    }
+
+    public TypeCastData getCast(TypeMirror targetType) {
+        for (TypeCastData cast : casts) {
+            if (ElementUtils.typeEquals(cast.getTargetType(), targetType)) {
+                return cast;
             }
         }
+        return null;
     }
 
-    public void setImplicitCasts(List<ImplicitCastData> implicitCasts) {
-        this.implicitCasts = implicitCasts;
+    public TypeCheckData getCheck(TypeMirror type) {
+        for (TypeCheckData check : checks) {
+            if (ElementUtils.typeEquals(check.getCheckedType(), type)) {
+                return check;
+            }
+        }
+        return null;
     }
 
     public List<ImplicitCastData> getImplicitCasts() {
         return implicitCasts;
     }
 
-    public void setCasts(List<TypeCastData> casts) {
-        this.casts = casts;
+    public List<TypeCastData> getCasts() {
+        return casts;
     }
 
-    public void setChecks(List<TypeCheckData> checks) {
-        this.checks = checks;
-    }
-
-    public void setGenericType(TypeMirror genericType) {
-        this.genericType = genericType;
-    }
-
-    public void setVoidType(TypeData voidType) {
-        this.voidType = voidType;
+    public List<TypeCheckData> getChecks() {
+        return checks;
     }
 
     @Override
     protected List<MessageContainer> findChildContainers() {
         List<MessageContainer> sinks = new ArrayList<>();
-        if (types != null) {
-            sinks.addAll(types);
-        }
         if (checks != null) {
             sinks.addAll(checks);
         }
@@ -116,75 +111,25 @@
         return sinks;
     }
 
-    public TypeData getVoidType() {
-        return voidType;
-    }
-
-    public List<TypeMirror> getBoxedTypeMirrors() {
-        return boxedTypeMirrors;
-    }
-
-    public List<TypeMirror> getPrimitiveTypeMirrors() {
-        return primitiveTypeMirrors;
-    }
-
-    public Set<String> getTypeIdentifiers() {
-        return cachedTypes.keySet();
-    }
-
-    public List<TypeData> getTypes() {
-        return types;
-    }
-
-    public TypeMirror getGenericType() {
-        return genericType;
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[template = " + ElementUtils.getSimpleName(getTemplateType()) + "]";
     }
 
-    public TypeData getGenericTypeData() {
-        TypeData result = types.get(types.size() - 2);
-        assert result.getBoxedType() == genericType;
-        return result;
-    }
-
-    public TypeData findTypeData(TypeMirror type) {
-        if (ElementUtils.typeEquals(voidType.getPrimitiveType(), type)) {
-            return voidType;
-        }
-
-        int index = findType(type);
-        if (index == -1) {
-            return null;
-        }
-        return types.get(index);
-    }
-
-    public int findType(TypeMirror type) {
-        TypeData data = cachedTypes.get(ElementUtils.getUniqueIdentifier(type));
-        if (data != null) {
-            return data.getIndex();
-        }
-        return -1;
-    }
-
-    @Override
-    public String toString() {
-        return getClass().getSimpleName() + "[template = " + ElementUtils.getSimpleName(getTemplateType()) + ", types = " + types + "]";
-    }
-
-    public List<ImplicitCastData> lookupByTargetType(TypeData targetType) {
+    public List<ImplicitCastData> lookupByTargetType(TypeMirror targetType) {
         if (getImplicitCasts() == null) {
             return Collections.emptyList();
         }
         List<ImplicitCastData> foundCasts = new ArrayList<>();
         for (ImplicitCastData cast : getImplicitCasts()) {
-            if (cast.getTargetType().equals(targetType)) {
+            if (ElementUtils.typeEquals(cast.getTargetType(), targetType)) {
                 foundCasts.add(cast);
             }
         }
         return foundCasts;
     }
 
-    public ImplicitCastData lookupCast(TypeData sourceType, TypeData targetType) {
+    public ImplicitCastData lookupCast(TypeMirror sourceType, TypeMirror targetType) {
         if (getImplicitCasts() == null) {
             return null;
         }
@@ -196,38 +141,59 @@
         return null;
     }
 
-    public boolean hasImplicitSourceTypes(TypeData targetType) {
+    public boolean hasImplicitSourceTypes(TypeMirror targetType) {
         if (getImplicitCasts() == null) {
             return false;
         }
         for (ImplicitCastData cast : getImplicitCasts()) {
-            if (cast.getTargetType() == targetType) {
+            if (ElementUtils.typeEquals(cast.getTargetType(), targetType)) {
                 return true;
             }
         }
         return false;
     }
 
-    public List<TypeData> lookupSourceTypes(TypeData type) {
-        List<TypeData> sourceTypes = new ArrayList<>();
-        sourceTypes.add(type);
-        if (getImplicitCasts() != null) {
-            for (ImplicitCastData cast : getImplicitCasts()) {
-                if (cast.getTargetType() == type) {
-                    sourceTypes.add(cast.getSourceType());
-                }
+    public List<TypeMirror> lookupTargetTypes() {
+        List<TypeMirror> sourceTypes = new ArrayList<>();
+        for (ImplicitCastData cast : getImplicitCasts()) {
+            sourceTypes.add(cast.getTargetType());
+        }
+        return ElementUtils.uniqueSortedTypes(sourceTypes);
+    }
+
+    public List<TypeMirror> lookupSourceTypes(TypeMirror targetType) {
+        List<TypeMirror> sourceTypes = new ArrayList<>();
+        sourceTypes.add(targetType);
+        for (ImplicitCastData cast : getImplicitCasts()) {
+            if (ElementUtils.typeEquals(cast.getTargetType(), targetType)) {
+                sourceTypes.add(cast.getSourceType());
             }
         }
-        Collections.sort(sourceTypes);
         return sourceTypes;
     }
 
-    public TypeData getBooleanType() {
-        return booleanType;
+    public boolean isImplicitSubtypeOf(TypeMirror source, TypeMirror target) {
+        List<ImplicitCastData> targetCasts = lookupByTargetType(target);
+        for (ImplicitCastData cast : targetCasts) {
+            if (ElementUtils.isSubtype(boxType(source), boxType(cast.getSourceType()))) {
+                return true;
+            }
+        }
+        return ElementUtils.isSubtype(boxType(source), boxType(target));
     }
 
-    public void setBooleanType(TypeData booleanType) {
-        this.booleanType = booleanType;
+    public TypeMirror boxType(TypeMirror type) {
+        return ElementUtils.boxType(getContext(), type);
+    }
+
+    public boolean hasType(TypeMirror type) {
+        if (legacyTypeIds == null) {
+            legacyTypeIds = new HashSet<>();
+            for (TypeMirror legacyType : legacyTypes) {
+                legacyTypeIds.add(ElementUtils.getTypeId(legacyType));
+            }
+        }
+        return legacyTypeIds.contains(ElementUtils.getTypeId(type));
     }
 
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java	Tue Apr 14 15:12:48 2015 +0200
@@ -59,7 +59,7 @@
             baseType = foundChild.getOriginalType();
         }
 
-        MethodSpec spec = new MethodSpec(new InheritsParameterSpec("child", baseType));
+        MethodSpec spec = new MethodSpec(new ParameterSpec("child", baseType));
         addDefaultFieldMethodSpec(spec);
         ParameterSpec childSpec = new ParameterSpec("castedChild", baseType);
         childSpec.setSignature(true);
@@ -96,22 +96,4 @@
         return cast;
     }
 
-    private static class InheritsParameterSpec extends ParameterSpec {
-
-        public InheritsParameterSpec(String name, TypeMirror... allowedTypes) {
-            super(name, Arrays.asList(allowedTypes), null);
-        }
-
-        @Override
-        public boolean matches(VariableElement variable) {
-            boolean found = false;
-            for (TypeMirror specType : getAllowedTypes()) {
-                if (ElementUtils.isAssignable(variable.asType(), specType)) {
-                    found = true;
-                    break;
-                }
-            }
-            return found;
-        }
-    }
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java	Tue Apr 14 22:12:03 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +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.dsl.processor.parser;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.model.*;
-
-public class ExecutableTypeMethodParser extends NodeMethodParser<ExecutableTypeData> {
-
-    private final List<TypeMirror> frameTypes;
-    private final NodeChildData child;
-
-    public ExecutableTypeMethodParser(ProcessorContext context, NodeData node, NodeChildData child, List<TypeMirror> frameTypes) {
-        super(context, node);
-        this.child = child;
-        this.frameTypes = frameTypes;
-        setParseNullOnError(false);
-        getParser().setEmitErrors(false);
-        getParser().setUseVarArgs(true);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        MethodSpec spec = createDefaultMethodSpec(method, mirror, false, null);
-        List<ParameterSpec> requiredSpecs = new ArrayList<>(spec.getRequired());
-        spec.getRequired().clear();
-
-        TypeSystemData typeSystem = getNode().getTypeSystem();
-        List<TypeMirror> allowedTypes = typeSystem.getPrimitiveTypeMirrors();
-        Set<String> allowedIdentifiers = typeSystem.getTypeIdentifiers();
-
-        if (child != null) {
-            for (NodeExecutionData executeWith : child.getExecuteWith()) {
-                ParameterSpec parameter = spec.addRequired(new ParameterSpec(executeWith.getName(), allowedTypes, allowedIdentifiers));
-                parameter.setExecution(executeWith);
-                parameter.setSignature(true);
-            }
-        } else {
-            for (ParameterSpec originalSpec : requiredSpecs) {
-                spec.addRequired(new ParameterSpec(originalSpec, allowedTypes, allowedIdentifiers));
-            }
-        }
-
-        spec.setIgnoreAdditionalSpecifications(true);
-        spec.setIgnoreAdditionalParameters(true);
-        spec.setVariableRequiredParameters(true);
-        // varargs
-        ParameterSpec otherParameters = new ParameterSpec("other", allowedTypes, allowedIdentifiers);
-        otherParameters.setSignature(true);
-        spec.addRequired(otherParameters);
-        return spec;
-    }
-
-    @Override
-    protected void addDefaultFrame(MethodSpec methodSpec) {
-        methodSpec.addOptional(new ParameterSpec("frame", frameTypes));
-    }
-
-    @Override
-    protected List<TypeMirror> nodeTypeMirrors(NodeData nodeData) {
-        return getNode().getTypeSystem().getPrimitiveTypeMirrors();
-    }
-
-    @Override
-    protected Set<String> nodeTypeIdentifiers(NodeData nodeData) {
-        return getNode().getTypeSystem().getTypeIdentifiers();
-    }
-
-    @Override
-    public final boolean isParsable(ExecutableElement method) {
-        if (method.getModifiers().contains(Modifier.STATIC)) {
-            return false;
-        } else if (method.getModifiers().contains(Modifier.NATIVE)) {
-            return false;
-        } else if (ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, Specialization.class) != null) {
-            return false;
-        } else if (method.getModifiers().contains(Modifier.PRIVATE)) {
-            return false;
-        }
-        return method.getSimpleName().toString().startsWith("execute");
-    }
-
-    @Override
-    public ExecutableTypeData create(TemplateMethod method, boolean invalid) {
-        TypeData resolvedType = method.getReturnType().getTypeSystemType();
-        return new ExecutableTypeData(method, method.getMethod(), getNode().getTypeSystem(), resolvedType);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return null;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GenericParser.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GenericParser.java	Tue Apr 14 15:12:48 2015 +0200
@@ -23,14 +23,11 @@
 package com.oracle.truffle.dsl.processor.parser;
 
 import java.lang.annotation.*;
-import java.util.*;
 
 import javax.lang.model.element.*;
-import javax.lang.model.type.*;
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
 import com.oracle.truffle.dsl.processor.model.*;
 import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind;
 
@@ -47,17 +44,9 @@
 
     @Override
     protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
-        List<ExecutableTypeData> execTypes = execution.getChild().findGenericExecutableTypes(getContext());
-        List<TypeMirror> types = new ArrayList<>();
-        Set<String> typeIds = new HashSet<>();
-        for (ExecutableTypeData type : execTypes) {
-            TypeMirror typeMirror = type.getType().getPrimitiveType();
-            types.add(typeMirror);
-            typeIds.add(ElementUtils.getUniqueIdentifier(typeMirror));
-        }
-        ParameterSpec spec = new ParameterSpec(execution.getName(), types, typeIds);
-        spec.setExecution(execution);
-        return spec;
+        ParameterSpec parameterSpec = super.createValueParameterSpec(execution);
+        parameterSpec.setAllowSubclasses(false);
+        return parameterSpec;
     }
 
     @Override
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ImplicitCastParser.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ImplicitCastParser.java	Tue Apr 14 15:12:48 2015 +0200
@@ -23,13 +23,13 @@
 package com.oracle.truffle.dsl.processor.parser;
 
 import java.lang.annotation.*;
-import java.util.*;
 
 import javax.lang.model.element.*;
 import javax.lang.model.type.*;
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
 import com.oracle.truffle.dsl.processor.model.*;
 
 public class ImplicitCastParser extends TypeSystemMethodParser<ImplicitCastData> {
@@ -45,10 +45,8 @@
 
     @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        List<TypeMirror> types = getTypeSystem().getPrimitiveTypeMirrors();
-        Set<String> identifiers = getTypeSystem().getTypeIdentifiers();
-        MethodSpec spec = new MethodSpec(new ParameterSpec("target", types, identifiers));
-        spec.addRequired(new ParameterSpec("source", types, identifiers)).setSignature(true);
+        MethodSpec spec = new MethodSpec(new ParameterSpec("target", getContext().getType(Object.class)));
+        spec.addRequired(new ParameterSpec("source", getContext().getType(Object.class))).setSignature(true);
         return spec;
     }
 
@@ -61,10 +59,10 @@
         Parameter target = method.findParameter("targetValue");
         Parameter source = method.findParameter("sourceValue");
 
-        TypeData targetType = target.getTypeSystemType();
-        TypeData sourceType = source.getTypeSystemType();
+        TypeMirror targetType = target.getType();
+        TypeMirror sourceType = source.getType();
 
-        if (targetType.equals(sourceType)) {
+        if (ElementUtils.typeEquals(targetType, sourceType)) {
             method.addError("Target type and source type of an @%s must not be the same type.", ImplicitCast.class.getSimpleName());
         }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java	Tue Apr 14 15:12:48 2015 +0200
@@ -48,10 +48,6 @@
         return template;
     }
 
-    public TypeSystemData getTypeSystem() {
-        return template.getTypeSystem();
-    }
-
     public boolean isEmitErrors() {
         return emitErrors;
     }
@@ -135,7 +131,7 @@
      * end matching the required arguments, parsing fails. Parameters prior to the parsed required
      * ones are cut and used to parse the optional parameters.
      */
-    private List<Parameter> parseParameters(MethodSpec spec, List<? extends VariableElement> parameterTypes, boolean varArgs) {
+    private static List<Parameter> parseParameters(MethodSpec spec, List<? extends VariableElement> parameterTypes, boolean varArgs) {
         List<Parameter> parsedRequired = null;
         int offset = 0;
         for (; offset <= parameterTypes.size(); offset++) {
@@ -166,7 +162,7 @@
         return finalParameters;
     }
 
-    private List<Parameter> parseParametersOptional(MethodSpec spec, List<? extends VariableElement> types) {
+    private static List<Parameter> parseParametersOptional(MethodSpec spec, List<? extends VariableElement> types) {
         List<Parameter> parsedParams = new ArrayList<>();
 
         int typeStartIndex = 0;
@@ -191,7 +187,7 @@
         return parsedParams;
     }
 
-    private List<Parameter> parseParametersRequired(MethodSpec spec, List<VariableElement> types, boolean typeVarArgs) {
+    private static List<Parameter> parseParametersRequired(MethodSpec spec, List<VariableElement> types, boolean typeVarArgs) {
         List<Parameter> parsedParams = new ArrayList<>();
         List<ParameterSpec> specifications = spec.getRequired();
         boolean specVarArgs = spec.isVariableRequiredParameters();
@@ -248,7 +244,7 @@
         return parsedParams;
     }
 
-    private Parameter matchAnnotatedParameter(MethodSpec spec, VariableElement variable) {
+    private static Parameter matchAnnotatedParameter(MethodSpec spec, VariableElement variable) {
         for (ParameterSpec parameterSpec : spec.getAnnotations()) {
             if (parameterSpec.matches(variable)) {
                 Parameter matchedParameter = matchParameter(parameterSpec, variable, -1, -1);
@@ -286,7 +282,7 @@
         }
     }
 
-    private Parameter matchParameter(ParameterSpec specification, VariableElement variable, int specificationIndex, int varArgsIndex) {
+    private static Parameter matchParameter(ParameterSpec specification, VariableElement variable, int specificationIndex, int varArgsIndex) {
         TypeMirror resolvedType = variable.asType();
         if (hasError(resolvedType)) {
             return null;
@@ -296,12 +292,6 @@
             return null;
         }
 
-        TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType);
-        if (resolvedTypeData != null) {
-            return new Parameter(specification, resolvedTypeData, variable, specificationIndex, varArgsIndex);
-        } else {
-            return new Parameter(specification, variable, specificationIndex, varArgsIndex);
-        }
+        return new Parameter(specification, variable, specificationIndex, varArgsIndex);
     }
-
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java	Tue Apr 14 15:12:48 2015 +0200
@@ -42,26 +42,25 @@
     }
 
     protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
-        NodeData childNode = execution.getChild().getNodeData();
-        ParameterSpec spec = new ParameterSpec(execution.getName(), nodeTypeMirrors(childNode), nodeTypeIdentifiers(childNode));
+        ParameterSpec spec = new ParameterSpec(execution.getName(), getPossibleParameterTypes(execution));
         spec.setExecution(execution);
         return spec;
     }
 
-    protected List<TypeMirror> nodeTypeMirrors(NodeData nodeData) {
-        return nodeData.getTypeSystem().getPrimitiveTypeMirrors();
-    }
-
-    protected Set<String> nodeTypeIdentifiers(NodeData nodeData) {
-        return nodeData.getTypeSystem().getTypeIdentifiers();
+    protected Collection<TypeMirror> getPossibleParameterTypes(NodeExecutionData execution) {
+        return getNode().getPossibleTypes(execution);
     }
 
     protected ParameterSpec createReturnParameterSpec() {
-        ParameterSpec returnValue = new ParameterSpec("returnValue", nodeTypeMirrors(getNode()), nodeTypeIdentifiers(getNode()));
+        ParameterSpec returnValue = new ParameterSpec("returnValue", getPossibleReturnTypes());
         returnValue.setExecution(getNode().getThisExecution());
         return returnValue;
     }
 
+    protected Collection<TypeMirror> getPossibleReturnTypes() {
+        return getNode().getPossibleTypes(getNode().getThisExecution());
+    }
+
     @Override
     public boolean isParsable(ExecutableElement method) {
         if (getAnnotationType() != null) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java	Tue Apr 14 15:12:48 2015 +0200
@@ -32,7 +32,7 @@
 
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.NodeField;
+import com.oracle.truffle.api.dsl.internal.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.expression.*;
@@ -45,6 +45,7 @@
 import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind;
 import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature;
 
+@DSLOptions
 public class NodeParser extends AbstractParser<NodeData> {
 
     public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Fallback.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, NodeChild.class,
@@ -145,8 +146,8 @@
 
         node.getFields().addAll(parseFields(lookupTypes, members));
         node.getChildren().addAll(parseChildren(lookupTypes, members));
-        node.getChildExecutions().addAll(parseExecutions(node.getChildren(), members));
-        node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node, null, context.getFrameTypes()).parse(members)));
+        node.getChildExecutions().addAll(parseExecutions(node.getFields(), node.getChildren(), members));
+        node.setExecutableTypes(groupExecutableTypes(parseExecutableTypeData(members, node.getChildExecutions().size(), context.getFrameTypes())));
 
         initializeExecutableTypes(node);
         initializeImportGuards(node, lookupTypes, members);
@@ -256,20 +257,19 @@
 
     private NodeData parseNodeData(TypeElement templateType, List<TypeElement> typeHierarchy) {
         AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class);
-        if (typeSystemMirror == null) {
-            NodeData nodeData = new NodeData(context, templateType);
-            nodeData.addError("No @%s annotation found in type hierarchy of %s.", TypeSystemReference.class.getSimpleName(), ElementUtils.getQualifiedName(templateType));
-            return nodeData;
+        TypeSystemData typeSystem = null;
+        if (typeSystemMirror != null) {
+            TypeMirror typeSystemType = ElementUtils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value");
+            typeSystem = (TypeSystemData) context.getTemplate(typeSystemType, true);
+            if (typeSystem == null) {
+                NodeData nodeData = new NodeData(context, templateType);
+                nodeData.addError("The used type system '%s' is invalid. Fix errors in the type system first.", ElementUtils.getQualifiedName(typeSystemType));
+                return nodeData;
+            }
+        } else {
+            // default dummy type system
+            typeSystem = new TypeSystemData(context, templateType, null, NodeParser.class.getAnnotation(DSLOptions.class), true);
         }
-
-        TypeMirror typeSystemType = ElementUtils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value");
-        final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSystemType, true);
-        if (typeSystem == null) {
-            NodeData nodeData = new NodeData(context, templateType);
-            nodeData.addError("The used type system '%s' is invalid. Fix errors in the type system first.", ElementUtils.getQualifiedName(typeSystemType));
-            return nodeData;
-        }
-
         AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class);
         String shortName = null;
         if (nodeInfoMirror != null) {
@@ -406,11 +406,7 @@
         return filteredChildren;
     }
 
-    private List<NodeExecutionData> parseExecutions(List<NodeChildData> children, List<? extends Element> elements) {
-        if (children == null) {
-            return null;
-        }
-
+    private List<NodeExecutionData> parseExecutions(List<NodeFieldData> fields, List<NodeChildData> children, List<? extends Element> elements) {
         // pre-parse short circuits
         Set<String> shortCircuits = new HashSet<>();
         List<ExecutableElement> methods = ElementFilter.methodsIn(elements);
@@ -433,6 +429,13 @@
             }
         }
 
+        List<NodeFieldData> nonGetterFields = new ArrayList<>();
+        for (NodeFieldData field : fields) {
+            if (field.getGetter() == null && field.isGenerated()) {
+                nonGetterFields.add(field);
+            }
+        }
+
         TypeMirror cacheAnnotation = context.getType(Cached.class);
         List<TypeMirror> frameTypes = context.getFrameTypes();
         // pre-parse specializations to find signature size
@@ -443,34 +446,40 @@
             }
             int currentArgumentIndex = 0;
             boolean skipShortCircuit = false;
-            outer: for (VariableElement var : method.getParameters()) {
+            parameter: for (VariableElement var : method.getParameters()) {
+                if (skipShortCircuit) {
+                    skipShortCircuit = false;
+                    continue parameter;
+                }
 
                 TypeMirror type = var.asType();
                 if (currentArgumentIndex == 0) {
                     // skip optionals
                     for (TypeMirror frameType : frameTypes) {
                         if (ElementUtils.typeEquals(type, frameType)) {
-                            continue outer;
+                            continue parameter;
+                        }
+                    }
+                }
+
+                if (currentArgumentIndex < nonGetterFields.size()) {
+                    for (NodeFieldData field : nonGetterFields) {
+                        if (ElementUtils.typeEquals(var.asType(), field.getType())) {
+                            continue parameter;
                         }
                     }
                 }
 
                 if (ElementUtils.findAnnotationMirror(var.getAnnotationMirrors(), cacheAnnotation) != null) {
-                    continue outer;
+                    continue parameter;
                 }
 
                 int childIndex = currentArgumentIndex < children.size() ? currentArgumentIndex : children.size() - 1;
-                if (childIndex == -1) {
-                    continue;
-                }
-                if (!skipShortCircuit) {
+                if (childIndex != -1) {
                     NodeChildData child = children.get(childIndex);
                     if (shortCircuits.contains(NodeExecutionData.createIndexedName(child, currentArgumentIndex - childIndex))) {
                         skipShortCircuit = true;
-                        continue;
                     }
-                } else {
-                    skipShortCircuit = false;
                 }
 
                 currentArgumentIndex++;
@@ -480,24 +489,65 @@
 
         List<NodeExecutionData> executions = new ArrayList<>();
         for (int i = 0; i < maxSignatureSize; i++) {
+            boolean varArgParameter = false;
             int childIndex = i;
-            boolean varArg = false;
-            if (childIndex >= children.size() - 1) {
+            if (i >= children.size() - 1) {
                 if (hasVarArgs) {
-                    childIndex = children.size() - 1;
-                    varArg = hasVarArgs;
-                } else if (childIndex >= children.size()) {
-                    break;
+                    varArgParameter = hasVarArgs;
+                    childIndex = Math.min(i, children.size() - 1);
+                } else if (i >= children.size()) {
+                    childIndex = -1;
                 }
             }
-            int varArgsIndex = varArg ? Math.abs(childIndex - i) : -1;
-            NodeChildData child = children.get(childIndex);
-            boolean shortCircuit = shortCircuits.contains(NodeExecutionData.createIndexedName(child, varArgsIndex));
-            executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit));
+            int varArgsIndex = -1;
+            boolean shortCircuit = false;
+            NodeChildData child = null;
+            if (childIndex != -1) {
+                varArgsIndex = varArgParameter ? Math.abs(childIndex - i) : -1;
+                child = children.get(childIndex);
+                shortCircuit = shortCircuits.contains(NodeExecutionData.createIndexedName(child, varArgsIndex));
+            }
+            executions.add(new NodeExecutionData(child, i, varArgsIndex, shortCircuit));
         }
         return executions;
     }
 
+    private List<ExecutableTypeData> parseExecutableTypeData(List<? extends Element> elements, int signatureSize, List<TypeMirror> frameTypes) {
+        List<ExecutableTypeData> typeData = new ArrayList<>();
+        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
+            Set<Modifier> modifiers = method.getModifiers();
+            if (modifiers.contains(Modifier.PRIVATE) || modifiers.contains(Modifier.STATIC)) {
+                continue;
+            }
+            if (!method.getSimpleName().toString().startsWith("execute")) {
+                continue;
+            }
+            if (ElementUtils.findAnnotationMirror(context.getEnvironment(), method, Specialization.class) != null) {
+                continue;
+            }
+
+            ExecutableTypeData executableType = new ExecutableTypeData(method, signatureSize, context.getFrameTypes());
+
+            if (executableType.getFrameParameter() != null) {
+                boolean supportedType = false;
+                for (TypeMirror type : frameTypes) {
+                    if (ElementUtils.isAssignable(type, executableType.getFrameParameter())) {
+                        supportedType = true;
+                        break;
+                    }
+                }
+                if (!supportedType) {
+                    continue;
+                }
+            }
+
+            typeData.add(executableType);
+        }
+
+        Collections.sort(typeData);
+        return typeData;
+    }
+
     private void initializeExecutableTypes(NodeData node) {
         List<ExecutableTypeData> allExecutes = node.getExecutableTypes();
 
@@ -507,10 +557,10 @@
         for (ExecutableTypeData execute : allExecutes) {
             evaluatedCounts.add(execute.getEvaluatedCount());
 
-            Parameter frame = execute.getFrame();
+            TypeMirror frame = execute.getFrameParameter();
             TypeMirror resolvedFrameType;
             if (frame != null) {
-                resolvedFrameType = frame.getType();
+                resolvedFrameType = frame;
                 if (frameType == null) {
                     frameType = resolvedFrameType;
                 } else if (!ElementUtils.typeEquals(frameType, resolvedFrameType)) {
@@ -540,7 +590,7 @@
             int voidCount = 0;
             for (ExecutableTypeData executableTypeData : genericExecutes) {
                 if (!executableTypeData.getMethod().getModifiers().contains(Modifier.FINAL)) {
-                    if (ElementUtils.isVoid(executableTypeData.getReturnType().getType())) {
+                    if (ElementUtils.isVoid(executableTypeData.getReturnType())) {
                         voidCount++;
                     } else {
                         genericCount++;
@@ -552,16 +602,16 @@
                 if (voidCount > 1) {
                     List<String> methodSignatures = new ArrayList<>();
                     for (ExecutableTypeData type : genericExecutes) {
-                        if (type.getType().isVoid()) {
-                            methodSignatures.add(type.createReferenceName());
+                        if (context.isType(type.getReturnType(), void.class)) {
+                            methodSignatures.add(ElementUtils.createReferenceName(type.getMethod()));
                         }
                     }
                     node.addWarning("Multiple accessible and overridable generic execute methods found %s. Remove all but one or mark all but one as final.", methodSignatures);
                 } else if (genericCount > 1) {
                     List<String> methodSignatures = new ArrayList<>();
                     for (ExecutableTypeData type : genericExecutes) {
-                        if (!type.getType().isVoid()) {
-                            methodSignatures.add(type.createReferenceName());
+                        if (!context.isType(type.getReturnType(), void.class)) {
+                            methodSignatures.add(ElementUtils.createReferenceName(type.getMethod()));
                         }
                     }
                     node.addWarning("Multiple accessible and overridable generic execute methods found %s. Remove all but one or mark all but one as final.", methodSignatures);
@@ -577,6 +627,35 @@
                             + "signature 'public abstract {Type} execute(VirtualFrame)' and must not throw any checked exceptions.");
         }
 
+        int nodeChildDeclarations = 0;
+        int nodeChildDeclarationsRequired = 0;
+        List<NodeExecutionData> executions = node.getChildExecutions();
+        for (NodeExecutionData execution : executions) {
+            if (execution.getChild() == null) {
+                nodeChildDeclarationsRequired = execution.getIndex() + 1;
+            } else {
+                nodeChildDeclarations++;
+            }
+        }
+
+        List<String> requireNodeChildDeclarations = new ArrayList<>();
+        for (ExecutableTypeData type : allExecutes) {
+            if (type.getEvaluatedCount() < nodeChildDeclarationsRequired) {
+                requireNodeChildDeclarations.add(ElementUtils.createReferenceName(type.getMethod()));
+            }
+        }
+
+        if (!requireNodeChildDeclarations.isEmpty()) {
+            node.addError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. "
+                            + "The following execute methods do not provide all evaluated values for the expected signature size %s: %s.", executions.size(), requireNodeChildDeclarations);
+        }
+
+        if (nodeChildDeclarations > 0 && executions.size() == node.getMinimalEvaluatedParameters()) {
+            for (NodeChildData child : node.getChildren()) {
+                child.addError("Unnecessary @NodeChild declaration. All evaluated child values are provided as parameters in execute methods.");
+            }
+        }
+
     }
 
     private static Map<Integer, List<ExecutableTypeData>> groupExecutableTypes(List<ExecutableTypeData> executableTypes) {
@@ -608,10 +687,6 @@
             child.setNode(fieldNodeData);
             if (fieldNodeData == null || fieldNodeData.hasErrors()) {
                 child.addError("Node type '%s' is invalid or not a subclass of Node.", ElementUtils.getQualifiedName(nodeType));
-            } else if (!ElementUtils.typeEquals(fieldNodeData.getTypeSystem().getTemplateType().asType(), (node.getTypeSystem().getTemplateType().asType()))) {
-                child.addError("The @%s of the node and the @%s of the @%s does not match. %s != %s. ", TypeSystem.class.getSimpleName(), TypeSystem.class.getSimpleName(),
-                                NodeChild.class.getSimpleName(), ElementUtils.getSimpleName(node.getTypeSystem().getTemplateType()),
-                                ElementUtils.getSimpleName(fieldNodeData.getTypeSystem().getTemplateType()));
             } else {
                 List<ExecutableTypeData> types = child.findGenericExecutableTypes(context);
                 if (types.isEmpty()) {
@@ -680,7 +755,11 @@
         if (node.hasErrors()) {
             return node;
         }
-        node.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, node, child, createAllowedChildFrameTypes(parentNode)).parse(members)));
+        List<TypeMirror> frameTypes = Collections.emptyList();
+        if (parentNode.getFrameType() != null) {
+            frameTypes = Arrays.asList(parentNode.getFrameType());
+        }
+        node.setExecutableTypes(groupExecutableTypes(parseExecutableTypeData(members, child.getExecuteWith().size(), frameTypes)));
         node.setFrameType(parentNode.getFrameType());
         return node;
     }
@@ -1159,13 +1238,13 @@
         List<VariableElement> parameterTypes = new ArrayList<>();
         int signatureIndex = 1;
         for (ParameterSpec spec : specification.getRequired()) {
-            parameterTypes.add(new CodeVariableElement(createGenericType(spec, node.getSpecializations(), signatureIndex), "arg" + signatureIndex));
+            parameterTypes.add(new CodeVariableElement(createGenericType(node, spec), "arg" + signatureIndex));
             if (spec.isSignature()) {
                 signatureIndex++;
             }
         }
 
-        TypeMirror returnType = createGenericType(specification.getReturnType(), node.getSpecializations(), 0);
+        TypeMirror returnType = createGenericType(node, specification.getReturnType());
         SpecializationData generic = parser.create("Generic", TemplateMethod.NO_NATURAL_ORDER, null, null, returnType, parameterTypes);
         if (generic == null) {
             throw new RuntimeException("Unable to create generic signature for node " + node.getNodeId() + " with " + parameterTypes + ". Specification " + specification + ".");
@@ -1174,41 +1253,22 @@
         return generic;
     }
 
-    private TypeMirror createGenericType(ParameterSpec spec, List<SpecializationData> specializations, int signatureIndex) {
+    private TypeMirror createGenericType(NodeData node, ParameterSpec spec) {
         NodeExecutionData execution = spec.getExecution();
+        Collection<TypeMirror> allowedTypes;
         if (execution == null) {
-            if (spec.getAllowedTypes().size() == 1) {
-                return spec.getAllowedTypes().get(0);
-            } else {
-                return ElementUtils.getCommonSuperType(context, spec.getAllowedTypes().toArray(new TypeMirror[0]));
-            }
+            allowedTypes = spec.getAllowedTypes();
         } else {
-            Set<TypeData> types = new HashSet<>();
-            for (SpecializationData specialization : specializations) {
-                types.add(specialization.getTypeSignature().get(signatureIndex));
-            }
-
-            NodeChildData child = execution.getChild();
-            TypeData genericType = null;
-            if (types.size() == 1) {
-                TypeData singleType = types.iterator().next();
-                ExecutableTypeData executable = child.findExecutableType(singleType);
-                if (executable != null && (signatureIndex == 0 || !executable.hasUnexpectedValue(context))) {
-                    genericType = singleType;
-                }
-            }
-            if (genericType == null) {
-                ExecutableTypeData type = child.findAnyGenericExecutableType(context);
-                if (type == null) {
-                    throw new AssertionError("No generic type not yet catched by parser.");
-                }
-                genericType = type.getType();
-            }
-            return genericType.getPrimitiveType();
+            allowedTypes = node.getPossibleTypes(execution);
+        }
+        if (allowedTypes.size() == 1) {
+            return allowedTypes.iterator().next();
+        } else {
+            return ElementUtils.getCommonSuperType(context, allowedTypes.toArray(new TypeMirror[allowedTypes.size()]));
         }
     }
 
-    private static void initializeUninitialized(final NodeData node) {
+    private void initializeUninitialized(final NodeData node) {
         SpecializationData generic = node.getGenericSpecialization();
         if (generic == null) {
             return;
@@ -1225,7 +1285,7 @@
                 }
             }
             if (types.size() > 1) {
-                generic.replaceParameter(parameter.getLocalName(), new Parameter(parameter, node.getTypeSystem().getGenericTypeData()));
+                generic.replaceParameter(parameter.getLocalName(), new Parameter(parameter, context.getType(Object.class)));
             }
         }
         TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", -1, node, generic.getSpecification(), null, null, generic.getReturnType(), generic.getParameters());
@@ -1241,14 +1301,14 @@
 
         SpecializationData generic = node.getGenericSpecialization();
 
-        List<TypeData> polymorphicSignature = new ArrayList<>();
+        List<TypeMirror> polymorphicSignature = new ArrayList<>();
         List<Parameter> updatePolymorphic = Arrays.asList();
         for (Parameter genericParameter : updatePolymorphic) {
             if (!genericParameter.getSpecification().isSignature()) {
                 continue;
             }
 
-            Set<TypeData> usedTypes = new HashSet<>();
+            Set<TypeMirror> usedTypes = new HashSet<>();
             for (SpecializationData specialization : node.getSpecializations()) {
                 if (!specialization.isSpecialized()) {
                     continue;
@@ -1257,14 +1317,14 @@
                 if (parameter == null) {
                     throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName());
                 }
-                usedTypes.add(parameter.getTypeSystemType());
+                usedTypes.add(parameter.getType());
             }
 
-            TypeData polymorphicType;
+            TypeMirror polymorphicType;
             if (usedTypes.size() == 1) {
                 polymorphicType = usedTypes.iterator().next();
             } else {
-                polymorphicType = node.getTypeSystem().getGenericTypeData();
+                polymorphicType = context.getType(Object.class);
             }
             polymorphicSignature.add(polymorphicType);
         }
@@ -1370,7 +1430,7 @@
             ExecutableTypeData found = null;
             List<ExecutableTypeData> executableElements = execution.getChild().findGenericExecutableTypes(context);
             for (ExecutableTypeData executable : executableElements) {
-                if (executable.getType().equalsType(parameter.getTypeSystemType())) {
+                if (ElementUtils.typeEquals(executable.getReturnType(), parameter.getType())) {
                     found = executable;
                     break;
                 }
@@ -1429,8 +1489,8 @@
 
         List<Element> elements = new ArrayList<>(originalElements);
         Set<Element> unusedElements = new HashSet<>(elements);
-        for (TemplateMethod method : nodeData.getAllTemplateMethods()) {
-            unusedElements.remove(method.getMethod());
+        for (ExecutableElement method : nodeData.getAllTemplateMethods()) {
+            unusedElements.remove(method);
         }
 
         for (NodeFieldData field : nodeData.getFields()) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java	Tue Apr 14 15:12:48 2015 +0200
@@ -24,6 +24,8 @@
 
 import java.util.*;
 
+import javax.lang.model.type.*;
+
 import com.oracle.truffle.dsl.processor.model.*;
 import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature;
 
@@ -299,9 +301,9 @@
     public static final class TypeGuard {
 
         private final int signatureIndex;
-        private final TypeData type;
+        private final TypeMirror type;
 
-        public TypeGuard(TypeData type, int signatureIndex) {
+        public TypeGuard(TypeMirror type, int signatureIndex) {
             this.type = type;
             this.signatureIndex = signatureIndex;
         }
@@ -338,7 +340,7 @@
             return signatureIndex;
         }
 
-        public TypeData getType() {
+        public TypeMirror getType() {
             return type;
         }
     }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCastParser.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCastParser.java	Tue Apr 14 15:12:48 2015 +0200
@@ -41,15 +41,17 @@
     @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
         TypeMirror targetTypeMirror = ElementUtils.getAnnotationValue(TypeMirror.class, mirror, "value");
-        MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", targetTypeMirror));
-        spec.addRequired(new ParameterSpec("value", getTypeSystem().getGenericType()));
+        ParameterSpec returnTypeSpec = new ParameterSpec("returnType", targetTypeMirror);
+        returnTypeSpec.setAllowSubclasses(false);
+        MethodSpec spec = new MethodSpec(returnTypeSpec);
+        spec.addRequired(new ParameterSpec("value", getContext().getType(Object.class)));
         return spec;
     }
 
     @Override
     public TypeCastData create(TemplateMethod method, boolean invalid) {
-        TypeData targetType = resolveCastOrCheck(method);
-        TypeData sourceType = getTypeSystem().getGenericTypeData();
+        TypeMirror targetType = resolveCastOrCheck(method);
+        TypeMirror sourceType = getContext().getType(Object.class);
         return new TypeCastData(method, sourceType, targetType);
     }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCheckParser.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCheckParser.java	Tue Apr 14 15:12:48 2015 +0200
@@ -25,6 +25,7 @@
 import java.lang.annotation.*;
 
 import javax.lang.model.element.*;
+import javax.lang.model.type.*;
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.dsl.processor.*;
@@ -39,13 +40,13 @@
     @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
         MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", getContext().getType(boolean.class)));
-        spec.addRequired(new ParameterSpec("value", getTypeSystem().getGenericType()));
+        spec.addRequired(new ParameterSpec("value", getContext().getType(Object.class)));
         return spec;
     }
 
     @Override
     public TypeCheckData create(TemplateMethod method, boolean invalid) {
-        TypeData targetType = resolveCastOrCheck(method);
+        TypeMirror targetType = resolveCastOrCheck(method);
         return new TypeCheckData(method, targetType, targetType);
     }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemMethodParser.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemMethodParser.java	Tue Apr 14 15:12:48 2015 +0200
@@ -25,7 +25,6 @@
 import javax.lang.model.element.*;
 import javax.lang.model.type.*;
 
-import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.java.*;
 import com.oracle.truffle.dsl.processor.model.*;
@@ -41,18 +40,13 @@
         return ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
     }
 
-    protected final TypeData resolveCastOrCheck(TemplateMethod method) {
+    protected final TypeMirror resolveCastOrCheck(TemplateMethod method) {
         Class<?> annotationType = getAnnotationType();
         TypeMirror targetTypeMirror = ElementUtils.getAnnotationValue(TypeMirror.class, method.getMessageAnnotation(), "value");
-        TypeData targetType = getTypeSystem().findTypeData(targetTypeMirror);
-        if (targetType == null) {
-            method.addError("The type '%s' is not declared in the @%s.", ElementUtils.getSimpleName(targetTypeMirror), TypeSystem.class.getSimpleName());
-            return null;
-        }
         if (!method.getMethod().getModifiers().contains(Modifier.PUBLIC) || !method.getMethod().getModifiers().contains(Modifier.STATIC)) {
             method.addError("@%s annotated method %s must be public and static.", annotationType.getSimpleName(), method.getMethodName());
         }
-        return targetType;
+        return targetTypeMirror;
     }
 
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java	Tue Apr 14 22:12:03 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java	Tue Apr 14 15:12:48 2015 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.truffle.dsl.processor.parser;
 
-import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
-
 import java.lang.annotation.*;
 import java.util.*;
 
@@ -33,7 +31,6 @@
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.dsl.internal.*;
-import com.oracle.truffle.dsl.processor.generator.*;
 import com.oracle.truffle.dsl.processor.java.*;
 import com.oracle.truffle.dsl.processor.model.*;
 
@@ -57,7 +54,7 @@
         }
         assert options != null;
 
-        TypeSystemData typeSystem = new TypeSystemData(context, templateType, templateTypeAnnotation, options);
+        TypeSystemData typeSystem = new TypeSystemData(context, templateType, templateTypeAnnotation, options, false);
 
         // annotation type on class path!?
         TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName());
@@ -75,24 +72,9 @@
             return typeSystem;
         }
 
-        List<TypeData> types = parseTypes(typeSystem);
-
-        TypeMirror genericType = context.getType(Object.class);
-        TypeData voidType = new TypeData(typeSystem, types.size(), null, context.getType(void.class), context.getType(Void.class));
-        types.add(voidType);
-
-        typeSystem.setTypes(types);
         if (typeSystem.hasErrors()) {
             return typeSystem;
         }
-        typeSystem.setGenericType(genericType);
-        typeSystem.setVoidType(voidType);
-
-        TypeData booleanType = typeSystem.findTypeData(context.getType(boolean.class));
-        if (booleanType == null) {
-            booleanType = new TypeData(typeSystem, types.size(), null, context.getType(boolean.class), context.getType(Boolean.class));
-        }
-        typeSystem.setBooleanType(booleanType);
 
         verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class);
 
@@ -105,25 +87,20 @@
             return typeSystem;
         }
 
-        typeSystem.setImplicitCasts(implicitCasts);
-        typeSystem.setCasts(casts);
-        typeSystem.setChecks(checks);
+        List<TypeMirror> legacyTypes = ElementUtils.getAnnotationValueList(TypeMirror.class, typeSystem.getTemplateTypeAnnotation(), "value");
+        typeSystem.getLegacyTypes().addAll(legacyTypes);
+        verifyTypes(typeSystem);
+        typeSystem.getLegacyTypes().add(context.getType(Object.class));
+        typeSystem.getLegacyTypes().add(context.getType(void.class));
+        verifyNamesUnique(typeSystem);
+
+        typeSystem.getImplicitCasts().addAll(implicitCasts);
+        typeSystem.getCasts().addAll(casts);
+        typeSystem.getChecks().addAll(checks);
 
         if (typeSystem.hasErrors()) {
             return typeSystem;
         }
-
-        for (TypeCheckData check : checks) {
-            check.getCheckedType().addTypeCheck(check);
-        }
-
-        for (TypeCastData cast : casts) {
-            cast.getTargetType().addTypeCast(cast);
-        }
-
-        verifyMethodSignatures(typeSystem);
-        verifyNamesUnique(typeSystem);
-
         return typeSystem;
     }
 
@@ -149,50 +126,28 @@
         }
     }
 
-    private List<TypeData> parseTypes(TypeSystemData typeSystem) {
-        List<TypeData> types = new ArrayList<>();
-        List<TypeMirror> typeMirrors = ElementUtils.getAnnotationValueList(TypeMirror.class, typeSystem.getTemplateTypeAnnotation(), "value");
-        if (typeMirrors.isEmpty()) {
-            typeSystem.addError("At least one type must be defined.");
-            return types;
-        }
-
-        final AnnotationValue annotationValue = ElementUtils.getAnnotationValue(typeSystem.getTemplateTypeAnnotation(), "value");
-        final TypeMirror objectType = context.getType(Object.class);
-
-        int index = 0;
-        for (TypeMirror primitiveType : typeMirrors) {
-            TypeMirror primitive = ElementUtils.fillInGenericWildcards(primitiveType);
-
-            TypeMirror boxedType = ElementUtils.boxType(context, primitive);
-            TypeData typeData = new TypeData(typeSystem, index, annotationValue, primitive, boxedType);
-
-            if (isPrimitiveWrapper(primitive)) {
-                typeData.addError("Types must not contain primitive wrapper types.");
+    private void verifyTypes(TypeSystemData typeSystem) {
+        for (TypeMirror type : typeSystem.getLegacyTypes()) {
+            if (isPrimitiveWrapper(type)) {
+                typeSystem.addError("Types must not contain primitive wrapper types.");
             }
 
-            if (ElementUtils.typeEquals(boxedType, objectType)) {
-                typeData.addError("Types must not contain the generic type java.lang.Object.");
+            if (ElementUtils.typeEquals(type, context.getType(Object.class))) {
+                typeSystem.addError("Types must not contain the generic type java.lang.Object.");
             }
-
-            types.add(typeData);
-            index++;
         }
 
-        verifyTypeOrder(types);
-
-        types.add(new TypeData(typeSystem, index, annotationValue, objectType, objectType));
-        return types;
+        verifyTypeOrder(typeSystem);
     }
 
-    private static void verifyTypeOrder(List<TypeData> types) {
+    private static void verifyTypeOrder(TypeSystemData typeSystem) {
         Map<String, List<String>> invalidTypes = new HashMap<>();
 
-        for (int i = types.size() - 1; i >= 0; i--) {
-            TypeData typeData = types.get(i);
-            TypeMirror type = typeData.getBoxedType();
+        for (int i = typeSystem.getLegacyTypes().size() - 1; i >= 0; i--) {
+            TypeMirror typeData = typeSystem.getLegacyTypes().get(i);
+            TypeMirror type = typeSystem.boxType(typeData);
             if (invalidTypes.containsKey(ElementUtils.getQualifiedName(type))) {
-                typeData.addError("Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", invalidTypes.get(ElementUtils.getQualifiedName(type)),
+                typeSystem.addError("Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", invalidTypes.get(ElementUtils.getQualifiedName(type)),
                                 ElementUtils.getQualifiedName(type));
             }
             TypeElement element = ElementUtils.fromTypeMirror(type);
@@ -200,7 +155,7 @@
             if (element != null) {
                 nextInvalidTypes.addAll(ElementUtils.getQualifiedSuperTypeNames(element));
             }
-            nextInvalidTypes.add(getQualifiedName(type));
+            nextInvalidTypes.add(ElementUtils.getQualifiedName(type));
 
             for (String qualifiedName : nextInvalidTypes) {
                 List<String> inheritedTypes = invalidTypes.get(qualifiedName);
@@ -208,7 +163,7 @@
                     inheritedTypes = new ArrayList<>();
                     invalidTypes.put(qualifiedName, inheritedTypes);
                 }
-                inheritedTypes.add(ElementUtils.getQualifiedName(typeData.getBoxedType()));
+                inheritedTypes.add(ElementUtils.getQualifiedName(typeSystem.boxType(typeData)));
             }
         }
     }
@@ -226,64 +181,11 @@
         return false;
     }
 
-    private void verifyMethodSignatures(TypeSystemData typeSystem) {
-        Set<String> generatedIsMethodNames = new HashSet<>();
-        Set<String> generatedAsMethodNames = new HashSet<>();
-        Set<String> generatedExpectMethodNames = new HashSet<>();
-
-        for (TypeData typeData : typeSystem.getTypes()) {
-            generatedIsMethodNames.add(TypeSystemCodeGenerator.isTypeMethodName(typeData));
-            generatedAsMethodNames.add(TypeSystemCodeGenerator.asTypeMethodName(typeData));
-            generatedExpectMethodNames.add(TypeSystemCodeGenerator.expectTypeMethodName(typeData));
-        }
-
-        List<ExecutableElement> methods = ElementFilter.methodsIn(typeSystem.getTemplateType().getEnclosedElements());
-        for (ExecutableElement method : methods) {
-            if (method.getModifiers().contains(Modifier.PRIVATE)) {
-                // will not conflict overridden methods
-                continue;
-            } else if (method.getParameters().size() != 1) {
-                continue;
-            }
-            String methodName = method.getSimpleName().toString();
-            if (generatedIsMethodNames.contains(methodName)) {
-                verifyIsMethod(typeSystem, method);
-            } else if (generatedAsMethodNames.contains(methodName)) {
-                verifyAsMethod(typeSystem, method);
-            } else if (generatedExpectMethodNames.contains(methodName)) {
-                verifyExpectMethod(typeSystem);
-            }
-        }
-    }
-
-    private boolean verifyIsMethod(TypeSystemData typeSystem, ExecutableElement method) {
-        AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, TypeCheck.class);
-        if (mirror == null) {
-            typeSystem.addError("Method starting with the pattern is${typeName} must be annotated with @%s.", TypeCheck.class.getSimpleName());
-            return false;
-        }
-        return true;
-    }
-
-    private boolean verifyAsMethod(TypeSystemData typeSystem, ExecutableElement method) {
-        AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, TypeCast.class);
-        if (mirror == null) {
-            typeSystem.addError("Method starting with the pattern as${typeName} must be annotated with @%s.", TypeCast.class.getSimpleName());
-            return false;
-        }
-        return true;
-    }
-
-    private static boolean verifyExpectMethod(TypeSystemData typeSystem) {
-        typeSystem.addError("Method starting with the pattern expect${typeName} must not be declared manually.");
-        return false;
-    }
-
     private static void verifyNamesUnique(TypeSystemData typeSystem) {
         Set<String> usedNames = new HashSet<>();
-        for (TypeData type : typeSystem.getTypes()) {
-            String boxedName = ElementUtils.getSimpleName(type.getBoxedType());
-            String primitiveName = ElementUtils.getSimpleName(type.getPrimitiveType());
+        for (TypeMirror type : typeSystem.getLegacyTypes()) {
+            String boxedName = ElementUtils.getSimpleName(typeSystem.boxType(type));
+            String primitiveName = ElementUtils.getSimpleName(type);
             if (usedNames.contains(boxedName)) {
                 typeSystem.addError("Two types result in the same boxed name: %s.", boxedName);
             } else if (usedNames.contains(primitiveName)) {
@@ -293,4 +195,5 @@
             usedNames.add(primitiveName);
         }
     }
+
 }