changeset 13527:25ecb47a6d0e

Truffle-DSL: Added support for references to child arrays in @ShortCircuit; Introduced new layer NodeExecutionData to the implementation model which is in between NodeChildData and the actual parameters..
author Christian Humer <christian.humer@gmail.com>
date Tue, 07 Jan 2014 12:22:47 +0100
parents 37ec2cabf397
children 5a0c694ef735
files graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeExecutionData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MethodSpec.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ParameterSpec.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/Filterator.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/FilteredIterable.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/Predicate.java
diffstat 24 files changed, 938 insertions(+), 622 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java	Tue Jan 07 12:22:47 2014 +0100
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.DoubleChildNodeFactory;
+import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.SingleChildNodeFactory;
+import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.VarArgsNodeFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ArgumentNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestArguments;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class ShortCircuitTest {
+
+    @Test
+    public void testSingleChild1() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        CallTarget callTarget = TestHelper.createCallTarget(SingleChildNodeFactory.create(arg0));
+        SingleChildNode.needsChild = true;
+        assertEquals(42, callTarget.call(new TestArguments(42)));
+        assertEquals(1, arg0.getInvocationCount());
+    }
+
+    @Test
+    public void testSingleChild2() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        CallTarget callTarget = TestHelper.createCallTarget(SingleChildNodeFactory.create(arg0));
+        SingleChildNode.needsChild = false;
+        assertEquals(0, callTarget.call(new TestArguments(42)));
+        assertEquals(0, arg0.getInvocationCount());
+    }
+
+    @NodeChild("child0")
+    abstract static class SingleChildNode extends ValueNode {
+
+        static boolean needsChild;
+
+        @ShortCircuit("child0")
+        boolean needsChild0() {
+            return needsChild;
+        }
+
+        @Specialization
+        int doIt(boolean hasChild0, int child0) {
+            assert hasChild0 == needsChild0();
+            return child0;
+        }
+
+    }
+
+    @Test
+    public void testDoubleChild1() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        ArgumentNode arg1 = new ArgumentNode(1);
+        CallTarget callTarget = TestHelper.createCallTarget(DoubleChildNodeFactory.create(arg0, arg1));
+        assertEquals(42, callTarget.call(new TestArguments(41, 42)));
+        assertEquals(1, arg1.getInvocationCount());
+    }
+
+    @Test
+    public void testDoubleChild2() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        ArgumentNode arg1 = new ArgumentNode(1);
+        CallTarget callTarget = TestHelper.createCallTarget(DoubleChildNodeFactory.create(arg0, arg1));
+        assertEquals(0, callTarget.call(new TestArguments(42, 42)));
+        assertEquals(0, arg1.getInvocationCount());
+    }
+
+    @NodeChildren({@NodeChild("child0"), @NodeChild("child1")})
+    @SuppressWarnings("unused")
+    abstract static class DoubleChildNode extends ValueNode {
+
+        @ShortCircuit("child1")
+        boolean needsChild1(Object leftValue) {
+            return leftValue.equals(41);
+        }
+
+        @Specialization
+        int doIt(int child0, boolean hasChild1, int child1) {
+            return child1;
+        }
+
+    }
+
+    @Test
+    public void testVarArgs1() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        ArgumentNode arg1 = new ArgumentNode(1);
+        CallTarget callTarget = TestHelper.createCallTarget(VarArgsNodeFactory.create(new ValueNode[]{arg0, arg1}));
+        assertEquals(42, callTarget.call(new TestArguments(41, 42)));
+        assertEquals(1, arg1.getInvocationCount());
+    }
+
+    @Test
+    public void testVarArgs2() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        ArgumentNode arg1 = new ArgumentNode(1);
+        CallTarget callTarget = TestHelper.createCallTarget(VarArgsNodeFactory.create(new ValueNode[]{arg0, arg1}));
+        assertEquals(0, callTarget.call(new TestArguments(42, 42)));
+        assertEquals(0, arg1.getInvocationCount());
+    }
+
+    @NodeChild(value = "children", type = ValueNode[].class)
+    abstract static class VarArgsNode extends ValueNode {
+
+        @ShortCircuit("children[1]")
+        boolean needsChild1(Object leftValue) {
+            return leftValue.equals(41);
+        }
+
+        @Specialization
+        @SuppressWarnings("unused")
+        int doIt(int child0, boolean hasChild1, int child1) {
+            return child1;
+        }
+
+    }
+
+}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java	Thu Dec 26 12:37:28 2013 -0800
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/CreateCastParser.java	Tue Jan 07 12:22:47 2014 +0100
@@ -46,17 +46,21 @@
     @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
         List<String> childNames = Utils.getAnnotationValueList(String.class, mirror, "value");
-        TypeMirror baseType = getContext().getTruffleTypes().getNode();
+        NodeChildData foundChild = null;
         for (String childName : childNames) {
-            NodeChildData child = getNode().findChild(childName);
-            if (child != null) {
-                baseType = child.getOriginalType();
+            foundChild = getNode().findChild(childName);
+            if (foundChild != null) {
                 break;
             }
         }
+        TypeMirror baseType = getContext().getTruffleTypes().getNode();
+        if (foundChild != null) {
+            baseType = foundChild.getOriginalType();
+        }
+
         MethodSpec spec = new MethodSpec(new InheritsParameterSpec(getContext(), "child", baseType));
         addDefaultFieldMethodSpec(spec);
-        spec.addRequired(new ParameterSpec("castedChild", baseType)).setSignature(true);
+        spec.addRequired(new ParameterSpec("castedChild", baseType));
         return spec;
     }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java	Thu Dec 26 12:37:28 2013 -0800
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ExecutableTypeMethodParser.java	Tue Jan 07 12:22:47 2014 +0100
@@ -29,7 +29,6 @@
 import javax.lang.model.type.*;
 
 import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.*;
 import com.oracle.truffle.dsl.processor.template.*;
 import com.oracle.truffle.dsl.processor.typesystem.*;
 
@@ -52,13 +51,11 @@
         for (ParameterSpec originalSpec : requiredSpecs) {
             spec.addRequired(new ParameterSpec(originalSpec, allowedTypes));
         }
-
-        spec.setVariableRequiredArguments(true);
-        ParameterSpec other = new ParameterSpec("other", allowedTypes);
-        other.setCardinality(Cardinality.MANY);
-        other.setSignature(true);
-        other.setIndexed(true);
-        spec.addRequired(other);
+        spec.setIgnoreAdditionalSpecifications(true);
+        spec.setIgnoreAdditionalParameters(true);
+        spec.setVariableRequiredParameters(true);
+        // varargs
+        spec.addRequired(new ParameterSpec("other", allowedTypes));
         return spec;
     }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java	Thu Dec 26 12:37:28 2013 -0800
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/GenericParser.java	Tue Jan 07 12:22:47 2014 +0100
@@ -44,23 +44,18 @@
     }
 
     @Override
-    protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, int evaluatedCount) {
-        List<ExecutableTypeData> execTypes = nodeData.findGenericExecutableTypes(getContext(), evaluatedCount);
+    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
+        List<ExecutableTypeData> execTypes = execution.getChild().getNodeData().findGenericExecutableTypes(getContext(), execution.getChild().getExecuteWith().size());
         List<TypeMirror> types = new ArrayList<>();
         for (ExecutableTypeData type : execTypes) {
             types.add(type.getType().getPrimitiveType());
         }
-        ParameterSpec spec = new ParameterSpec(valueName, types);
-        spec.setSignature(true);
+        ParameterSpec spec = new ParameterSpec(execution.getName(), types);
+        spec.setExecution(execution);
         return spec;
     }
 
     @Override
-    protected ParameterSpec createReturnParameterSpec() {
-        return super.createValueParameterSpec("returnValue", getNode(), 0);
-    }
-
-    @Override
     public SpecializationData create(TemplateMethod method, boolean invalid) {
         SpecializationData data = new SpecializationData(method, true, false, false);
         return data;
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.java	Thu Dec 26 12:37:28 2013 -0800
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeChildData.java	Tue Jan 07 12:22:47 2014 +0100
@@ -45,10 +45,6 @@
         }
     }
 
-    public enum ExecutionKind {
-        DEFAULT, SHORT_CIRCUIT
-    }
-
     private final NodeData parent;
     private final Element sourceElement;
     private final AnnotationMirror sourceAnnotationMirror;
@@ -59,14 +55,13 @@
     private final Element accessElement;
 
     private final Cardinality cardinality;
-    private final ExecutionKind executionKind;
 
     private List<NodeChildData> executeWith = Collections.emptyList();
 
     private NodeData nodeData;
 
     public NodeChildData(NodeData parent, Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement,
-                    Cardinality cardinality, ExecutionKind executionKind) {
+                    Cardinality cardinality) {
         this.parent = parent;
         this.sourceElement = sourceElement;
         this.sourceAnnotationMirror = sourceMirror;
@@ -75,7 +70,6 @@
         this.originalType = originalNodeType;
         this.accessElement = accessElement;
         this.cardinality = cardinality;
-        this.executionKind = executionKind;
     }
 
     public List<NodeChildData> getExecuteWith() {
@@ -92,18 +86,12 @@
         }
 
         boolean used = false;
-        SpecializationData generic = parent.getGenericSpecialization();
-        for (ActualParameter param : generic.getParameters()) {
-            if (!param.getSpecification().isSignature()) {
-                continue;
-            }
-            NodeChildData child = parent.findChild(param.getSpecification().getName());
-            if (child == this) {
+        for (NodeExecutionData execution : parent.getChildExecutions()) {
+            if (execution.getChild() == this) {
                 used = true;
                 break;
             }
         }
-
         if (!used) {
             return false;
         }
@@ -145,10 +133,6 @@
         return sourceAnnotationMirror;
     }
 
-    public boolean isShortCircuit() {
-        return executionKind == ExecutionKind.SHORT_CIRCUIT;
-    }
-
     void setNode(NodeData nodeData) {
         this.nodeData = nodeData;
         if (nodeData != null) {
@@ -168,10 +152,6 @@
         return cardinality;
     }
 
-    public ExecutionKind getExecutionKind() {
-        return executionKind;
-    }
-
     public NodeData getNodeData() {
         return nodeData;
     }
@@ -182,7 +162,7 @@
 
     @Override
     public String toString() {
-        return "NodeFieldData[name=" + getName() + ", kind=" + cardinality + ", execution=" + executionKind + ", node=" + getNodeData() + "]";
+        return "NodeFieldData[name=" + getName() + ", kind=" + cardinality + ", node=" + getNodeData() + "]";
     }
 
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Thu Dec 26 12:37:28 2013 -0800
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Tue Jan 07 12:22:47 2014 +0100
@@ -37,7 +37,6 @@
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.ast.*;
 import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.ExecutionKind;
 import com.oracle.truffle.dsl.processor.node.SpecializationGroup.TypeGuard;
 import com.oracle.truffle.dsl.processor.template.*;
 import com.oracle.truffle.dsl.processor.typesystem.*;
@@ -632,21 +631,9 @@
             List<TypeMirror> signatureTypes = new ArrayList<>();
             assert !node.getSpecializations().isEmpty();
             SpecializationData data = node.getSpecializations().get(0);
-            for (ActualParameter parameter : data.getParameters()) {
-                ParameterSpec spec = parameter.getSpecification();
-                NodeChildData field = node.findChild(spec.getName());
-                if (field == null) {
-                    continue;
-                }
-
-                TypeMirror type;
-                if (field.getCardinality() == Cardinality.MANY && field.getNodeType().getKind() == TypeKind.ARRAY) {
-                    type = ((ArrayType) field.getNodeType()).getComponentType();
-                } else {
-                    type = field.getNodeType();
-                }
-
-                signatureTypes.add(type);
+
+            for (ActualParameter parameter : data.getSignatureParameters()) {
+                signatureTypes.add(parameter.getSpecification().getExecution().getNodeType());
             }
 
             builder.startReturn().tree(createAsList(builder, signatureTypes, classType)).end();
@@ -1014,16 +1001,13 @@
             CodeTreeBuilder oldBuilder = builder.create();
             CodeTreeBuilder resetBuilder = builder.create();
 
-            for (ActualParameter param : getModel().getParameters()) {
-                if (!param.getSpecification().isSignature()) {
-                    continue;
-                }
-                NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName());
+            for (ActualParameter param : getModel().getSignatureParameters()) {
+                NodeChildData child = param.getSpecification().getExecution().getChild();
 
                 CodeTreeBuilder access = builder.create();
                 access.string("this.").string(child.getName());
                 if (child.getCardinality().isMany()) {
-                    access.string("[").string(String.valueOf(param.getSpecificationIndex())).string("]");
+                    access.string("[").string(String.valueOf(param.getSpecificationVarArgsIndex())).string("]");
                 }
 
                 String oldName = "old" + Utils.firstLetterUpperCase(param.getLocalName());
@@ -1117,11 +1101,7 @@
             builder.startStatement().startCall("builder", "append").doubleQuote(" (").end().end();
 
             String sep = null;
-            for (ActualParameter parameter : node.getGenericSpecialization().getParameters()) {
-                if (!parameter.getSpecification().isSignature()) {
-                    continue;
-                }
-
+            for (ActualParameter parameter : node.getGenericSpecialization().getSignatureParameters()) {
                 builder.startStatement();
                 builder.string("builder");
                 if (sep != null) {
@@ -1210,15 +1190,6 @@
                 }
             }
 
-            for (VariableElement var : type.getFields()) {
-                NodeChildData child = node.findChild(var.getSimpleName().toString());
-                if (child != null) {
-                    method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName()));
-                } else {
-                    method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString()));
-                }
-            }
-
             if (superConstructor != null) {
                 builder.startStatement().startSuperCall();
                 for (VariableElement param : superConstructor.getParameters()) {
@@ -1228,11 +1199,18 @@
             }
 
             for (VariableElement var : type.getFields()) {
+                NodeExecutionData execution = node.findExecution(var.getSimpleName().toString());
+                NodeChildData child = execution != null ? execution.getChild() : null;
+
+                if (execution != null) {
+                    method.getParameters().add(new CodeVariableElement(execution.getNodeType(), execution.getName()));
+                } else {
+                    method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString()));
+                }
+
                 builder.startStatement();
                 String fieldName = var.getSimpleName().toString();
 
-                NodeChildData child = node.findChild(fieldName);
-
                 CodeTree init = createStaticCast(builder, child, fieldName);
                 init = createAdoptChild(builder, var.asType(), init);
 
@@ -1520,19 +1498,15 @@
                     }
                 }
 
-                NodeChildData child = node.findChild(valueParam.getSpecification().getName());
-                if (child == null) {
-                    throw new IllegalStateException();
-                }
-
-                CodeTree implicitGuard = createTypeGuard(guardsBuilder, child, valueParam, typeGuard.getType(), typedCasts);
+                NodeExecutionData execution = valueParam.getSpecification().getExecution();
+                CodeTree implicitGuard = createTypeGuard(guardsBuilder, execution, valueParam, typeGuard.getType(), typedCasts);
                 if (implicitGuard != null) {
                     guardsBuilder.string(guardsAnd);
                     guardsBuilder.tree(implicitGuard);
                     guardsAnd = " && ";
                 }
 
-                CodeTree cast = createCast(castBuilder, child, valueParam, typeGuard.getType(), checkMinimumState, typedCasts);
+                CodeTree cast = createCast(castBuilder, execution, valueParam, typeGuard.getType(), checkMinimumState, typedCasts);
                 if (cast != null) {
                     castBuilder.tree(cast);
                 }
@@ -1604,8 +1578,8 @@
             return false;
         }
 
-        private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType, boolean typedCasts) {
-            NodeData node = field.getNodeData();
+        private CodeTree createTypeGuard(CodeTreeBuilder parent, NodeExecutionData execution, ActualParameter source, TypeData targetType, boolean typedCasts) {
+            NodeData node = execution.getChild().getNodeData();
 
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
 
@@ -1617,7 +1591,7 @@
 
             builder.startGroup();
 
-            if (field.isShortCircuit()) {
+            if (execution.isShortCircuit()) {
                 ActualParameter shortCircuit = source.getPreviousParameter();
                 assert shortCircuit != null;
                 builder.string("(");
@@ -1644,7 +1618,7 @@
             }
             builder.end().end(); // call
 
-            if (field.isShortCircuit()) {
+            if (execution.isShortCircuit()) {
                 builder.string(")");
             }
 
@@ -1654,8 +1628,8 @@
         }
 
         // TODO merge redundancies with #createTypeGuard
-        private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType, boolean checkMinimumState, boolean typedCasts) {
-            NodeData node = field.getNodeData();
+        private CodeTree createCast(CodeTreeBuilder parent, NodeExecutionData execution, ActualParameter source, TypeData targetType, boolean checkMinimumState, boolean typedCasts) {
+            NodeData node = execution.getChild().getNodeData();
             TypeData sourceType = source.getTypeSystemType();
 
             if (!sourceType.needsCastTo(getContext(), targetType)) {
@@ -1663,7 +1637,7 @@
             }
 
             CodeTree condition = null;
-            if (field.isShortCircuit()) {
+            if (execution.isShortCircuit()) {
                 ActualParameter shortCircuit = source.getPreviousParameter();
                 assert shortCircuit != null;
                 condition = CodeTreeBuilder.singleString(valueName(shortCircuit));
@@ -1836,11 +1810,8 @@
                 replaceCall.startCall("replace");
             }
             replaceCall.startGroup().startNew(className).string(source);
-            for (ActualParameter param : current.getParameters()) {
-                if (!param.getSpecification().isSignature()) {
-                    continue;
-                }
-                NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName());
+            for (ActualParameter param : current.getSignatureParameters()) {
+                NodeChildData child = param.getSpecification().getExecution().getChild();
                 List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
                 if (types.size() > 1) {
                     replaceCall.string(implicitTypeName(param));
@@ -1897,11 +1868,7 @@
             boolean returnVoid = type.isVoid();
 
             List<ActualParameter> executeParameters = new ArrayList<>();
-            for (ActualParameter sourceParameter : executable.getParameters()) {
-                if (!sourceParameter.getSpecification().isSignature()) {
-                    continue;
-                }
-
+            for (ActualParameter sourceParameter : executable.getSignatureParameters()) {
                 ActualParameter targetParameter = castExecutable.findParameter(sourceParameter.getLocalName());
                 if (targetParameter != null) {
                     executeParameters.add(targetParameter);
@@ -1968,14 +1935,13 @@
         protected CodeTree createExecuteChildren(CodeTreeBuilder parent, ExecutableTypeData sourceExecutable, SpecializationData specialization, List<ActualParameter> targetParameters,
                         ActualParameter unexpectedParameter) {
             CodeTreeBuilder builder = parent.create();
-            NodeData node = specialization.getNode();
             for (ActualParameter targetParameter : targetParameters) {
-                NodeChildData child = node.findChild(targetParameter.getSpecification().getName());
                 if (!targetParameter.getSpecification().isSignature()) {
                     continue;
                 }
-                CodeTree executionExpressions = createExecuteChild(builder, child, sourceExecutable, targetParameter, unexpectedParameter);
-                CodeTree unexpectedTree = createCatchUnexpectedTree(builder, executionExpressions, specialization, sourceExecutable, targetParameter, isShortCircuit(child), unexpectedParameter);
+                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);
 
                 if (shortCircuitTree == executionExpressions) {
@@ -1993,15 +1959,16 @@
             return builder.getRoot();
         }
 
-        private ExecutableTypeData resolveExecutableType(NodeChildData child, TypeData type) {
-            ExecutableTypeData targetExecutable = child.findExecutableType(getContext(), type);
+        private ExecutableTypeData resolveExecutableType(NodeExecutionData execution, TypeData type) {
+            ExecutableTypeData targetExecutable = execution.getChild().findExecutableType(getContext(), type);
             if (targetExecutable == null) {
-                targetExecutable = child.findAnyGenericExecutableType(getContext());
+                targetExecutable = execution.getChild().findAnyGenericExecutableType(getContext());
             }
             return targetExecutable;
         }
 
-        private CodeTree createExecuteChild(CodeTreeBuilder parent, NodeChildData child, ExecutableTypeData sourceExecutable, ActualParameter targetParameter, ActualParameter unexpectedParameter) {
+        private CodeTree createExecuteChild(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, ActualParameter targetParameter,
+                        ActualParameter unexpectedParameter) {
             SpecializationData specialization = getModel();
             TreeSet<TypeData> possiblePolymorphicTypes = lookupPolymorphicTargetTypes(targetParameter);
             if (specialization.isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null && possiblePolymorphicTypes.size() > 1) {
@@ -2020,28 +1987,25 @@
                     builder.string(polymorphicTypeName(targetParameter)).string(" == ").typeLiteral(possiblePolymoprhicType.getPrimitiveType());
                     builder.end().startBlock();
                     builder.startStatement();
-                    builder.tree(createExecuteChildExpression(parent, child, sourceType, new ActualParameter(targetParameter, possiblePolymoprhicType), unexpectedParameter, null));
+                    builder.tree(createExecuteChildExpression(parent, execution, sourceType, new ActualParameter(targetParameter, possiblePolymoprhicType), unexpectedParameter, null));
                     builder.end();
                     builder.end();
                 }
 
                 builder.startElseBlock();
-                builder.startStatement().tree(createExecuteChildImplicit(parent, child, sourceExecutable, targetParameter, unexpectedParameter)).end();
+                builder.startStatement().tree(createExecuteChildImplicit(parent, execution, sourceExecutable, targetParameter, unexpectedParameter)).end();
                 builder.end();
 
                 return builder.getRoot();
             } else {
-                return createExecuteChildImplicit(parent, child, sourceExecutable, targetParameter, unexpectedParameter);
+                return createExecuteChildImplicit(parent, execution, sourceExecutable, targetParameter, unexpectedParameter);
             }
         }
 
         protected final List<ActualParameter> getImplicitTypeParamters(SpecializationData model) {
             List<ActualParameter> parameter = new ArrayList<>();
-            for (ActualParameter param : model.getParameters()) {
-                if (!param.getSpecification().isSignature()) {
-                    continue;
-                }
-                NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName());
+            for (ActualParameter param : model.getSignatureParameters()) {
+                NodeChildData child = param.getSpecification().getExecution().getChild();
                 List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
                 if (types.size() > 1) {
                     parameter.add(param);
@@ -2065,7 +2029,7 @@
             return possiblePolymorphicTypes;
         }
 
-        private CodeTree createExecuteChildImplicit(CodeTreeBuilder parent, NodeChildData child, ExecutableTypeData sourceExecutable, ActualParameter param, ActualParameter unexpectedParameter) {
+        private CodeTree createExecuteChildImplicit(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData sourceExecutable, ActualParameter param, ActualParameter unexpectedParameter) {
             CodeTreeBuilder builder = parent.create();
             ActualParameter sourceParameter = sourceExecutable.findParameter(param.getLocalName());
             String childExecuteName = createExecuteChildMethodName(param, sourceParameter != null);
@@ -2089,19 +2053,20 @@
 
                 builder.end();
             } else {
-                List<TypeData> sourceTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
+                List<TypeData> sourceTypes = execution.getChild().getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
                 TypeData expectType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null;
                 if (sourceTypes.size() > 1) {
                     builder.tree(createExecuteChildImplicitExpressions(parent, param, expectType));
                 } else {
-                    builder.tree(createExecuteChildExpression(parent, child, expectType, param, unexpectedParameter, null));
+                    builder.tree(createExecuteChildExpression(parent, execution, expectType, param, unexpectedParameter, null));
                 }
             }
             return builder.getRoot();
         }
 
         private String createExecuteChildMethodName(ActualParameter param, boolean expect) {
-            NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName());
+            NodeExecutionData execution = param.getSpecification().getExecution();
+            NodeChildData child = execution.getChild();
             if (child.getExecuteWith().size() > 0) {
                 return null;
             }
@@ -2110,7 +2075,8 @@
                 return null;
             }
             String prefix = expect ? "expect" : "execute";
-            return prefix + Utils.firstLetterUpperCase(child.getName()) + Utils.firstLetterUpperCase(Utils.getSimpleName(param.getType())) + param.getSpecificationIndex();
+            String suffix = execution.getIndex() > -1 ? String.valueOf(execution.getIndex()) : "";
+            return prefix + Utils.firstLetterUpperCase(child.getName()) + Utils.firstLetterUpperCase(Utils.getSimpleName(param.getType())) + suffix;
         }
 
         private List<CodeExecutableElement> createExecuteChilds(ActualParameter param, Set<TypeData> expectTypes) {
@@ -2155,7 +2121,7 @@
         private CodeTree createExecuteChildImplicitExpressions(CodeTreeBuilder parent, ActualParameter targetParameter, TypeData expectType) {
             CodeTreeBuilder builder = parent.create();
             NodeData node = getModel().getNode();
-            NodeChildData child = node.findChild(targetParameter.getSpecification().getName());
+            NodeExecutionData execution = targetParameter.getSpecification().getExecution();
             List<TypeData> sourceTypes = node.getTypeSystem().lookupSourceTypes(targetParameter.getTypeSystemType());
             boolean elseIf = false;
             int index = 0;
@@ -2169,18 +2135,18 @@
                     builder.startElseBlock();
                 }
 
-                ExecutableTypeData implictExecutableTypeData = child.findExecutableType(getContext(), sourceType);
+                ExecutableTypeData implictExecutableTypeData = execution.getChild().findExecutableType(getContext(), sourceType);
                 if (implictExecutableTypeData == null) {
                     /*
                      * For children with executeWith.size() > 0 an executable type may not exist so
                      * use the generic executable type which is guaranteed to exist. An expect call
                      * is inserted automatically by #createExecuteExpression.
                      */
-                    implictExecutableTypeData = child.getNodeData().findExecutableType(node.getTypeSystem().getGenericTypeData(), child.getExecuteWith().size());
+                    implictExecutableTypeData = execution.getChild().getNodeData().findExecutableType(node.getTypeSystem().getGenericTypeData(), execution.getChild().getExecuteWith().size());
                 }
 
-                ImplicitCastData cast = child.getNodeData().getTypeSystem().lookupCast(sourceType, targetParameter.getTypeSystemType());
-                CodeTree execute = createExecuteChildExpression(builder, child, expectType, targetParameter, null, cast);
+                ImplicitCastData cast = execution.getChild().getNodeData().getTypeSystem().lookupCast(sourceType, targetParameter.getTypeSystemType());
+                CodeTree execute = createExecuteChildExpression(builder, execution, expectType, targetParameter, null, cast);
                 builder.statement(execute);
                 builder.end();
                 index++;
@@ -2188,8 +2154,8 @@
             return builder.getRoot();
         }
 
-        private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData child, TypeData sourceParameterType, ActualParameter targetParameter, ActualParameter unexpectedParameter,
-                        ImplicitCastData cast) {
+        private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData execution, TypeData sourceParameterType, ActualParameter targetParameter,
+                        ActualParameter unexpectedParameter, ImplicitCastData cast) {
             // assignments: targetType <- castTargetType <- castSourceType <- sourceType
             TypeData sourceType = sourceParameterType;
             TypeData targetType = targetParameter.getTypeSystemType();
@@ -2203,15 +2169,15 @@
 
             CodeTree expression;
             if (sourceType == null) {
-                ExecutableTypeData targetExecutable = resolveExecutableType(child, castSourceType);
-                expression = createExecuteChildExpression(parent, child, targetParameter, targetExecutable, unexpectedParameter);
+                ExecutableTypeData targetExecutable = resolveExecutableType(execution, castSourceType);
+                expression = createExecuteChildExpression(parent, execution, targetExecutable, unexpectedParameter);
                 sourceType = targetExecutable.getType();
             } else {
                 expression = CodeTreeBuilder.singleString(valueNameEvaluated(targetParameter));
             }
 
             // target = expectTargetType(implicitCast(expectCastSourceType(source)))
-            TypeSystemData typeSystem = child.getNodeData().getTypeSystem();
+            TypeSystemData typeSystem = execution.getChild().getNodeData().getTypeSystem();
             expression = createExpectType(typeSystem, sourceType, castSourceType, expression);
             expression = createImplicitCast(parent, typeSystem, cast, expression);
             expression = createExpectType(typeSystem, castTargetType, targetType, expression);
@@ -2248,32 +2214,32 @@
         }
 
         private boolean hasUnexpected(ActualParameter sourceParameter, ActualParameter targetParameter, ActualParameter unexpectedParameter) {
-            NodeChildData child = getModel().getNode().findChild(targetParameter.getSpecification().getName());
+            NodeExecutionData execution = targetParameter.getSpecification().getExecution();
 
             if (getModel().isPolymorphic() && targetParameter.getTypeSystemType().isGeneric() && unexpectedParameter == null) {
                 // check for other polymorphic types
                 TreeSet<TypeData> polymorphicTargetTypes = lookupPolymorphicTargetTypes(targetParameter);
                 if (polymorphicTargetTypes.size() > 1) {
                     for (TypeData polymorphicTargetType : polymorphicTargetTypes) {
-                        if (hasUnexpectedType(child, sourceParameter, polymorphicTargetType)) {
+                        if (hasUnexpectedType(execution, sourceParameter, polymorphicTargetType)) {
                             return true;
                         }
                     }
                 }
             }
 
-            if (hasUnexpectedType(child, sourceParameter, targetParameter.getTypeSystemType())) {
+            if (hasUnexpectedType(execution, sourceParameter, targetParameter.getTypeSystemType())) {
                 return true;
             }
             return false;
         }
 
-        private boolean hasUnexpectedType(NodeChildData child, ActualParameter sourceParameter, TypeData targetType) {
+        private boolean hasUnexpectedType(NodeExecutionData execution, ActualParameter sourceParameter, TypeData targetType) {
             List<TypeData> implicitSourceTypes = getModel().getNode().getTypeSystem().lookupSourceTypes(targetType);
 
             for (TypeData implicitSourceType : implicitSourceTypes) {
                 TypeData sourceType;
-                ExecutableTypeData targetExecutable = resolveExecutableType(child, implicitSourceType);
+                ExecutableTypeData targetExecutable = resolveExecutableType(execution, implicitSourceType);
                 if (sourceParameter != null) {
                     sourceType = sourceParameter.getTypeSystemType();
                 } else {
@@ -2357,11 +2323,10 @@
             return builder.getRoot();
         }
 
-        private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeChildData targetChild, ActualParameter targetParameter, ExecutableTypeData targetExecutable,
-                        ActualParameter unexpectedParameter) {
+        private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData targetExecution, ExecutableTypeData targetExecutable, ActualParameter unexpectedParameter) {
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-            if (targetChild != null) {
-                builder.tree(createAccessChild(builder, targetChild, targetParameter));
+            if (targetExecution != null) {
+                builder.tree(createAccessChild(builder, targetExecution));
                 builder.string(".");
             }
 
@@ -2375,8 +2340,8 @@
                     builder.string(parameter.getLocalName());
                 } else {
 
-                    if (index < targetChild.getExecuteWith().size()) {
-                        NodeChildData child = targetChild.getExecuteWith().get(index);
+                    if (index < targetExecution.getChild().getExecuteWith().size()) {
+                        NodeChildData child = targetExecution.getChild().getExecuteWith().get(index);
 
                         ParameterSpec spec = getModel().getSpecification().findParameterSpec(child.getName());
                         List<ActualParameter> specializationParams = getModel().findParameters(spec);
@@ -2415,31 +2380,31 @@
             return builder.getRoot();
         }
 
-        private CodeTree createAccessChild(CodeTreeBuilder parent, NodeChildData targetChild, ActualParameter targetParameter) throws AssertionError {
+        private CodeTree createAccessChild(CodeTreeBuilder parent, NodeExecutionData targetExecution) throws AssertionError {
             CodeTreeBuilder builder = parent.create();
-            Element accessElement = targetChild.getAccessElement();
+            Element accessElement = targetExecution.getChild().getAccessElement();
             if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) {
-                builder.string("this.").string(targetChild.getName());
+                builder.string("this.").string(targetExecution.getChild().getName());
             } else if (accessElement.getKind() == ElementKind.FIELD) {
                 builder.string("this.").string(accessElement.getSimpleName().toString());
             } else {
                 throw new AssertionError();
             }
-            if (targetParameter.getSpecification().isIndexed()) {
-                builder.string("[" + targetParameter.getSpecificationIndex() + "]");
+            if (targetExecution.isIndexed()) {
+                builder.string("[" + targetExecution.getIndex() + "]");
             }
             return builder.getRoot();
         }
 
         private CodeTree createShortCircuitTree(CodeTreeBuilder parent, CodeTree body, SpecializationData specialization, ActualParameter parameter, ActualParameter exceptionParam) {
-            NodeChildData forField = specialization.getNode().findChild(parameter.getSpecification().getName());
-            if (!isShortCircuit(forField)) {
+            NodeExecutionData execution = parameter.getSpecification().getExecution();
+            if (execution == null || !execution.isShortCircuit()) {
                 return body;
             }
 
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
             ActualParameter shortCircuitParam = specialization.getPreviousParam(parameter);
-            builder.tree(createShortCircuitValue(builder, specialization, forField, shortCircuitParam, exceptionParam));
+            builder.tree(createShortCircuitValue(builder, specialization, execution, shortCircuitParam, exceptionParam));
             builder.declaration(parameter.getType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getType()));
             builder.startIf().string(shortCircuitParam.getLocalName()).end();
             builder.startBlock();
@@ -2454,16 +2419,13 @@
             return builder.getRoot();
         }
 
-        private boolean isShortCircuit(NodeChildData forField) {
-            return forField != null && forField.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT;
-        }
-
-        private CodeTree createShortCircuitValue(CodeTreeBuilder parent, SpecializationData specialization, NodeChildData forField, ActualParameter shortCircuitParam, ActualParameter exceptionParam) {
+        private CodeTree createShortCircuitValue(CodeTreeBuilder parent, SpecializationData specialization, NodeExecutionData execution, ActualParameter shortCircuitParam,
+                        ActualParameter exceptionParam) {
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
             int shortCircuitIndex = 0;
-            for (NodeChildData field : specialization.getNode().getChildren()) {
-                if (field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) {
-                    if (field == forField) {
+            for (NodeExecutionData otherExectuion : specialization.getNode().getChildExecutions()) {
+                if (otherExectuion.isShortCircuit()) {
+                    if (otherExectuion == execution) {
                         break;
                     }
                     shortCircuitIndex++;
@@ -2856,39 +2818,43 @@
             int signatureIndex = -1;
             for (VariableElement param : method.getParameters()) {
                 CodeVariableElement var = CodeVariableElement.clone(param);
-                ActualParameter actualParameter = execType.getParameters().get(i);
-                if (actualParameter.getSpecification().isSignature()) {
-                    signatureIndex++;
-                }
-
+                ActualParameter actualParameter = i < execType.getParameters().size() ? execType.getParameters().get(i) : null;
                 String name;
-                if (evaluated && actualParameter.getSpecification().isSignature()) {
-                    name = valueNameEvaluated(actualParameter);
-                } else {
-                    name = valueName(actualParameter);
-                }
-
-                int varArgCount = getModel().getSignatureSize() - signatureIndex;
-                if (evaluated && actualParameter.isVarArgs()) {
-                    ActualParameter baseVarArgs = actualParameter;
-                    name = valueName(baseVarArgs) + "Args";
-
-                    builder.startAssert().string(name).string(" != null").end();
-                    builder.startAssert().string(name).string(".length == ").string(String.valueOf(varArgCount)).end();
-                    if (varArgCount > 0) {
-                        List<ActualParameter> varArgsParameter = execType.getParameters().subList(i, execType.getParameters().size());
-                        for (ActualParameter varArg : varArgsParameter) {
-                            if (varArgCount <= 0) {
-                                break;
+                if (actualParameter != null) {
+                    if (actualParameter.getSpecification().isSignature()) {
+                        signatureIndex++;
+                    }
+
+                    if (evaluated && actualParameter.getSpecification().isSignature()) {
+                        name = valueNameEvaluated(actualParameter);
+                    } else {
+                        name = valueName(actualParameter);
+                    }
+
+                    int varArgCount = getModel().getSignatureSize() - signatureIndex;
+                    if (evaluated && actualParameter.isTypeVarArgs()) {
+                        ActualParameter baseVarArgs = actualParameter;
+                        name = valueName(baseVarArgs) + "Args";
+
+                        builder.startAssert().string(name).string(" != null").end();
+                        builder.startAssert().string(name).string(".length == ").string(String.valueOf(varArgCount)).end();
+                        if (varArgCount > 0) {
+                            List<ActualParameter> varArgsParameter = execType.getParameters().subList(i, execType.getParameters().size());
+                            for (ActualParameter varArg : varArgsParameter) {
+                                if (varArgCount <= 0) {
+                                    break;
+                                }
+                                TypeMirror type = baseVarArgs.getType();
+                                if (type.getKind() == TypeKind.ARRAY) {
+                                    type = ((ArrayType) type).getComponentType();
+                                }
+                                builder.declaration(type, valueNameEvaluated(varArg), name + "[" + varArg.getTypeVarArgsIndex() + "]");
+                                varArgCount--;
                             }
-                            TypeMirror type = baseVarArgs.getType();
-                            if (type.getKind() == TypeKind.ARRAY) {
-                                type = ((ArrayType) type).getComponentType();
-                            }
-                            builder.declaration(type, valueNameEvaluated(varArg), name + "[" + varArg.getVarArgsIndex() + "]");
-                            varArgCount--;
                         }
                     }
+                } else {
+                    name = "arg" + i;
                 }
                 var.setName(name);
                 method.getParameters().set(i, var);
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java	Thu Dec 26 12:37:28 2013 -0800
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java	Tue Jan 07 12:22:47 2014 +0100
@@ -28,7 +28,6 @@
 import javax.lang.model.type.*;
 
 import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.*;
 import com.oracle.truffle.dsl.processor.template.*;
 import com.oracle.truffle.dsl.processor.typesystem.*;
 
@@ -41,6 +40,7 @@
 
     private TypeSystemData typeSystem;
     private List<NodeChildData> children;
+    private List<NodeExecutionData> childExecutions;
     private List<NodeFieldData> fields;
     private TypeMirror nodeType;
     private ParameterSpec instanceParameterSpec;
@@ -78,6 +78,14 @@
         this.assumptions = splitSource.assumptions;
     }
 
+    public List<NodeExecutionData> getChildExecutions() {
+        return childExecutions;
+    }
+
+    void setChildExecutions(List<NodeExecutionData> signature) {
+        this.childExecutions = signature;
+    }
+
     public int getSignatureSize() {
         if (getSpecializations() != null && !getSpecializations().isEmpty()) {
             return getSpecializations().get(0).getSignatureSize();
@@ -374,16 +382,6 @@
         return result;
     }
 
-    public NodeChildData[] filterFields(ExecutionKind usage) {
-        List<NodeChildData> filteredFields = new ArrayList<>();
-        for (NodeChildData field : getChildren()) {
-            if (usage == null || field.getExecutionKind() == usage) {
-                filteredFields.add(field);
-            }
-        }
-        return filteredFields.toArray(new NodeChildData[filteredFields.size()]);
-    }
-
     public boolean needsRewrites(ProcessorContext context) {
         boolean needsRewrites = false;
 
@@ -490,6 +488,18 @@
         return b.toString();
     }
 
+    public NodeExecutionData findExecution(String name) {
+        if (getChildExecutions() == null) {
+            return null;
+        }
+        for (NodeExecutionData execution : getChildExecutions()) {
+            if (execution.getName().equals(name)) {
+                return execution;
+            }
+        }
+        return null;
+    }
+
     public NodeChildData findChild(String name) {
         for (NodeChildData field : getChildren()) {
             if (field.getName().equals(name)) {
@@ -593,4 +603,5 @@
     public int compareTo(NodeData o) {
         return getNodeId().compareTo(o.getNodeId());
     }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeExecutionData.java	Tue Jan 07 12:22:47 2014 +0100
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.node;
+
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.node.NodeChildData.*;
+
+public class NodeExecutionData {
+
+    private final NodeChildData child;
+    private final String name;
+    private final int index;
+    private final boolean shortCircuit;
+
+    public NodeExecutionData(NodeChildData child, int index, boolean shortCircuit) {
+        this.child = child;
+        this.index = index;
+        this.shortCircuit = shortCircuit;
+        this.name = createName();
+    }
+
+    private String createName() {
+        if (isIndexed()) {
+            return child.getName() + index;
+        }
+        return child.getName();
+    }
+
+    public TypeMirror getNodeType() {
+        TypeMirror type;
+        if (child.getCardinality() == Cardinality.MANY && child.getNodeType().getKind() == TypeKind.ARRAY) {
+            type = ((ArrayType) child.getNodeType()).getComponentType();
+        } else {
+            type = child.getNodeType();
+        }
+        return type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public NodeChildData getChild() {
+        return child;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public boolean isIndexed() {
+        return index > -1;
+    }
+
+    public boolean isShortCircuit() {
+        return shortCircuit;
+    }
+
+    public String getShortCircuitId() {
+        return createShortCircuitId(child, index);
+    }
+
+    public static String createShortCircuitId(NodeChildData child, int varArgsIndex) {
+        String shortCircuitName = child.getName();
+        if (child.getCardinality().isMany()) {
+            shortCircuitName = shortCircuitName + "[" + varArgsIndex + "]";
+        }
+        return shortCircuitName;
+    }
+
+}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java	Thu Dec 26 12:37:28 2013 -0800
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeMethodParser.java	Tue Jan 07 12:22:47 2014 +0100
@@ -28,7 +28,6 @@
 import javax.lang.model.type.*;
 
 import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.*;
 import com.oracle.truffle.dsl.processor.template.*;
 
 public abstract class NodeMethodParser<E extends TemplateMethod> extends TemplateMethodParser<NodeData, E> {
@@ -41,10 +40,9 @@
         return template;
     }
 
-    @SuppressWarnings("unused")
-    protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, int evaluatedCount) {
-        ParameterSpec spec = new ParameterSpec(valueName, nodeTypeMirrors(nodeData));
-        spec.setSignature(true);
+    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
+        ParameterSpec spec = new ParameterSpec(execution.getName(), nodeTypeMirrors(execution.getChild().getNodeData()));
+        spec.setExecution(execution);
         return spec;
     }
 
@@ -61,7 +59,7 @@
     }
 
     protected ParameterSpec createReturnParameterSpec() {
-        return createValueParameterSpec("returnValue", getNode(), 0);
+        return new ParameterSpec("returnValue", nodeTypeMirrors(getNode()));
     }
 
     @Override
@@ -85,31 +83,21 @@
         return methodSpec;
     }
 
-    public void addDefaultChildren(boolean shortCircuitsEnabled, String breakName, MethodSpec methodSpec) {
-        // children are null when parsing executable types
-        if (getNode().getChildren() != null) {
-            for (NodeChildData child : getNode().getChildren()) {
-                String valueName = child.getName();
-                if (breakName != null && valueName.equals(breakName)) {
-                    break;
-                }
-                if (child.getExecutionKind() == ExecutionKind.DEFAULT) {
-                    ParameterSpec spec = createValueParameterSpec(child.getName(), child.getNodeData(), child.getExecuteWith().size());
-                    if (child.getCardinality().isMany()) {
-                        spec.setCardinality(Cardinality.MANY);
-                        spec.setIndexed(true);
-                    }
-                    methodSpec.addRequired(spec);
-                } else if (child.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) {
+    public void addDefaultChildren(boolean shortCircuitsEnabled, String breakName, MethodSpec spec) {
+        if (getNode().getChildren() == null) {
+            // children are null when parsing executable types
+            return;
+        }
 
-                    if (shortCircuitsEnabled) {
-                        methodSpec.addRequired(new ParameterSpec(shortCircuitValueName(valueName), getContext().getType(boolean.class)));
-                    }
-                    methodSpec.addRequired(createValueParameterSpec(valueName, child.getNodeData(), child.getExecuteWith().size()));
-                } else {
-                    assert false;
-                }
+        for (NodeExecutionData execution : getNode().getChildExecutions()) {
+            if (breakName != null && execution.getShortCircuitId().equals(breakName)) {
+                break;
             }
+
+            if (execution.isShortCircuit() && shortCircuitsEnabled) {
+                spec.addRequired(new ParameterSpec(shortCircuitValueName(execution.getName()), getContext().getType(boolean.class)));
+            }
+            spec.addRequired(createValueParameterSpec(execution));
         }
     }
 
@@ -130,6 +118,9 @@
     }
 
     protected void addDefaultImplicitThis(ExecutableElement method, MethodSpec methodSpec) {
+        if (method == null) {
+            return;
+        }
         TypeMirror declaredType = Utils.findNearestEnclosingType(method).asType();
 
         if (!method.getModifiers().contains(Modifier.STATIC) && !Utils.isAssignable(getContext(), declaredType, getContext().getTruffleTypes().getNode())) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Thu Dec 26 12:37:28 2013 -0800
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Tue Jan 07 12:22:47 2014 +0100
@@ -34,9 +34,8 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.node.NodeChildData.Cardinality;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.ExecutionKind;
 import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.template.TemplateMethod.Signature;
+import com.oracle.truffle.dsl.processor.template.TemplateMethod.TypeSignature;
 import com.oracle.truffle.dsl.processor.typesystem.*;
 
 public class NodeParser extends TemplateParser<NodeData> {
@@ -205,7 +204,6 @@
 
             finalizeSpecializations(elements, splittedNode);
             verifyNode(splittedNode, elements);
-            expandExecutableTypeVarArgs(splittedNode);
             createPolymorphicSpecializations(splittedNode);
             assignShortCircuitsToSpecializations(splittedNode);
         }
@@ -218,26 +216,6 @@
         return node;
     }
 
-    private static void expandExecutableTypeVarArgs(NodeData node) {
-        for (ExecutableTypeData executableMethod : node.getExecutableTypes()) {
-            if (!(executableMethod.getMethod().isVarArgs() && executableMethod.getSpecification().isVariableRequiredArguments())) {
-                continue;
-            }
-            int expandArguments = node.getSignatureSize() - executableMethod.getSignatureSize();
-            if (expandArguments > 0) {
-                int signatureSize = executableMethod.getSignatureSize();
-                ActualParameter parameter = executableMethod.getSignatureParameter(signatureSize - 1);
-                for (int i = 0; i < expandArguments; i++) {
-                    int newVarArgsIndex = parameter.getVarArgsIndex() + i + 1;
-                    int newSpecificationIndex = parameter.getSpecificationIndex() + i + 1;
-                    executableMethod.getParameters().add(
-                                    new ActualParameter(parameter.getSpecification(), parameter.getTypeSystemType(), newSpecificationIndex, newVarArgsIndex, parameter.isImplicit()));
-                }
-
-            }
-        }
-    }
-
     private void createPolymorphicSpecializations(NodeData node) {
         if (!node.needsRewrites(context) || !node.isPolymorphic()) {
             node.setPolymorphicSpecializations(Collections.<SpecializationData> emptyList());
@@ -277,7 +255,7 @@
         }
 
         SpecializationData specialization = new SpecializationData(generic, false, false, true);
-        specialization.updateSignature(new Signature(polymorphicSignature));
+        specialization.updateSignature(new TypeSignature(polymorphicSignature));
         specialization.setNode(node);
         node.setGenericPolymorphicSpecialization(specialization);
         // TODO remove polymoprhic specializations
@@ -336,6 +314,7 @@
         nodeData.setTypeSystem(typeSystem);
         nodeData.setFields(parseFields(typeHierarchy, elements));
         nodeData.setChildren(parseChildren(nodeData, elements, typeHierarchy));
+        nodeData.setChildExecutions(parseDefaultSignature(nodeData, elements));
         nodeData.setExecutableTypes(groupExecutableTypes(new ExecutableTypeMethodParser(context, nodeData).parse(elements)));
 
         // resolveChildren invokes cyclic parsing.
@@ -345,6 +324,90 @@
         return nodeData;
     }
 
+    private List<NodeExecutionData> parseDefaultSignature(NodeData node, List<? extends Element> elements) {
+        if (node.getChildren() == null) {
+            return null;
+        }
+
+        // pre-parse short circuits
+        Set<String> shortCircuits = new HashSet<>();
+        List<ExecutableElement> methods = ElementFilter.methodsIn(elements);
+        for (ExecutableElement method : methods) {
+            AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
+            if (mirror != null) {
+                shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value"));
+            }
+        }
+
+        boolean hasVarArgs = false;
+        int maxSignatureSize = 0;
+        if (!node.getChildren().isEmpty()) {
+            int lastIndex = node.getChildren().size() - 1;
+            hasVarArgs = node.getChildren().get(lastIndex).getCardinality() == Cardinality.MANY;
+            if (hasVarArgs) {
+                maxSignatureSize = lastIndex;
+            } else {
+                maxSignatureSize = node.getChildren().size();
+            }
+        }
+
+        // pre-parse specializations
+        for (ExecutableElement method : methods) {
+            AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, Specialization.class);
+            if (mirror == null) {
+                continue;
+            }
+
+            int currentArgumentCount = 0;
+            boolean skipShortCircuit = false;
+            for (VariableElement var : method.getParameters()) {
+                TypeMirror type = var.asType();
+                if (currentArgumentCount == 0) {
+                    // skip optionals
+                    if (Utils.typeEquals(type, context.getTruffleTypes().getFrame())) {
+                        continue;
+                    }
+                    // TODO skip optional fields?
+                }
+                int childIndex = currentArgumentCount < node.getChildren().size() ? currentArgumentCount : node.getChildren().size() - 1;
+                if (childIndex == -1) {
+                    continue;
+                }
+                if (!skipShortCircuit) {
+                    NodeChildData child = node.getChildren().get(childIndex);
+                    if (shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, currentArgumentCount - childIndex))) {
+                        skipShortCircuit = true;
+                        continue;
+                    }
+                } else {
+                    skipShortCircuit = false;
+                }
+
+                currentArgumentCount++;
+            }
+            maxSignatureSize = Math.max(maxSignatureSize, currentArgumentCount);
+        }
+
+        List<NodeExecutionData> executions = new ArrayList<>();
+        for (int i = 0; i < maxSignatureSize; i++) {
+            int childIndex = i;
+            boolean varArg = false;
+            if (childIndex >= node.getChildren().size() - 1) {
+                if (hasVarArgs) {
+                    childIndex = node.getChildren().size() - 1;
+                    varArg = hasVarArgs;
+                } else if (childIndex >= node.getChildren().size()) {
+                    break;
+                }
+            }
+            int varArgsIndex = varArg ? Math.abs(childIndex - i) : -1;
+            NodeChildData child = node.getChildren().get(childIndex);
+            boolean shortCircuit = shortCircuits.contains(NodeExecutionData.createShortCircuitId(child, varArgsIndex));
+            executions.add(new NodeExecutionData(child, varArgsIndex, shortCircuit));
+        }
+        return executions;
+    }
+
     private List<NodeFieldData> parseFields(List<TypeElement> typeHierarchy, List<? extends Element> elements) {
         Set<String> names = new HashSet<>();
 
@@ -470,12 +533,7 @@
 
                 Element getter = findGetter(elements, name, childType);
 
-                ExecutionKind kind = ExecutionKind.DEFAULT;
-                if (shortCircuits.contains(name)) {
-                    kind = ExecutionKind.SHORT_CIRCUIT;
-                }
-
-                NodeChildData nodeChild = new NodeChildData(parent, type, childMirror, name, childType, originalChildType, getter, cardinality, kind);
+                NodeChildData nodeChild = new NodeChildData(parent, type, childMirror, name, childType, originalChildType, getter, cardinality);
 
                 parsedChildren.add(nodeChild);
 
@@ -727,62 +785,64 @@
     }
 
     private SpecializationData createGenericSpecialization(final NodeData node, List<SpecializationData> specializations) {
-        SpecializationData genericSpecialization;
         SpecializationData specialization = specializations.get(0);
         GenericParser parser = new GenericParser(context, node);
         MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, true, null);
+        specification.getImplicitRequiredTypes().clear();
 
-        List<ActualParameter> parameters = new ArrayList<>();
-        for (ActualParameter parameter : specialization.getReturnTypeAndParameters()) {
-            if (!parameter.getSpecification().isSignature()) {
-                parameters.add(new ActualParameter(parameter));
-                continue;
+        List<TypeMirror> parameterTypes = new ArrayList<>();
+        int signatureIndex = 1;
+        for (ParameterSpec spec : specification.getRequired()) {
+            parameterTypes.add(createGenericType(spec, specializations, signatureIndex));
+            if (spec.isSignature()) {
+                signatureIndex++;
             }
-            NodeData childNode = node;
-            NodeChildData child = node.findChild(parameter.getSpecification().getName());
-            if (child != null) {
-                childNode = child.getNodeData();
+        }
+        TypeMirror returnType = createGenericType(specification.getReturnType(), specializations, 0);
+        return parser.create("Generic", null, null, returnType, parameterTypes);
+    }
+
+    private TypeMirror createGenericType(ParameterSpec spec, List<SpecializationData> specializations, int signatureIndex) {
+        NodeExecutionData execution = spec.getExecution();
+        if (execution == null) {
+            if (spec.getAllowedTypes().size() == 1) {
+                return spec.getAllowedTypes().get(0);
+            } else {
+                return Utils.getCommonSuperType(context, spec.getAllowedTypes().toArray(new TypeMirror[0]));
+            }
+        } else {
+            Set<TypeData> types = new HashSet<>();
+            for (SpecializationData specialization : specializations) {
+                types.add(specialization.getTypeSignature().get(signatureIndex));
             }
 
-            TypeData genericType = null;
+            NodeChildData child = execution.getChild();
 
-            Set<TypeData> types = new HashSet<>();
-            for (SpecializationData otherSpecialization : specializations) {
-                ActualParameter otherParameter = otherSpecialization.findParameter(parameter.getLocalName());
-                if (otherParameter != null) {
-                    types.add(otherParameter.getTypeSystemType());
+            TypeData genericType = null;
+            if (types.size() == 1) {
+                ExecutableTypeData executable = child.findExecutableType(context, types.iterator().next());
+                if (executable != null && !executable.hasUnexpectedValue(context)) {
+                    genericType = types.iterator().next();
                 }
             }
-
-            assert !types.isEmpty();
-
-            if (types.size() == 1) {
-                ExecutableTypeData executable = childNode.findExecutableType(types.iterator().next(), 0);
-                if (executable != null && !executable.hasUnexpectedValue(context)) {
-                    genericType = types.iterator().next();
-                } else {
-                    genericType = childNode.findAnyGenericExecutableType(context, 0).getType();
-                }
-            } else {
-                genericType = childNode.findAnyGenericExecutableType(context, 0).getType();
+            if (genericType == null) {
+                genericType = child.findAnyGenericExecutableType(context).getType();
             }
-
-            parameters.add(new ActualParameter(parameter, genericType));
+            return genericType.getPrimitiveType();
         }
-        ActualParameter returnType = parameters.get(0);
-        parameters = parameters.subList(1, parameters.size());
-
-        TemplateMethod genericMethod = new TemplateMethod("Generic", node, specification, null, null, returnType, parameters);
-        genericSpecialization = new SpecializationData(genericMethod, true, false, false);
-        return genericSpecialization;
     }
 
     private void assignShortCircuitsToSpecializations(NodeData node) {
         Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits());
 
         boolean valid = true;
-        for (NodeChildData field : node.filterFields(ExecutionKind.SHORT_CIRCUIT)) {
-            String valueName = field.getName();
+        List<NodeExecutionData> shortCircuitExecutions = new ArrayList<>();
+        for (NodeExecutionData execution : node.getChildExecutions()) {
+            if (!execution.isShortCircuit()) {
+                continue;
+            }
+            shortCircuitExecutions.add(execution);
+            String valueName = execution.getShortCircuitId();
             List<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName);
 
             if (availableCircuits == null || availableCircuits.isEmpty()) {
@@ -809,7 +869,7 @@
 
             ShortCircuitData genericCircuit = null;
             for (ShortCircuitData circuit : availableCircuits) {
-                if (isGenericShortCutMethod(node, circuit)) {
+                if (isGenericShortCutMethod(circuit)) {
                     genericCircuit = circuit;
                     break;
                 }
@@ -832,16 +892,15 @@
             return;
         }
 
-        NodeChildData[] fields = node.filterFields(ExecutionKind.SHORT_CIRCUIT);
         List<SpecializationData> specializations = new ArrayList<>();
         specializations.addAll(node.getSpecializations());
         specializations.addAll(node.getPolymorphicSpecializations());
 
         for (SpecializationData specialization : specializations) {
-            List<ShortCircuitData> assignedShortCuts = new ArrayList<>(fields.length);
+            List<ShortCircuitData> assignedShortCuts = new ArrayList<>(shortCircuitExecutions.size());
 
-            for (int i = 0; i < fields.length; i++) {
-                List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(fields[i].getName());
+            for (NodeExecutionData shortCircuit : shortCircuitExecutions) {
+                List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(shortCircuit.getShortCircuitId());
 
                 ShortCircuitData genericShortCircuit = null;
                 ShortCircuitData compatibleShortCircuit = null;
@@ -897,7 +956,7 @@
             List<String> paramIds = new LinkedList<>();
             paramIds.add(Utils.getTypeId(other.getReturnType().getType()));
             for (ActualParameter param : other.getParameters()) {
-                if (other.getNode().findChild(param.getSpecification().getName()) == null) {
+                if (param.getSpecification().getExecution() == null) {
                     continue;
                 }
                 paramIds.add(Utils.getTypeId(param.getType()));
@@ -1230,14 +1289,14 @@
         return null;
     }
 
-    private boolean isGenericShortCutMethod(NodeData node, TemplateMethod method) {
+    private boolean isGenericShortCutMethod(ShortCircuitData method) {
         for (ActualParameter parameter : method.getParameters()) {
-            NodeChildData field = node.findChild(parameter.getSpecification().getName());
-            if (field == null) {
+            NodeExecutionData execution = parameter.getSpecification().getExecution();
+            if (execution == null) {
                 continue;
             }
             ExecutableTypeData found = null;
-            List<ExecutableTypeData> executableElements = field.findGenericExecutableTypes(context);
+            List<ExecutableTypeData> executableElements = execution.getChild().findGenericExecutableTypes(context);
             for (ExecutableTypeData executable : executableElements) {
                 if (executable.getType().equalsType(parameter.getTypeSystemType())) {
                     found = executable;
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java	Thu Dec 26 12:37:28 2013 -0800
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/ShortCircuitParser.java	Tue Jan 07 12:22:47 2014 +0100
@@ -29,7 +29,6 @@
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.*;
 import com.oracle.truffle.dsl.processor.template.*;
 
 public class ShortCircuitParser extends NodeMethodParser<ShortCircuitData> {
@@ -40,15 +39,17 @@
         super(context, node);
 
         shortCircuitValues = new HashSet<>();
-        NodeChildData[] shortCircuitFields = node.filterFields(ExecutionKind.SHORT_CIRCUIT);
-        for (NodeChildData field : shortCircuitFields) {
-            shortCircuitValues.add(field.getName());
+        for (NodeExecutionData execution : node.getChildExecutions()) {
+            if (execution.isShortCircuit()) {
+                shortCircuitValues.add(execution.getShortCircuitId());
+            }
         }
     }
 
     @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
         String shortCircuitValue = Utils.getAnnotationValue(String.class, mirror, "value");
+
         return createDefaultMethodSpec(method, mirror, true, shortCircuitValue);
     }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java	Thu Dec 26 12:37:28 2013 -0800
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java	Tue Jan 07 12:22:47 2014 +0100
@@ -99,20 +99,12 @@
             return false;
         }
 
-        for (ActualParameter parameter : getParameters()) {
-            if (!parameter.getSpecification().isSignature()) {
-                continue;
-            }
-            NodeChildData child = getNode().findChild(parameter.getSpecification().getName());
-            if (child == null) {
-                continue;
-            }
+        for (ActualParameter parameter : getSignatureParameters()) {
             ActualParameter genericParameter = getNode().getGenericSpecialization().findParameter(parameter.getLocalName());
             if (!parameter.getTypeSystemType().equals(genericParameter.getTypeSystemType())) {
                 return false;
             }
         }
-
         return true;
     }
 
@@ -126,12 +118,8 @@
         if (!getAssumptions().isEmpty()) {
             return true;
         }
-        for (ActualParameter parameter : getParameters()) {
-            NodeChildData child = getNode().findChild(parameter.getSpecification().getName());
-            if (child == null) {
-                continue;
-            }
-            ExecutableTypeData type = child.findExecutableType(context, parameter.getTypeSystemType());
+        for (ActualParameter parameter : getSignatureParameters()) {
+            ExecutableTypeData type = parameter.getSpecification().getExecution().getChild().findExecutableType(context, parameter.getTypeSystemType());
             if (type.hasUnexpectedValue(context)) {
                 return true;
             }
@@ -254,7 +242,7 @@
 
     @Override
     public String toString() {
-        return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getSignature());
+        return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getTypeSignature());
     }
 
     public void forceFrame(TypeMirror frameType) {
@@ -267,7 +255,7 @@
     }
 
     public boolean equalsGuards(SpecializationData specialization) {
-        if (assumptions.equals(specialization.getAssumptions()) && guards.equals(specialization.getGuards()) && getSignature().equalsParameters(specialization.getSignature())) {
+        if (assumptions.equals(specialization.getAssumptions()) && guards.equals(specialization.getGuards()) && getTypeSignature().equalsParameters(specialization.getTypeSignature())) {
             return true;
         }
         return false;
@@ -281,4 +269,5 @@
         }
         return false;
     }
+
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java	Thu Dec 26 12:37:28 2013 -0800
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationGroup.java	Tue Jan 07 12:22:47 2014 +0100
@@ -28,7 +28,7 @@
 
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.template.*;
-import com.oracle.truffle.dsl.processor.template.TemplateMethod.Signature;
+import com.oracle.truffle.dsl.processor.template.TemplateMethod.TypeSignature;
 import com.oracle.truffle.dsl.processor.typesystem.*;
 
 /**
@@ -55,7 +55,7 @@
         this.specialization = data;
 
         this.assumptions.addAll(data.getAssumptions());
-        Signature sig = data.getSignature();
+        TypeSignature sig = data.getTypeSignature();
         for (int i = 1; i < sig.size(); i++) {
             typeGuards.add(new TypeGuard(sig.get(i), i - 1));
         }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java	Thu Dec 26 12:37:28 2013 -0800
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ActualParameter.java	Tue Jan 07 12:22:47 2014 +0100
@@ -33,24 +33,24 @@
     private TypeData typeSystemType;
     private TemplateMethod method;
     private final String localName;
-    private final int specificationIndex;
-    private final int varArgsIndex;
+    private final int specificationVarArgsIndex;
+    private final int typeVarArgsIndex;
     private final boolean implicit;
-    private final TypeMirror type;
+    private final TypeMirror actualType;
 
-    public ActualParameter(ParameterSpec specification, TypeMirror actualType, int specificationIndex, int varArgsIndex, boolean implicit) {
+    public ActualParameter(ParameterSpec specification, TypeMirror actualType, int specificationVarArgsIndex, int typeVarArgsIndex, boolean implicit) {
         this.specification = specification;
-        this.type = actualType;
+        this.actualType = actualType;
         this.typeSystemType = null;
 
-        this.specificationIndex = specificationIndex;
+        this.specificationVarArgsIndex = specificationVarArgsIndex;
         this.implicit = implicit;
-        String valueName = specification.getName() + "Value";
 
-        if (specification.isIndexed()) {
-            valueName += specificationIndex;
+        String valueName = specification.getName() + "Value";
+        if (specificationVarArgsIndex > -1) {
+            valueName += "_" + specificationVarArgsIndex;
         }
-        this.varArgsIndex = varArgsIndex;
+        this.typeVarArgsIndex = typeVarArgsIndex;
         this.localName = valueName;
     }
 
@@ -60,29 +60,29 @@
     }
 
     public ActualParameter(ActualParameter parameter, TypeData otherType) {
-        this(parameter.specification, otherType, parameter.specificationIndex, parameter.varArgsIndex, parameter.implicit);
+        this(parameter.specification, otherType, parameter.specificationVarArgsIndex, parameter.typeVarArgsIndex, parameter.implicit);
     }
 
     public ActualParameter(ActualParameter parameter) {
         this.specification = parameter.specification;
-        this.type = parameter.type;
+        this.actualType = parameter.actualType;
         this.typeSystemType = parameter.typeSystemType;
-        this.specificationIndex = parameter.specificationIndex;
+        this.specificationVarArgsIndex = parameter.specificationVarArgsIndex;
         this.implicit = parameter.implicit;
         this.localName = parameter.localName;
-        this.varArgsIndex = parameter.varArgsIndex;
+        this.typeVarArgsIndex = parameter.typeVarArgsIndex;
     }
 
-    public int getVarArgsIndex() {
-        return varArgsIndex;
+    public int getTypeVarArgsIndex() {
+        return typeVarArgsIndex;
     }
 
     public boolean isImplicit() {
         return implicit;
     }
 
-    public int getSpecificationIndex() {
-        return specificationIndex;
+    public int getSpecificationVarArgsIndex() {
+        return specificationVarArgsIndex;
     }
 
     public String getLocalName() {
@@ -102,15 +102,15 @@
     }
 
     public TypeMirror getType() {
-        return type;
+        return actualType;
     }
 
     public TypeData getTypeSystemType() {
         return typeSystemType;
     }
 
-    public boolean isVarArgs() {
-        return varArgsIndex >= 0;
+    public boolean isTypeVarArgs() {
+        return typeVarArgsIndex >= 0;
     }
 
     public ActualParameter getPreviousParameter() {
@@ -119,6 +119,6 @@
 
     @Override
     public String toString() {
-        return Utils.getSimpleName(type);
+        return Utils.getSimpleName(actualType);
     }
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java	Thu Dec 26 12:37:28 2013 -0800
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java	Tue Jan 07 12:22:47 2014 +0100
@@ -64,8 +64,8 @@
         }
         verifyExpectedMessages(context, log, childMessages);
 
-        for (Message message : getMessages()) {
-            emitDefault(context, baseElement, log, message);
+        for (int i = getMessages().size() - 1; i >= 0; i--) {
+            emitDefault(context, baseElement, log, getMessages().get(i));
         }
 
         for (MessageContainer sink : findChildContainers()) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MethodSpec.java	Thu Dec 26 12:37:28 2013 -0800
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MethodSpec.java	Tue Jan 07 12:22:47 2014 +0100
@@ -27,7 +27,6 @@
 import javax.lang.model.type.*;
 
 import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.*;
 
 public class MethodSpec {
 
@@ -37,34 +36,36 @@
     private final List<ParameterSpec> optional = new ArrayList<>();
     private final List<ParameterSpec> required = new ArrayList<>();
 
-    private int minimumRequiredArguments;
-    private boolean variableRequiredArguments;
+    private boolean ignoreAdditionalParameters;
+    private boolean ignoreAdditionalSpecifications;
+    private boolean variableRequiredParameters;
+
     private List<TypeDef> typeDefinitions;
 
     public MethodSpec(ParameterSpec returnType) {
         this.returnType = returnType;
     }
 
-    public void setMinimumRequiredArguments(int minimumRequiredArguments) {
-        this.minimumRequiredArguments = minimumRequiredArguments;
+    public void setVariableRequiredParameters(boolean variableRequiredParameters) {
+        this.variableRequiredParameters = variableRequiredParameters;
     }
 
-    public int getMinimumRequiredArguments() {
-        return minimumRequiredArguments;
-    }
-
-    public void setVariableRequiredArguments(boolean variableArguments) {
-        this.variableRequiredArguments = variableArguments;
-    }
-
-    public boolean isVariableRequiredArguments() {
-        return variableRequiredArguments;
+    public boolean isVariableRequiredParameters() {
+        return variableRequiredParameters;
     }
 
     public void addImplicitRequiredType(TypeMirror type) {
         this.implicitRequiredTypes.add(type);
     }
 
+    public void setIgnoreAdditionalParameters(boolean ignoreAdditionalParameter) {
+        this.ignoreAdditionalParameters = ignoreAdditionalParameter;
+    }
+
+    public boolean isIgnoreAdditionalParameters() {
+        return ignoreAdditionalParameters;
+    }
+
     public void addOptional(ParameterSpec spec) {
         optional.add(spec);
     }
@@ -158,15 +159,18 @@
             sep = ", ";
         }
 
-        for (ParameterSpec requiredSpec : getRequired()) {
+        for (int i = 0; i < getRequired().size(); i++) {
+            ParameterSpec requiredSpec = getRequired().get(i);
             b.append(sep);
-            if (requiredSpec.getCardinality() == Cardinality.MANY) {
-                b.append("{");
+
+            if (isVariableRequiredParameters() && i == getRequired().size() - 1) {
+                b.append(("{"));
             }
             b.append(createTypeSignature(requiredSpec, false));
-            if (requiredSpec.getCardinality() == Cardinality.MANY) {
-                b.append("}");
+            if (isVariableRequiredParameters() && i == getRequired().size() - 1) {
+                b.append(("}"));
             }
+
             sep = ", ";
         }
 
@@ -234,4 +238,12 @@
         }
     }
 
+    public void setIgnoreAdditionalSpecifications(boolean ignoreAdditoinalSpecifications) {
+        this.ignoreAdditionalSpecifications = ignoreAdditoinalSpecifications;
+    }
+
+    public boolean isIgnoreAdditionalSpecifications() {
+        return ignoreAdditionalSpecifications;
+    }
+
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ParameterSpec.java	Thu Dec 26 12:37:28 2013 -0800
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/ParameterSpec.java	Tue Jan 07 12:22:47 2014 +0100
@@ -27,44 +27,46 @@
 import javax.lang.model.type.*;
 
 import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.*;
-import com.oracle.truffle.dsl.processor.template.MethodSpec.*;
+import com.oracle.truffle.dsl.processor.node.*;
+import com.oracle.truffle.dsl.processor.template.MethodSpec.TypeDef;
 
 public class ParameterSpec {
 
     private final String name;
     private final List<TypeMirror> allowedTypes;
 
-    /** Cardinality one or multiple. */
-    private Cardinality cardinality = Cardinality.ONE;
-    /** Type is part of the method signature. Relevant for comparisons. */
-    private boolean signature;
-    /** Type must be indexed when parsing. */
-    private boolean indexed;
     /** Type is bound to local final variable. */
     private boolean local;
 
+    /** Optional bound execution of node. */
+    private NodeExecutionData execution;
     private TypeDef typeDefinition;
 
-    public ParameterSpec(String name, TypeMirror... allowedTypes) {
-        this(name, Arrays.asList(allowedTypes));
-    }
-
     public ParameterSpec(String name, List<TypeMirror> allowedTypes) {
         this.name = name;
         this.allowedTypes = allowedTypes;
     }
 
+    public ParameterSpec(String name, TypeMirror type) {
+        this(name, Arrays.asList(type));
+    }
+
     public ParameterSpec(ParameterSpec o, List<TypeMirror> allowedTypes) {
         this.name = o.name;
-        this.cardinality = o.cardinality;
-        this.signature = o.signature;
-        this.indexed = o.indexed;
         this.local = o.local;
         this.typeDefinition = o.typeDefinition;
+        this.execution = o.execution;
         this.allowedTypes = allowedTypes;
     }
 
+    public NodeExecutionData getExecution() {
+        return execution;
+    }
+
+    public void setExecution(NodeExecutionData executionData) {
+        this.execution = executionData;
+    }
+
     void setTypeDefinition(TypeDef typeDefinition) {
         this.typeDefinition = typeDefinition;
     }
@@ -73,42 +75,22 @@
         return typeDefinition;
     }
 
-    public void setSignature(boolean signature) {
-        this.signature = signature;
-    }
-
     public void setLocal(boolean local) {
         this.local = local;
     }
 
     public boolean isSignature() {
-        return signature;
+        return execution != null;
     }
 
     public boolean isLocal() {
         return local;
     }
 
-    public boolean isIndexed() {
-        return indexed;
-    }
-
-    public void setIndexed(boolean indexed) {
-        this.indexed = indexed;
-    }
-
-    public void setCardinality(Cardinality cardinality) {
-        this.cardinality = cardinality;
-    }
-
     public String getName() {
         return name;
     }
 
-    public Cardinality getCardinality() {
-        return cardinality;
-    }
-
     public List<TypeMirror> getAllowedTypes() {
         return allowedTypes;
     }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java	Thu Dec 26 12:37:28 2013 -0800
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java	Tue Jan 07 12:22:47 2014 +0100
@@ -29,6 +29,7 @@
 
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.typesystem.*;
+import com.oracle.truffle.dsl.processor.util.*;
 
 /**
  * Note: this class has a natural ordering that is inconsistent with equals.
@@ -133,6 +134,14 @@
         return requiredParameters;
     }
 
+    public Iterable<ActualParameter> getSignatureParameters() {
+        return new FilteredIterable<>(getParameters(), new Predicate<ActualParameter>() {
+            public boolean evaluate(ActualParameter value) {
+                return value.getSpecification().isSignature();
+            }
+        });
+    }
+
     public List<ActualParameter> getParameters() {
         return parameters;
     }
@@ -213,12 +222,10 @@
         return signatureSize;
     }
 
-    public Signature getSignature() {
-        Signature signature = new Signature();
-        for (ActualParameter parameter : getReturnTypeAndParameters()) {
-            if (!parameter.getSpecification().isSignature()) {
-                continue;
-            }
+    public TypeSignature getTypeSignature() {
+        TypeSignature signature = new TypeSignature();
+        signature.types.add(getReturnType().getTypeSystemType());
+        for (ActualParameter parameter : getSignatureParameters()) {
             TypeData typeData = parameter.getTypeSystemType();
             if (typeData != null) {
                 signature.types.add(typeData);
@@ -241,7 +248,7 @@
         return null;
     }
 
-    public void updateSignature(Signature signature) {
+    public void updateSignature(TypeSignature signature) {
         assert signature.size() >= 1;
         int signatureIndex = 0;
         for (ActualParameter parameter : getReturnTypeAndParameters()) {
@@ -297,8 +304,8 @@
             throw new IllegalStateException("Cannot compare two methods with different type systems.");
         }
 
-        List<TypeMirror> signature1 = getSignatureTypes(getReturnTypeAndParameters());
-        List<TypeMirror> signature2 = getSignatureTypes(compareMethod.getReturnTypeAndParameters());
+        List<TypeMirror> signature1 = getSignatureTypes(this);
+        List<TypeMirror> signature2 = getSignatureTypes(compareMethod);
         if (signature1.size() != signature2.size()) {
             return signature2.size() - signature1.size();
         }
@@ -347,25 +354,24 @@
         return Utils.getSimpleName(signature1).compareTo(Utils.getSimpleName(signature2));
     }
 
-    public static List<TypeMirror> getSignatureTypes(List<ActualParameter> params) {
+    public static List<TypeMirror> getSignatureTypes(TemplateMethod method) {
         List<TypeMirror> types = new ArrayList<>();
-        for (ActualParameter param : params) {
-            if (param.getSpecification().isSignature()) {
-                types.add(param.getType());
-            }
+        types.add(method.getReturnType().getType());
+        for (ActualParameter param : method.getSignatureParameters()) {
+            types.add(param.getType());
         }
         return types;
     }
 
-    public static class Signature implements Iterable<TypeData>, Comparable<Signature> {
+    public static class TypeSignature implements Iterable<TypeData>, Comparable<TypeSignature> {
 
         final List<TypeData> types;
 
-        public Signature() {
+        public TypeSignature() {
             this.types = new ArrayList<>();
         }
 
-        public Signature(List<TypeData> signature) {
+        public TypeSignature(List<TypeData> signature) {
             this.types = signature;
         }
 
@@ -382,7 +388,7 @@
             return types.get(index);
         }
 
-        public int compareTo(Signature other) {
+        public int compareTo(TypeSignature other) {
             if (this == other) {
                 return 0;
             } else if (types.size() != other.types.size()) {
@@ -404,7 +410,7 @@
             return 0;
         }
 
-        public Signature combine(Signature genericSignature, Signature other) {
+        public TypeSignature combine(TypeSignature genericSignature, TypeSignature other) {
             assert types.size() == other.types.size();
             assert genericSignature.types.size() == other.types.size();
 
@@ -412,7 +418,7 @@
                 return this;
             }
 
-            Signature signature = new Signature();
+            TypeSignature signature = new TypeSignature();
             for (int i = 0; i < types.size(); i++) {
                 TypeData type1 = types.get(i);
                 TypeData type2 = other.types.get(i);
@@ -425,7 +431,7 @@
             return signature;
         }
 
-        public boolean equalsParameters(Signature other) {
+        public boolean equalsParameters(TypeSignature other) {
             if (size() != other.size()) {
                 return false;
             }
@@ -434,8 +440,8 @@
 
         @Override
         public boolean equals(Object obj) {
-            if (obj instanceof Signature) {
-                return ((Signature) obj).types.equals(types);
+            if (obj instanceof TypeSignature) {
+                return ((TypeSignature) obj).types.equals(types);
             }
             return super.equals(obj);
         }
@@ -449,7 +455,7 @@
             return types.toString();
         }
 
-        public boolean hasAnyParameterMatch(Signature other) {
+        public boolean hasAnyParameterMatch(TypeSignature other) {
             for (int i = 1; i < types.size(); i++) {
                 TypeData type1 = types.get(i);
                 TypeData type2 = other.types.get(i);
@@ -460,7 +466,7 @@
             return false;
         }
 
-        public boolean isCompatibleTo(Signature signature) {
+        public boolean isCompatibleTo(TypeSignature signature) {
             if (size() != signature.size()) {
                 return false;
             }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java	Thu Dec 26 12:37:28 2013 -0800
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethodParser.java	Tue Jan 07 12:22:47 2014 +0100
@@ -33,7 +33,6 @@
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.node.NodeChildData.*;
 import com.oracle.truffle.dsl.processor.typesystem.*;
 
 public abstract class TemplateMethodParser<T extends Template, E extends TemplateMethod> {
@@ -147,14 +146,23 @@
             id = Utils.getAnnotationValue(String.class, idAnnotation, "value");
         }
 
-        ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
+        TypeMirror returnType = method.getReturnType();
+        List<TypeMirror> parameterTypes = new ArrayList<>();
+        for (VariableElement var : method.getParameters()) {
+            parameterTypes.add(var.asType());
+        }
 
-        ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, -1, false);
+        return parseImpl(methodSpecification, id, method, annotation, returnType, parameterTypes);
+    }
+
+    private E parseImpl(MethodSpec methodSpecification, String id, ExecutableElement method, AnnotationMirror annotation, TypeMirror returnType, List<TypeMirror> parameterTypes) {
+        ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
+        ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, returnType, template, -1, -1, false);
         if (returnTypeMirror == null) {
             if (emitErrors) {
                 E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()), true);
                 String expectedReturnType = returnTypeSpec.toSignatureString(true);
-                String actualReturnType = Utils.getSimpleName(method.getReturnType());
+                String actualReturnType = Utils.getSimpleName(returnType);
 
                 String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
                                 methodSpecification.toSignatureString(method.getSimpleName().toString()));
@@ -165,12 +173,7 @@
             }
         }
 
-        List<TypeMirror> parameterTypes = new ArrayList<>();
-        for (VariableElement var : method.getParameters()) {
-            parameterTypes.add(var.asType());
-        }
-
-        List<ActualParameter> parameters = parseParameters(methodSpecification, parameterTypes, isUseVarArgs() && method.isVarArgs());
+        List<ActualParameter> parameters = parseParameters(methodSpecification, parameterTypes, isUseVarArgs() && method != null ? method.isVarArgs() : false);
         if (parameters == null) {
             if (isEmitErrors()) {
                 E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()), true);
@@ -207,34 +210,31 @@
      * Parameter parsing tries to parse required arguments starting from offset 0 with increasing
      * offset until it finds a signature end that matches the required specification. If there is no
      * end matching the required arguments, parsing fails. Parameters prior to the parsed required
-     * ones are cut and used to parse the optional parameters. All those remaining parameters must
-     * be consumed otherwise its an error.
+     * ones are cut and used to parse the optional parameters.
      */
     private List<ActualParameter> parseParameters(MethodSpec spec, List<TypeMirror> parameterTypes, boolean varArgs) {
         List<TypeMirror> implicitTypes = spec.getImplicitRequiredTypes();
 
-        int offset = -1;
         List<ActualParameter> parsedRequired = null;
-        ConsumableListIterator<TypeMirror> types = null;
-        while (parsedRequired == null && offset < parameterTypes.size()) {
-            offset++;
-            types = new ConsumableListIterator<>(new ArrayList<>(implicitTypes));
-            types.data.addAll(parameterTypes.subList(offset, parameterTypes.size()));
-            parsedRequired = parseParametersRequired(spec, types, varArgs);
+        int offset = 0;
+        for (; offset <= parameterTypes.size(); offset++) {
+            List<TypeMirror> parameters = new ArrayList<>(implicitTypes);
+            parameters.addAll(parameterTypes.subList(offset, parameterTypes.size()));
+            parsedRequired = parseParametersRequired(spec, parameters, varArgs);
+            if (parsedRequired != null) {
+                break;
+            }
         }
 
-        if (parsedRequired == null && offset >= 0) {
+        if (parsedRequired == null) {
             return null;
         }
 
-        List<TypeMirror> potentialOptionals;
-        if (offset == -1) {
-            potentialOptionals = parameterTypes;
-        } else {
-            potentialOptionals = parameterTypes.subList(0, offset);
+        if (parsedRequired.isEmpty() && offset == 0) {
+            offset = parameterTypes.size();
         }
-        types = new ConsumableListIterator<>(potentialOptionals);
-        List<ActualParameter> parsedOptionals = parseParametersOptional(spec, types);
+        List<TypeMirror> potentialOptionals = parameterTypes.subList(0, offset);
+        List<ActualParameter> parsedOptionals = parseParametersOptional(spec, potentialOptionals);
         if (parsedOptionals == null) {
             return null;
         }
@@ -245,99 +245,105 @@
         return finalParameters;
     }
 
-    private List<ActualParameter> parseParametersOptional(MethodSpec spec, ConsumableListIterator<TypeMirror> types) {
+    private List<ActualParameter> parseParametersOptional(MethodSpec spec, List<TypeMirror> types) {
         List<ActualParameter> parsedParams = new ArrayList<>();
-        // parse optional parameters
-        ConsumableListIterator<ParameterSpec> optionals = new ConsumableListIterator<>(spec.getOptional());
-        for (TypeMirror type : types) {
-            int oldIndex = types.getIndex();
-            int optionalCount = 1;
-            for (ParameterSpec paramspec : optionals) {
-                ActualParameter optionalParam = matchParameter(paramspec, type, template, 0, -1, false);
+
+        int typeStartIndex = 0;
+        List<ParameterSpec> specifications = spec.getOptional();
+        outer: for (int specIndex = 0; specIndex < specifications.size(); specIndex++) {
+            ParameterSpec specification = specifications.get(specIndex);
+            for (int typeIndex = typeStartIndex; typeIndex < types.size(); typeIndex++) {
+                TypeMirror actualType = types.get(typeIndex);
+                ActualParameter optionalParam = matchParameter(specification, actualType, template, -1, -1, false);
                 if (optionalParam != null) {
-                    optionals.consume(optionalCount);
-                    types.consume();
                     parsedParams.add(optionalParam);
-                    break;
+                    typeStartIndex = typeIndex + 1;
+                    continue outer;
                 }
-                optionalCount++;
-            }
-            if (oldIndex == types.getIndex()) {
-                // nothing found anymore skip optional
-                break;
             }
         }
-        if (types.getIndex() <= types.data.size() - 1) {
+
+        if (typeStartIndex < types.size()) {
+            // not enough types found
             return null;
         }
         return parsedParams;
     }
 
-    private List<ActualParameter> parseParametersRequired(MethodSpec spec, ConsumableListIterator<TypeMirror> types, boolean varArgs) {
+    private List<ActualParameter> parseParametersRequired(MethodSpec spec, List<TypeMirror> types, boolean typeVarArgs) {
         List<ActualParameter> parsedParams = new ArrayList<>();
+        List<ParameterSpec> specifications = spec.getRequired();
+        boolean specVarArgs = spec.isVariableRequiredParameters();
+        int typeIndex = 0;
+        int specificationIndex = 0;
 
-        int varArgsParameterIndex = -1;
-        int specificationParameterIndex = 0;
-        ConsumableListIterator<ParameterSpec> required = new ConsumableListIterator<>(spec.getRequired());
-        while (required.get() != null || types.get() != null) {
-            if (required.get() == null || types.get() == null) {
-                if (required.get() != null && required.get().getCardinality() == Cardinality.MANY) {
-                    required.consume();
-                    specificationParameterIndex = 0;
-                    continue;
+        ParameterSpec specification;
+        while ((specification = nextSpecification(specifications, specificationIndex, specVarArgs)) != null) {
+            TypeMirror actualType = nextActualType(types, typeIndex, typeVarArgs);
+            if (actualType == null) {
+                if (spec.isIgnoreAdditionalSpecifications()) {
+                    break;
                 }
+                return null;
+            }
+
+            boolean implicit = typeIndex < spec.getImplicitRequiredTypes().size();
+            int typeVarArgsIndex = typeVarArgs ? typeIndex - types.size() + 1 : -1;
+            int specVarArgsIndex = specVarArgs ? specificationIndex - specifications.size() + 1 : -1;
+
+            if (typeVarArgsIndex >= 0 && specVarArgsIndex >= 0) {
+                // both specifications and types have a variable number of arguments
+                // we would get into an endless loop if we would continue
                 break;
             }
-            TypeMirror actualType = types.get();
-            if (varArgs && types.isLast()) {
-                if (actualType.getKind() == TypeKind.ARRAY) {
-                    actualType = ((ArrayType) actualType).getComponentType();
-                }
-                varArgsParameterIndex++;
+
+            ActualParameter resolvedParameter = matchParameter(specification, actualType, template, specVarArgsIndex, typeVarArgsIndex, implicit);
+            if (resolvedParameter == null) {
+                return null;
             }
-            boolean implicit = types.getIndex() < spec.getImplicitRequiredTypes().size();
-            ActualParameter resolvedParameter = matchParameter(required.get(), actualType, template, specificationParameterIndex, varArgsParameterIndex, implicit);
-            if (resolvedParameter == null) {
-                if (required.get().getCardinality() == Cardinality.MANY) {
-                    required.consume();
-                    continue;
-                }
-                // direct mismatch but required -> error
-                return null;
+            parsedParams.add(resolvedParameter);
+            typeIndex++;
+            specificationIndex++;
+        }
+
+        if (typeIndex < types.size()) {
+            // additional types available
+            if (spec.isIgnoreAdditionalParameters()) {
+                return parsedParams;
             } else {
-                parsedParams.add(resolvedParameter);
-
-                if (varArgs && types.isLast()) {
-                    /* Both varargs spec and varargs definition. Need to consume to terminate. */
-                    if (required.get().getCardinality() == Cardinality.MANY) {
-                        types.consume();
-                    }
-                } else {
-                    types.consume();
-                }
-
-                if (required.get().getCardinality() == Cardinality.ONE) {
-                    required.consume();
-                    specificationParameterIndex = 0;
-                } else if (required.get().getCardinality() == Cardinality.MANY) {
-                    specificationParameterIndex++;
-                }
+                return null;
             }
         }
 
-        if (!types.toList().isEmpty() && !(varArgs && types.isLast())) {
-            // additional types -> error
-            return null;
-        }
-
-        if (!required.toList().isEmpty() && !spec.isVariableRequiredArguments()) {
-            // additional specifications -> error
-            return null;
-        }
         return parsedParams;
     }
 
-    private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template originalTemplate, int specificationIndex, int varArgsIndex, boolean implicit) {
+    private static ParameterSpec nextSpecification(List<ParameterSpec> specifications, int specIndex, boolean varArgs) {
+        if (varArgs && specIndex >= specifications.size() - 1 && !specifications.isEmpty()) {
+            return specifications.get(specifications.size() - 1);
+        } else if (specIndex < specifications.size()) {
+            return specifications.get(specIndex);
+        } else {
+            return null;
+        }
+    }
+
+    private static TypeMirror nextActualType(List<TypeMirror> types, int typeIndex, boolean varArgs) {
+        if (varArgs && typeIndex >= types.size() - 1 && !types.isEmpty()) {
+            // unpack varargs array argument
+            TypeMirror actualType = types.get(types.size() - 1);
+            if (actualType.getKind() == TypeKind.ARRAY) {
+                actualType = ((ArrayType) actualType).getComponentType();
+            }
+            return actualType;
+        } else if (typeIndex < types.size()) {
+            return types.get(typeIndex);
+        } else {
+            return null;
+        }
+    }
+
+    protected final ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template originalTemplate, int specificationIndex, int varArgsIndex, boolean implicit) {
         TypeMirror resolvedType = mirror;
         if (hasError(resolvedType)) {
             resolvedType = context.resolveNotYetCompiledType(mirror, originalTemplate);
@@ -355,57 +361,7 @@
         }
     }
 
-    /* Helper class for parsing. */
-    private static class ConsumableListIterator<E> implements Iterable<E> {
-
-        private final List<E> data;
-        private int index;
-
-        public ConsumableListIterator(List<E> data) {
-            this.data = data;
-        }
-
-        public E get() {
-            if (index >= data.size()) {
-                return null;
-            }
-            return data.get(index);
-        }
-
-        public boolean isLast() {
-            return index == data.size() - 1;
-        }
-
-        public E consume() {
-            return consume(1);
-        }
-
-        public E consume(int count) {
-            if (index + count <= data.size()) {
-                index += count;
-                return get();
-            } else {
-                throw new ArrayIndexOutOfBoundsException(count + 1);
-            }
-        }
-
-        public int getIndex() {
-            return index;
-        }
-
-        @Override
-        public Iterator<E> iterator() {
-            return toList().iterator();
-        }
-
-        public List<E> toList() {
-            if (index < data.size()) {
-                return data.subList(index, data.size());
-            } else {
-                return Collections.<E> emptyList();
-            }
-        }
-
+    public final E create(String id, ExecutableElement methodMetadata, AnnotationMirror mirror, TypeMirror returnType, List<TypeMirror> parameterTypes) {
+        return parseImpl(createSpecification(methodMetadata, mirror), id, methodMetadata, mirror, returnType, parameterTypes);
     }
-
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java	Thu Dec 26 12:37:28 2013 -0800
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/GuardParser.java	Tue Jan 07 12:22:47 2014 +0100
@@ -23,10 +23,8 @@
 package com.oracle.truffle.dsl.processor.typesystem;
 
 import java.lang.annotation.*;
-import java.util.*;
 
 import javax.lang.model.element.*;
-import javax.lang.model.type.*;
 
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.node.*;
@@ -53,16 +51,18 @@
     }
 
     @Override
+    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
+        return super.createValueParameterSpec(execution);
+    }
+
+    @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
         MethodSpec spec = createDefaultMethodSpec(method, mirror, true, null);
-        spec.setVariableRequiredArguments(true);
+        spec.setIgnoreAdditionalSpecifications(true);
         spec.getRequired().clear();
 
         for (ActualParameter parameter : specialization.getRequiredParameters()) {
-            List<TypeMirror> assignableTypes = Utils.getAssignableTypes(getContext(), parameter.getType());
-            ParameterSpec paramSpec = new ParameterSpec(parameter.getLocalName(), assignableTypes);
-            paramSpec.setSignature(true);
-            spec.addRequired(paramSpec);
+            spec.addRequired(new ParameterSpec(parameter.getSpecification(), Utils.getAssignableTypes(getContext(), parameter.getType())));
         }
 
         return spec;
@@ -80,31 +80,7 @@
 
     @Override
     public GuardData create(TemplateMethod method, boolean invalid) {
-        GuardData guard = new GuardData(method, specialization, negated);
-        /*
-         * Update parameters in way that parameter specifications match again the node field names
-         * etc.
-         */
-        List<ActualParameter> newParameters = new ArrayList<>();
-        for (ActualParameter parameter : guard.getParameters()) {
-            ActualParameter specializationParameter = specialization.findParameter(parameter.getSpecification().getName());
-            if (specializationParameter == null) {
-                newParameters.add(parameter);
-            } else {
-                ActualParameter p;
-                if (parameter.getTypeSystemType() != null) {
-                    p = new ActualParameter(specializationParameter.getSpecification(), parameter.getTypeSystemType(), specializationParameter.getSpecificationIndex(),
-                                    specializationParameter.getVarArgsIndex(), parameter.isImplicit());
-                } else {
-                    p = new ActualParameter(specializationParameter.getSpecification(), parameter.getType(), specializationParameter.getSpecificationIndex(),
-                                    specializationParameter.getVarArgsIndex(), parameter.isImplicit());
-                }
-                newParameters.add(p);
-            }
-        }
-        guard.setParameters(newParameters);
-
-        return guard;
+        return new GuardData(method, specialization, negated);
     }
 
     @Override
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastParser.java	Thu Dec 26 12:37:28 2013 -0800
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/ImplicitCastParser.java	Tue Jan 07 12:22:47 2014 +0100
@@ -50,7 +50,7 @@
             types.add(typeData.getPrimitiveType());
         }
         MethodSpec spec = new MethodSpec(new ParameterSpec("target", types));
-        spec.addRequired(new ParameterSpec("source", types)).setSignature(true);
+        spec.addRequired(new ParameterSpec("source", types));
         return spec;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/Filterator.java	Tue Jan 07 12:22:47 2014 +0100
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.util;
+
+import java.util.*;
+
+public class Filterator<T> implements Iterator<T> {
+
+    private final Predicate<T> includePredicate;
+    private final Iterator<T> elements;
+
+    private boolean hasCached;
+    private T cached;
+
+    public Filterator(Iterator<T> elements, Predicate<T> includePredicate) {
+        this.elements = elements;
+        this.includePredicate = includePredicate;
+    }
+
+    public boolean hasNext() {
+        if (hasCached) {
+            return true;
+        }
+        nextValue();
+        return hasCached;
+    }
+
+    private void nextValue() {
+        while (!hasCached && elements.hasNext()) {
+            T element = elements.next();
+            if (includePredicate.evaluate(element)) {
+                cached = element;
+                hasCached = true;
+            }
+        }
+    }
+
+    public T next() {
+        T foundCached = getCached();
+        if (foundCached != null) {
+            return foundCached;
+        } else {
+            nextValue();
+            if (!hasCached) {
+                throw new NoSuchElementException();
+            }
+            return getCached();
+        }
+    }
+
+    private T getCached() {
+        if (hasCached) {
+            hasCached = false;
+            T value = cached;
+            cached = null;
+            return value;
+        }
+        return null;
+    }
+
+    public void remove() {
+        elements.remove();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/FilteredIterable.java	Tue Jan 07 12:22:47 2014 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.util;
+
+import java.util.*;
+
+public class FilteredIterable<E> implements Iterable<E> {
+
+    private final Iterable<E> delegate;
+    private final Predicate<E> containedPredicate;
+
+    public FilteredIterable(Iterable<E> delegate, Predicate<E> containedPredicate) {
+        this.delegate = delegate;
+        this.containedPredicate = containedPredicate;
+    }
+
+    public Iterator<E> iterator() {
+        return new Filterator<>(delegate.iterator(), containedPredicate);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/Predicate.java	Tue Jan 07 12:22:47 2014 +0100
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.util;
+
+public interface Predicate<T> {
+
+    boolean evaluate(T value);
+
+}