changeset 18753:f6b8787dc113

Truffle-DSL: replace complex factory system with a much simpler version
author Christian Humer <christian.humer@gmail.com>
date Mon, 29 Dec 2014 23:38:21 +0100
parents 1acaa69ff61b
children 59bf50cc5a32
files graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AnnotationProcessor.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractClassElementFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractCodeElementFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractCompilationUnitFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/CodeTypeElementFactory.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/NodeBaseFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeFactoryFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/PolymorphicNodeFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/SpecializedNodeFactory.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/java/model/CodeTypeElement.java
diffstat 13 files changed, 549 insertions(+), 662 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AnnotationProcessor.java	Mon Dec 29 23:38:16 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AnnotationProcessor.java	Mon Dec 29 23:38:21 2014 +0100
@@ -40,11 +40,11 @@
 class AnnotationProcessor<M extends Template> {
 
     private final AbstractParser<M> parser;
-    private final AbstractCompilationUnitFactory<M> factory;
+    private final CodeTypeElementFactory<M> factory;
 
     private final Set<String> processedElements = new HashSet<>();
 
-    public AnnotationProcessor(AbstractParser<M> parser, AbstractCompilationUnitFactory<M> factory) {
+    public AnnotationProcessor(AbstractParser<M> parser, CodeTypeElementFactory<M> factory) {
         this.parser = parser;
         this.factory = factory;
     }
@@ -77,7 +77,10 @@
             context.registerTemplate(type, model);
 
             if (model != null) {
-                CodeCompilationUnit unit = factory.process(null, model);
+                CodeTypeElement unit = factory.create(ProcessorContext.getInstance(), model);
+                if (unit == null) {
+                    return;
+                }
                 unit.setGeneratorAnnotationMirror(model.getTemplateTypeAnnotation());
                 unit.setGeneratorElement(model.getTemplateType());
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractClassElementFactory.java	Mon Dec 29 23:38:16 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.generator;
-
-import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
-import static javax.lang.model.element.Modifier.*;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.java.model.*;
-import com.oracle.truffle.dsl.processor.model.*;
-
-abstract class AbstractClassElementFactory<M> extends AbstractCodeElementFactory<M> {
-
-    @Override
-    protected abstract CodeTypeElement create(M m);
-
-    @Override
-    public CodeTypeElement getElement() {
-        return (CodeTypeElement) super.getElement();
-    }
-
-    protected CodeExecutableElement createConstructorUsingFields(Set<Modifier> modifiers, CodeTypeElement clazz) {
-        CodeExecutableElement method = new CodeExecutableElement(modifiers, null, clazz.getSimpleName().toString());
-        CodeTreeBuilder builder = method.createBuilder();
-        TypeElement superClass = fromTypeMirror(clazz.getSuperclass());
-        ExecutableElement constructor = findConstructor(superClass);
-        if (constructor != null && constructor.getParameters().size() > 0) {
-            builder.startStatement();
-            builder.startSuperCall();
-            for (VariableElement parameter : constructor.getParameters()) {
-                method.addParameter(new CodeVariableElement(parameter.asType(), parameter.getSimpleName().toString()));
-                builder.string(parameter.getSimpleName().toString());
-            }
-            builder.end(); // super
-            builder.end(); // statement
-        }
-
-        for (VariableElement field : clazz.getFields()) {
-            if (field.getModifiers().contains(STATIC)) {
-                continue;
-            }
-            String fieldName = field.getSimpleName().toString();
-            method.addParameter(new CodeVariableElement(field.asType(), fieldName));
-            builder.startStatement();
-            builder.string("this.");
-            builder.string(fieldName);
-            builder.string(" = ");
-            if (isAssignable(field.asType(), getContext().getTruffleTypes().getNode())) {
-                builder.string("adoptChild(").string(fieldName).string(")");
-            } else {
-                builder.string(fieldName);
-            }
-            builder.end(); // statement
-        }
-
-        return method;
-    }
-
-    private static ExecutableElement findConstructor(TypeElement clazz) {
-        List<ExecutableElement> constructors = ElementFilter.constructorsIn(clazz.getEnclosedElements());
-        if (constructors.isEmpty()) {
-            return null;
-        } else {
-            return constructors.get(0);
-        }
-    }
-
-    protected CodeExecutableElement createSuperConstructor(TypeElement type, ExecutableElement element) {
-        if (element.getModifiers().contains(Modifier.PRIVATE)) {
-            return null;
-        }
-        CodeExecutableElement executable = CodeExecutableElement.clone(getContext().getEnvironment(), element);
-        executable.setReturnType(null);
-        executable.setSimpleName(CodeNames.of(type.getSimpleName().toString()));
-        CodeTreeBuilder b = executable.createBuilder();
-        b.startStatement();
-        b.startSuperCall();
-        for (VariableElement v : element.getParameters()) {
-            b.string(v.getSimpleName().toString());
-        }
-        b.end();
-        b.end();
-
-        return executable;
-    }
-
-    protected CodeTypeElement createClass(Template model, Set<Modifier> modifiers, String simpleName, TypeMirror superType, boolean enumType) {
-        TypeElement templateType = model.getTemplateType();
-
-        PackageElement pack = getContext().getEnvironment().getElementUtils().getPackageOf(templateType);
-        CodeTypeElement clazz = new CodeTypeElement(modifiers, enumType ? ElementKind.ENUM : ElementKind.CLASS, pack, simpleName);
-        TypeMirror resolvedSuperType = superType;
-        if (resolvedSuperType == null) {
-            resolvedSuperType = getContext().getType(Object.class);
-        }
-        clazz.setSuperClass(resolvedSuperType);
-
-        CodeAnnotationMirror generatedByAnnotation = new CodeAnnotationMirror((DeclaredType) getContext().getType(GeneratedBy.class));
-        generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("value"), new CodeAnnotationValue(templateType.asType()));
-        if (model.getTemplateMethodName() != null) {
-            generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("methodName"), new CodeAnnotationValue(model.getTemplateMethodName()));
-        }
-
-        clazz.addAnnotationMirror(generatedByAnnotation);
-        return clazz;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractCodeElementFactory.java	Mon Dec 29 23:38:16 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.generator;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.model.*;
-
-abstract class AbstractCodeElementFactory<M> {
-
-    protected final ProcessorContext context;
-    private M model;
-
-    private CodeElement<? super Element> element;
-
-    public AbstractCodeElementFactory() {
-        this.context = ProcessorContext.getInstance();
-    }
-
-    protected abstract CodeElement<?> create(M m);
-
-    @SuppressWarnings("unused")
-    protected void createChildren(M m) {
-    }
-
-    @SuppressWarnings({"unchecked", "rawtypes"})
-    public CodeElement<?> process(CodeElement parent, M m) {
-        model = m;
-        element = (CodeElement<? super Element>) create(model);
-        if (parent != null) {
-            parent.add(element);
-        }
-        if (element != null) {
-            createChildren(model);
-        }
-        return element;
-    }
-
-    @SuppressWarnings("rawtypes")
-    public CodeElement getElement() {
-        return element;
-    }
-
-    protected <MO, K extends Element> void add(AbstractCodeElementFactory<MO> factory, MO m) {
-        factory.process(this.element, m);
-    }
-
-    public ProcessorContext getContext() {
-        return context;
-    }
-
-    public M getModel() {
-        return model;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/AbstractCompilationUnitFactory.java	Mon Dec 29 23:38:16 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.generator;
-
-import com.oracle.truffle.dsl.processor.java.model.*;
-
-public abstract class AbstractCompilationUnitFactory<M> extends AbstractCodeElementFactory<M> {
-
-    @Override
-    public final CodeCompilationUnit create(M m) {
-        return new CodeCompilationUnit();
-    }
-
-    @SuppressWarnings("rawtypes")
-    @Override
-    public CodeCompilationUnit process(CodeElement parent, M m) {
-        return (CodeCompilationUnit) super.process(parent, m);
-    }
-
-    @Override
-    protected abstract void createChildren(M m);
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/CodeTypeElementFactory.java	Mon Dec 29 23:38:21 2014 +0100
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, 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.generator;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public abstract class CodeTypeElementFactory<M> {
+
+    public abstract CodeTypeElement create(ProcessorContext context, M m);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java	Mon Dec 29 23:38:21 2014 +0100
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2014, 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.generator;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+import static javax.lang.model.element.Modifier.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class GeneratorUtils {
+
+    public static CodeExecutableElement createConstructorUsingFields(ProcessorContext context, Set<Modifier> modifiers, CodeTypeElement clazz) {
+        CodeExecutableElement method = new CodeExecutableElement(modifiers, null, clazz.getSimpleName().toString());
+        CodeTreeBuilder builder = method.createBuilder();
+        TypeElement superClass = fromTypeMirror(clazz.getSuperclass());
+        ExecutableElement constructor = findConstructor(superClass);
+        if (constructor != null && constructor.getParameters().size() > 0) {
+            builder.startStatement();
+            builder.startSuperCall();
+            for (VariableElement parameter : constructor.getParameters()) {
+                method.addParameter(new CodeVariableElement(parameter.asType(), parameter.getSimpleName().toString()));
+                builder.string(parameter.getSimpleName().toString());
+            }
+            builder.end(); // super
+            builder.end(); // statement
+        }
+
+        for (VariableElement field : clazz.getFields()) {
+            if (field.getModifiers().contains(STATIC)) {
+                continue;
+            }
+            String fieldName = field.getSimpleName().toString();
+            method.addParameter(new CodeVariableElement(field.asType(), fieldName));
+            builder.startStatement();
+            builder.string("this.");
+            builder.string(fieldName);
+            builder.string(" = ");
+            if (isAssignable(field.asType(), context.getTruffleTypes().getNode())) {
+                builder.string("adoptChild(").string(fieldName).string(")");
+            } else {
+                builder.string(fieldName);
+            }
+            builder.end(); // statement
+        }
+
+        return method;
+    }
+
+    private static ExecutableElement findConstructor(TypeElement clazz) {
+        List<ExecutableElement> constructors = ElementFilter.constructorsIn(clazz.getEnclosedElements());
+        if (constructors.isEmpty()) {
+            return null;
+        } else {
+            return constructors.get(0);
+        }
+    }
+
+    public static CodeExecutableElement createSuperConstructor(ProcessorContext context, TypeElement type, ExecutableElement element) {
+        if (element.getModifiers().contains(Modifier.PRIVATE)) {
+            return null;
+        }
+        CodeExecutableElement executable = CodeExecutableElement.clone(context.getEnvironment(), element);
+        executable.setReturnType(null);
+        executable.setSimpleName(CodeNames.of(type.getSimpleName().toString()));
+        CodeTreeBuilder b = executable.createBuilder();
+        b.startStatement();
+        b.startSuperCall();
+        for (VariableElement v : element.getParameters()) {
+            b.string(v.getSimpleName().toString());
+        }
+        b.end();
+        b.end();
+
+        return executable;
+    }
+
+    public static CodeTypeElement createClass(Template model, Set<Modifier> modifiers, String simpleName, TypeMirror superType, boolean enumType) {
+        TypeElement templateType = model.getTemplateType();
+
+        ProcessorContext context = ProcessorContext.getInstance();
+
+        PackageElement pack = context.getEnvironment().getElementUtils().getPackageOf(templateType);
+        CodeTypeElement clazz = new CodeTypeElement(modifiers, enumType ? ElementKind.ENUM : ElementKind.CLASS, pack, simpleName);
+        TypeMirror resolvedSuperType = superType;
+        if (resolvedSuperType == null) {
+            resolvedSuperType = context.getType(Object.class);
+        }
+        clazz.setSuperClass(resolvedSuperType);
+
+        CodeAnnotationMirror generatedByAnnotation = new CodeAnnotationMirror((DeclaredType) context.getType(GeneratedBy.class));
+        generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("value"), new CodeAnnotationValue(templateType.asType()));
+        if (model.getTemplateMethodName() != null) {
+            generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("methodName"), new CodeAnnotationValue(model.getTemplateMethodName()));
+        }
+
+        clazz.addAnnotationMirror(generatedByAnnotation);
+        return clazz;
+    }
+
+}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeBaseFactory.java	Mon Dec 29 23:38:16 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeBaseFactory.java	Mon Dec 29 23:38:21 2014 +0100
@@ -42,7 +42,7 @@
 import com.oracle.truffle.dsl.processor.parser.*;
 import com.oracle.truffle.dsl.processor.parser.SpecializationGroup.TypeGuard;
 
-class NodeBaseFactory extends AbstractClassElementFactory<SpecializationData> {
+class NodeBaseFactory {
 
     private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode";
 
@@ -60,6 +60,83 @@
 
     static final String METADATA_FIELD_NAME = "METADATA";
 
+    protected final ProcessorContext context;
+    protected final NodeData node;
+    protected final SpecializationData specialization;
+
+    public NodeBaseFactory(ProcessorContext context, NodeData node, SpecializationData specialization) {
+        this.context = context;
+        this.node = node;
+        this.specialization = specialization;
+    }
+
+    public CodeTypeElement create() {
+        CodeTypeElement clazz = GeneratorUtils.createClass(node, modifiers(PRIVATE, ABSTRACT, STATIC), baseClassName(node), node.getNodeType(), false);
+        clazz.getImplements().add(context.getTruffleTypes().getDslNode());
+
+        for (NodeChildData child : node.getChildren()) {
+            clazz.add(createChildField(child));
+
+            if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) {
+                ExecutableElement getter = (ExecutableElement) child.getAccessElement();
+                CodeExecutableElement method = CodeExecutableElement.clone(context.getEnvironment(), getter);
+                method.getModifiers().remove(Modifier.ABSTRACT);
+                CodeTreeBuilder builder = method.createBuilder();
+                builder.startReturn().string("this.").string(child.getName()).end();
+                clazz.add(method);
+            }
+        }
+
+        for (NodeFieldData field : node.getFields()) {
+            if (!field.isGenerated()) {
+                continue;
+            }
+
+            clazz.add(new CodeVariableElement(modifiers(PROTECTED, FINAL), field.getType(), field.getName()));
+            if (field.getGetter() != null && field.getGetter().getModifiers().contains(Modifier.ABSTRACT)) {
+                CodeExecutableElement method = CodeExecutableElement.clone(context.getEnvironment(), field.getGetter());
+                method.getModifiers().remove(Modifier.ABSTRACT);
+                method.createBuilder().startReturn().string("this.").string(field.getName()).end();
+                clazz.add(method);
+            }
+        }
+
+        for (String assumption : node.getAssumptions()) {
+            clazz.add(createAssumptionField(assumption));
+        }
+
+        createConstructors(clazz);
+
+        SpecializationGroup rootGroup = createSpecializationGroups(node);
+
+        if (node.needsRewrites(context)) {
+            if (node.isPolymorphic(context)) {
+
+                CodeVariableElement var = new CodeVariableElement(modifiers(PROTECTED), clazz.asType(), "next0");
+                var.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getTruffleTypes().getChildAnnotation()));
+                clazz.add(var);
+
+                CodeExecutableElement genericCachedExecute = createCachedExecute(node.getPolymorphicSpecialization());
+                clazz.add(genericCachedExecute);
+
+            }
+
+            for (CodeExecutableElement method : createImplicitChildrenAccessors()) {
+                clazz.add(method);
+            }
+            clazz.add(createInfoMessage());
+            clazz.add(createMonomorphicRewrite());
+            clazz.add(createCreateSpecializationMethod(rootGroup));
+        }
+
+        clazz.add(createAdoptChildren0());
+        clazz.add(createGetMetadata0(true));
+        clazz.add(createUpdateTypes0());
+        clazz.add(createGetNext());
+
+        return clazz;
+    }
+
     public static List<ExecutableElement> findUserConstructors(TypeMirror nodeType) {
         List<ExecutableElement> constructors = new ArrayList<>();
         for (ExecutableElement constructor : ElementFilter.constructorsIn(ElementUtils.fromTypeMirror(nodeType).getEnclosedElements())) {
@@ -102,85 +179,13 @@
         return false;
     }
 
-    @Override
-    protected CodeTypeElement create(SpecializationData specialization) {
-        NodeData node = specialization.getNode();
-        CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, ABSTRACT, STATIC), baseClassName(node), node.getNodeType(), false);
-        clazz.getImplements().add(context.getTruffleTypes().getDslNode());
-
-        for (NodeChildData child : node.getChildren()) {
-            clazz.add(createChildField(child));
-
-            if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) {
-                ExecutableElement getter = (ExecutableElement) child.getAccessElement();
-                CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), getter);
-                method.getModifiers().remove(Modifier.ABSTRACT);
-                CodeTreeBuilder builder = method.createBuilder();
-                builder.startReturn().string("this.").string(child.getName()).end();
-                clazz.add(method);
-            }
-        }
-
-        for (NodeFieldData field : node.getFields()) {
-            if (!field.isGenerated()) {
-                continue;
-            }
-
-            clazz.add(new CodeVariableElement(modifiers(PROTECTED, FINAL), field.getType(), field.getName()));
-            if (field.getGetter() != null && field.getGetter().getModifiers().contains(Modifier.ABSTRACT)) {
-                CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), field.getGetter());
-                method.getModifiers().remove(Modifier.ABSTRACT);
-                method.createBuilder().startReturn().string("this.").string(field.getName()).end();
-                clazz.add(method);
-            }
-        }
-
-        for (String assumption : node.getAssumptions()) {
-            clazz.add(createAssumptionField(assumption));
-        }
-
-        createConstructors(node, clazz);
-
-        return clazz;
-    }
-
-    @Override
-    protected void createChildren(SpecializationData specialization) {
-        NodeData node = specialization.getNode();
-        CodeTypeElement clazz = getElement();
-
-        SpecializationGroup rootGroup = createSpecializationGroups(node);
-
-        if (node.needsRewrites(context)) {
-            if (node.isPolymorphic(context)) {
-
-                CodeVariableElement var = new CodeVariableElement(modifiers(PROTECTED), clazz.asType(), "next0");
-                var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation()));
-                clazz.add(var);
-
-                CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getPolymorphicSpecialization());
-                clazz.add(genericCachedExecute);
-
-            }
-
-            for (CodeExecutableElement method : createImplicitChildrenAccessors()) {
-                clazz.add(method);
-            }
-            clazz.add(createInfoMessage(node));
-            clazz.add(createMonomorphicRewrite());
-            clazz.add(createCreateSpecializationMethod(node, rootGroup));
-        }
-
-        clazz.add(createAdoptChildren0());
-        clazz.add(createGetMetadata0(true));
-        clazz.add(createUpdateTypes0());
-        clazz.add(createGetNext());
+    public SpecializationData getSpecialization() {
+        return specialization;
     }
 
     private Element createGetNext() {
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), context.getType(Node.class), "getNext0");
         CodeTreeBuilder builder = method.createBuilder();
-        NodeData node = getModel().getNode();
 
         if (node.isPolymorphic(context)) {
             builder.startReturn().string("next0").end();
@@ -196,11 +201,11 @@
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(void.class), "updateTypes0");
         method.getParameters().add(new CodeVariableElement(classArray, "types"));
 
-        if (getModel().isPolymorphic()) {
+        if (getSpecialization().isPolymorphic()) {
             CodeTreeBuilder builder = method.createBuilder();
 
             int index = 0;
-            for (NodeExecutionData execution : getModel().getNode().getChildExecutions()) {
+            for (NodeExecutionData execution : getSpecialization().getNode().getChildExecutions()) {
                 String fieldName = polymorphicTypeName(execution);
 
                 builder.startStatement();
@@ -227,7 +232,6 @@
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), context.getType(void.class), "adoptChildren0");
         method.getParameters().add(new CodeVariableElement(context.getTruffleTypes().getNode(), "other"));
         method.getParameters().add(new CodeVariableElement(context.getTruffleTypes().getNode(), "newNext"));
-        NodeData node = getModel().getNode();
         CodeTreeBuilder builder = method.createBuilder();
         List<NodeExecutionData> executions = node.getChildExecutions();
 
@@ -253,11 +257,11 @@
             builder.end();
         }
 
-        if (getModel().getNode().isPolymorphic(context)) {
+        if (getSpecialization().getNode().isPolymorphic(context)) {
             builder.startIf().string("newNext == null").end().startBlock();
             builder.statement("this.next0 = null");
             builder.end().startElseBlock();
-            builder.statement("this.next0 = (" + baseClassName(getModel().getNode()) + ") newNext");
+            builder.statement("this.next0 = (" + baseClassName(getSpecialization().getNode()) + ") newNext");
             builder.end();
         }
 
@@ -265,7 +269,6 @@
     }
 
     private List<CodeExecutableElement> createImplicitChildrenAccessors() {
-        NodeData node = getModel().getNode();
         List<Set<TypeData>> prototype = Collections.nCopies(node.getGenericSpecialization().getParameters().size(), null);
         List<Set<TypeData>> expectTypes = new ArrayList<>(prototype);
 
@@ -317,15 +320,15 @@
 
     private CodeTree truffleBooleanOption(CodeTreeBuilder parent, String name) {
         CodeTreeBuilder builder = parent.create();
-        builder.staticReference(getContext().getTruffleTypes().getTruffleOptions(), name);
+        builder.staticReference(context.getTruffleTypes().getTruffleOptions(), name);
         return builder.getRoot();
     }
 
-    private final void addInternalValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame, boolean disableFrame, boolean evaluated) {
-        if (forceFrame && !disableFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
-            method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue"));
+    private final void addInternalValueParameters(CodeExecutableElement executableMethod, TemplateMethod method, boolean forceFrame, boolean disableFrame, boolean evaluated) {
+        if (forceFrame && !disableFrame && method.getSpecification().findParameterSpec("frame") != null) {
+            executableMethod.addParameter(new CodeVariableElement(context.getTruffleTypes().getFrame(), "frameValue"));
         }
-        for (Parameter parameter : specialization.getParameters()) {
+        for (Parameter parameter : method.getParameters()) {
             ParameterSpec spec = parameter.getSpecification();
             if ((disableFrame || forceFrame) && spec.getName().equals("frame")) {
                 continue;
@@ -339,13 +342,13 @@
                 name = valueNameEvaluated(parameter);
             }
 
-            method.addParameter(new CodeVariableElement(parameter.getType(), name));
+            executableMethod.addParameter(new CodeVariableElement(parameter.getType(), name));
         }
     }
 
-    private Element createInfoMessage(NodeData node) {
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), getContext().getType(String.class), CREATE_INFO);
-        method.addParameter(new CodeVariableElement(getContext().getType(String.class), "message"));
+    private Element createInfoMessage() {
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, STATIC), context.getType(String.class), CREATE_INFO);
+        method.addParameter(new CodeVariableElement(context.getType(String.class), "message"));
         addInternalValueParameters(method, node.getGenericSpecialization(), false, false, false);
 
         CodeTreeBuilder builder = method.createBuilder();
@@ -399,23 +402,23 @@
         return method;
     }
 
-    private CodeExecutableElement createCachedExecute(NodeData node, SpecializationData polymorph) {
+    private CodeExecutableElement createCachedExecute(SpecializationData polymorph) {
         CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED, ABSTRACT), polymorph.getReturnType().getType(), EXECUTE_CHAINED);
         addInternalValueParameters(cachedExecute, polymorph, true, false, false);
 
         ExecutableTypeData sourceExecutableType = node.findExecutableType(polymorph.getReturnType().getTypeSystemType(), 0);
-        boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(getContext());
+        boolean sourceThrowsUnexpected = sourceExecutableType != null && sourceExecutableType.hasUnexpectedValue(context);
         if (sourceThrowsUnexpected && sourceExecutableType.getType().equals(node.getGenericSpecialization().getReturnType().getTypeSystemType())) {
             sourceThrowsUnexpected = false;
         }
         if (sourceThrowsUnexpected) {
-            cachedExecute.getThrownTypes().add(getContext().getType(UnexpectedResultException.class));
+            cachedExecute.getThrownTypes().add(context.getType(UnexpectedResultException.class));
         }
         return cachedExecute;
 
     }
 
-    private void createConstructors(NodeData node, CodeTypeElement clazz) {
+    private void createConstructors(CodeTypeElement clazz) {
         List<ExecutableElement> constructors = findUserConstructors(node.getNodeType());
         ExecutableElement sourceSectionConstructor = null;
         if (constructors.isEmpty()) {
@@ -428,7 +431,7 @@
                 }
             }
         }
-        if (node.needsRewrites(getContext())) {
+        if (node.needsRewrites(context)) {
             ExecutableElement copyConstructor = findCopyConstructor(node.getNodeType());
             clazz.add(createCopyConstructor(clazz, copyConstructor, sourceSectionConstructor));
         }
@@ -438,8 +441,6 @@
         CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString());
         CodeTreeBuilder builder = method.createBuilder();
 
-        NodeData node = getModel().getNode();
-
         if (superConstructor != null) {
             for (VariableElement param : superConstructor.getParameters()) {
                 method.getParameters().add(CodeVariableElement.clone(param));
@@ -478,7 +479,7 @@
     }
 
     private CodeTree createStaticCast(CodeTreeBuilder parent, NodeChildData child, String fieldName) {
-        NodeData parentNode = getModel().getNode();
+        NodeData parentNode = getSpecialization().getNode();
         if (child != null) {
             CreateCastData createCast = parentNode.findCast(child.getName());
             if (createCast != null) {
@@ -505,7 +506,7 @@
             }
             final String varName = var.getSimpleName().toString();
             final TypeMirror varType = var.asType();
-            if (ElementUtils.isAssignable(varType, getContext().getTruffleTypes().getNodeArray())) {
+            if (ElementUtils.isAssignable(varType, context.getTruffleTypes().getNodeArray())) {
                 CodeTree size = builder.create().string("copy.", varName, ".length").getRoot();
                 builder.startStatement().string("this.").string(varName).string(" = ").startNewArray((ArrayType) varType, size).end().end();
             } else {
@@ -517,7 +518,7 @@
     }
 
     private CodeVariableElement createAssumptionField(String assumption) {
-        CodeVariableElement var = new CodeVariableElement(getContext().getTruffleTypes().getAssumption(), assumption);
+        CodeVariableElement var = new CodeVariableElement(context.getTruffleTypes().getAssumption(), assumption);
         var.getModifiers().add(Modifier.FINAL);
         return var;
     }
@@ -530,9 +531,9 @@
         DeclaredType annotationType;
         if (child.getCardinality() == Cardinality.MANY) {
             var.getModifiers().add(Modifier.FINAL);
-            annotationType = getContext().getTruffleTypes().getChildrenAnnotation();
+            annotationType = context.getTruffleTypes().getChildrenAnnotation();
         } else {
-            annotationType = getContext().getTruffleTypes().getChildAnnotation();
+            annotationType = context.getTruffleTypes().getChildAnnotation();
         }
 
         var.getAnnotationMirrors().add(new CodeAnnotationMirror(annotationType));
@@ -553,13 +554,12 @@
     }
 
     protected final CodeExecutableElement createExecuteUninitialized() {
-        NodeData node = getModel().getNode();
         SpecializationData generic = node.getGenericSpecialization();
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), generic.getReturnType().getType(), EXECUTE_UNINITIALIZED);
         addInternalValueParameters(method, generic, true, false, false);
         CodeTreeBuilder builder = method.createBuilder();
 
-        boolean needsFrame = node.isFrameUsedByAnyGuard(getContext());
+        boolean needsFrame = node.isFrameUsedByAnyGuard(context);
         CodeTreeBuilder createSpecializationCall = builder.create();
         createSpecializationCall.startCall(SPECIALIZE);
         addInternalValueParameterNames(createSpecializationCall, generic, generic, null, needsFrame, !needsFrame, null);
@@ -602,18 +602,16 @@
     }
 
     private CodeExecutableElement createMonomorphicRewrite() {
-        NodeData node = getModel().getNode();
-
         SpecializationData generic = node.getGenericSpecialization();
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), generic.getReturnType().getType(), REWRITE);
         addInternalValueParameters(method, generic, true, false, false);
-        method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason"));
+        method.addParameter(new CodeVariableElement(context.getType(String.class), "reason"));
 
-        boolean needsFrame = node.isFrameUsedByAnyGuard(getContext());
+        boolean needsFrame = node.isFrameUsedByAnyGuard(context);
         CodeTreeBuilder builder = method.createBuilder();
 
         builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerAsserts(), "neverPartOfCompilation").end().end();
-        String baseClassName = baseClassName(getModel().getNode());
+        String baseClassName = baseClassName(getSpecialization().getNode());
         CodeTreeBuilder createSpecializationCall = builder.create();
         createSpecializationCall.startCall(SPECIALIZE);
         addInternalValueParameterNames(createSpecializationCall, generic, generic, null, needsFrame, !needsFrame, null);
@@ -631,13 +629,13 @@
         builder.end();
 
         builder.startStatement();
-        builder.type(getContext().getType(String.class)).string(" message = ").tree(createInfoCall(builder, generic, "reason"));
+        builder.type(context.getType(String.class)).string(" message = ").tree(createInfoCall(builder, generic, "reason"));
         builder.end();
 
         builder.declaration(baseClassName, "returnNode",
                         builder.create().startStaticCall(context.getTruffleTypes().getDslShare(), DSLSHARE_REWRITE).string("this").string("newNode").string("message").end().getRoot());
         builder.startIf().string("returnNode == null").end().startBlock();
-        builder.tree(createRewritePolymorphic(builder, node, "this"));
+        builder.tree(createRewritePolymorphic(builder, "this"));
         builder.end();
 
         builder.startReturn();
@@ -649,7 +647,7 @@
         return method;
     }
 
-    private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node, String currentNode) {
+    private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, String currentNode) {
         String polyClassName = nodePolymorphicClassName(node);
         CodeTreeBuilder builder = parent.create();
 
@@ -667,14 +665,14 @@
         return builder.getRoot();
     }
 
-    private CodeExecutableElement createCreateSpecializationMethod(NodeData node, SpecializationGroup group) {
+    private CodeExecutableElement createCreateSpecializationMethod(SpecializationGroup group) {
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), new GeneratedTypeMirror(ElementUtils.getPackageName(node.getTemplateType()), baseClassName(node)),
                         SPECIALIZE);
 
-        final boolean needsFrame = node.isFrameUsedByAnyGuard(getContext());
+        final boolean needsFrame = node.isFrameUsedByAnyGuard(context);
 
         if (!needsFrame) {
-            method.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getTruffleBoundary()));
+            method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getTruffleTypes().getTruffleBoundary()));
         }
 
         addInternalValueParameters(method, node.getGenericSpecialization(), needsFrame, !needsFrame, false);
@@ -707,7 +705,7 @@
                 builder.tree(createDeoptimize(builder));
             }
             builder.startReturn();
-            builder.cast(baseClassName(getModel().getNode()));
+            builder.cast(baseClassName(getSpecialization().getNode()));
             builder.startGroup().startCall(className, NodeFactoryFactory.FACTORY_METHOD_NAME).string("this");
             for (Parameter param : current.getSignatureParameters()) {
                 NodeChildData child = param.getSpecification().getExecution().getChild();
@@ -802,8 +800,6 @@
     }
 
     private int emitGuards(CodeTreeBuilder builder, SpecializationData source, SpecializationGroup group, boolean emitAssumptions, boolean typedCasts, boolean castForGuardsOnly) {
-        NodeData node = source.getNode();
-
         CodeTreeBuilder guardsBuilder = builder.create();
         CodeTreeBuilder castBuilder = builder.create();
         CodeTreeBuilder guardsCastBuilder = builder.create();
@@ -935,7 +931,7 @@
     }
 
     private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeExecutionData execution, Parameter source, TypeData targetType, boolean typedCasts) {
-        NodeData node = execution.getChild().getNodeData();
+        NodeData childNode = execution.getChild().getNodeData();
 
         CodeTreeBuilder builder = new CodeTreeBuilder(parent);
 
@@ -957,7 +953,7 @@
 
         String castMethodName;
         String castTypeName = null;
-        List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
+        List<TypeData> types = getSpecialization().getNode().getTypeSystem().lookupSourceTypes(targetType);
         if (types.size() > 1) {
             castMethodName = TypeSystemCodeGenerator.isImplicitTypeMethodName(targetType);
             if (typedCasts) {
@@ -967,7 +963,7 @@
             castMethodName = TypeSystemCodeGenerator.isTypeMethodName(targetType);
         }
 
-        startCallTypeSystemMethod(builder, node.getTypeSystem(), castMethodName);
+        startCallTypeSystemMethod(builder, childNode.getTypeSystem(), castMethodName);
         builder.string(valueName(source));
         if (castTypeName != null) {
             builder.string(castTypeName);
@@ -985,7 +981,7 @@
 
     // TODO merge redundancies with #createTypeGuard
     private CodeTree createCast(CodeTreeBuilder parent, NodeExecutionData execution, Parameter source, TypeData targetType, boolean typedCasts) {
-        NodeData node = execution.getChild().getNodeData();
+        NodeData childNode = execution.getChild().getNodeData();
         TypeData sourceType = source.getTypeSystemType();
 
         if (!sourceType.needsCastTo(targetType)) {
@@ -1001,7 +997,7 @@
 
         String castMethodName;
         String castTypeName = null;
-        List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
+        List<TypeData> types = getSpecialization().getNode().getTypeSystem().lookupSourceTypes(targetType);
         if (types.size() > 1) {
             castMethodName = TypeSystemCodeGenerator.asImplicitTypeMethodName(targetType);
             if (typedCasts) {
@@ -1017,7 +1013,7 @@
             args.add(CodeTreeBuilder.singleString(castTypeName));
         }
 
-        CodeTree cast = createCallTypeSystemMethod(parent, node, castMethodName, args.toArray(new CodeTree[0]));
+        CodeTree cast = createCallTypeSystemMethod(parent, childNode, castMethodName, args.toArray(new CodeTree[0]));
 
         CodeTreeBuilder builder = parent.create();
         builder.tree(createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, cast));
@@ -1034,11 +1030,11 @@
         }
 
         CodeTreeBuilder builder = parent.create();
-        List<TypeData> types = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
+        List<TypeData> types = getSpecialization().getNode().getTypeSystem().lookupSourceTypes(targetType);
         if (types.size() > 1) {
             CodeTree castType = createCallTypeSystemMethod(parent, execution.getChild().getNodeData(), TypeSystemCodeGenerator.getImplicitClass(targetType),
                             CodeTreeBuilder.singleString(valueName(source)));
-            builder.tree(createLazyAssignment(builder, implicitTypeName(source), getContext().getType(Class.class), condition, castType));
+            builder.tree(createLazyAssignment(builder, implicitTypeName(source), context.getType(Class.class), condition, castType));
         }
         return builder.getRoot();
     }
@@ -1057,7 +1053,7 @@
         CodeTreeBuilder builder = new CodeTreeBuilder(parent);
 
         if (current.getMethod() == null) {
-            emitEncounteredSynthetic(builder, getModel().getNode(), current);
+            emitEncounteredSynthetic(builder, getSpecialization().getNode(), current);
         } else {
             builder.startReturn().tree(createTemplateMethodCall(builder, null, source, current, null)).end();
         }
@@ -1076,7 +1072,7 @@
         for (SpecializationThrowsData exception : current.getExceptions()) {
             builder.end().startCatchBlock(exception.getJavaClass(), "rewriteEx");
             builder.tree(createDeoptimize(builder));
-            builder.tree(createCallRewriteMonomorphic(builder, false, current.getNode().getGenericSpecialization().getReturnType().getTypeSystemType(), current, null,
+            builder.tree(createCallRewriteMonomorphic(builder, false, current.getNode().getGenericSpecialization().getReturnType().getTypeSystemType(), null,
                             "Thrown " + ElementUtils.getSimpleName(exception.getJavaClass())));
         }
         builder.end();
@@ -1084,14 +1080,13 @@
         return builder.getRoot();
     }
 
-    protected CodeTree createCastingExecute(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData executable, ExecutableTypeData castExecutable) {
+    protected CodeTree createCastingExecute(CodeTreeBuilder parent, ExecutableTypeData executable, ExecutableTypeData castExecutable) {
         TypeData type = executable.getType();
         CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-        NodeData node = specialization.getNode();
 
         TypeData primaryType = castExecutable.getType();
 
-        boolean needsTry = castExecutable.hasUnexpectedValue(getContext());
+        boolean needsTry = castExecutable.hasUnexpectedValue(context);
         boolean returnVoid = type.isVoid();
 
         List<Parameter> executeParameters = new ArrayList<>();
@@ -1109,7 +1104,7 @@
         }
 
         builder.tree(createExecuteChildren(builder, executable, specialization, executeParameters, null));
-        boolean hasUnexpected = executable.hasUnexpectedValue(getContext());
+        boolean hasUnexpected = executable.hasUnexpectedValue(context);
 
         CodeTree primaryExecuteCall = createTemplateMethodCall(builder, null, executable, castExecutable, null, executeParameterNames);
         if (needsTry) {
@@ -1160,7 +1155,7 @@
         return createCastType(node.getTypeSystem(), sourceType, exepctedType, hasUnexpected, value);
     }
 
-    protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<Parameter> targetParameters,
+    protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData currentSpecialization, List<Parameter> targetParameters,
                     Parameter unexpectedParameter) {
         CodeTreeBuilder builder = parent.create();
         for (Parameter targetParameter : targetParameters) {
@@ -1169,8 +1164,9 @@
             }
             NodeExecutionData execution = targetParameter.getSpecification().getExecution();
             CodeTree executionExpressions = createExecuteChild(builder, execution, sourceExecutable, targetParameter, unexpectedParameter);
-            CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpressions, specialization, sourceExecutable, targetParameter, execution.isShortCircuit(), unexpectedParameter);
-            CodeTree shortCircuitTree = createShortCircuitTree(builder, unexpectedTree, specialization, targetParameter, unexpectedParameter);
+            CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpressions, currentSpecialization, sourceExecutable, targetParameter, execution.isShortCircuit(),
+                            unexpectedParameter);
+            CodeTree shortCircuitTree = createShortCircuitTree(builder, unexpectedTree, currentSpecialization, targetParameter, unexpectedParameter);
 
             if (shortCircuitTree == executionExpressions) {
                 if (containsNewLine(executionExpressions)) {
@@ -1188,15 +1184,14 @@
     }
 
     private ExecutableTypeData resolveExecutableType(NodeExecutionData execution, TypeData type) {
-        ExecutableTypeData targetExecutable = execution.getChild().findExecutableType(getContext(), type);
+        ExecutableTypeData targetExecutable = execution.getChild().findExecutableType(context, type);
         if (targetExecutable == null) {
-            targetExecutable = execution.getChild().findAnyGenericExecutableType(getContext());
+            targetExecutable = execution.getChild().findAnyGenericExecutableType(context);
         }
         return targetExecutable;
     }
 
     private CodeTree createExecuteChild(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, Parameter targetParameter, Parameter unexpectedParameter) {
-        SpecializationData specialization = getModel();
         if (specialization.isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null) {
             List<TypeData> possiblePolymorphicTypes = lookupPolymorphicTargetTypes(targetParameter);
             if (possiblePolymorphicTypes.size() > 1) {
@@ -1242,7 +1237,6 @@
     }
 
     private final List<TypeData> lookupPolymorphicTargetTypes(Parameter param) {
-        SpecializationData specialization = getModel();
         Set<TypeData> possiblePolymorphicTypes = new HashSet<>();
         for (SpecializationData otherSpecialization : specialization.getNode().getSpecializations()) {
             if (!otherSpecialization.isSpecialized()) {
@@ -1332,12 +1326,12 @@
         }
 
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, expectType != null ? STATIC : FINAL), param.getType(), childExecuteName);
-        method.getThrownTypes().add(getContext().getTruffleTypes().getUnexpectedValueException());
-        method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue"));
+        method.getThrownTypes().add(context.getTruffleTypes().getUnexpectedValueException());
+        method.addParameter(new CodeVariableElement(context.getTruffleTypes().getFrame(), "frameValue"));
         if (expectType != null) {
             method.addParameter(new CodeVariableElement(expectType.getPrimitiveType(), valueNameEvaluated(param)));
         }
-        method.addParameter(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param)));
+        method.addParameter(new CodeVariableElement(context.getType(Class.class), implicitTypeName(param)));
 
         CodeTreeBuilder builder = method.createBuilder();
         builder.declaration(param.getType(), valueName(param));
@@ -1349,7 +1343,6 @@
 
     private CodeTree createExecuteChildImplicitExpressions(CodeTreeBuilder parent, Parameter targetParameter, TypeData expectType) {
         CodeTreeBuilder builder = parent.create();
-        NodeData node = getModel().getNode();
         NodeExecutionData execution = targetParameter.getSpecification().getExecution();
         List<TypeData> sourceTypes = node.getTypeSystem().lookupSourceTypes(targetParameter.getTypeSystemType());
         boolean elseIf = false;
@@ -1364,7 +1357,7 @@
                 builder.startElseBlock();
             }
 
-            ExecutableTypeData implictExecutableTypeData = execution.getChild().findExecutableType(getContext(), sourceType);
+            ExecutableTypeData implictExecutableTypeData = execution.getChild().findExecutableType(context, sourceType);
             if (implictExecutableTypeData == null) {
                 /*
                  * For children with executeWith.size() > 0 an executable type may not exist so use
@@ -1448,7 +1441,7 @@
     private boolean hasUnexpected(Parameter sourceParameter, Parameter targetParameter, Parameter unexpectedParameter) {
         NodeExecutionData execution = targetParameter.getSpecification().getExecution();
 
-        if (getModel().isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null) {
+        if (getSpecialization().isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null) {
             // check for other polymorphic types
             List<TypeData> polymorphicTargetTypes = lookupPolymorphicTargetTypes(targetParameter);
             if (polymorphicTargetTypes.size() > 1) {
@@ -1467,7 +1460,7 @@
     }
 
     private boolean hasUnexpectedType(NodeExecutionData execution, Parameter sourceParameter, TypeData targetType) {
-        List<TypeData> implicitSourceTypes = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
+        List<TypeData> implicitSourceTypes = getSpecialization().getNode().getTypeSystem().lookupSourceTypes(targetType);
 
         for (TypeData implicitSourceType : implicitSourceTypes) {
             TypeData sourceType;
@@ -1475,13 +1468,13 @@
             if (sourceParameter != null) {
                 sourceType = sourceParameter.getTypeSystemType();
             } else {
-                if (targetExecutable.hasUnexpectedValue(getContext())) {
+                if (targetExecutable.hasUnexpectedValue(context)) {
                     return true;
                 }
                 sourceType = targetExecutable.getType();
             }
 
-            ImplicitCastData cast = getModel().getNode().getTypeSystem().lookupCast(implicitSourceType, targetType);
+            ImplicitCastData cast = getSpecialization().getNode().getTypeSystem().lookupCast(implicitSourceType, targetType);
             if (cast != null) {
                 if (cast.getSourceType().needsCastTo(targetType)) {
                     return true;
@@ -1495,8 +1488,8 @@
         return false;
     }
 
-    private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, ExecutableTypeData currentExecutable, Parameter param, boolean shortCircuit,
-                    Parameter unexpectedParameter) {
+    private CodeTree createCatchUnexpectedTree(CodeTreeBuilder parent, CodeTree body, SpecializationData currentSpecialization, ExecutableTypeData currentExecutable, Parameter param,
+                    boolean shortCircuit, Parameter unexpectedParameter) {
         CodeTreeBuilder builder = new CodeTreeBuilder(parent);
         Parameter sourceParameter = currentExecutable.findParameter(param.getLocalName());
         boolean unexpected = hasUnexpected(sourceParameter, param, unexpectedParameter);
@@ -1516,34 +1509,33 @@
         }
 
         builder.end().startCatchBlock(getUnexpectedValueException(), "ex");
-        SpecializationData generic = specialization.getNode().getGenericSpecialization();
+        SpecializationData generic = currentSpecialization.getNode().getGenericSpecialization();
         Parameter genericParameter = generic.findParameter(param.getLocalName());
 
         List<Parameter> genericParameters = generic.getParametersAfter(genericParameter);
         builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter));
-        if (specialization.isPolymorphic()) {
-            builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param));
+        if (currentSpecialization.isPolymorphic()) {
+            builder.tree(createReturnOptimizeTypes(builder, currentExecutable, currentSpecialization, param));
         } else {
-            builder.tree(createCallRewriteMonomorphic(builder, currentExecutable.hasUnexpectedValue(context), currentExecutable.getType(), specialization, param, "Expected " + param.getLocalName() +
-                            " instanceof " + ElementUtils.getSimpleName(param.getType())));
+            builder.tree(createCallRewriteMonomorphic(builder, currentExecutable.hasUnexpectedValue(context), currentExecutable.getType(), param, "Expected " + param.getLocalName() + " instanceof " +
+                            ElementUtils.getSimpleName(param.getType())));
         }
         builder.end(); // catch block
 
         return builder.getRoot();
     }
 
-    private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, Parameter param) {
-        NodeData node = specialization.getNode();
+    private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData currentSpecialization, Parameter param) {
         SpecializationData polymorphic = node.getPolymorphicSpecialization();
 
         CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-        builder.startStatement().string(polymorphicTypeName(param.getSpecification().getExecution())).string(" = ").typeLiteral(getContext().getType(Object.class)).end();
+        builder.startStatement().string(polymorphicTypeName(param.getSpecification().getExecution())).string(" = ").typeLiteral(context.getType(Object.class)).end();
 
         builder.startReturn();
 
         CodeTreeBuilder execute = new CodeTreeBuilder(builder);
         execute.startCall("next0", EXECUTE_CHAINED);
-        addInternalValueParameterNames(execute, specialization, polymorphic, param.getLocalName(), true, false, null);
+        addInternalValueParameterNames(execute, currentSpecialization, polymorphic, param.getLocalName(), true, false, null);
         execute.end();
 
         TypeData sourceType = polymorphic.getReturnType().getTypeSystemType();
@@ -1574,8 +1566,8 @@
                 if (index < targetExecution.getChild().getExecuteWith().size()) {
                     NodeChildData child = targetExecution.getChild().getExecuteWith().get(index);
 
-                    ParameterSpec spec = getModel().getSpecification().findParameterSpec(child.getName());
-                    List<Parameter> specializationParams = getModel().findParameters(spec);
+                    ParameterSpec spec = getSpecialization().getSpecification().findParameterSpec(child.getName());
+                    List<Parameter> specializationParams = getSpecialization().findParameters(spec);
 
                     if (specializationParams.isEmpty()) {
                         builder.defaultValue(parameter.getType());
@@ -1590,13 +1582,13 @@
 
                     if (unexpectedParameter != null && unexpectedParameter.getLocalName().equals(specializationParam.getLocalName())) {
                         localName = "ex.getResult()";
-                        sourceType = getModel().getNode().getTypeSystem().getGenericTypeData();
+                        sourceType = getSpecialization().getNode().getTypeSystem().getGenericTypeData();
                     }
 
                     CodeTree value = CodeTreeBuilder.singleString(localName);
 
                     if (sourceType.needsCastTo(targetType)) {
-                        value = createCallTypeSystemMethod(builder, getModel().getNode(), TypeSystemCodeGenerator.asTypeMethodName(targetType), value);
+                        value = createCallTypeSystemMethod(builder, getSpecialization().getNode(), TypeSystemCodeGenerator.asTypeMethodName(targetType), value);
                     }
                     builder.tree(value);
                 } else {
@@ -1611,15 +1603,15 @@
         return builder.getRoot();
     }
 
-    private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, Parameter parameter, Parameter exceptionParam) {
+    private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, SpecializationData currentSpecialization, Parameter parameter, Parameter exceptionParam) {
         NodeExecutionData execution = parameter.getSpecification().getExecution();
         if (execution == null || !execution.isShortCircuit()) {
             return body;
         }
 
         CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-        Parameter shortCircuitParam = specialization.getPreviousParam(parameter);
-        builder.tree(createShortCircuitValue(builder, specialization, execution, shortCircuitParam, exceptionParam));
+        Parameter shortCircuitParam = currentSpecialization.getPreviousParam(parameter);
+        builder.tree(createShortCircuitValue(builder, currentSpecialization, execution, shortCircuitParam, exceptionParam));
         builder.declaration(parameter.getType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getType()));
         builder.startIf().string(shortCircuitParam.getLocalName()).end();
         builder.startBlock();
@@ -1654,8 +1646,7 @@
         return builder.getRoot();
     }
 
-    protected CodeTree createCallRewriteMonomorphic(CodeTreeBuilder parent, boolean hasUnexpected, TypeData returnType, SpecializationData current, Parameter exceptionParam, String reason) {
-        NodeData node = current.getNode();
+    protected CodeTree createCallRewriteMonomorphic(CodeTreeBuilder parent, boolean hasUnexpected, TypeData returnType, Parameter exceptionParam, String reason) {
         SpecializationData generic = node.getGenericSpecialization();
         CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent);
         specializeCall.startCall(REWRITE);
@@ -2014,7 +2005,7 @@
     }
 
     private TypeMirror getUnexpectedValueException() {
-        return getContext().getTruffleTypes().getUnexpectedValueException();
+        return context.getTruffleTypes().getUnexpectedValueException();
     }
 
     interface CodeBlock<T> {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java	Mon Dec 29 23:38:16 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java	Mon Dec 29 23:38:21 2014 +0100
@@ -26,27 +26,69 @@
 
 import javax.lang.model.element.*;
 
+import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.java.model.*;
 import com.oracle.truffle.dsl.processor.model.*;
 
-public class NodeCodeGenerator extends AbstractCompilationUnitFactory<NodeData> {
+public class NodeCodeGenerator extends CodeTypeElementFactory<NodeData> {
 
     @Override
-    @SuppressWarnings("unchecked")
-    protected void createChildren(NodeData node) {
-        List<CodeTypeElement> casts = new ArrayList<>(getElement().getEnclosedElements());
-        getElement().getEnclosedElements().clear();
+    public CodeTypeElement create(ProcessorContext context, NodeData node) {
+        List<CodeTypeElement> enclosedTypes = new ArrayList<>();
+        for (NodeData childNode : node.getEnclosingNodes()) {
+            CodeTypeElement type = create(context, childNode);
+            if (type != null) {
+                enclosedTypes.add(type);
+            }
+        }
+        List<CodeTypeElement> generatedNodes = generateNodes(context, node);
 
-        Map<NodeData, List<TypeElement>> childTypes = new LinkedHashMap<>();
-        for (NodeData nodeChild : node.getEnclosingNodes()) {
-            NodeCodeGenerator generator = new NodeCodeGenerator();
-            childTypes.put(nodeChild, generator.process(null, nodeChild).getEnclosedElements());
-        }
+        if (!generatedNodes.isEmpty() || !enclosedTypes.isEmpty()) {
+            CodeTypeElement type = wrapGeneratedNodes(context, node, generatedNodes);
 
-        if (node.needsFactory() || node.getNodeDeclaringChildren().size() > 0) {
-            NodeFactoryFactory factory = new NodeFactoryFactory(childTypes);
-            add(factory, node);
-            factory.getElement().getEnclosedElements().addAll(casts);
+            for (CodeTypeElement enclosedFactory : enclosedTypes) {
+                Set<Modifier> modifiers = enclosedFactory.getModifiers();
+                if (!modifiers.contains(Modifier.STATIC)) {
+                    modifiers.add(Modifier.STATIC);
+                }
+                type.add(enclosedFactory);
+            }
+            return type;
+        } else {
+            return null;
         }
     }
+
+    private static CodeTypeElement wrapGeneratedNodes(ProcessorContext context, NodeData node, List<CodeTypeElement> generatedNodes) {
+        // wrap all types into a generated factory
+        CodeTypeElement factoryElement = new NodeFactoryFactory(context, node, generatedNodes.isEmpty() ? null : generatedNodes.get(0)).create();
+        for (CodeTypeElement generatedNode : generatedNodes) {
+            factoryElement.add(generatedNode);
+        }
+        return factoryElement;
+    }
+
+    private static List<CodeTypeElement> generateNodes(ProcessorContext context, NodeData node) {
+        if (!node.needsFactory()) {
+            return Collections.emptyList();
+        }
+        List<CodeTypeElement> nodeTypes = new ArrayList<>();
+        SpecializationData generic = node.getGenericSpecialization() == null ? node.getSpecializations().get(0) : node.getGenericSpecialization();
+        CodeTypeElement baseNode = new NodeBaseFactory(context, node, generic).create();
+        nodeTypes.add(baseNode);
+
+        for (SpecializationData specialization : node.getSpecializations()) {
+            if (!specialization.isReachable() || specialization.isGeneric()) {
+                continue;
+            }
+            if (specialization.isPolymorphic() && node.isPolymorphic(context)) {
+                nodeTypes.add(new PolymorphicNodeFactory(context, node, specialization, baseNode).create());
+                continue;
+            }
+
+            nodeTypes.add(new SpecializedNodeFactory(context, node, specialization, baseNode).create());
+        }
+        return nodeTypes;
+    }
+
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeFactoryFactory.java	Mon Dec 29 23:38:16 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeFactoryFactory.java	Mon Dec 29 23:38:21 2014 +0100
@@ -32,100 +32,59 @@
 import javax.lang.model.util.*;
 
 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.java.model.*;
 import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror;
 import com.oracle.truffle.dsl.processor.model.*;
 
-class NodeFactoryFactory extends AbstractClassElementFactory<NodeData> {
+class NodeFactoryFactory {
 
     static final String FACTORY_METHOD_NAME = "create0";
 
-    private final Map<NodeData, List<TypeElement>> childTypes;
-    private CodeTypeElement generatedNode;
+    private final ProcessorContext context;
+    private final NodeData node;
+    private final CodeTypeElement createdFactoryElement;
 
-    NodeFactoryFactory(Map<NodeData, List<TypeElement>> childElements) {
-        this.childTypes = childElements;
+    public NodeFactoryFactory(ProcessorContext context, NodeData node, CodeTypeElement createdClass) {
+        this.context = context;
+        this.node = node;
+        this.createdFactoryElement = createdClass;
     }
 
     private static String factoryClassName(NodeData node) {
         return node.getNodeId() + "Factory";
     }
 
-    @Override
-    protected CodeTypeElement create(NodeData node) {
+    public CodeTypeElement create() {
         Modifier visibility = ElementUtils.getVisibility(node.getTemplateType().getModifiers());
+        TypeMirror nodeFactory = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(context.getTruffleTypes().getNodeFactoryBase()), node.getNodeType());
 
-        CodeTypeElement clazz = createClass(node, modifiers(), factoryClassName(node), null, false);
+        CodeTypeElement clazz = GeneratorUtils.createClass(node, modifiers(), factoryClassName(node), null, false);
         if (visibility != null) {
             clazz.getModifiers().add(visibility);
         }
         clazz.getModifiers().add(Modifier.FINAL);
-        return clazz;
-    }
 
-    @Override
-    protected void createChildren(NodeData node) {
-        CodeTypeElement clazz = getElement();
-
-        Modifier createVisibility = ElementUtils.getVisibility(clazz.getModifiers());
-
-        if (node.needsFactory()) {
-            NodeBaseFactory factory = new NodeBaseFactory();
-            add(factory, node.getGenericSpecialization() == null ? node.getSpecializations().get(0) : node.getGenericSpecialization());
-            generatedNode = factory.getElement();
-
-            createFactoryMethods(node, clazz, createVisibility);
-
-            for (SpecializationData specialization : node.getSpecializations()) {
-                if (!specialization.isReachable() || specialization.isGeneric()) {
-                    continue;
-                }
-
-                if (specialization.isPolymorphic() && node.isPolymorphic(context)) {
-                    PolymorphicNodeFactory polymorphicFactory = new PolymorphicNodeFactory(generatedNode);
-                    add(polymorphicFactory, specialization);
-                    continue;
-                }
+        if (createdFactoryElement != null) {
+            createFactoryMethods(clazz, visibility);
 
-                add(new SpecializedNodeFactory(generatedNode), specialization);
-            }
-
-            TypeMirror nodeFactory = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(getContext().getTruffleTypes().getNodeFactoryBase()), node.getNodeType());
             clazz.setSuperClass(nodeFactory);
-            clazz.add(createNodeFactoryConstructor(node));
-            clazz.add(createCreateNodeMethod(node));
-            clazz.add(createGetInstanceMethod(node, createVisibility));
-            clazz.add(createInstanceConstant(node, clazz.asType()));
-        }
-
-        for (NodeData childNode : childTypes.keySet()) {
-            if (childNode.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) {
-                continue;
-            }
-
-            for (TypeElement type : childTypes.get(childNode)) {
-                Set<Modifier> typeModifiers = ((CodeTypeElement) type).getModifiers();
-                Modifier visibility = ElementUtils.getVisibility(type.getModifiers());
-                typeModifiers.clear();
-                if (visibility != null) {
-                    typeModifiers.add(visibility);
-                }
-
-                typeModifiers.add(Modifier.STATIC);
-                typeModifiers.add(Modifier.FINAL);
-                clazz.add(type);
-            }
+            clazz.add(createNodeFactoryConstructor());
+            clazz.add(createCreateNodeMethod());
+            clazz.add(createGetInstanceMethod(visibility));
+            clazz.add(createInstanceConstant(clazz.asType()));
         }
 
         List<NodeData> children = node.getNodeDeclaringChildren();
         if (node.getDeclaringNode() == null && children.size() > 0) {
-            clazz.add(createGetFactories(node));
+            clazz.add(createGetFactories());
         }
 
+        return clazz;
     }
 
-    private Element createNodeFactoryConstructor(NodeData node) {
+    private Element createNodeFactoryConstructor() {
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), null, factoryClassName(node));
         CodeTreeBuilder builder = method.createBuilder();
         builder.startStatement();
@@ -150,7 +109,7 @@
         // node signatures
         builder.startGroup();
         builder.startNewArray(new ArrayCodeTypeMirror(new ArrayCodeTypeMirror(context.getType(Class.class))), null);
-        List<ExecutableElement> constructors = NodeBaseFactory.findUserConstructors(generatedNode.asType());
+        List<ExecutableElement> constructors = NodeBaseFactory.findUserConstructors(createdFactoryElement.asType());
         for (ExecutableElement constructor : constructors) {
             builder.startGroup();
             if (constructor.getParameters().isEmpty()) {
@@ -171,14 +130,14 @@
         return method;
     }
 
-    private CodeExecutableElement createCreateNodeMethod(NodeData node) {
+    private CodeExecutableElement createCreateNodeMethod() {
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNode");
-        CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Object.class), "arguments");
+        CodeVariableElement arguments = new CodeVariableElement(context.getType(Object.class), "arguments");
         method.setVarArgs(true);
         method.addParameter(arguments);
 
         CodeTreeBuilder builder = method.createBuilder();
-        List<ExecutableElement> signatures = NodeBaseFactory.findUserConstructors(generatedNode.asType());
+        List<ExecutableElement> signatures = NodeBaseFactory.findUserConstructors(createdFactoryElement.asType());
         boolean ifStarted = false;
 
         for (ExecutableElement element : signatures) {
@@ -195,7 +154,7 @@
                     builder.string("(arguments[" + index + "] == null || ");
                 }
                 builder.string("arguments[" + index + "] instanceof ");
-                builder.type(ElementUtils.boxType(getContext(), param.asType()));
+                builder.type(ElementUtils.boxType(context, param.asType()));
                 if (!param.asType().getKind().isPrimitive()) {
                     builder.string(")");
                 }
@@ -221,15 +180,15 @@
         }
 
         builder.startElseBlock();
-        builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class));
+        builder.startThrow().startNew(context.getType(IllegalArgumentException.class));
         builder.doubleQuote("Invalid create signature.");
         builder.end().end();
         builder.end(); // else block
         return method;
     }
 
-    private ExecutableElement createGetInstanceMethod(NodeData node, Modifier visibility) {
-        TypeElement nodeFactoryType = ElementUtils.fromTypeMirror(getContext().getType(NodeFactory.class));
+    private ExecutableElement createGetInstanceMethod(Modifier visibility) {
+        TypeElement nodeFactoryType = ElementUtils.fromTypeMirror(context.getType(NodeFactory.class));
         TypeMirror returnType = ElementUtils.getDeclaredType(nodeFactoryType, node.getNodeType());
 
         CodeExecutableElement method = new CodeExecutableElement(modifiers(), returnType, "getInstance");
@@ -264,7 +223,7 @@
         }
     }
 
-    private static CodeVariableElement createInstanceConstant(NodeData node, TypeMirror factoryType) {
+    private CodeVariableElement createInstanceConstant(TypeMirror factoryType) {
         String varName = instanceVarName(node);
         CodeVariableElement var = new CodeVariableElement(modifiers(), factoryType, varName);
         var.getModifiers().add(Modifier.PRIVATE);
@@ -272,7 +231,7 @@
         return var;
     }
 
-    private ExecutableElement createGetFactories(NodeData node) {
+    private ExecutableElement createGetFactories() {
         List<NodeData> children = node.getNodeDeclaringChildren();
         if (node.needsFactory()) {
             children.add(node);
@@ -288,23 +247,23 @@
             }
             prev = child.getNodeType();
         }
-        TypeMirror commonNodeSuperType = ElementUtils.getCommonSuperType(getContext(), nodeTypesList.toArray(new TypeMirror[nodeTypesList.size()]));
+        TypeMirror commonNodeSuperType = ElementUtils.getCommonSuperType(context, nodeTypesList.toArray(new TypeMirror[nodeTypesList.size()]));
 
-        Types types = getContext().getEnvironment().getTypeUtils();
-        TypeMirror factoryType = getContext().getType(NodeFactory.class);
+        Types types = context.getEnvironment().getTypeUtils();
+        TypeMirror factoryType = context.getType(NodeFactory.class);
         TypeMirror baseType;
         if (allSame) {
             baseType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(factoryType), commonNodeSuperType);
         } else {
             baseType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null));
         }
-        TypeMirror listType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(getContext().getType(List.class)), baseType);
+        TypeMirror listType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(context.getType(List.class)), baseType);
 
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories");
 
         CodeTreeBuilder builder = method.createBuilder();
         builder.startReturn();
-        builder.startStaticCall(getContext().getType(Arrays.class), "asList");
+        builder.startStaticCall(context.getType(Arrays.class), "asList");
 
         for (NodeData child : children) {
             builder.startGroup();
@@ -326,15 +285,15 @@
         return method;
     }
 
-    private void createFactoryMethods(NodeData node, CodeTypeElement clazz, Modifier createVisibility) {
-        List<ExecutableElement> constructors = NodeBaseFactory.findUserConstructors(generatedNode.asType());
+    private void createFactoryMethods(CodeTypeElement clazz, Modifier createVisibility) {
+        List<ExecutableElement> constructors = NodeBaseFactory.findUserConstructors(createdFactoryElement.asType());
         for (ExecutableElement constructor : constructors) {
-            clazz.add(createCreateMethod(node, createVisibility, constructor));
+            clazz.add(createCreateMethod(createVisibility, constructor));
         }
     }
 
-    private CodeExecutableElement createCreateMethod(NodeData node, Modifier visibility, ExecutableElement constructor) {
-        CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), constructor);
+    private CodeExecutableElement createCreateMethod(Modifier visibility, ExecutableElement constructor) {
+        CodeExecutableElement method = CodeExecutableElement.clone(context.getEnvironment(), constructor);
         method.setSimpleName(CodeNames.of("create"));
         method.getModifiers().clear();
         if (visibility != null) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/PolymorphicNodeFactory.java	Mon Dec 29 23:38:16 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/PolymorphicNodeFactory.java	Mon Dec 29 23:38:21 2014 +0100
@@ -30,61 +30,56 @@
 import javax.lang.model.type.*;
 
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.java.model.*;
 import com.oracle.truffle.dsl.processor.model.*;
 
 class PolymorphicNodeFactory extends SpecializedNodeFactory {
 
-    public PolymorphicNodeFactory(CodeTypeElement nodeGen) {
-        super(nodeGen);
+    public PolymorphicNodeFactory(ProcessorContext context, NodeData node, SpecializationData specialization, CodeTypeElement nodeGen) {
+        super(context, node, specialization, nodeGen);
     }
 
     @Override
-    public CodeTypeElement create(SpecializationData polymorph) {
-        NodeData node = polymorph.getNode();
+    public CodeTypeElement create() {
         TypeMirror baseType = node.getNodeType();
         if (nodeGen != null) {
             baseType = nodeGen.asType();
         }
-        CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node), baseType, false);
+        CodeTypeElement clazz = GeneratorUtils.createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node), baseType, false);
 
-        clazz.getAnnotationMirrors().add(createNodeInfo(node, NodeCost.POLYMORPHIC));
+        clazz.getAnnotationMirrors().add(createNodeInfo(NodeCost.POLYMORPHIC));
 
-        for (Parameter polymorphParameter : polymorph.getSignatureParameters()) {
+        for (Parameter polymorphParameter : specialization.getSignatureParameters()) {
             if (!polymorphParameter.getTypeSystemType().isGeneric()) {
                 continue;
             }
             Set<TypeData> types = new HashSet<>();
-            for (SpecializationData specialization : node.getSpecializations()) {
-                if (!specialization.isSpecialized()) {
+            for (SpecializationData otherSpecialization : node.getSpecializations()) {
+                if (!otherSpecialization.isSpecialized()) {
                     continue;
                 }
-                Parameter parameter = specialization.findParameter(polymorphParameter.getLocalName());
+                Parameter parameter = otherSpecialization.findParameter(polymorphParameter.getLocalName());
                 assert parameter != null;
                 types.add(parameter.getTypeSystemType());
             }
 
         }
 
-        for (NodeExecutionData execution : getModel().getNode().getChildExecutions()) {
+        for (NodeExecutionData execution : node.getChildExecutions()) {
             String fieldName = polymorphicTypeName(execution);
-            CodeVariableElement var = new CodeVariableElement(modifiers(PRIVATE), getContext().getType(Class.class), fieldName);
-            var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getCompilationFinal()));
+            CodeVariableElement var = new CodeVariableElement(modifiers(PRIVATE), context.getType(Class.class), fieldName);
+            var.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getTruffleTypes().getCompilationFinal()));
             clazz.add(var);
         }
 
+        createConstructors(clazz);
+        createExecuteMethods(clazz);
+
+        clazz.add(createUpdateTypes0());
+        createCachedExecuteMethods(clazz);
+
         return clazz;
     }
 
-    @Override
-    protected void createChildren(SpecializationData specialization) {
-        CodeTypeElement clazz = getElement();
-
-        createConstructors(clazz);
-        createExecuteMethods(specialization);
-
-        clazz.add(createUpdateTypes0());
-        createCachedExecuteMethods(specialization);
-    }
-
 }
\ No newline at end of file
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/SpecializedNodeFactory.java	Mon Dec 29 23:38:16 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/SpecializedNodeFactory.java	Mon Dec 29 23:38:21 2014 +0100
@@ -32,6 +32,7 @@
 import javax.lang.model.util.*;
 
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.java.*;
 import com.oracle.truffle.dsl.processor.java.model.*;
 import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror;
@@ -42,18 +43,18 @@
 
     protected final CodeTypeElement nodeGen;
 
-    public SpecializedNodeFactory(CodeTypeElement nodeGen) {
+    public SpecializedNodeFactory(ProcessorContext context, NodeData node, SpecializationData specialization, CodeTypeElement nodeGen) {
+        super(context, node, specialization);
         this.nodeGen = nodeGen;
     }
 
     @Override
-    public CodeTypeElement create(SpecializationData specialization) {
-        NodeData node = specialization.getNode();
+    public CodeTypeElement create() {
         TypeMirror baseType = node.getNodeType();
         if (nodeGen != null) {
             baseType = nodeGen.asType();
         }
-        CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false);
+        CodeTypeElement clazz = GeneratorUtils.createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodeSpecializationClassName(specialization), baseType, false);
 
         if (specialization.isSpecialized() || specialization.isUninitialized()) {
             clazz.add(createGetMetadata0(false));
@@ -72,12 +73,38 @@
         } else {
             throw new AssertionError();
         }
-        clazz.getAnnotationMirrors().add(createNodeInfo(node, cost));
+        clazz.getAnnotationMirrors().add(createNodeInfo(cost));
 
         if (specialization.isUninitialized() && node.getGenericSpecialization().isReachable()) {
             clazz.add(createUninitializedGetCostOverride());
         }
 
+        createConstructors(clazz);
+
+        createExecuteMethods(clazz);
+        createCachedExecuteMethods(clazz);
+
+        if (specialization.isUninitialized()) {
+            if (specialization.getNode().isFallbackReachable()) {
+                CodeVariableElement var = new CodeVariableElement(modifiers(Modifier.PRIVATE), context.getType(boolean.class), CONTAINS_FALLBACK);
+                var.addAnnotationMirror(new CodeAnnotationMirror(context.getTruffleTypes().getCompilationFinal()));
+                clazz.add(var);
+            }
+            clazz.add(createExecuteUninitialized());
+        }
+
+        if (!specialization.isUninitialized() && specialization.getNode().needsRewrites(context)) {
+            clazz.add(createCopyConstructorFactoryMethod(clazz, nodeGen.asType()));
+        } else {
+            for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) {
+                if (constructor.getParameters().size() == 1 && ((CodeVariableElement) constructor.getParameters().get(0)).getType().equals(nodeGen.asType())) {
+                    // skip copy constructor - not used
+                    continue;
+                }
+                clazz.add(createConstructorFactoryMethod(clazz, constructor));
+            }
+        }
+
         return clazz;
     }
 
@@ -97,9 +124,6 @@
 
         CodeTreeBuilder builder = includes.createInitBuilder();
 
-        SpecializationData specialization = getModel();
-        NodeData node = specialization.getNode();
-
         Set<SpecializationData> contains = specialization.getContains();
         if (specialization.isUninitialized()) {
             contains = new HashSet<>();
@@ -115,10 +139,10 @@
         }
 
         builder.startNew(context.getTruffleTypes().getDslMetadata());
-        builder.startGroup().string(nodeSpecializationClassName(getModel()), ".class").end();
+        builder.startGroup().string(nodeSpecializationClassName(getSpecialization()), ".class").end();
         builder.tree(createSpecializationListLiteral(builder, contains));
-        builder.tree(createSpecializationListLiteral(builder, getModel().getExcludedBy()));
-        builder.tree(createSpecializationTypeLiteral(builder, SpecializationData.getSignatureTypes(getModel())));
+        builder.tree(createSpecializationListLiteral(builder, getSpecialization().getExcludedBy()));
+        builder.tree(createSpecializationTypeLiteral(builder, SpecializationData.getSignatureTypes(getSpecialization())));
         builder.string("0").string("0");
         builder.end();
         return includes;
@@ -149,10 +173,10 @@
             builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
         } else {
             builder.startNewArray(classArray, null);
-            for (SpecializationData specialization : list) {
-                SpecializationData s = specialization;
+            for (SpecializationData current : list) {
+                SpecializationData s = current;
                 if (s.isGeneric() || s.isPolymorphic()) {
-                    s = getModel().getNode().getUninitializedSpecialization();
+                    s = getSpecialization().getNode().getUninitializedSpecialization();
                 }
                 builder.startGroup().string(nodeSpecializationClassName(s)).string(".class").end();
             }
@@ -162,54 +186,22 @@
         return builder.getRoot();
     }
 
-    protected CodeAnnotationMirror createNodeInfo(NodeData node, NodeCost cost) {
+    protected CodeAnnotationMirror createNodeInfo(NodeCost cost) {
         String shortName = node.getShortName();
-        CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(getContext().getTruffleTypes().getNodeInfoAnnotation());
+        CodeAnnotationMirror nodeInfoMirror = new CodeAnnotationMirror(context.getTruffleTypes().getNodeInfoAnnotation());
         if (shortName != null) {
             nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("shortName"), new CodeAnnotationValue(shortName));
         }
 
-        DeclaredType nodeinfoCost = getContext().getTruffleTypes().getNodeCost();
+        DeclaredType nodeinfoCost = context.getTruffleTypes().getNodeCost();
         VariableElement varKind = ElementUtils.findVariableElement(nodeinfoCost, cost.name());
 
         nodeInfoMirror.setElementValue(nodeInfoMirror.findExecutableElement("cost"), new CodeAnnotationValue(varKind));
         return nodeInfoMirror;
     }
 
-    @Override
-    protected void createChildren(SpecializationData specialization) {
-        CodeTypeElement clazz = getElement();
-        createConstructors(clazz);
-
-        createExecuteMethods(specialization);
-        createCachedExecuteMethods(specialization);
-
-        if (specialization.isUninitialized()) {
-            if (specialization.getNode().isFallbackReachable()) {
-                CodeVariableElement var = new CodeVariableElement(modifiers(Modifier.PRIVATE), context.getType(boolean.class), CONTAINS_FALLBACK);
-                var.addAnnotationMirror(new CodeAnnotationMirror(context.getTruffleTypes().getCompilationFinal()));
-                clazz.add(var);
-            }
-            clazz.add(createExecuteUninitialized());
-        }
-
-        if (!specialization.isUninitialized() && specialization.getNode().needsRewrites(context)) {
-            clazz.add(createCopyConstructorFactoryMethod(nodeGen.asType(), specialization));
-        } else {
-            for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) {
-                if (constructor.getParameters().size() == 1 && ((CodeVariableElement) constructor.getParameters().get(0)).getType().equals(nodeGen.asType())) {
-                    // skip copy constructor - not used
-                    continue;
-                }
-                clazz.add(createConstructorFactoryMethod(specialization, constructor));
-            }
-        }
-    }
-
     protected void createConstructors(CodeTypeElement clazz) {
         TypeElement superTypeElement = ElementUtils.fromTypeMirror(clazz.getSuperclass());
-        SpecializationData specialization = getModel();
-        NodeData node = specialization.getNode();
         for (ExecutableElement constructor : ElementFilter.constructorsIn(superTypeElement.getEnclosedElements())) {
             if (specialization.isUninitialized()) {
                 // ignore copy constructors for uninitialized if not polymorphic
@@ -223,7 +215,7 @@
                 }
             }
 
-            CodeExecutableElement superConstructor = createSuperConstructor(clazz, constructor);
+            CodeExecutableElement superConstructor = GeneratorUtils.createSuperConstructor(context, clazz, constructor);
             if (superConstructor == null) {
                 continue;
             }
@@ -232,9 +224,9 @@
             builder.tree(body);
 
             if (superConstructor != null) {
-                for (Parameter param : getImplicitTypeParameters(getModel())) {
-                    clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), implicitTypeName(param)));
-                    superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param)));
+                for (Parameter param : getImplicitTypeParameters(getSpecialization())) {
+                    clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), context.getType(Class.class), implicitTypeName(param)));
+                    superConstructor.getParameters().add(new CodeVariableElement(context.getType(Class.class), implicitTypeName(param)));
 
                     builder.startStatement();
                     builder.string("this.").string(implicitTypeName(param)).string(" = ").string(implicitTypeName(param));
@@ -246,9 +238,7 @@
         }
     }
 
-    protected void createExecuteMethods(SpecializationData specialization) {
-        NodeData node = specialization.getNode();
-        CodeTypeElement clazz = getElement();
+    protected void createExecuteMethods(CodeTypeElement clazz) {
 
         List<ExecutableTypeData> primaryExecutes = null;
         int lastEvaluatedCount = -1;
@@ -259,13 +249,13 @@
             }
             if (execType.getEvaluatedCount() != lastEvaluatedCount) {
                 lastEvaluatedCount = execType.getEvaluatedCount();
-                primaryExecutes = findFunctionalExecutableType(specialization, lastEvaluatedCount);
+                primaryExecutes = findFunctionalExecutableType(lastEvaluatedCount);
             }
 
             CodeExecutableElement executeMethod = createExecutableTypeOverride(execType, true);
             clazz.add(executeMethod);
             CodeTreeBuilder builder = executeMethod.getBuilder();
-            CodeTree result = createExecuteBody(builder, specialization, execType, primaryExecutes);
+            CodeTree result = createExecuteBody(builder, execType, primaryExecutes);
             if (result != null) {
                 builder.tree(result);
             } else {
@@ -274,17 +264,14 @@
         }
     }
 
-    protected void createCachedExecuteMethods(SpecializationData specialization) {
-        NodeData node = specialization.getNode();
+    protected void createCachedExecuteMethods(CodeTypeElement clazz) {
         if (!node.isPolymorphic(context)) {
             return;
         }
 
-        CodeTypeElement clazz = getElement();
-
         final SpecializationData polymorphic = node.getPolymorphicSpecialization();
         ExecutableElement executeCached = nodeGen.getMethod(EXECUTE_CHAINED);
-        CodeExecutableElement executeMethod = CodeExecutableElement.clone(getContext().getEnvironment(), executeCached);
+        CodeExecutableElement executeMethod = CodeExecutableElement.clone(context.getEnvironment(), executeCached);
         executeMethod.getModifiers().remove(Modifier.ABSTRACT);
         CodeTreeBuilder builder = executeMethod.createBuilder();
 
@@ -325,14 +312,14 @@
         return builder.getRoot();
     }
 
-    private CodeTree createExecuteBody(CodeTreeBuilder parent, SpecializationData specialization, ExecutableTypeData execType, List<ExecutableTypeData> primaryExecutes) {
+    private CodeTree createExecuteBody(CodeTreeBuilder parent, ExecutableTypeData execType, List<ExecutableTypeData> primaryExecutes) {
         CodeTreeBuilder builder = new CodeTreeBuilder(parent);
 
         if (primaryExecutes.contains(execType) || primaryExecutes.isEmpty()) {
-            builder.tree(createFunctionalExecute(builder, specialization, execType));
+            builder.tree(createFunctionalExecute(builder, execType));
         } else if (needsCastingExecuteMethod(execType)) {
             assert !primaryExecutes.isEmpty();
-            builder.tree(createCastingExecute(builder, specialization, execType, primaryExecutes.get(0)));
+            builder.tree(createCastingExecute(builder, execType, primaryExecutes.get(0)));
         } else {
             return null;
         }
@@ -341,7 +328,7 @@
     }
 
     private CodeExecutableElement createExecutableTypeOverride(ExecutableTypeData execType, boolean evaluated) {
-        CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), execType.getMethod());
+        CodeExecutableElement method = CodeExecutableElement.clone(context.getEnvironment(), execType.getMethod());
 
         method.getAnnotationMirrors().clear();
         for (VariableElement variable : method.getParameters()) {
@@ -366,7 +353,7 @@
                     name = valueName(actualParameter);
                 }
 
-                int varArgCount = getModel().getSignatureSize() - signatureIndex;
+                int varArgCount = getSpecialization().getSignatureSize() - signatureIndex;
                 if (evaluated && actualParameter.isTypeVarArgs()) {
                     Parameter baseVarArgs = actualParameter;
                     name = valueName(baseVarArgs) + "Args";
@@ -411,7 +398,7 @@
         return false;
     }
 
-    private List<ExecutableTypeData> findFunctionalExecutableType(SpecializationData specialization, int evaluatedCount) {
+    private List<ExecutableTypeData> findFunctionalExecutableType(int evaluatedCount) {
         TypeData primaryType = specialization.getReturnType().getTypeSystemType();
         List<ExecutableTypeData> otherTypes = specialization.getNode().getExecutableTypes(evaluatedCount);
 
@@ -425,7 +412,7 @@
         // no direct matches found use generic where the type is Object
         if (filteredTypes.isEmpty()) {
             for (ExecutableTypeData compareType : otherTypes) {
-                if (compareType.getType().isGeneric() && !compareType.hasUnexpectedValue(getContext())) {
+                if (compareType.getType().isGeneric() && !compareType.hasUnexpectedValue(context)) {
                     filteredTypes.add(compareType);
                 }
             }
@@ -442,7 +429,7 @@
         return filteredTypes;
     }
 
-    private CodeTree createFunctionalExecute(CodeTreeBuilder parent, final SpecializationData specialization, final ExecutableTypeData executable) {
+    private CodeTree createFunctionalExecute(CodeTreeBuilder parent, final ExecutableTypeData executable) {
         CodeTreeBuilder builder = new CodeTreeBuilder(parent);
 
         if (specialization.isUninitialized()) {
@@ -456,23 +443,21 @@
         if (specialization.findNextSpecialization() != null) {
             CodeTreeBuilder returnBuilder = new CodeTreeBuilder(builder);
             returnBuilder.tree(createDeoptimize(builder));
-            returnBuilder.tree(createCallRewriteMonomorphic(builder, executable.hasUnexpectedValue(context), executable.getType(), specialization, null, "One of guards " + specialization.getGuards() +
-                            " failed"));
+            returnBuilder.tree(createCallRewriteMonomorphic(builder, executable.hasUnexpectedValue(context), executable.getType(), null, "One of guards " + specialization.getGuards() + " failed"));
             returnSpecialized = returnBuilder.getRoot();
         }
 
         builder.tree(createExecuteTree(builder, specialization, SpecializationGroup.create(specialization), new CodeBlock<SpecializationData>() {
 
             public CodeTree create(CodeTreeBuilder b, SpecializationData current) {
-                return createExecute(b, executable, specialization);
+                return createExecute(b, executable);
             }
         }, returnSpecialized, false, false, false, false));
 
         return builder.getRoot();
     }
 
-    private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable, SpecializationData specialization) {
-        NodeData node = specialization.getNode();
+    private CodeTree createExecute(CodeTreeBuilder parent, ExecutableTypeData executable) {
         CodeTreeBuilder builder = new CodeTreeBuilder(parent);
         if (!specialization.getExceptions().isEmpty() || !specialization.getAssumptions().isEmpty()) {
             builder.startTryBlock();
@@ -494,7 +479,7 @@
             addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, false, null);
             returnBuilder.end();
         } else if (specialization.getMethod() == null && !node.needsRewrites(context)) {
-            emitEncounteredSynthetic(builder, getModel().getNode(), specialization);
+            emitEncounteredSynthetic(builder, getSpecialization().getNode(), specialization);
         } else {
             returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null));
         }
@@ -522,31 +507,30 @@
             for (SpecializationThrowsData exception : specialization.getExceptions()) {
                 builder.end().startCatchBlock(exception.getJavaClass(), "ex");
                 builder.tree(createDeoptimize(builder));
-                builder.tree(createCallRewriteMonomorphic(parent, executable.hasUnexpectedValue(context), executable.getType(), specialization, null,
-                                "Thrown " + ElementUtils.getSimpleName(exception.getJavaClass())));
+                builder.tree(createCallRewriteMonomorphic(parent, executable.hasUnexpectedValue(context), executable.getType(), null, "Thrown " + ElementUtils.getSimpleName(exception.getJavaClass())));
             }
             builder.end();
         }
         if (!specialization.getAssumptions().isEmpty()) {
-            builder.end().startCatchBlock(getContext().getTruffleTypes().getInvalidAssumption(), "ex");
-            builder.tree(createCallRewriteMonomorphic(parent, executable.hasUnexpectedValue(context), executable.getType(), specialization, null, "Assumption failed"));
+            builder.end().startCatchBlock(context.getTruffleTypes().getInvalidAssumption(), "ex");
+            builder.tree(createCallRewriteMonomorphic(parent, executable.hasUnexpectedValue(context), executable.getType(), null, "Assumption failed"));
             builder.end();
         }
 
         return builder.getRoot();
     }
 
-    private CodeExecutableElement createCopyConstructorFactoryMethod(TypeMirror baseType, SpecializationData specialization) {
+    private CodeExecutableElement createCopyConstructorFactoryMethod(CodeTypeElement clazz, TypeMirror baseType) {
         List<Parameter> implicitTypeParams = getImplicitTypeParameters(specialization);
         String baseName = "current";
         CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), NodeFactoryFactory.FACTORY_METHOD_NAME);
         method.addParameter(new CodeVariableElement(specialization.getNode().getNodeType(), baseName));
         for (Parameter implicitTypeParam : implicitTypeParams) {
-            method.addParameter(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(implicitTypeParam)));
+            method.addParameter(new CodeVariableElement(context.getType(Class.class), implicitTypeName(implicitTypeParam)));
         }
         CodeTreeBuilder builder = method.createBuilder();
         builder.startReturn();
-        builder.startNew(getElement().asType());
+        builder.startNew(clazz.asType());
         builder.startGroup().cast(baseType, CodeTreeBuilder.singleString(baseName)).end();
         for (Parameter param : implicitTypeParams) {
             builder.string(implicitTypeName(param));
@@ -555,13 +539,13 @@
         return method;
     }
 
-    private CodeExecutableElement createConstructorFactoryMethod(SpecializationData specialization, ExecutableElement constructor) {
+    private CodeExecutableElement createConstructorFactoryMethod(CodeTypeElement clazz, ExecutableElement constructor) {
         List<? extends VariableElement> parameters = constructor.getParameters();
         CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), NodeFactoryFactory.FACTORY_METHOD_NAME,
                         parameters.toArray(new CodeVariableElement[parameters.size()]));
         CodeTreeBuilder builder = method.createBuilder();
         builder.startReturn();
-        builder.startNew(getElement().asType());
+        builder.startNew(clazz.asType());
         for (VariableElement param : parameters) {
             builder.string(((CodeVariableElement) param).getName());
         }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java	Mon Dec 29 23:38:16 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java	Mon Dec 29 23:38:21 2014 +0100
@@ -29,11 +29,12 @@
 
 import javax.lang.model.type.*;
 
+import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.java.*;
 import com.oracle.truffle.dsl.processor.java.model.*;
 import com.oracle.truffle.dsl.processor.model.*;
 
-public class TypeSystemCodeGenerator extends AbstractCompilationUnitFactory<TypeSystemData> {
+public class TypeSystemCodeGenerator extends CodeTypeElementFactory<TypeSystemData> {
 
     public static String isTypeMethodName(TypeData type) {
         return "is" + ElementUtils.getTypeId(type.getBoxedType());
@@ -69,20 +70,27 @@
     }
 
     @Override
-    protected void createChildren(TypeSystemData m) {
-        add(new TypeClassFactory(), m);
+    public CodeTypeElement create(ProcessorContext context, TypeSystemData typeSystem) {
+        return new TypeClassFactory(context, typeSystem).create();
     }
 
-    private static class TypeClassFactory extends AbstractClassElementFactory<TypeSystemData> {
+    private static class TypeClassFactory {
 
         private static final String LOCAL_VALUE = "value";
 
-        @Override
-        public CodeTypeElement create(TypeSystemData typeSystem) {
+        private final ProcessorContext context;
+        private final TypeSystemData typeSystem;
+
+        public TypeClassFactory(ProcessorContext context, TypeSystemData typeSystem) {
+            this.context = context;
+            this.typeSystem = typeSystem;
+        }
+
+        public CodeTypeElement create() {
             String name = typeName(typeSystem);
-            CodeTypeElement clazz = createClass(typeSystem, modifiers(PUBLIC, FINAL), name, typeSystem.getTemplateType().asType(), false);
+            CodeTypeElement clazz = GeneratorUtils.createClass(typeSystem, modifiers(PUBLIC, FINAL), name, typeSystem.getTemplateType().asType(), false);
 
-            clazz.add(createConstructorUsingFields(modifiers(PROTECTED), clazz));
+            clazz.add(GeneratorUtils.createConstructorUsingFields(context, modifiers(PROTECTED), clazz));
             CodeVariableElement singleton = createSingleton(clazz);
             clazz.add(singleton);
 
@@ -120,21 +128,20 @@
         }
 
         private CodeVariableElement createSingleton(CodeTypeElement clazz) {
-            CodeVariableElement field = new CodeVariableElement(modifiers(PUBLIC, STATIC, FINAL), clazz.asType(), singletonName(getModel()));
+            CodeVariableElement field = new CodeVariableElement(modifiers(PUBLIC, STATIC, FINAL), clazz.asType(), singletonName(typeSystem));
             field.createInitBuilder().startNew(clazz.asType()).end();
             return field;
         }
 
         private CodeExecutableElement createIsImplicitTypeMethod(TypeData type, boolean typed) {
-            TypeSystemData typeSystem = getModel();
             List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type);
             if (casts.isEmpty()) {
                 return null;
             }
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(boolean.class), TypeSystemCodeGenerator.isImplicitTypeMethodName(type));
-            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(boolean.class), TypeSystemCodeGenerator.isImplicitTypeMethodName(type));
+            method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
             if (typed) {
-                method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "typeHint"));
+                method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint"));
             }
             CodeTreeBuilder builder = method.createBuilder();
 
@@ -165,15 +172,14 @@
         }
 
         private CodeExecutableElement createAsImplicitTypeMethod(TypeData type, boolean typed) {
-            TypeSystemData typeSystem = getModel();
             List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type);
             if (casts.isEmpty()) {
                 return null;
             }
             CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asImplicitTypeMethodName(type));
-            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
+            method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
             if (typed) {
-                method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "typeHint"));
+                method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint"));
             }
 
             List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
@@ -204,20 +210,19 @@
             }
 
             builder.startElseBlock();
-            builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
-            builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end();
+            builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
+            builder.startThrow().startNew(context.getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end();
             builder.end();
             return method;
         }
 
         private CodeExecutableElement createGetTypeIndex(TypeData type) {
-            TypeSystemData typeSystem = getModel();
             List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type);
             if (casts.isEmpty()) {
                 return null;
             }
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(Class.class), TypeSystemCodeGenerator.getImplicitClass(type));
-            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(Class.class), TypeSystemCodeGenerator.getImplicitClass(type));
+            method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
 
             List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
             CodeTreeBuilder builder = method.createBuilder();
@@ -231,8 +236,8 @@
             }
 
             builder.startElseBlock();
-            builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
-            builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end();
+            builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end();
+            builder.startThrow().startNew(context.getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end();
             builder.end();
 
             return method;
@@ -243,10 +248,10 @@
                 return null;
             }
 
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getContext().getType(boolean.class), TypeSystemCodeGenerator.isTypeMethodName(type));
-            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(boolean.class), TypeSystemCodeGenerator.isTypeMethodName(type));
+            method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
 
-            DeclaredType suppressWarnings = (DeclaredType) getContext().getType(SuppressWarnings.class);
+            DeclaredType suppressWarnings = (DeclaredType) context.getType(SuppressWarnings.class);
             CodeAnnotationMirror annotationMirror = new CodeAnnotationMirror(suppressWarnings);
             annotationMirror.setElementValue(annotationMirror.findExecutableElement("value"), new CodeAnnotationValue("static-method"));
             method.getAnnotationMirrors().add(annotationMirror);
@@ -263,10 +268,10 @@
             }
 
             CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asTypeMethodName(type));
-            method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE));
+            method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
 
             CodeTreeBuilder body = method.createBuilder();
-            String assertMessage = typeName(getModel()) + "." + asTypeMethodName(type) + ": " + ElementUtils.getSimpleName(type.getBoxedType()) + " expected";
+            String assertMessage = typeName(typeSystem) + "." + asTypeMethodName(type) + ": " + ElementUtils.getSimpleName(type.getBoxedType()) + " expected";
             body.startAssert().startCall(isTypeMethodName(type)).string(LOCAL_VALUE).end().string(" : ").doubleQuote(assertMessage).end();
             body.startReturn().cast(type.getPrimitiveType(), body.create().string(LOCAL_VALUE).getTree()).end();
 
@@ -276,13 +281,13 @@
         private CodeExecutableElement createExpectTypeMethod(TypeData expectedType, TypeData sourceType) {
             CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), expectedType.getPrimitiveType(), TypeSystemCodeGenerator.expectTypeMethodName(expectedType));
             method.addParameter(new CodeVariableElement(sourceType.getPrimitiveType(), LOCAL_VALUE));
-            method.addThrownType(getContext().getTruffleTypes().getUnexpectedValueException());
+            method.addThrownType(context.getTruffleTypes().getUnexpectedValueException());
 
             CodeTreeBuilder body = method.createBuilder();
             body.startIf().startCall(TypeSystemCodeGenerator.isTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end().startBlock();
             body.startReturn().startCall(TypeSystemCodeGenerator.asTypeMethodName(expectedType)).string(LOCAL_VALUE).end().end();
             body.end(); // if-block
-            body.startThrow().startNew(getContext().getTruffleTypes().getUnexpectedValueException()).string(LOCAL_VALUE).end().end();
+            body.startThrow().startNew(context.getTruffleTypes().getUnexpectedValueException()).string(LOCAL_VALUE).end().end();
 
             return method;
         }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeElement.java	Mon Dec 29 23:38:16 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeElement.java	Mon Dec 29 23:38:21 2014 +0100
@@ -108,7 +108,7 @@
     }
 
     public boolean isTopLevelClass() {
-        return super.getEnclosingElement() instanceof CodeCompilationUnit;
+        return super.getEnclosingElement() instanceof CodeCompilationUnit || super.getEnclosingElement() == null;
     }
 
     private Name createQualifiedName() {