changeset 10602:b8fe1fe004ec

Truffle-DSL: fixed bugs in the generated polymorphic code generation.
author Christian Humer <christian.humer@gmail.com>
date Tue, 02 Jul 2013 19:21:59 +0200
parents 5acc3f3016b7
children 2e7e7a22940f
files 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/NodeParser.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/template/TemplateMethod.java
diffstat 5 files changed, 129 insertions(+), 72 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Tue Jul 02 14:51:22 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Tue Jul 02 19:21:59 2013 +0200
@@ -79,7 +79,7 @@
         }
 
         String name = Utils.firstLetterUpperCase(nodeid);
-        if (specialization == node.getGenericPolymorphicSpecializtion()) {
+        if (specialization == node.getGenericPolymorphicSpecialization()) {
             name += "PolymorphicNode";
         } else {
             name += "Polymorphic" + polymorphicIndex(node, specialization) + "Node";
@@ -101,7 +101,7 @@
 
     private static String executeCachedName(SpecializationData polymorphic) {
         NodeData node = polymorphic.getNode();
-        boolean generic = polymorphic == node.getGenericPolymorphicSpecializtion();
+        boolean generic = polymorphic == node.getGenericPolymorphicSpecialization();
 
         if (generic) {
             return "executeCachedGeneric0";
@@ -116,7 +116,7 @@
             if (specialization == polymorphic) {
                 break;
             }
-            if (specialization != node.getGenericPolymorphicSpecializtion()) {
+            if (specialization != node.getGenericPolymorphicSpecialization()) {
                 index++;
             }
         }
@@ -687,10 +687,10 @@
 
                 if (node.getPolymorphicDepth() > 1) {
                     PolymorphicNodeFactory generic = new PolymorphicNodeFactory(getContext(), generatedNode, true);
-                    add(generic, node.getGenericPolymorphicSpecializtion());
+                    add(generic, node.getGenericPolymorphicSpecialization());
 
                     for (SpecializationData specialization : node.getPolymorphicSpecializations()) {
-                        if (specialization == node.getGenericPolymorphicSpecializtion()) {
+                        if (specialization == node.getGenericPolymorphicSpecialization()) {
                             continue;
                         }
                         add(new PolymorphicNodeFactory(context, generic.getElement(), false), specialization);
@@ -1094,10 +1094,10 @@
 
                     clazz.add(createCreateSpecialization(node));
 
-                    CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getGenericPolymorphicSpecializtion(), null);
+                    CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getGenericPolymorphicSpecialization(), null);
                     clazz.add(genericCachedExecute);
                     for (SpecializationData polymorph : node.getPolymorphicSpecializations()) {
-                        if (polymorph == node.getGenericPolymorphicSpecializtion()) {
+                        if (polymorph == node.getGenericPolymorphicSpecialization()) {
                             continue;
                         }
                         clazz.add(createCachedExecute(node, polymorph, genericCachedExecute));
@@ -1214,10 +1214,10 @@
             CodeExecutableElement cachedExecute = new CodeExecutableElement(modifiers(PROTECTED), polymorph.getReturnType().getType(), name);
             addInternalValueParameters(cachedExecute, polymorph, true, true);
 
-            if (polymorph == node.getGenericPolymorphicSpecializtion()) {
+            if (polymorph == node.getGenericPolymorphicSpecialization()) {
                 cachedExecute.getModifiers().add(ABSTRACT);
             } else {
-                SpecializationData genericPolymorph = node.getGenericPolymorphicSpecializtion();
+                SpecializationData genericPolymorph = node.getGenericPolymorphicSpecialization();
                 CodeTreeBuilder builder = cachedExecute.createBuilder();
                 ExecutableTypeData genericExecutable = new ExecutableTypeData(genericPolymorph, genericPolymorphMethod, node.getTypeSystem(), genericPolymorph.getReturnType().getTypeSystemType());
                 ExecutableTypeData specificExecutable = new ExecutableTypeData(polymorph, cachedExecute, node.getTypeSystem(), polymorph.getReturnType().getTypeSystemType());
@@ -1378,6 +1378,7 @@
 
             DeclaredType annotationType;
             if (child.getCardinality() == Cardinality.MANY) {
+                var.getModifiers().add(Modifier.FINAL);
                 annotationType = getContext().getTruffleTypes().getChildrenAnnotation();
             } else {
                 annotationType = getContext().getTruffleTypes().getChildAnnotation();
@@ -1415,26 +1416,31 @@
 
             List<SpecializationData> specializations = node.getSpecializations();
 
+            boolean firstUnreachable = true;
+            SpecializationData previous = null;
             for (SpecializationData current : specializations) {
-                if (current.isUninitialized() || !current.isReachable()) {
+                if (current.isUninitialized()) {
                     continue;
                 }
-                CodeTreeBuilder execute = new CodeTreeBuilder(builder);
 
-                execute.tree(createGenericInvokeAndSpecialize(builder, node.getGenericSpecialization(), current));
+                if (current.isReachable()) {
+                    CodeTree execute = createGenericInvokeAndSpecialize(builder, node.getGenericSpecialization(), current);
 
-                if (!current.isGeneric()) {
-                    builder.startStatement().string("allowed = allowed || (minimumState == ").string(nodeSpecializationClassName(current)).string(".class)").end();
+                    if (!current.isGeneric()) {
+                        builder.startStatement().string("allowed = allowed || (minimumState == ").string(nodeSpecializationClassName(current)).string(".class)").end();
+                    }
+
+                    builder.tree(createGuardAndCast(builder, prefix, current.getNode().getGenericSpecialization(), current, true, execute, null, true, false));
+                } else {
+                    if (firstUnreachable) {
+                        if (previous != null && !previous.isGenericSpecialization(getContext()) && !previous.hasRewrite(getContext())) {
+                            emitEncounteredSynthetic(builder, current);
+                        }
+                        firstUnreachable = false;
+                    }
+                    builder.string("// unreachable ").string(current.getId()).newLine();
                 }
-
-                builder.tree(createGuardAndCast(builder, prefix, current.getNode().getGenericSpecialization(), current, true, execute.getRoot(), null, true, false));
-            }
-
-            for (SpecializationData current : specializations) {
-                if (current.isUninitialized() || current.isReachable()) {
-                    continue;
-                }
-                builder.string("// unreachable ").string(current.getId()).newLine();
+                previous = current;
             }
 
             return method;
@@ -1527,7 +1533,7 @@
                         builder.startWhile().string("searchNode != null").end();
                         builder.startBlock();
                         builder.statement("searchNode = searchNode.getParent()");
-                        builder.startIf().instanceOf("searchNode", nodePolymorphicClassName(node, node.getGenericPolymorphicSpecializtion())).end();
+                        builder.startIf().instanceOf("searchNode", nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization())).end();
                         builder.startBlock().breakStatement().end();
                         builder.end();
                         builder.startStatement().startCall("searchNode", "replace");
@@ -1586,15 +1592,26 @@
         }
 
         private CodeTree createRewritePolymorphic(CodeTreeBuilder parent, NodeData node) {
-            String className = nodePolymorphicClassName(node, node.getGenericPolymorphicSpecializtion());
+            String className = nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization());
             CodeTreeBuilder builder = parent.create();
             builder.startStatement();
             builder.string(className);
             builder.string(" polymorphic = ");
             builder.startNew(className).string("this").end();
             builder.end();
-            for (NodeChildData child : node.getChildren()) {
-                builder.startStatement().string("this.").string(child.getName()).string(" = null").end();
+
+            for (ActualParameter param : node.getGenericSpecialization().getParameters()) {
+                if (!param.getSpecification().isSignature()) {
+                    continue;
+                }
+                NodeChildData child = node.findChild(param.getSpecification().getName());
+                if (child != null) {
+                    builder.startStatement().string("this.").string(child.getName());
+                    if (child.getCardinality().isMany()) {
+                        builder.string("[").string(String.valueOf(param.getIndex())).string("]");
+                    }
+                    builder.string(" = null").end();
+                }
             }
             builder.startStatement().startCall("super", "replace");
             builder.string("polymorphic");
@@ -1814,7 +1831,7 @@
                 builder.tree(createDeoptimize(builder));
                 builder.tree(createExecuteChildren(parent, currentExecutable, generic, genericParameters, genericParameter, false));
                 if (specialization.isPolymorphic()) {
-                    builder.tree(createReturnOptimizeTypes(builder, specialization, param));
+                    builder.tree(createReturnOptimizeTypes(builder, currentExecutable, specialization, param));
                 } else {
                     builder.tree(createReturnExecuteAndSpecialize(builder, currentExecutable, specialization.findNextSpecialization(), param, "Expected " + param.getLocalName() + " instanceof " +
                                     Utils.getSimpleName(param.getType())));
@@ -1825,10 +1842,10 @@
             return builder.getRoot();
         }
 
-        private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, SpecializationData specialization, ActualParameter param) {
+        private CodeTree createReturnOptimizeTypes(CodeTreeBuilder parent, ExecutableTypeData currentExecutable, SpecializationData specialization, ActualParameter param) {
             NodeData node = specialization.getNode();
             assert !node.getPolymorphicSpecializations().isEmpty();
-            SpecializationData generic = node.getGenericPolymorphicSpecializtion();
+            SpecializationData generic = node.getGenericPolymorphicSpecialization();
 
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
             builder.startReturn();
@@ -1839,9 +1856,8 @@
             execute.end();
 
             TypeData sourceType = generic.getReturnType().getTypeSystemType();
-            TypeData targetType = specialization.getReturnType().getTypeSystemType();
 
-            builder.tree(createCastType(node, sourceType, targetType, true, execute.getRoot()));
+            builder.tree(createExpectExecutableType(node, sourceType, currentExecutable, execute.getRoot()));
 
             builder.end();
             return builder.getRoot();
@@ -1875,6 +1891,7 @@
                 if (!parameter.getSpecification().isSignature()) {
                     builder.string(parameter.getLocalName());
                 } else {
+
                     if (index < targetField.getExecuteWith().size()) {
                         NodeChildData child = targetField.getExecuteWith().get(index);
 
@@ -2201,7 +2218,7 @@
 
         private CodeTree createAppendPolymorphic(CodeTreeBuilder parent, SpecializationData specialization) {
             NodeData node = specialization.getNode();
-            String genericClassName = nodePolymorphicClassName(node, node.getGenericPolymorphicSpecializtion());
+            String genericClassName = nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization());
 
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
             builder.startStatement().startStaticCall(getContext().getTruffleTypes().getCompilerDirectives(), "transferToInterpreter").end().end();
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java	Tue Jul 02 14:51:22 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java	Tue Jul 02 19:21:59 2013 +0200
@@ -47,7 +47,7 @@
 
     private List<SpecializationData> specializations;
     private List<SpecializationData> polymorphicSpecializations;
-    private SpecializationData genericPolymoprhicSpecialization;
+    private SpecializationData genericPolymorphicSpecialization;
     private List<SpecializationListenerData> specializationListeners;
     private Map<Integer, List<ExecutableTypeData>> executableTypes;
     private List<ShortCircuitData> shortCircuits;
@@ -522,12 +522,12 @@
         return polymorphicSpecializations;
     }
 
-    void setGenericPolymoprhicSpecialization(SpecializationData genericPolymoprhicSpecialization) {
-        this.genericPolymoprhicSpecialization = genericPolymoprhicSpecialization;
+    void setGenericPolymorphicSpecialization(SpecializationData genericPolymoprhicSpecialization) {
+        this.genericPolymorphicSpecialization = genericPolymoprhicSpecialization;
     }
 
-    public SpecializationData getGenericPolymorphicSpecializtion() {
-        return genericPolymoprhicSpecialization;
+    public SpecializationData getGenericPolymorphicSpecialization() {
+        return genericPolymorphicSpecialization;
     }
 
     void setSpecializationListeners(List<SpecializationListenerData> specializationListeners) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Tue Jul 02 14:51:22 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Tue Jul 02 19:21:59 2013 +0200
@@ -255,6 +255,14 @@
         SpecializationData generic = node.getGenericSpecialization();
         for (Signature signature : sortedSignatures) {
             SpecializationData specialization = new SpecializationData(generic, false, false, true);
+
+            for (Iterator<ActualParameter> iterator = specialization.getParameters().iterator(); iterator.hasNext();) {
+                ActualParameter param = iterator.next();
+                if (param.getSpecification().isLocal()) {
+                    iterator.remove();
+                }
+            }
+
             specialization.forceFrame(context.getTruffleTypes().getFrame());
             specialization.setNode(node);
             specialization.updateSignature(signature);
@@ -265,7 +273,7 @@
             }
         }
 
-        node.setGenericPolymoprhicSpecialization(polymorphicGeneric);
+        node.setGenericPolymorphicSpecialization(polymorphicGeneric);
         node.setPolymorphicSpecializations(specializations);
     }
 
@@ -575,36 +583,7 @@
         } else if (generics.size() == 1) {
             genericSpecialization = generics.get(0);
         } else if (node.needsRewrites(context)) {
-            SpecializationData specialization = specializations.get(0);
-            GenericParser parser = new GenericParser(context, node);
-            MethodSpec specification = parser.createDefaultMethodSpec(specialization.getMethod(), null, true, null);
-
-            ExecutableTypeData anyGenericReturnType = node.findAnyGenericExecutableType(context, 0);
-            assert anyGenericReturnType != null;
-
-            ActualParameter returnType = new ActualParameter(specification.getReturnType(), anyGenericReturnType.getType(), 0, false);
-            List<ActualParameter> parameters = new ArrayList<>();
-            for (ActualParameter specializationParameter : specialization.getParameters()) {
-                ParameterSpec parameterSpec = specification.findParameterSpec(specializationParameter.getSpecification().getName());
-                NodeChildData child = node.findChild(parameterSpec.getName());
-                TypeData actualType;
-                if (child == null) {
-                    actualType = specializationParameter.getTypeSystemType();
-                } else {
-                    ExecutableTypeData paramType = child.findAnyGenericExecutableType(context);
-                    assert paramType != null;
-                    actualType = paramType.getType();
-                }
-
-                if (actualType != null) {
-                    parameters.add(new ActualParameter(parameterSpec, actualType, specializationParameter.getIndex(), specializationParameter.isImplicit()));
-                } else {
-                    parameters.add(new ActualParameter(parameterSpec, specializationParameter.getType(), specializationParameter.getIndex(), specializationParameter.isImplicit()));
-                }
-            }
-            TemplateMethod genericMethod = new TemplateMethod("Generic", node, specification, null, null, returnType, parameters);
-            genericSpecialization = new SpecializationData(genericMethod, true, false, false);
-
+            genericSpecialization = createGenericSpecialization(node, specializations);
             specializations.add(genericSpecialization);
         }
 
@@ -684,6 +663,57 @@
         }
     }
 
+    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);
+
+        List<ActualParameter> parameters = new ArrayList<>();
+        for (ActualParameter parameter : specialization.getReturnTypeAndParameters()) {
+            if (!parameter.getSpecification().isSignature()) {
+                parameters.add(new ActualParameter(parameter));
+                continue;
+            }
+            NodeData childNode = node;
+            NodeChildData child = node.findChild(parameter.getSpecification().getName());
+            if (child != null) {
+                childNode = child.getNodeData();
+            }
+
+            TypeData genericType = null;
+
+            Set<TypeData> types = new HashSet<>();
+            for (SpecializationData otherSpecialization : specializations) {
+                ActualParameter otherParameter = otherSpecialization.findParameter(parameter.getLocalName());
+                if (otherParameter != null) {
+                    types.add(otherParameter.getTypeSystemType());
+                }
+            }
+
+            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();
+            }
+
+            parameters.add(new ActualParameter(parameter, genericType));
+        }
+        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());
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java	Tue Jul 02 14:51:22 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java	Tue Jul 02 19:21:59 2013 +0200
@@ -107,7 +107,8 @@
             if (child == null) {
                 continue;
             }
-            if (!parameter.getTypeSystemType().isGeneric()) {
+            ActualParameter genericParameter = getNode().getGenericSpecialization().findParameter(parameter.getLocalName());
+            if (!parameter.getTypeSystemType().equals(genericParameter.getTypeSystemType())) {
                 return false;
             }
         }
@@ -223,6 +224,16 @@
         this.assumptions = assumptions;
     }
 
+    public SpecializationData findPreviousSpecialization() {
+        List<SpecializationData> specializations = node.getSpecializations();
+        for (int i = 0; i < specializations.size() - 1; i++) {
+            if (specializations.get(i) == this && i > 0) {
+                return specializations.get(i - 1);
+            }
+        }
+        return null;
+    }
+
     public SpecializationData findNextSpecialization() {
         List<SpecializationData> specializations = node.getSpecializations();
         for (int i = 0; i < specializations.size() - 1; i++) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java	Tue Jul 02 14:51:22 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/TemplateMethod.java	Tue Jul 02 19:21:59 2013 +0200
@@ -28,7 +28,6 @@
 import javax.lang.model.type.*;
 
 import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.template.TemplateMethod.Signature;
 import com.oracle.truffle.dsl.processor.typesystem.*;
 
 /**
@@ -141,7 +140,7 @@
     public List<ActualParameter> findParameters(ParameterSpec spec) {
         List<ActualParameter> foundParameters = new ArrayList<>();
         for (ActualParameter param : getReturnTypeAndParameters()) {
-            if (param.getSpecification().equals(spec)) {
+            if (param.getSpecification().getName().equals(spec.getName())) {
                 foundParameters.add(param);
             }
         }