changeset 14641:f0bb82ebe30c

Truffle-DSL: some fixes and optimizations to the generated code. Fixed polymorphic specialization nodes could still reference children in some cases. Removed generation of getCost methods since they were very expensive to call. Removed generation of copyPolymorphic, setNext0. Made generated executeGeneric0 and executeAndSpecialize0 final.
author Christian Humer <christian.humer@gmail.com>
date Thu, 20 Mar 2014 17:50:41 +0100
parents b2e2132c0eff
children 2a4b6003ef03
files graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java
diffstat 3 files changed, 32 insertions(+), 86 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java	Thu Mar 20 13:53:36 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java	Thu Mar 20 17:50:41 2014 +0100
@@ -64,7 +64,7 @@
         TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
         assertEquals("(int,boolean)", executeWith(node, 42, false));
         assertEquals("(int,int)", executeWith(node, 42, 42));
-        assertEquals(NodeCost.NONE, node.getNode().getCost());
+        assertEquals(NodeCost.POLYMORPHIC, node.getNode().getCost());
         assertParent(node.getNode(), node.getNode().getLeft());
         assertParent(node.getNode(), node.getNode().getRight());
     }
@@ -75,7 +75,7 @@
         assertEquals("(int,boolean)", executeWith(node, 42, false));
         assertEquals("(boolean,boolean)", executeWith(node, true, false));
         assertEquals("(int,int)", executeWith(node, 42, 42));
-        assertEquals(NodeCost.NONE, node.getNode().getCost());
+        assertEquals(NodeCost.POLYMORPHIC, node.getNode().getCost());
         assertParent(node.getNode(), node.getNode().getLeft());
         assertParent(node.getNode(), node.getNode().getRight());
     }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java	Thu Mar 20 13:53:36 2014 +0100
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java	Thu Mar 20 17:50:41 2014 +0100
@@ -42,7 +42,7 @@
         assertEquals(21, executeWith(node, false, false));
         assertEquals(42, executeWith(node, 21, 21));
         assertEquals("(boolean,int)", executeWith(node, false, 42));
-        assertEquals(NodeCost.NONE, node.getNode().getCost());
+        assertEquals(NodeCost.POLYMORPHIC, node.getNode().getCost());
     }
 
     @SuppressWarnings("unused")
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Thu Mar 20 13:53:36 2014 +0100
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Thu Mar 20 17:50:41 2014 +0100
@@ -98,13 +98,17 @@
         return param.getLocalName();
     }
 
-    private static CodeTree createAccessChild(NodeExecutionData targetExecution) {
+    private static CodeTree createAccessChild(NodeExecutionData targetExecution, String thisReference) {
+        String reference = thisReference;
+        if (reference == null) {
+            reference = "this";
+        }
         CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
         Element accessElement = targetExecution.getChild().getAccessElement();
         if (accessElement == null || accessElement.getKind() == ElementKind.METHOD) {
-            builder.string("this.").string(targetExecution.getChild().getName());
+            builder.string(reference).string(".").string(targetExecution.getChild().getName());
         } else if (accessElement.getKind() == ElementKind.FIELD) {
-            builder.string("this.").string(accessElement.getSimpleName().toString());
+            builder.string(reference).string(".").string(accessElement.getSimpleName().toString());
         } else {
             throw new AssertionError();
         }
@@ -322,7 +326,7 @@
      * variant2 $condition != null
      * $type $name = $value;
      * </pre>
-     * 
+     *
      * .
      */
     private static CodeTree createLazyAssignment(CodeTreeBuilder parent, String name, TypeMirror type, CodeTree condition, CodeTree value) {
@@ -357,7 +361,7 @@
                     nodes.nullLiteral();
                     arguments.string(valueName(parameter.getPreviousParameter()));
                 }
-                nodes.tree(createAccessChild(executionData));
+                nodes.tree(createAccessChild(executionData, null));
                 arguments.string(valueName(parameter));
                 empty = false;
             }
@@ -928,12 +932,6 @@
                     var.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getChildAnnotation()));
                     clazz.add(var);
 
-                    CodeExecutableElement setter = new CodeExecutableElement(modifiers(PROTECTED), context.getType(void.class), "setNext0");
-                    setter.getParameters().add(new CodeVariableElement(clazz.asType(), "next0"));
-                    CodeTreeBuilder builder = setter.createBuilder();
-                    builder.statement("this.next0 = insert(next0)");
-                    clazz.add(setter);
-
                     CodeExecutableElement genericCachedExecute = createCachedExecute(node, node.getPolymorphicSpecialization());
                     clazz.add(genericCachedExecute);
 
@@ -948,41 +946,21 @@
             }
 
             if (needsInvokeCopyConstructorMethod()) {
-                clazz.add(createInvokeCopyConstructor(clazz.asType(), null));
-                clazz.add(createCopyPolymorphicConstructor(clazz.asType()));
+                clazz.add(createCopy(clazz.asType(), null));
             }
 
             if (node.getGenericSpecialization() != null && node.getGenericSpecialization().isReachable()) {
                 clazz.add(createGenericExecute(node, rootGroup));
             }
 
-            clazz.add(createGetCost(node, null, NodeCost.MONOMORPHIC));
         }
 
         protected boolean needsInvokeCopyConstructorMethod() {
             return getModel().getNode().isPolymorphic();
         }
 
-        protected CodeExecutableElement createGetCost(NodeData node, SpecializationData specialization, NodeCost cost) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getTruffleTypes().getNodeCost(), "getCost");
-
-            TypeMirror nodeInfoKind = context.getTruffleTypes().getNodeCost();
-
-            CodeTreeBuilder builder = method.createBuilder();
-            if (node.isPolymorphic() && specialization == null) {
-                // assume next0 exists
-                builder.startIf().string("next0 != null && next0.getCost() != ").staticReference(nodeInfoKind, "UNINITIALIZED").end();
-                builder.startBlock();
-                builder.startReturn().staticReference(nodeInfoKind, "POLYMORPHIC").end();
-                builder.end();
-            }
-
-            builder.startReturn().staticReference(nodeInfoKind, cost.name()).end();
-            return method;
-        }
-
-        protected CodeExecutableElement createInvokeCopyConstructor(TypeMirror baseType, SpecializationData specialization) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), baseType, "invokeCopyConstructor");
+        protected CodeExecutableElement createCopy(TypeMirror baseType, SpecializationData specialization) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), baseType, "copyWithConstructor");
             if (specialization == null) {
                 method.getModifiers().add(ABSTRACT);
             } else {
@@ -998,36 +976,6 @@
             return method;
         }
 
-        protected CodeExecutableElement createCopyPolymorphicConstructor(TypeMirror baseType) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), baseType, "copyPolymorphic");
-            CodeTreeBuilder builder = method.createBuilder();
-            CodeTreeBuilder nullBuilder = builder.create();
-            CodeTreeBuilder oldBuilder = builder.create();
-            CodeTreeBuilder resetBuilder = builder.create();
-
-            for (ActualParameter param : getModel().getSignatureParameters()) {
-                NodeExecutionData execution = param.getSpecification().getExecution();
-
-                CodeTree access = createAccessChild(execution);
-
-                String oldName = "old" + Utils.firstLetterUpperCase(param.getLocalName());
-                oldBuilder.declaration(execution.getChild().getNodeData().getNodeType(), oldName, access);
-                nullBuilder.startStatement().tree(access).string(" = null").end();
-                resetBuilder.startStatement().tree(access).string(" = ").string(oldName).end();
-            }
-
-            builder.tree(oldBuilder.getRoot());
-            builder.tree(nullBuilder.getRoot());
-
-            builder.startStatement().type(baseType).string(" copy = ");
-            builder.startCall("invokeCopyConstructor").end();
-            builder.end();
-
-            builder.tree(resetBuilder.getRoot());
-            builder.startReturn().string("copy").end();
-            return method;
-        }
-
         private List<CodeExecutableElement> createImplicitChildrenAccessors() {
             NodeData node = getModel().getNode();
             // Map<NodeChildData, Set<TypeData>> expectTypes = new HashMap<>();
@@ -1280,7 +1228,7 @@
 
         private CodeExecutableElement createGenericExecuteAndSpecialize(final NodeData node, SpecializationGroup rootGroup) {
             TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType();
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_SPECIALIZE_NAME);
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), genericReturnType, EXECUTE_SPECIALIZE_NAME);
             method.addParameter(new CodeVariableElement(getContext().getType(int.class), "minimumState"));
             addInternalValueParameters(method, node.getGenericSpecialization(), true, false);
             method.addParameter(new CodeVariableElement(getContext().getType(String.class), "reason"));
@@ -1341,7 +1289,7 @@
 
         private CodeExecutableElement createGenericExecute(NodeData node, SpecializationGroup group) {
             TypeMirror genericReturnType = node.getGenericSpecialization().getReturnType().getType();
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED), genericReturnType, EXECUTE_GENERIC_NAME);
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), genericReturnType, EXECUTE_GENERIC_NAME);
 
             if (!node.needsFrame(getContext())) {
                 method.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getSlowPath()));
@@ -1816,11 +1764,16 @@
             String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization());
             CodeTreeBuilder builder = parent.create();
 
-            builder.declaration(getElement().asType(), "currentCopy", currentNode + ".copyPolymorphic()");
+            builder.declaration(getElement().asType(), "currentCopy", currentNode + ".copyWithConstructor()");
+            for (ActualParameter param : getModel().getSignatureParameters()) {
+                NodeExecutionData execution = param.getSpecification().getExecution();
+                builder.startStatement().tree(createAccessChild(execution, "currentCopy")).string(" = ").nullLiteral().end();
+            }
+            builder.startStatement().string("currentCopy.next0 = ").startNew(uninitializedName).string("currentCopy").end().end();
+
             builder.declaration(polyClassName, "polymorphic", builder.create().startNew(polyClassName).string(currentNode).end());
+            builder.startStatement().string("polymorphic.next0 = ").string("currentCopy").end();
             builder.startStatement().startCall(currentNode, "replace").string("polymorphic").string("message").end().end();
-            builder.startStatement().startCall("polymorphic", "setNext0").string("currentCopy").end().end();
-            builder.startStatement().startCall("currentCopy", "setNext0").startNew(uninitializedName).string(currentNode).end().end().end();
 
             builder.startReturn();
             builder.startCall("currentCopy.next0", EXECUTE_POLYMORPHIC_NAME);
@@ -2300,7 +2253,7 @@
         private CodeTree createExecuteChildExpression(CodeTreeBuilder parent, NodeExecutionData targetExecution, ExecutableTypeData targetExecutable, ActualParameter unexpectedParameter) {
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
             if (targetExecution != null) {
-                builder.tree(createAccessChild(targetExecution));
+                builder.tree(createAccessChild(targetExecution, null));
                 builder.string(".");
             }
 
@@ -2465,7 +2418,7 @@
             }
             CodeTypeElement clazz = createClass(node, modifiers(PRIVATE, STATIC, FINAL), nodePolymorphicClassName(node), baseType, false);
 
-            clazz.getAnnotationMirrors().add(createNodeInfo(node, NodeCost.NONE));
+            clazz.getAnnotationMirrors().add(createNodeInfo(node, NodeCost.POLYMORPHIC));
 
             for (ActualParameter polymorphParameter : polymorph.getSignatureParameters()) {
                 if (!polymorphParameter.getTypeSystemType().isGeneric()) {
@@ -2508,11 +2461,10 @@
             }
 
             if (needsInvokeCopyConstructorMethod()) {
-                clazz.add(createInvokeCopyConstructor(nodeGen.asType(), specialization));
+                clazz.add(createCopy(nodeGen.asType(), specialization));
             }
 
             createCachedExecuteMethods(specialization);
-            clazz.add(createGetCost(specialization.getNode(), specialization, NodeCost.NONE));
         }
 
         private ExecutableElement createUpdateType(ActualParameter parameter) {
@@ -2558,7 +2510,7 @@
             } else if (specialization.isUninitialized()) {
                 cost = NodeCost.UNINITIALIZED;
             } else if (specialization.isPolymorphic()) {
-                cost = NodeCost.NONE;
+                cost = NodeCost.POLYMORPHIC;
             } else if (specialization.isSpecialized()) {
                 cost = NodeCost.MONOMORPHIC;
             } else {
@@ -2594,13 +2546,7 @@
                 getElement().add(createUpdateTypes(nodeGen.asType()));
             }
             if (needsInvokeCopyConstructorMethod()) {
-                clazz.add(createInvokeCopyConstructor(nodeGen.asType(), specialization));
-            }
-
-            if (specialization.isGeneric()) {
-                clazz.add(createGetCost(specialization.getNode(), specialization, NodeCost.MEGAMORPHIC));
-            } else if (specialization.isUninitialized()) {
-                clazz.add(createGetCost(specialization.getNode(), specialization, NodeCost.UNINITIALIZED));
+                clazz.add(createCopy(nodeGen.asType(), specialization));
             }
         }
 
@@ -2726,9 +2672,9 @@
             builder.end();
 
             builder.startElseBlock();
-            builder.startStatement().startCall("setNext0");
+            builder.startStatement().string("next0 = ");
             builder.startNew(nodeSpecializationClassName(node.getUninitializedSpecialization())).string("this").end();
-            builder.end().end();
+            builder.end();
 
             CodeTreeBuilder specializeCall = new CodeTreeBuilder(builder);
             specializeCall.startCall(EXECUTE_SPECIALIZE_NAME);