changeset 8595:8a1115c92271

Implemented codegen guard definitions can now omit unused parameters.
author Christian Humer <christian.humer@gmail.com>
date Mon, 01 Apr 2013 21:43:20 +0200
parents ce6e8672f798
children 6ef9fc7375c7
files graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/MethodParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java
diffstat 17 files changed, 648 insertions(+), 488 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java	Mon Apr 01 12:19:15 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Log.java	Mon Apr 01 21:43:20 2013 +0200
@@ -33,7 +33,7 @@
  */
 public class Log {
 
-    public static final boolean DEBUG = false;
+    public static final boolean DEBUG = true;
 
     private final ProcessingEnvironment processingEnv;
 
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java	Mon Apr 01 12:19:15 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java	Mon Apr 01 21:43:20 2013 +0200
@@ -42,18 +42,16 @@
 
     @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+
         List<TypeMirror> types = new ArrayList<>();
         types.addAll(getNode().getTypeSystem().getPrimitiveTypeMirrors());
         types.add(getContext().getType(void.class));
 
         ParameterSpec returnTypeSpec = new ParameterSpec("executedValue", types);
         returnTypeSpec.setSignature(true);
-
-        List<ParameterSpec> parameters = new ArrayList<>();
-        ParameterSpec frameSpec = new ParameterSpec("frame", getContext().getTruffleTypes().getFrame());
-        frameSpec.setOptional(true);
-        parameters.add(frameSpec);
-        return new MethodSpec(new ArrayList<TypeMirror>(), returnTypeSpec, parameters);
+        MethodSpec spec = new MethodSpec(returnTypeSpec);
+        spec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame()));
+        return spec;
     }
 
     @Override
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java	Mon Apr 01 12:19:15 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java	Mon Apr 01 21:43:20 2013 +0200
@@ -44,7 +44,7 @@
     }
 
     @Override
-    protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, boolean optional) {
+    protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData) {
         List<ExecutableTypeData> execTypes = nodeData.findGenericExecutableTypes(getContext());
         List<TypeMirror> types = new ArrayList<>();
         for (ExecutableTypeData type : execTypes) {
@@ -57,7 +57,7 @@
 
     @Override
     protected ParameterSpec createReturnParameterSpec() {
-        return super.createValueParameterSpec("returnValue", getNode(), false);
+        return super.createValueParameterSpec("returnValue", getNode());
     }
 
     @Override
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/MethodParser.java	Mon Apr 01 12:19:15 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.codegen.processor.node;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.codegen.processor.*;
-import com.oracle.truffle.codegen.processor.node.NodeFieldData.*;
-import com.oracle.truffle.codegen.processor.template.*;
-import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
-
-public abstract class MethodParser<E extends TemplateMethod> extends TemplateMethodParser<NodeData, E> {
-
-    public MethodParser(ProcessorContext context, NodeData node) {
-        super(context, node);
-    }
-
-    public NodeData getNode() {
-        return template;
-    }
-
-    protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, boolean optional) {
-        ParameterSpec spec = new ParameterSpec(valueName, nodeTypeMirrors(nodeData));
-        spec.setOptional(optional);
-        spec.setSignature(true);
-        return spec;
-    }
-
-    private static List<TypeMirror> nodeTypeMirrors(NodeData nodeData) {
-        Set<TypeMirror> typeMirrors = new LinkedHashSet<>();
-
-        for (ExecutableTypeData typeData : nodeData.getExecutableTypes()) {
-            typeMirrors.add(typeData.getType().getPrimitiveType());
-        }
-
-        typeMirrors.add(nodeData.getTypeSystem().getGenericType());
-
-        return new ArrayList<>(typeMirrors);
-    }
-
-    protected ParameterSpec createReturnParameterSpec() {
-        return createValueParameterSpec("operation", getNode(), false);
-    }
-
-    @Override
-    public boolean isParsable(ExecutableElement method) {
-        return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
-    }
-
-    @SuppressWarnings("unused")
-    protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, String shortCircuitName) {
-        List<ParameterSpec> defaultParameters = new ArrayList<>();
-
-        if (getNode().supportsFrame()) {
-            ParameterSpec frameSpec = new ParameterSpec("frame", getContext().getTruffleTypes().getFrame());
-            frameSpec.setOptional(true);
-            defaultParameters.add(frameSpec);
-        }
-
-        TypeMirror declaredType = Utils.findNearestEnclosingType(method).asType();
-
-        List<TypeMirror> prefixTypes = new ArrayList<>();
-
-        if (!method.getModifiers().contains(Modifier.STATIC) && !Utils.isAssignable(declaredType, template.getNodeType())) {
-            prefixTypes.add(getNode().getTemplateType().asType());
-        }
-
-        for (NodeFieldData field : getNode().getFields()) {
-            if (field.getKind() == FieldKind.FIELD) {
-                ParameterSpec spec = new ParameterSpec(field.getName(), field.getType());
-                spec.setOptional(true);
-                spec.setLocal(true);
-                defaultParameters.add(spec);
-            }
-        }
-
-        for (NodeFieldData field : getNode().getFields()) {
-            if (field.getExecutionKind() == ExecutionKind.IGNORE) {
-                continue;
-            }
-
-            if (field.getExecutionKind() == ExecutionKind.DEFAULT) {
-                ParameterSpec spec = createValueParameterSpec(field.getName(), field.getNodeData(), false);
-                if (field.getKind() == FieldKind.CHILDREN) {
-                    spec.setCardinality(Cardinality.MULTIPLE);
-                    spec.setIndexed(true);
-                }
-                defaultParameters.add(spec);
-            } else if (field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) {
-                String valueName = field.getName();
-                if (shortCircuitName != null && valueName.equals(shortCircuitName)) {
-                    break;
-                }
-
-                defaultParameters.add(new ParameterSpec(shortCircuitValueName(valueName), getContext().getType(boolean.class)));
-                defaultParameters.add(createValueParameterSpec(valueName, field.getNodeData(), false));
-            } else {
-                assert false;
-            }
-        }
-
-        return new MethodSpec(prefixTypes, createReturnParameterSpec(), defaultParameters);
-    }
-
-    private static String shortCircuitValueName(String valueName) {
-        return "has" + Utils.firstLetterUpperCase(valueName);
-    }
-
-}
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Mon Apr 01 12:19:15 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Mon Apr 01 21:43:20 2013 +0200
@@ -117,24 +117,28 @@
         }
     }
 
-    private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, TemplateMethod target, TemplateMethod sourceMethod, TemplateMethod castMethod, String unexpectedValueName) {
+    private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName) {
         CodeTreeBuilder builder = parent.create();
 
-        boolean castedValues = sourceMethod != castMethod;
+        boolean castedValues = sourceMethod != targetMethod;
 
         builder.startGroup();
-        ExecutableElement method = target.getMethod();
+        ExecutableElement method = targetMethod.getMethod();
         if (method == null) {
-            throw new IllegalStateException("Cannot call synthtetic operation methods.");
+            throw new IllegalStateException("Cannot call synthetic operation methods.");
         }
         TypeElement targetClass = Utils.findNearestEnclosingType(method.getEnclosingElement());
-        NodeData node = (NodeData) castMethod.getTemplate();
+        NodeData node = (NodeData) targetMethod.getTemplate();
         TypeSystemData typeSystem = node.getTypeSystem();
 
-        boolean accessible = target.canBeAccessedByInstanceOf(node.getNodeType());
+        boolean accessible = targetMethod.canBeAccessedByInstanceOf(node.getNodeType());
         if (accessible) {
             if (builder.findMethod().getModifiers().contains(STATIC)) {
-                builder.string(THIS_NODE_LOCAL_VAR_NAME);
+                if (method.getModifiers().contains(STATIC)) {
+                    builder.type(targetClass.asType());
+                } else {
+                    builder.string(THIS_NODE_LOCAL_VAR_NAME);
+                }
             } else {
                 builder.string("super");
             }
@@ -143,8 +147,8 @@
                 builder.type(targetClass.asType());
             } else {
                 ActualParameter parameter = null;
-                for (ActualParameter searchParameter : target.getParameters()) {
-                    if (!searchParameter.getSpecification().isOptional()) {
+                for (ActualParameter searchParameter : targetMethod.getParameters()) {
+                    if (searchParameter.getSpecification().isSignature()) {
                         parameter = searchParameter;
                         break;
                     }
@@ -172,10 +176,10 @@
         builder.string(".");
         builder.startCall(method.getSimpleName().toString());
 
-        for (ActualParameter targetParameter : castMethod.getParameters()) {
+        for (ActualParameter targetParameter : targetMethod.getParameters()) {
             ActualParameter valueParameter = sourceMethod.findParameter(targetParameter.getLocalName());
             if (valueParameter == null) {
-                continue;
+                valueParameter = targetParameter;
             }
             TypeData targetType = targetParameter.getActualTypeData(typeSystem);
 
@@ -257,12 +261,34 @@
         body.string(".").startCall(methodName);
     }
 
-    private CodeTree createGuardAndCast(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, boolean onSpecialization,
+    private CodeTree createGuardAndCast(CodeTreeBuilder parent, String conditionPrefix, SpecializationData sourceSpecialization, SpecializationData targetSpecialization, boolean castValues,
                     CodeTree guardedStatements, CodeTree elseStatements) {
 
+        NodeData node = targetSpecialization.getNode();
         CodeTreeBuilder builder = new CodeTreeBuilder(parent);
-        CodeTree implicitGuards = createImplicitGuards(parent, conditionPrefix, valueSpecialization, guardedSpecialization);
-        CodeTree explicitGuards = createExplicitGuards(parent, implicitGuards == null ? conditionPrefix : null, valueSpecialization, guardedSpecialization);
+        CodeTree implicitGuards = createImplicitGuards(parent, conditionPrefix, sourceSpecialization, targetSpecialization);
+        CodeTree explicitGuards = createExplicitGuards(parent, implicitGuards == null ? conditionPrefix : null, sourceSpecialization, targetSpecialization);
+
+        Set<String> valuesNeedsCast;
+        if (castValues) {
+            // cast all
+            valuesNeedsCast = null;
+        } else {
+            // find out which values needs a cast
+            valuesNeedsCast = new HashSet<>();
+            for (GuardData guard : targetSpecialization.getGuards()) {
+                for (ActualParameter parameter : guard.getParameters()) {
+                    NodeFieldData field = node.findField(parameter.getSpecification().getName());
+                    if (field == null) {
+                        continue;
+                    }
+                    TypeData typeData = parameter.getActualTypeData(node.getTypeSystem());
+                    if (typeData != null && !typeData.isGeneric()) {
+                        valuesNeedsCast.add(parameter.getLocalName());
+                    }
+                }
+            }
+        }
 
         int ifCount = 0;
 
@@ -274,9 +300,7 @@
             ifCount++;
         }
 
-        if (explicitGuards != null || !onSpecialization) {
-            builder.tree(createCasts(parent, valueSpecialization, guardedSpecialization));
-        }
+        builder.tree(createCasts(parent, valuesNeedsCast, sourceSpecialization, targetSpecialization));
 
         if (explicitGuards != null) {
             builder.startIf();
@@ -309,7 +333,7 @@
             // Explicitly specified guards
             for (GuardData guard : guardedSpecialization.getGuards()) {
                 builder.string(andOperator);
-                builder.tree(createTemplateMethodCall(parent, guard, valueSpecialization, guardedSpecialization, null));
+                builder.tree(createTemplateMethodCall(parent, valueSpecialization, guard, null));
                 andOperator = " && ";
             }
         }
@@ -317,7 +341,7 @@
         return builder.isEmpty() ? null : builder.getRoot();
     }
 
-    private CodeTree createCasts(CodeTreeBuilder parent, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) {
+    private CodeTree createCasts(CodeTreeBuilder parent, Set<String> castWhiteList, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) {
         CodeTreeBuilder builder = new CodeTreeBuilder(parent);
         // Implict guards based on method signature
         for (ActualParameter guardedParam : guardedSpecialization.getParameters()) {
@@ -327,6 +351,10 @@
             }
             ActualParameter valueParam = valueSpecialization.findParameter(guardedParam.getLocalName());
 
+            if (castWhiteList != null && !castWhiteList.contains(guardedParam.getLocalName())) {
+                continue;
+            }
+
             CodeTree cast = createCast(parent, field, valueParam, guardedParam);
             if (cast == null) {
                 continue;
@@ -943,7 +971,7 @@
             CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE, STATIC), node.getNodeType(), "specialize");
             method.addParameter(new CodeVariableElement(node.getNodeType(), THIS_NODE_LOCAL_VAR_NAME));
             method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState"));
-            addInternalValueParameters(method, node.getGenericSpecialization(), false);
+            addInternalValueParameters(method, node.getGenericSpecialization(), true);
 
             CodeTreeBuilder body = method.createBuilder();
             body.startStatement().string("boolean allowed = (minimumState == ").string(nodeSpecializationClassName(node.getSpecializations().get(0))).string(".class)").end();
@@ -957,7 +985,7 @@
                 guarded.string(THIS_NODE_LOCAL_VAR_NAME);
                 guarded.end().end();
 
-                body.tree(createGuardAndCast(body, "allowed", node.getGenericSpecialization(), specialization, true, guarded.getRoot(), null));
+                body.tree(createGuardAndCast(body, "allowed", node.getGenericSpecialization(), specialization, false, guarded.getRoot(), null));
             }
             body.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end();
 
@@ -1013,7 +1041,7 @@
                 addInternalValueParameterNames(nextBuilder, next, null, true, true);
                 nextBuilder.end().end();
 
-                invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, false, invokeMethod, nextBuilder.getRoot());
+                invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, true, invokeMethod, nextBuilder.getRoot());
             }
 
             builder.tree(invokeMethod);
@@ -1032,7 +1060,7 @@
                 emitEncounteredSynthetic(builder);
             } else {
                 builder.startReturn();
-                builder.tree(createTemplateMethodCall(builder, specialization, specialization.getNode().getGenericSpecialization(), specialization, null));
+                builder.tree(createTemplateMethodCall(builder, specialization.getNode().getGenericSpecialization(), specialization, null));
                 builder.end(); // return
             }
 
@@ -1202,7 +1230,7 @@
             if (next != null) {
                 returnSpecialized = createReturnSpecializeAndExecute(builder, next, null);
             }
-            builder.tree(createGuardAndCast(builder, null, specialization, specialization, false, executeNode, returnSpecialized));
+            builder.tree(createGuardAndCast(builder, null, specialization, specialization, true, executeNode, returnSpecialized));
         }
 
         private CodeTree createDeoptimize(CodeTreeBuilder parent) {
@@ -1225,7 +1253,7 @@
                 builder.startCall(factoryClassName(node), "specialize");
                 builder.string("this");
                 builder.typeLiteral(builder.findMethod().getEnclosingElement().asType());
-                addInternalValueParameterNames(builder, specialization, null, false, true);
+                addInternalValueParameterNames(builder, specialization, null, true, true);
                 builder.end(); // call replace, call specialize
             } else {
                 builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end();
@@ -1263,7 +1291,7 @@
                 builder.end().end();
             } else {
                 builder.startReturn();
-                builder.tree(createTemplateMethodCall(builder, specialization, specialization, specialization, null));
+                builder.tree(createTemplateMethodCall(builder, specialization, specialization, null));
                 builder.end(); // return
             }
 
@@ -1294,7 +1322,7 @@
         private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) {
             for (TemplateMethod listener : node.getSpecializationListeners()) {
                 builder.startStatement();
-                builder.tree(createTemplateMethodCall(builder, listener, listener, listener, null));
+                builder.tree(createTemplateMethodCall(builder, listener, listener, null));
                 builder.end(); // statement
             }
         }
@@ -1390,7 +1418,7 @@
             builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(shortCircuitParam)).string(" = ");
             ShortCircuitData shortCircuitData = specialization.getShortCircuits().get(shortCircuitIndex);
 
-            builder.tree(createTemplateMethodCall(builder, shortCircuitData, shortCircuitData, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null));
+            builder.tree(createTemplateMethodCall(builder, shortCircuitData, shortCircuitData, exceptionParam != null ? exceptionParam.getLocalName() : null));
 
             builder.end(); // statement
 
@@ -1443,7 +1471,7 @@
             builder.startStatement();
             builder.startCall("replace");
             builder.startCall(factoryClassName(specialization.getNode()), "specialize").string("this").string("minimumState");
-            addInternalValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), null, false, true);
+            addInternalValueParameterNames(builder, specialization.getNode().getGenericSpecialization(), null, true, true);
             builder.end();
             builder.end(); // call replace
             builder.end(); // statement
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java	Mon Apr 01 12:19:15 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java	Mon Apr 01 21:43:20 2013 +0200
@@ -313,7 +313,7 @@
     private String dump(int level) {
         String indent = "";
         for (int i = 0; i < level; i++) {
-            indent += "  ";
+            indent += "    ";
         }
         StringBuilder builder = new StringBuilder();
 
@@ -341,7 +341,7 @@
         if (value instanceof List) {
             List<?> list = (List<?>) value;
             if (!list.isEmpty()) {
-                b.append(String.format("\n%s  %s = %s", indent, propertyName, dumpList((List<?>) value)));
+                b.append(String.format("\n%s  %s = %s", indent, propertyName, dumpList(indent, (List<?>) value)));
             }
         } else {
             if (value != null) {
@@ -350,7 +350,7 @@
         }
     }
 
-    private static String dumpList(List<?> array) {
+    private static String dumpList(String indent, List<?> array) {
         if (array == null) {
             return "null";
         }
@@ -364,12 +364,12 @@
         StringBuilder b = new StringBuilder();
         b.append("[");
         for (Object object : array) {
-            b.append("\n");
-            b.append("    ");
+            b.append("\n        ");
+            b.append(indent);
             b.append(object);
             b.append(", ");
         }
-        b.append("\n  ]");
+        b.append("\n    ").append(indent).append("]");
         return b.toString();
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java	Mon Apr 01 21:43:20 2013 +0200
@@ -0,0 +1,130 @@
+/*
+ * 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.codegen.processor.node;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.node.NodeFieldData.*;
+import com.oracle.truffle.codegen.processor.template.*;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
+
+public abstract class NodeMethodParser<E extends TemplateMethod> extends TemplateMethodParser<NodeData, E> {
+
+    public NodeMethodParser(ProcessorContext context, NodeData node) {
+        super(context, node);
+    }
+
+    public NodeData getNode() {
+        return template;
+    }
+
+    protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData) {
+        ParameterSpec spec = new ParameterSpec(valueName, nodeTypeMirrors(nodeData));
+        spec.setSignature(true);
+        return spec;
+    }
+
+    private static List<TypeMirror> nodeTypeMirrors(NodeData nodeData) {
+        Set<TypeMirror> typeMirrors = new LinkedHashSet<>();
+
+        for (ExecutableTypeData typeData : nodeData.getExecutableTypes()) {
+            typeMirrors.add(typeData.getType().getPrimitiveType());
+        }
+
+        typeMirrors.add(nodeData.getTypeSystem().getGenericType());
+
+        return new ArrayList<>(typeMirrors);
+    }
+
+    protected ParameterSpec createReturnParameterSpec() {
+        return createValueParameterSpec("operation", getNode());
+    }
+
+    @Override
+    public boolean isParsable(ExecutableElement method) {
+        return Utils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
+    }
+
+    @SuppressWarnings("unused")
+    protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, String shortCircuitName) {
+        MethodSpec methodSpec = new MethodSpec(createReturnParameterSpec());
+
+        if (getNode().supportsFrame()) {
+            methodSpec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame()));
+        }
+
+        resolveAndAddImplicitThis(methodSpec, method);
+
+        for (NodeFieldData field : getNode().getFields()) {
+            if (field.getKind() == FieldKind.FIELD) {
+                ParameterSpec spec = new ParameterSpec(field.getName(), field.getType());
+                spec.setLocal(true);
+                methodSpec.addOptional(spec);
+            }
+        }
+
+        for (NodeFieldData field : getNode().getFields()) {
+            if (field.getExecutionKind() == ExecutionKind.IGNORE) {
+                continue;
+            }
+
+            if (field.getExecutionKind() == ExecutionKind.DEFAULT) {
+                ParameterSpec spec = createValueParameterSpec(field.getName(), field.getNodeData());
+                if (field.getKind() == FieldKind.CHILDREN) {
+                    spec.setCardinality(Cardinality.MULTIPLE);
+                    spec.setIndexed(true);
+                }
+                methodSpec.addRequired(spec);
+            } else if (field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) {
+                String valueName = field.getName();
+                if (shortCircuitName != null && valueName.equals(shortCircuitName)) {
+                    break;
+                }
+
+                methodSpec.addRequired(new ParameterSpec(shortCircuitValueName(valueName), getContext().getType(boolean.class)));
+                methodSpec.addRequired(createValueParameterSpec(valueName, field.getNodeData()));
+            } else {
+                assert false;
+            }
+        }
+
+        return methodSpec;
+    }
+
+    protected void resolveAndAddImplicitThis(MethodSpec methodSpec, ExecutableElement method) {
+        TypeMirror declaredType = Utils.findNearestEnclosingType(method).asType();
+
+        if (!method.getModifiers().contains(Modifier.STATIC) && !Utils.isAssignable(declaredType, getContext().getTruffleTypes().getNode())) {
+            methodSpec.addImplicitRequiredType(getNode().getTemplateType().asType());
+        }
+    }
+
+    private static String shortCircuitValueName(String valueName) {
+        return "has" + Utils.firstLetterUpperCase(valueName);
+    }
+
+}
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Mon Apr 01 12:19:15 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java	Mon Apr 01 21:43:20 2013 +0200
@@ -335,13 +335,7 @@
             specializations.add(new SpecializationData(uninializedMethod, false, true));
         }
 
-        Collections.sort(specializations, new Comparator<SpecializationData>() {
-
-            @Override
-            public int compare(SpecializationData o1, SpecializationData o2) {
-                return compareSpecialization(o1, o2);
-            }
-        });
+        Collections.sort(specializations);
 
         node.setSpecializations(specializations);
 
@@ -372,27 +366,13 @@
         for (String guardDefinition : specialization.getGuardDefinitions()) {
             GuardParser parser = new GuardParser(context, specialization, guardDefinition);
             List<GuardData> guards = parser.parse(methods);
-            Collections.sort(guards, new Comparator<GuardData>() {
-
-                @Override
-                public int compare(GuardData o1, GuardData o2) {
-                    int compare = o1.compareBySignature(o2);
-                    if (compare == 0) {
-                        compare = o1.getId().compareTo(o2.getId());
-                    }
-                    if (compare == 0) {
-                        TypeElement enclosingType1 = Utils.findNearestEnclosingType(o1.getMethod());
-                        TypeElement enclosingType2 = Utils.findNearestEnclosingType(o2.getMethod());
-                        compare = enclosingType1.getQualifiedName().toString().compareTo(enclosingType2.getQualifiedName().toString());
-                    }
-                    return compare;
-                }
-            });
             if (!guards.isEmpty()) {
                 foundGuards.add(guards.get(0));
             } else {
                 // error no guard found
-                specialization.addError("No guard found with with name '%s'.", guardDefinition);
+                MethodSpec spec = parser.createSpecification(specialization.getMethod(), null);
+                spec.applyTypeDefinitions("types");
+                specialization.addError("Guard with method name '%s' not found. Expected signature: %n%s", guardDefinition, spec.toSignatureString("guard"));
             }
         }
 
@@ -573,17 +553,17 @@
         boolean valid = true;
         int args = -1;
         for (SpecializationData specializationData : nodeData.getSpecializations()) {
-            int specializationArgs = 0;
+            int signatureArgs = 0;
             for (ActualParameter param : specializationData.getParameters()) {
-                if (!param.getSpecification().isOptional()) {
-                    specializationArgs++;
+                if (param.getSpecification().isSignature()) {
+                    signatureArgs++;
                 }
             }
-            if (args != -1 && args != specializationArgs) {
+            if (args != -1 && args != signatureArgs) {
                 valid = false;
                 break;
             }
-            args = specializationArgs;
+            args = signatureArgs;
         }
         if (!valid) {
             for (SpecializationData specialization : nodeData.getSpecializations()) {
@@ -759,7 +739,11 @@
 
         NodeFieldData fieldData = new NodeFieldData(var, findAccessElement(var), mirror, kind, execution);
         if (type != null && mirror != null) {
-            NodeData fieldNodeData = resolveNode(Utils.fromTypeMirror(type));
+            TypeElement typeElement = Utils.fromTypeMirror(type);
+            if (typeElement == null) {
+                return null;
+            }
+            NodeData fieldNodeData = resolveNode(typeElement);
             fieldData.setNode(fieldNodeData);
 
             if (fieldNodeData == null) {
@@ -974,7 +958,7 @@
             SpecializationData m1 = specializations.get(i);
             for (int j = i + 1; j < specializations.size(); j++) {
                 SpecializationData m2 = specializations.get(j);
-                int inferredOrder = compareSpecialization(m1, m2);
+                int inferredOrder = m1.compareBySignature(m2);
 
                 if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) {
                     int specOrder = m1.getOrder() - m2.getOrder();
@@ -1014,26 +998,6 @@
         }
     }
 
-    private static int compareSpecialization(SpecializationData m1, SpecializationData m2) {
-        if (m1 == m2) {
-            return 0;
-        }
-
-        if (m1.getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) {
-            return m1.getOrder() - m2.getOrder();
-        } else if (m1.isUninitialized() ^ m2.isUninitialized()) {
-            return m1.isUninitialized() ? -1 : 1;
-        } else if (m1.isGeneric() ^ m2.isGeneric()) {
-            return m1.isGeneric() ? 1 : -1;
-        }
-
-        if (m1.getTemplate() != m2.getTemplate()) {
-            throw new UnsupportedOperationException("Cannot compare two specializations with different templates.");
-        }
-
-        return m1.compareBySignature(m2);
-    }
-
     @Override
     public Class<? extends Annotation> getAnnotationType() {
         return null;
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java	Mon Apr 01 12:19:15 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java	Mon Apr 01 21:43:20 2013 +0200
@@ -95,6 +95,31 @@
         return false;
     }
 
+    @Override
+    public int compareBySignature(TemplateMethod other) {
+        if (this == other) {
+            return 0;
+        } else if (!(other instanceof SpecializationData)) {
+            return super.compareBySignature(other);
+        }
+
+        SpecializationData m2 = (SpecializationData) other;
+
+        if (getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) {
+            return getOrder() - m2.getOrder();
+        } else if (isUninitialized() ^ m2.isUninitialized()) {
+            return isUninitialized() ? -1 : 1;
+        } else if (isGeneric() ^ m2.isGeneric()) {
+            return isGeneric() ? 1 : -1;
+        }
+
+        if (getTemplate() != m2.getTemplate()) {
+            throw new UnsupportedOperationException("Cannot compare two specializations with different templates.");
+        }
+
+        return super.compareBySignature(m2);
+    }
+
     public NodeData getNode() {
         return node;
     }
@@ -165,4 +190,8 @@
         return !getGuards().isEmpty();
     }
 
+    @Override
+    public String toString() {
+        return String.format("%s [id = %s, method = %s, guards = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards());
+    }
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java	Mon Apr 01 12:19:15 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/MethodSpec.java	Mon Apr 01 21:43:20 2013 +0200
@@ -26,33 +26,74 @@
 
 import javax.lang.model.type.*;
 
+import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.ParameterSpec.Cardinality;
+
 public class MethodSpec {
 
-    private final List<TypeMirror> implicitTypes;
+    private final List<TypeMirror> implicitRequiredTypes = new ArrayList<>();
 
     private final ParameterSpec returnType;
-    private final List<ParameterSpec> parameters;
+    private final List<ParameterSpec> optional = new ArrayList<>();
+    private final List<ParameterSpec> required = new ArrayList<>();
+
+    private boolean variableRequiredArguments;
+    private List<TypeDef> typeDefinitions;
 
-    public MethodSpec(List<TypeMirror> prefixTypes, ParameterSpec returnType, List<ParameterSpec> parameters) {
-        this.implicitTypes = prefixTypes;
+    public MethodSpec(ParameterSpec returnType) {
         this.returnType = returnType;
-        this.parameters = parameters;
+    }
+
+    public void setVariableRequiredArguments(boolean variableArguments) {
+        this.variableRequiredArguments = variableArguments;
     }
 
-    public List<TypeMirror> getImplicitTypes() {
-        return implicitTypes;
+    public boolean isVariableRequiredArguments() {
+        return variableRequiredArguments;
+    }
+
+    public void addImplicitRequiredType(TypeMirror type) {
+        this.implicitRequiredTypes.add(type);
+    }
+
+    public void addOptional(ParameterSpec spec) {
+        optional.add(spec);
+    }
+
+    public void addRequired(ParameterSpec spec) {
+        required.add(spec);
+    }
+
+    public List<TypeMirror> getImplicitRequiredTypes() {
+        return implicitRequiredTypes;
     }
 
     public ParameterSpec getReturnType() {
         return returnType;
     }
 
-    public List<ParameterSpec> getParameters() {
-        return parameters;
+    public List<ParameterSpec> getRequired() {
+        return required;
+    }
+
+    public List<ParameterSpec> getOptional() {
+        return optional;
+    }
+
+    public void makeTypeDefinitions() {
+
+    }
+
+    public List<ParameterSpec> getAll() {
+        List<ParameterSpec> specs = new ArrayList<>();
+        specs.add(getReturnType());
+        specs.addAll(getOptional());
+        specs.addAll(getRequired());
+        return specs;
     }
 
     public ParameterSpec findParameterSpec(String name) {
-        for (ParameterSpec spec : parameters) {
+        for (ParameterSpec spec : getAll()) {
             if (spec.getName().equals(name)) {
                 return spec;
             }
@@ -60,4 +101,131 @@
         return null;
     }
 
+    public void applyTypeDefinitions(String prefix) {
+        this.typeDefinitions = createTypeDefinitions(prefix);
+    }
+
+    private List<TypeDef> createTypeDefinitions(String prefix) {
+        List<TypeDef> typeDefs = new ArrayList<>();
+
+        int defIndex = 0;
+        for (ParameterSpec spec : getAll()) {
+            List<TypeMirror> allowedTypes = spec.getAllowedTypes();
+            List<TypeMirror> types = spec.getAllowedTypes();
+            if (types != null && allowedTypes.size() > 1) {
+                TypeDef foundDef = null;
+                for (TypeDef def : typeDefs) {
+                    if (allowedTypes.equals(def.getTypes())) {
+                        foundDef = def;
+                        break;
+                    }
+                }
+                if (foundDef == null) {
+                    foundDef = new TypeDef(types, prefix + defIndex);
+                    typeDefs.add(foundDef);
+                    defIndex++;
+                }
+
+                spec.setTypeDefinition(foundDef);
+            }
+        }
+
+        return typeDefs;
+    }
+
+    public String toSignatureString(String methodName) {
+        StringBuilder b = new StringBuilder();
+        b.append("    ");
+        b.append(createTypeSignature(returnType, true));
+
+        b.append(" ");
+        b.append(methodName);
+        b.append("(");
+
+        String sep = "";
+
+        for (ParameterSpec optionalSpec : getOptional()) {
+            b.append(sep);
+            b.append("[");
+            b.append(createTypeSignature(optionalSpec, false));
+            b.append("]");
+            sep = ", ";
+        }
+
+        for (ParameterSpec requiredSpec : getRequired()) {
+            b.append(sep);
+            if (requiredSpec.getCardinality() == Cardinality.MULTIPLE) {
+                b.append("{");
+            }
+            b.append(createTypeSignature(requiredSpec, false));
+            if (requiredSpec.getCardinality() == Cardinality.MULTIPLE) {
+                b.append("}");
+            }
+            sep = ", ";
+        }
+
+        b.append(")");
+
+        if (typeDefinitions != null && !typeDefinitions.isEmpty()) {
+            b.append("\n\n");
+
+            String lineSep = "";
+            for (TypeDef def : typeDefinitions) {
+                b.append(lineSep);
+                b.append("    <").append(def.getName()).append(">");
+                b.append(" = {");
+                String separator = "";
+                for (TypeMirror type : def.getTypes()) {
+                    b.append(separator).append(Utils.getSimpleName(type));
+                    separator = ", ";
+                }
+                b.append("}");
+                lineSep = "\n";
+
+            }
+        }
+        return b.toString();
+    }
+
+    private static String createTypeSignature(ParameterSpec spec, boolean typeOnly) {
+        StringBuilder builder = new StringBuilder();
+        TypeDef foundTypeDef = spec.getTypeDefinition();
+        if (foundTypeDef != null) {
+            builder.append("<" + foundTypeDef.getName() + ">");
+        } else if (spec.getAllowedTypes().size() >= 1) {
+            builder.append(Utils.getSimpleName(spec.getAllowedTypes().get(0)));
+        } else {
+            builder.append("void");
+        }
+        if (!typeOnly) {
+            builder.append(" ");
+            builder.append(spec.getName());
+        }
+        return builder.toString();
+    }
+
+    @Override
+    public String toString() {
+        return toSignatureString("methodName");
+    }
+
+    static class TypeDef {
+
+        private final List<TypeMirror> types;
+        private final String name;
+
+        public TypeDef(List<TypeMirror> types, String name) {
+            this.types = types;
+            this.name = name;
+        }
+
+        public List<TypeMirror> getTypes() {
+            return types;
+        }
+
+        public String getName() {
+            return name;
+        }
+    }
+
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java	Mon Apr 01 12:19:15 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java	Mon Apr 01 21:43:20 2013 +0200
@@ -27,6 +27,7 @@
 import javax.lang.model.type.*;
 
 import com.oracle.truffle.codegen.processor.*;
+import com.oracle.truffle.codegen.processor.template.MethodSpec.TypeDef;
 
 public class ParameterSpec {
 
@@ -38,9 +39,7 @@
     private final List<TypeMirror> allowedTypes;
 
     /** Cardinality one or multiple. */
-    private Cardinality cardinality;
-    /** Type is optional can be dismissed. */
-    private boolean optional;
+    private Cardinality cardinality = Cardinality.ONE;
     /** Type is part of the method signature. Relevant for comparisons. */
     private boolean signature;
     /** Type must be indexed when parsing. */
@@ -48,6 +47,8 @@
     /** Type is bound to local final variable. */
     private boolean local;
 
+    private TypeDef typeDefinition;
+
     public ParameterSpec(String name, TypeMirror... allowedTypes) {
         this(name, Arrays.asList(allowedTypes));
     }
@@ -57,8 +58,12 @@
         this.allowedTypes = allowedTypes;
     }
 
-    public void setOptional(boolean optional) {
-        this.optional = optional;
+    void setTypeDefinition(TypeDef typeDefinition) {
+        this.typeDefinition = typeDefinition;
+    }
+
+    TypeDef getTypeDefinition() {
+        return typeDefinition;
     }
 
     public void setSignature(boolean signature) {
@@ -93,10 +98,6 @@
         return name;
     }
 
-    public boolean isOptional() {
-        return optional;
-    }
-
     public Cardinality getCardinality() {
         return cardinality;
     }
@@ -114,4 +115,25 @@
         return false;
     }
 
+    @Override
+    public String toString() {
+        return toSignatureString(false);
+    }
+
+    public String toSignatureString(boolean typeOnly) {
+        StringBuilder builder = new StringBuilder();
+        if (typeDefinition != null) {
+            builder.append("<" + typeDefinition.getName() + ">");
+        } else if (getAllowedTypes().size() >= 1) {
+            builder.append(Utils.getSimpleName(getAllowedTypes().get(0)));
+        } else {
+            builder.append("void");
+        }
+        if (!typeOnly) {
+            builder.append(" ");
+            builder.append(getName());
+        }
+        return builder.toString();
+    }
+
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java	Mon Apr 01 12:19:15 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java	Mon Apr 01 21:43:20 2013 +0200
@@ -30,7 +30,10 @@
 import com.oracle.truffle.codegen.processor.*;
 import com.oracle.truffle.codegen.processor.typesystem.*;
 
-public class TemplateMethod extends MessageContainer {
+/**
+ * Note: this class has a natural ordering that is inconsistent with equals.
+ */
+public class TemplateMethod extends MessageContainer implements Comparable<TemplateMethod> {
 
     private String id;
     private final Template template;
@@ -38,7 +41,7 @@
     private final ExecutableElement method;
     private final AnnotationMirror markerAnnotation;
     private final ActualParameter returnType;
-    private final List<ActualParameter> parameters;
+    private List<ActualParameter> parameters;
 
     public TemplateMethod(String id, Template template, MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, ActualParameter returnType,
                     List<ActualParameter> parameters) {
@@ -62,6 +65,10 @@
         getMessages().addAll(method.getMessages());
     }
 
+    public void setParameters(List<ActualParameter> parameters) {
+        this.parameters = parameters;
+    }
+
     @Override
     public Element getMessageElement() {
         return method;
@@ -97,6 +104,16 @@
         return returnType;
     }
 
+    public List<ActualParameter> getRequiredParameters() {
+        List<ActualParameter> requiredParameters = new ArrayList<>();
+        for (ActualParameter parameter : getParameters()) {
+            if (getSpecification().getRequired().contains(parameter.getSpecification())) {
+                requiredParameters.add(parameter);
+            }
+        }
+        return requiredParameters;
+    }
+
     public List<ActualParameter> getParameters() {
         return parameters;
     }
@@ -117,15 +134,6 @@
         return Collections.unmodifiableList(allParameters);
     }
 
-    public ActualParameter findParameter(ParameterSpec spec) {
-        for (ActualParameter param : getParameters()) {
-            if (param.getSpecification().getName().equals(spec.getName())) {
-                return param;
-            }
-        }
-        return null;
-    }
-
     public boolean canBeAccessedByInstanceOf(TypeMirror type) {
         TypeMirror methodType = Utils.findNearestEnclosingType(getMethod()).asType();
         return Utils.isAssignable(type, methodType) || Utils.isAssignable(methodType, type);
@@ -149,7 +157,7 @@
 
     @Override
     public String toString() {
-        return "id = " + getId() + ", " + getClass().getSimpleName() + " [method = " + getMethod() + "]";
+        return String.format("%s [id = %s, method = %s]", getClass().getSimpleName(), getId(), getMethod());
     }
 
     public ActualParameter getPreviousParam(ActualParameter searchParam) {
@@ -177,6 +185,26 @@
         return types;
     }
 
+    @Override
+    public int compareTo(TemplateMethod o) {
+        if (this == o) {
+            return 0;
+        }
+
+        int compare = compareBySignature(o);
+        if (compare == 0) {
+            // if signature sorting failed sort by id
+            compare = getId().compareTo(o.getId());
+        }
+        if (compare == 0) {
+            // if still no difference sort by enclosing type name
+            TypeElement enclosingType1 = Utils.findNearestEnclosingType(getMethod());
+            TypeElement enclosingType2 = Utils.findNearestEnclosingType(o.getMethod());
+            compare = enclosingType1.getQualifiedName().toString().compareTo(enclosingType2.getQualifiedName().toString());
+        }
+        return compare;
+    }
+
     public int compareBySignature(TemplateMethod compareMethod) {
         TypeSystemData typeSystem = getTemplate().getTypeSystem();
         if (typeSystem != compareMethod.getTemplate().getTypeSystem()) {
@@ -186,7 +214,7 @@
         List<TypeData> signature1 = getSignature(typeSystem);
         List<TypeData> signature2 = compareMethod.getSignature(typeSystem);
         if (signature1.size() != signature2.size()) {
-            return signature1.size() - signature2.size();
+            return signature2.size() - signature1.size();
         }
 
         int result = 0;
@@ -194,7 +222,7 @@
             int typeResult = compareActualParameter(typeSystem, signature1.get(i), signature2.get(i));
             if (result == 0) {
                 result = typeResult;
-            } else if (Math.signum(result) != Math.signum(typeResult)) {
+            } else if (typeResult != 0 && Math.signum(result) != Math.signum(typeResult)) {
                 // We cannot define an order.
                 return 0;
             }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java	Mon Apr 01 12:19:15 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java	Mon Apr 01 21:43:20 2013 +0200
@@ -110,13 +110,7 @@
                 valid = false;
             }
         }
-        Collections.sort(parsedMethods, new Comparator<TemplateMethod>() {
-
-            @Override
-            public int compare(TemplateMethod o1, TemplateMethod o2) {
-                return o1.getMethodName().compareTo(o2.getMethodName());
-            }
-        });
+        Collections.sort(parsedMethods);
 
         if (!valid && parseNullOnError) {
             return null;
@@ -130,27 +124,25 @@
             return null;
         }
 
+        methodSpecification.applyTypeDefinitions("types");
+
         String id = method.getSimpleName().toString();
         AnnotationMirror idAnnotation = Utils.findAnnotationMirror(context.getEnvironment(), method, NodeId.class);
         if (idAnnotation != null) {
             id = Utils.getAnnotationValue(String.class, idAnnotation, "value");
         }
 
-        List<TypeDef> typeDefs = createTypeDefinitions(methodSpecification.getReturnType(), methodSpecification.getParameters());
-
         ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
-        List<ParameterSpec> parameterSpecs = new ArrayList<>();
-        parameterSpecs.addAll(methodSpecification.getParameters());
 
         ActualParameter returnTypeMirror = matchParameter(returnTypeSpec, method.getReturnType(), template, 0, false);
         if (returnTypeMirror == null) {
             if (emitErrors) {
                 E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()));
-                String expectedReturnType = createTypeSignature(returnTypeSpec, typeDefs, true);
+                String expectedReturnType = returnTypeSpec.toSignatureString(true);
                 String actualReturnType = Utils.getSimpleName(method.getReturnType());
 
                 String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
-                                createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs));
+                                methodSpecification.toSignatureString(method.getSimpleName().toString()));
                 invalidMethod.addError(message);
                 return invalidMethod;
             } else {
@@ -163,12 +155,12 @@
             parameterTypes.add(var.asType());
         }
 
-        List<ActualParameter> parameters = parseParameters(parameterTypes, methodSpecification.getImplicitTypes(), parameterSpecs);
+        List<ActualParameter> parameters = parseParameters(methodSpecification, parameterTypes);
         if (parameters == null) {
             if (isEmitErrors()) {
                 E invalidMethod = create(new TemplateMethod(id, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<ActualParameter> emptyList()));
                 String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(methodSpecification, method),
-                                createExpectedSignature(method.getSimpleName().toString(), returnTypeSpec, parameterSpecs, typeDefs));
+                                methodSpecification.toSignatureString(method.getSimpleName().toString()));
                 invalidMethod.addError(message);
                 return invalidMethod;
             } else {
@@ -180,87 +172,95 @@
     }
 
     private static String createActualSignature(MethodSpec spec, ExecutableElement method) {
-        List<String> types = new ArrayList<>();
-        for (TypeMirror implicitType : spec.getImplicitTypes()) {
-            types.add("implicit " + Utils.getSimpleName(implicitType));
+        StringBuilder b = new StringBuilder("(");
+        String sep = "";
+        for (TypeMirror implicitType : spec.getImplicitRequiredTypes()) {
+            b.append(sep);
+            b.append("implicit " + Utils.getSimpleName(implicitType));
+            sep = ", ";
         }
         for (VariableElement var : method.getParameters()) {
-            types.add(Utils.getSimpleName(var.asType()));
-        }
-
-        StringBuilder b = new StringBuilder("(");
-        for (Iterator<String> iterator = types.iterator(); iterator.hasNext();) {
-            b.append(iterator.next());
-            if (iterator.hasNext()) {
-                b.append(", ");
-            }
+            b.append(sep);
+            b.append(Utils.getSimpleName(var.asType()));
+            sep = ", ";
         }
         b.append(")");
         return b.toString();
     }
 
-    private List<ActualParameter> parseParameters(List<TypeMirror> types, List<TypeMirror> implicitTypes, List<ParameterSpec> parameterSpecs) {
-        Iterator<? extends TypeMirror> parameterIterator = types.iterator();
-        Iterator<? extends TypeMirror> implicitParametersIterator = implicitTypes.iterator();
-        Iterator<? extends ParameterSpec> specificationIterator = parameterSpecs.iterator();
+    private List<ActualParameter> parseParameters(MethodSpec spec, List<TypeMirror> parameterTypes) {
+        List<ActualParameter> parsedParams = new ArrayList<>();
+        ConsumableListIterator<TypeMirror> types = new ConsumableListIterator<>(parameterTypes);
 
-        TypeMirror parameter = parameterIterator.hasNext() ? parameterIterator.next() : null;
-        TypeMirror implicitParameter = implicitParametersIterator.hasNext() ? implicitParametersIterator.next() : null;
-        ParameterSpec specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
+        // 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, false);
+                if (optionalParam != null) {
+                    optionals.consume(optionalCount);
+                    types.consume();
+                    parsedParams.add(optionalParam);
+                    break;
+                }
+                optionalCount++;
+            }
+            if (oldIndex == types.getIndex()) {
+                // nothing found anymore skip optional
+                break;
+            }
+        }
+
+        List<TypeMirror> typesWithImplicit = new ArrayList<>(spec.getImplicitRequiredTypes());
+        typesWithImplicit.addAll(types.toList());
+        types = new ConsumableListIterator<>(typesWithImplicit);
 
         int specificationParameterIndex = 0;
-        List<ActualParameter> resolvedParameters = new ArrayList<>();
-        while (parameter != null || specification != null || implicitParameter != null) {
-            if (parameter == null || specification == null) {
-                if (specification != null && (specification.isOptional() || specification.getCardinality() == Cardinality.MULTIPLE)) {
-                    specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
+        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.MULTIPLE) {
+                    required.consume();
                     specificationParameterIndex = 0;
                     continue;
                 }
-                return null;
+                break;
             }
-
-            ActualParameter resolvedParameter = null;
-
-            boolean implicit = false;
-            if (implicitParameter != null) {
-                resolvedParameter = matchParameter(specification, implicitParameter, template, specificationParameterIndex, true);
-                if (resolvedParameter != null) {
-                    implicit = true;
-                }
-            }
-
-            if (resolvedParameter == null) {
-                resolvedParameter = matchParameter(specification, parameter, template, specificationParameterIndex, false);
-            }
-
+            boolean implicit = types.getIndex() < spec.getImplicitRequiredTypes().size();
+            ActualParameter resolvedParameter = matchParameter(required.get(), types.get(), template, specificationParameterIndex, implicit);
             if (resolvedParameter == null) {
-                // mismatch
-                if (specification.isOptional()) {
-                    specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
-                    specificationParameterIndex = 0;
-                } else {
-                    return null;
+                if (required.get().getCardinality() == Cardinality.MULTIPLE) {
+                    required.consume();
+                    continue;
                 }
+                // direct mismatch but required -> error
+                return null;
             } else {
-                resolvedParameters.add(resolvedParameter);
-
-                // match
-                if (implicit) {
-                    implicitParameter = implicitParametersIterator.hasNext() ? implicitParametersIterator.next() : null;
-                } else {
-                    parameter = parameterIterator.hasNext() ? parameterIterator.next() : null;
-                }
-
-                if (specification.getCardinality() == Cardinality.ONE) {
-                    specification = specificationIterator.hasNext() ? specificationIterator.next() : null;
+                parsedParams.add(resolvedParameter);
+                types.consume();
+                if (required.get().getCardinality() == Cardinality.ONE) {
+                    required.consume();
                     specificationParameterIndex = 0;
-                } else if (specification.getCardinality() == Cardinality.MULTIPLE) {
+                } else if (required.get().getCardinality() == Cardinality.MULTIPLE) {
                     specificationParameterIndex++;
                 }
             }
         }
-        return resolvedParameters;
+
+        if (!types.toList().isEmpty()) {
+            // additional types -> error
+            return null;
+        }
+
+        if (!required.toList().isEmpty() && !spec.isVariableRequiredArguments()) {
+            // additional specifications -> error
+            return null;
+        }
+
+        // success!
+        return parsedParams;
     }
 
     private ActualParameter matchParameter(ParameterSpec specification, TypeMirror mirror, Template typeSystem, int index, boolean implicit) {
@@ -275,143 +275,53 @@
         return new ActualParameter(specification, resolvedType, index, implicit);
     }
 
-    protected List<TypeDef> createTypeDefinitions(ParameterSpec returnType, List<? extends ParameterSpec> parameters) {
-        List<TypeDef> typeDefs = new ArrayList<>();
+    /* Helper class for parsing. */
+    private static class ConsumableListIterator<E> implements Iterable<E> {
 
-        List<ParameterSpec> allParams = new ArrayList<>();
-        allParams.add(returnType);
-        allParams.addAll(parameters);
+        private final List<E> data;
+        private int index;
+
+        public ConsumableListIterator(List<E> data) {
+            this.data = data;
+        }
 
-        int defIndex = 0;
-        for (ParameterSpec spec : allParams) {
-            List<TypeMirror> allowedTypes = spec.getAllowedTypes();
-            List<TypeMirror> types = spec.getAllowedTypes();
-            if (types != null && allowedTypes.size() > 1) {
-                TypeDef foundDef = null;
-                for (TypeDef def : typeDefs) {
-                    if (allowedTypes.equals(def.getTypes())) {
-                        foundDef = def;
-                        break;
-                    }
-                }
-                if (foundDef == null) {
-                    foundDef = new TypeDef(types, "Types" + defIndex);
-                    typeDefs.add(foundDef);
-                    defIndex++;
-                }
+        public E get() {
+            if (index >= data.size()) {
+                return null;
+            }
+            return data.get(index);
+        }
 
-                foundDef.getParameters().add(spec);
+        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);
             }
         }
 
-        return typeDefs;
-    }
-
-    protected static class TypeDef {
-
-        private final List<TypeMirror> types;
-        private final String name;
-        private final List<ParameterSpec> parameters = new ArrayList<>();
-
-        public TypeDef(List<TypeMirror> types, String name) {
-            this.types = types;
-            this.name = name;
+        public int getIndex() {
+            return index;
         }
 
-        public List<ParameterSpec> getParameters() {
-            return parameters;
-        }
-
-        public List<TypeMirror> getTypes() {
-            return types;
+        @Override
+        public Iterator<E> iterator() {
+            return toList().iterator();
         }
 
-        public String getName() {
-            return name;
-        }
-    }
-
-    public static String createExpectedSignature(String methodName, ParameterSpec returnType, List<? extends ParameterSpec> parameters, List<TypeDef> typeDefs) {
-        StringBuilder b = new StringBuilder();
-
-        b.append("    ");
-        b.append(createTypeSignature(returnType, typeDefs, true));
-
-        b.append(" ");
-        b.append(methodName);
-        b.append("(");
-
-        for (int i = 0; i < parameters.size(); i++) {
-            ParameterSpec specification = parameters.get(i);
-            if (specification.isOptional()) {
-                b.append("[");
+        public List<E> toList() {
+            if (index < data.size()) {
+                return data.subList(index, data.size());
+            } else {
+                return Collections.<E> emptyList();
             }
-            if (specification.getCardinality() == Cardinality.MULTIPLE) {
-                b.append("{");
-            }
-
-            b.append(createTypeSignature(specification, typeDefs, false));
-
-            if (specification.isOptional()) {
-                b.append("]");
-            }
-
-            if (specification.getCardinality() == Cardinality.MULTIPLE) {
-                b.append("}");
-            }
-
-            if (i < parameters.size() - 1) {
-                b.append(", ");
-            }
-
         }
 
-        b.append(")");
-
-        if (!typeDefs.isEmpty()) {
-            b.append("\n\n");
-
-            String lineSep = "";
-            for (TypeDef def : typeDefs) {
-                b.append(lineSep);
-                b.append("    <").append(def.getName()).append(">");
-                b.append(" = {");
-                String separator = "";
-                for (TypeMirror type : def.getTypes()) {
-                    b.append(separator).append(Utils.getSimpleName(type));
-                    separator = ", ";
-                }
-                b.append("}");
-                lineSep = "\n";
-
-            }
-        }
-        return b.toString();
-    }
-
-    private static String createTypeSignature(ParameterSpec spec, List<TypeDef> typeDefs, boolean typeOnly) {
-        StringBuilder builder = new StringBuilder();
-        if (spec.getAllowedTypes().size() > 1) {
-            TypeDef foundTypeDef = null;
-            for (TypeDef typeDef : typeDefs) {
-                if (typeDef.getParameters().contains(spec)) {
-                    foundTypeDef = typeDef;
-                    break;
-                }
-            }
-            if (foundTypeDef != null) {
-                builder.append("<" + foundTypeDef.getName() + ">");
-            }
-        } else if (spec.getAllowedTypes().size() == 1) {
-            builder.append(Utils.getSimpleName(spec.getAllowedTypes().get(0)));
-        } else {
-            builder.append("void");
-        }
-        if (!typeOnly) {
-            builder.append(" ");
-            builder.append(spec.getName());
-        }
-        return builder.toString();
     }
 
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java	Mon Apr 01 12:19:15 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardData.java	Mon Apr 01 21:43:20 2013 +0200
@@ -22,12 +22,20 @@
  */
 package com.oracle.truffle.codegen.processor.typesystem;
 
+import com.oracle.truffle.codegen.processor.node.*;
 import com.oracle.truffle.codegen.processor.template.*;
 
 public class GuardData extends TemplateMethod {
 
-    public GuardData(TemplateMethod method) {
+    private final SpecializationData specialization;
+
+    public GuardData(TemplateMethod method, SpecializationData specialization) {
         super(method);
+        this.specialization = specialization;
+    }
+
+    public SpecializationData getSpecialization() {
+        return specialization;
     }
 
 }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java	Mon Apr 01 12:19:15 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java	Mon Apr 01 21:43:20 2013 +0200
@@ -26,7 +26,6 @@
 import java.util.*;
 
 import javax.lang.model.element.*;
-import javax.lang.model.type.*;
 
 import com.oracle.truffle.codegen.processor.*;
 import com.oracle.truffle.codegen.processor.node.*;
@@ -47,15 +46,22 @@
 
     @Override
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        List<ParameterSpec> specs = new ArrayList<>();
-        for (ActualParameter parameter : specialization.getParameters()) {
-            ParameterSpec spec = new ParameterSpec(parameter.getSpecification().getName(), parameter.getActualType());
-            spec.setSignature(true);
-            spec.setOptional(true);
-            specs.add(spec);
+        MethodSpec spec = createDefaultMethodSpec(method, mirror, null);
+        spec.setVariableRequiredArguments(true);
+        spec.getRequired().clear();
+
+        for (ActualParameter parameter : specialization.getRequiredParameters()) {
+            ParameterSpec paramSpec = new ParameterSpec(parameter.getLocalName(), parameter.getActualType(), getNode().getTypeSystem().getGenericType());
+            paramSpec.setSignature(true);
+            spec.addRequired(paramSpec);
         }
-        ParameterSpec returnTypeSpec = new ParameterSpec("returnType", getContext().getType(boolean.class));
-        return new MethodSpec(Collections.<TypeMirror> emptyList(), returnTypeSpec, specs);
+
+        return spec;
+    }
+
+    @Override
+    protected ParameterSpec createReturnParameterSpec() {
+        return new ParameterSpec("returnType", getContext().getType(boolean.class));
     }
 
     @Override
@@ -65,7 +71,23 @@
 
     @Override
     public GuardData create(TemplateMethod method) {
-        return new GuardData(method);
+        GuardData guard = new GuardData(method, specialization);
+        /*
+         * 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 {
+                newParameters.add(new ActualParameter(specializationParameter.getSpecification(), parameter.getActualType(), specializationParameter.getIndex(), parameter.isImplicit()));
+            }
+        }
+        guard.setParameters(newParameters);
+
+        return guard;
     }
 
     @Override
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java	Mon Apr 01 12:19:15 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCastParser.java	Mon Apr 01 21:43:20 2013 +0200
@@ -23,10 +23,8 @@
 package com.oracle.truffle.codegen.processor.typesystem;
 
 import java.lang.annotation.*;
-import java.util.*;
 
 import javax.lang.model.element.*;
-import javax.lang.model.type.*;
 
 import com.oracle.truffle.api.codegen.*;
 import com.oracle.truffle.codegen.processor.*;
@@ -44,14 +42,8 @@
         if (targetType == null) {
             return null;
         }
-        List<ParameterSpec> specs = new ArrayList<>();
-        ParameterSpec valueSpec = new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors());
-        valueSpec.setSignature(true);
-        specs.add(valueSpec);
-
-        ParameterSpec returnTypeSpec = new ParameterSpec("returnType", targetType.getPrimitiveType());
-        returnTypeSpec.setSignature(true);
-        MethodSpec spec = new MethodSpec(Collections.<TypeMirror> emptyList(), returnTypeSpec, specs);
+        MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", targetType.getPrimitiveType()));
+        spec.addRequired(new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors()));
         return spec;
     }
 
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java	Mon Apr 01 12:19:15 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeCheckParser.java	Mon Apr 01 21:43:20 2013 +0200
@@ -23,10 +23,8 @@
 package com.oracle.truffle.codegen.processor.typesystem;
 
 import java.lang.annotation.*;
-import java.util.*;
 
 import javax.lang.model.element.*;
-import javax.lang.model.type.*;
 
 import com.oracle.truffle.api.codegen.*;
 import com.oracle.truffle.codegen.processor.*;
@@ -44,13 +42,8 @@
         if (targetType == null) {
             return null;
         }
-        List<ParameterSpec> specs = new ArrayList<>();
-        ParameterSpec valueSpec = new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors());
-        valueSpec.setSignature(true);
-        specs.add(valueSpec);
-        ParameterSpec returnTypeSpec = new ParameterSpec("returnType", getContext().getType(boolean.class));
-        returnTypeSpec.setSignature(true);
-        MethodSpec spec = new MethodSpec(Collections.<TypeMirror> emptyList(), returnTypeSpec, specs);
+        MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", getContext().getType(boolean.class)));
+        spec.addRequired(new ParameterSpec("value", getTypeSystem().getPrimitiveTypeMirrors()));
         return spec;
     }