changeset 7846:91cc98eae8ee

Refactor guard creation methods are not flexible enough to handle two if guards.
author Christian Humer <christian.humer@gmail.com>
date Tue, 19 Feb 2013 14:29:12 +0100
parents 0110e781b6fa
children 06a7cd6aaf00
files graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeVariableElement.java graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java
diffstat 4 files changed, 183 insertions(+), 103 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java	Tue Feb 19 11:31:23 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java	Tue Feb 19 14:29:12 2013 +0100
@@ -114,7 +114,7 @@
     }
 
     public CodeTreeBuilder createBuilder() {
-        CodeTreeBuilder builder = new CodeTreeBuilder();
+        CodeTreeBuilder builder = new CodeTreeBuilder(null);
         this.bodyTree = builder.getTree();
         this.bodyTree.setEnclosingElement(this);
         this.body = null;
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java	Tue Feb 19 11:31:23 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java	Tue Feb 19 14:29:12 2013 +0100
@@ -33,17 +33,25 @@
 
 public class CodeTreeBuilder {
 
+    private final CodeTreeBuilder parent;
+
     private BuilderCodeTree currentElement;
     private final BuilderCodeTree root;
 
-    public CodeTreeBuilder() {
+    private int treeCount;
+
+    public CodeTreeBuilder(CodeTreeBuilder parent) {
         this.root = new BuilderCodeTree(GROUP, null, null);
         this.currentElement = root;
+        this.parent = parent;
     }
 
-    public CodeTreeBuilder(CodeTree tree) {
-        this.root = (BuilderCodeTree) tree;
-        this.currentElement = root;
+    public int getTreeCount() {
+        return treeCount;
+    }
+
+    public boolean isEmpty() {
+        return treeCount == 0;
     }
 
     public CodeTreeBuilder statement(String statement) {
@@ -55,11 +63,11 @@
     }
 
     public static CodeTreeBuilder createBuilder() {
-        return new CodeTreeBuilder();
+        return new CodeTreeBuilder(null);
     }
 
     public static CodeTree singleString(String s) {
-        return new CodeTreeBuilder().string(s).getTree();
+        return new CodeTreeBuilder(null).string(s).getTree();
     }
 
     private CodeTreeBuilder push(CodeTreeKind kind) {
@@ -89,11 +97,14 @@
                 currentElement = tree;
                 break;
         }
+        treeCount++;
         return this;
     }
 
     private void clearLast(CodeTreeKind kind) {
-        clearLastRec(kind, currentElement.getEnclosedElements());
+        if (clearLastRec(kind, currentElement.getEnclosedElements())) {
+            treeCount--;
+        }
     }
 
     public CodeTreeBuilder startStatement() {
@@ -358,6 +369,13 @@
         return push(CodeTreeKind.INDENT);
     }
 
+    public CodeTreeBuilder end(int times) {
+        for (int i = 0; i < times; i++) {
+            end();
+        }
+        return this;
+    }
+
     public CodeTreeBuilder end() {
         BuilderCodeTree tree = currentElement;
         EndCallback callback = tree.getAtEndListener();
@@ -372,9 +390,9 @@
     }
 
     private void toParent() {
-        Element parent = currentElement.getEnclosingElement();
+        Element parentElement = currentElement.getEnclosingElement();
         if (currentElement != root) {
-            this.currentElement = (BuilderCodeTree) parent;
+            this.currentElement = (BuilderCodeTree) parentElement;
         } else {
             this.currentElement = root;
         }
@@ -433,7 +451,7 @@
     }
 
     public CodeTreeBuilder create() {
-        return new CodeTreeBuilder();
+        return new CodeTreeBuilder(null);
     }
 
     public CodeTreeBuilder type(TypeMirror type) {
@@ -496,7 +514,11 @@
         while (element != null && (element.getKind() != ElementKind.METHOD)) {
             element = element.getEnclosingElement();
         }
-        return element != null ? (ExecutableElement) element : null;
+        ExecutableElement found = element != null ? (ExecutableElement) element : null;
+        if (found == null && parent != null) {
+            found = parent.findMethod();
+        }
+        return found;
     }
 
     public CodeTreeBuilder returnTrue() {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeVariableElement.java	Tue Feb 19 11:31:23 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeVariableElement.java	Tue Feb 19 14:29:12 2013 +0100
@@ -58,7 +58,7 @@
     }
 
     public CodeTreeBuilder createInitBuilder() {
-        CodeTreeBuilder builder = new CodeTreeBuilder();
+        CodeTreeBuilder builder = new CodeTreeBuilder(null);
         init = builder.getTree();
         init.setEnclosingElement(this);
         return builder;
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Tue Feb 19 11:31:23 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Tue Feb 19 14:29:12 2013 +0100
@@ -69,7 +69,8 @@
 
     private static String specializationId(SpecializationData specialization) {
         String name = "";
-        if (specialization.getNode().getSpecializations().length > 1) {
+        NodeData node = specialization.getNode();
+        if (node.getSpecializations().length > 1) {
             name = specialization.getMethodName();
             if (name.startsWith("do")) {
                 name = name.substring(2);
@@ -192,32 +193,77 @@
         body.string(".").startCall(methodName);
     }
 
-    private static String emitExplicitGuards(ProcessorContext context, CodeTreeBuilder body, String prefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization,
+    private static CodeTree createGuardAndCast(ProcessorContext context, CodeTreeBuilder parent, String prefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization,
+                    boolean onSpecialization, CodeTree guardedStatements, CodeTree elseStatements) {
+
+        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+        CodeTree implicitGuards = createImplicitGuards(context, parent, prefix, valueSpecialization, guardedSpecialization);
+        CodeTree explicitGuards = createExplicitGuards(context, parent, implicitGuards == null ? prefix : null, valueSpecialization, guardedSpecialization, onSpecialization);
+
+        int ifCount = 0;
+
+        if (implicitGuards != null) {
+            builder.startIf();
+            builder.tree(implicitGuards);
+            builder.end();
+            builder.startBlock();
+            ifCount++;
+        }
+
+        if (explicitGuards != null) {
+            builder.startIf();
+            builder.tree(explicitGuards);
+            builder.end();
+            builder.startBlock();
+            ifCount++;
+        }
+
+        if (implicitGuards == null && explicitGuards == null && prefix != null && !prefix.isEmpty()) {
+            builder.startIf().string(prefix).end().startBlock();
+            ifCount++;
+        }
+
+        builder.tree(guardedStatements);
+
+        builder.end(ifCount);
+        if (ifCount > 0 && elseStatements != null) {
+            builder.startElseBlock();
+            builder.tree(elseStatements);
+            builder.end();
+        }
+
+        return builder.getRoot();
+    }
+
+    private static CodeTree createExplicitGuards(ProcessorContext context, CodeTreeBuilder parent, String prefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization,
                     boolean onSpecialization) {
-        String andOperator = prefix;
+        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+        String andOperator = (prefix != null && !prefix.isEmpty()) ? (prefix + " && ") : "";
         if (guardedSpecialization.getGuards().length > 0) {
             // Explicitly specified guards
             for (SpecializationGuardData guard : guardedSpecialization.getGuards()) {
                 if ((guard.isOnSpecialization() && onSpecialization) || (guard.isOnExecution() && !onSpecialization)) {
-                    body.string(andOperator);
+                    builder.string(andOperator);
 
-                    startCallOperationMethod(body, guard.getGuardDeclaration());
-                    addValueParameterNamesWithCasts(context, body, valueSpecialization, guardedSpecialization);
+                    startCallOperationMethod(builder, guard.getGuardDeclaration());
+                    addValueParameterNamesWithCasts(context, builder, valueSpecialization, guardedSpecialization);
 
-                    body.end().end(); // call
+                    builder.end().end(); // call
                     andOperator = " && ";
                 }
             }
         }
-        return andOperator;
+
+        return builder.isEmpty() ? null : builder.getRoot();
     }
 
-    private static String emitImplicitGuards(ProcessorContext context, CodeTreeBuilder body, String prefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) {
+    private static CodeTree createImplicitGuards(ProcessorContext context, CodeTreeBuilder parent, String prefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) {
         NodeData node = guardedSpecialization.getNode();
         TypeSystemData typeSystem = node.getTypeSystem();
 
+        CodeTreeBuilder builder = new CodeTreeBuilder(parent);
         // Implict guards based on method signature
-        String andOperator = prefix;
+        String andOperator = (prefix != null && !prefix.isEmpty()) ? (prefix + " && ") : "";
         for (NodeFieldData field : node.getFields()) {
             ActualParameter guardedParam = guardedSpecialization.findParameter(field.getName());
             ActualParameter valueParam = valueSpecialization.findParameter(field.getName());
@@ -229,29 +275,30 @@
                 continue;
             }
 
-            body.string(andOperator);
+            builder.string(andOperator);
 
-            body.startGroup();
+            builder.startGroup();
 
             if (field.isShortCircuit()) {
                 ActualParameter shortCircuit = guardedSpecialization.getPreviousParam(guardedParam);
-                body.string("(");
-                body.string("!").string(valueName(guardedSpecialization, shortCircuit));
-                body.string(" || ");
+                builder.string("(");
+                builder.string("!").string(valueName(guardedSpecialization, shortCircuit));
+                builder.string(" || ");
             }
 
-            startCallTypeSystemMethod(context, body, guardedSpecialization.getNode(), TypeSystemCodeGenerator.isTypeMethodName(guardedType));
-            body.string(valueName(guardedSpecialization, guardedParam));
-            body.end().end(); // call
+            startCallTypeSystemMethod(context, builder, guardedSpecialization.getNode(), TypeSystemCodeGenerator.isTypeMethodName(guardedType));
+            builder.string(valueName(guardedSpecialization, guardedParam));
+            builder.end().end(); // call
 
             if (field.isShortCircuit()) {
-                body.string(")");
+                builder.string(")");
             }
 
-            body.end(); // group
+            builder.end(); // group
             andOperator = " && ";
         }
-        return andOperator;
+
+        return builder.isEmpty() ? null : builder.getRoot();
     }
 
     @Override
@@ -468,19 +515,12 @@
                 SpecializationData specialization = node.getSpecializations()[i];
                 body.startStatement().string("allowed = allowed || (minimumState == ").string(nodeClassName(specialization)).string(".class)").end();
 
-                if (specialization.isGeneric()) {
-                    body.startIf().string("allowed").end().startBlock();
-                } else {
-                    body.startIf().string("allowed");
-                    String prefix = " && ";
-                    prefix = emitImplicitGuards(getContext(), body, prefix, node.getGenericSpecialization(), specialization);
-                    emitExplicitGuards(getContext(), body, prefix, node.getGenericSpecialization(), specialization, true);
-                    body.end().startBlock();
-                }
-                body.startReturn().startNew(nodeClassName(specialization));
-                body.string(THIS_NODE_LOCAL_VAR_NAME);
-                body.end().end();
-                body.end(); // block
+                CodeTreeBuilder guarded = new CodeTreeBuilder(body);
+                guarded.startReturn().startNew(nodeClassName(specialization));
+                guarded.string(THIS_NODE_LOCAL_VAR_NAME);
+                guarded.end().end();
+
+                body.tree(createGuardAndCast(getContext(), body, "allowed", node.getGenericSpecialization(), specialization, true, guarded.getRoot(), null));
             }
             body.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end();
 
@@ -524,14 +564,15 @@
         }
 
         private void emitGeneratedGenericSpecialization(CodeTreeBuilder builder, SpecializationData current, SpecializationData next) {
+            CodeTreeBuilder invokeMethodBuilder = new CodeTreeBuilder(builder);
+            emitInvokeDoMethod(invokeMethodBuilder, current, 0);
+            CodeTree invokeMethod = invokeMethodBuilder.getRoot();
+
             if (next != null) {
-                builder.startIf();
-                String prefix = emitImplicitGuards(context, builder, "", current.getNode().getGenericSpecialization(), current);
-                emitExplicitGuards(context, builder, prefix, current.getNode().getGenericSpecialization(), current, false);
-                builder.end().startBlock();
+                invokeMethod = createGuardAndCast(getContext(), builder, "", current.getNode().getGenericSpecialization(), current, false, invokeMethod, null);
             }
 
-            emitInvokeDoMethod(builder, current, 0);
+            builder.tree(invokeMethod);
 
             if (next != null) {
                 builder.end();
@@ -699,58 +740,62 @@
         }
 
         private void buildFunctionalExecuteMethod(CodeTreeBuilder builder, SpecializationData specialization) {
-            NodeData node = specialization.getNode();
-            TypeSystemData typeSystem = node.getTypeSystem();
-
             if (specialization.isUninitialized()) {
-                builder.startStatement();
-                builder.startStaticCall(getContext().getTruffleTypes().getTruffleIntrinsics(), "deoptimize").end();
-                builder.end();
+                builder.tree(createDeoptimize(builder));
             }
 
-            for (NodeFieldData field : node.getFields()) {
-                if (field.getExecutionKind() == ExecutionKind.IGNORE) {
-                    continue;
-                }
+            builder.tree(createExecuteChildren(builder, specialization));
 
-                ActualParameter parameterType = specialization.findParameter(field.getName());
-
-                if (parameterType.getActualTypeData(typeSystem).isGeneric()) {
-                    buildGenericValueExecute(builder, specialization, field, null);
-                } else {
-                    buildSpecializedValueExecute(builder, specialization, field);
-                }
+            if (specialization.isUninitialized()) {
+                builder.tree(createSpecializeCall(builder, specialization));
             }
 
-            if (specialization.hasDynamicGuards()) {
-                builder.startIf();
+            CodeTree executeNode = createExecute(builder, specialization);
+
+            SpecializationData next = specialization.findNextSpecialization();
+            CodeTree returnSpecialized = null;
+            if (next != null) {
+                returnSpecialized = createReturnSpecializeAndExecute(builder, next, null);
+            }
+            builder.tree(createGuardAndCast(context, builder, "", specialization, specialization, false, executeNode, returnSpecialized));
+        }
+
+        private CodeTree createDeoptimize(CodeTreeBuilder parent) {
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            builder.startStatement();
+            builder.startStaticCall(getContext().getTruffleTypes().getTruffleIntrinsics(), "deoptimize").end();
+            builder.end();
+            return builder.getRoot();
+        }
+
+        private CodeTree createSpecializeCall(CodeTreeBuilder parent, SpecializationData specialization) {
+            NodeData node = specialization.getNode();
 
-                String prefix = emitImplicitGuards(getContext(), builder, "", specialization, specialization);
-                emitExplicitGuards(getContext(), builder, prefix, specialization, specialization, false);
-                builder.end().startBlock();
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            emitSpecializationListeners(builder, node);
+
+            builder.startStatement();
+            builder.startCall("replace");
+            if (node.needsRewrites(getContext())) {
+                builder.startCall(factoryClassName(node), "specialize");
+                builder.string("this");
+                builder.typeLiteral(builder.findMethod().getEnclosingElement().asType());
+                addValueParameterNames(builder, specialization, null, false);
+                builder.end(); // call replace, call specialize
+            } else {
+                builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end();
             }
+            builder.end().end();
+            return builder.getRoot();
+        }
 
+        private CodeTree createExecute(CodeTreeBuilder parent, SpecializationData specialization) {
+            NodeData node = specialization.getNode();
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
             if (specialization.getExceptions().length > 0) {
                 builder.startTryBlock();
             }
 
-            if (specialization.isUninitialized()) {
-                emitSpecializationListeners(builder, node);
-
-                builder.startStatement();
-                builder.startCall("replace");
-                if (node.needsRewrites(getContext())) {
-                    builder.startCall(factoryClassName(node), "specialize");
-                    builder.string("this");
-                    builder.typeLiteral(builder.getRoot().getEnclosingClass().asType());
-                    addValueParameterNames(builder, specialization, null, false);
-                    builder.end(); // call replace, call specialize
-                } else {
-                    builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end();
-                }
-                builder.end().end();
-            }
-
             if ((specialization.isUninitialized() || specialization.isGeneric()) && node.needsRewrites(getContext())) {
                 builder.startReturn().startCall(factoryClassName(node), generatedGenericMethodName(null));
                 builder.string("this");
@@ -772,15 +817,29 @@
             if (specialization.getExceptions().length > 0) {
                 for (SpecializationThrowsData exception : specialization.getExceptions()) {
                     builder.end().startCatchBlock(exception.getJavaClass(), "ex");
-                    emitReturnSpecializeAndExecute(builder, exception.getTransitionTo(), null);
+                    builder.tree(createReturnSpecializeAndExecute(parent, exception.getTransitionTo(), null));
                 }
                 builder.end();
             }
-            if (specialization.hasDynamicGuards()) {
-                builder.end().startElseBlock();
-                emitReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), null);
-                builder.end();
+            return builder.getRoot();
+        }
+
+        private CodeTree createExecuteChildren(CodeTreeBuilder parent, SpecializationData specialization) {
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
+            for (NodeFieldData field : specialization.getNode().getFields()) {
+                if (field.getExecutionKind() == ExecutionKind.IGNORE) {
+                    continue;
+                }
+
+                ActualParameter parameterType = specialization.findParameter(field.getName());
+
+                if (parameterType.getActualTypeData(specialization.getNode().getTypeSystem()).isGeneric()) {
+                    buildGenericValueExecute(builder, specialization, field, null);
+                } else {
+                    buildSpecializedValueExecute(builder, specialization, field);
+                }
             }
+            return builder.getRoot();
         }
 
         private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) {
@@ -866,7 +925,7 @@
                         execute = true;
                     }
                 }
-                emitReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), param.getSpecification());
+                builder.tree(createReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), param.getSpecification()));
                 builder.end(); // catch block
             }
 
@@ -914,16 +973,18 @@
             }
         }
 
-        private void emitReturnSpecializeAndExecute(CodeTreeBuilder builder, SpecializationData nextSpecialization, ParameterSpec exceptionSpec) {
-            CodeTreeBuilder specializeCall = CodeTreeBuilder.createBuilder();
+        private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, SpecializationData nextSpecialization, ParameterSpec exceptionSpec) {
+            CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent);
             specializeCall.startCall("specializeAndExecute");
             specializeCall.string(nodeClassName(nextSpecialization) + ".class");
             addValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionSpec != null ? exceptionSpec.getName() : null, true);
             specializeCall.end().end();
 
+            CodeTreeBuilder builder = new CodeTreeBuilder(parent);
             builder.startReturn();
             builder.tree(specializeCall.getRoot());
             builder.end();
+            return builder.getRoot();
         }
 
         private void buildSpecializeStateMethod(CodeTypeElement clazz, SpecializationData specialization) {
@@ -942,10 +1003,7 @@
 
             CodeTreeBuilder builder = method.createBuilder();
 
-            builder.startStatement();
-            builder.startStaticCall(getContext().getTruffleTypes().getTruffleIntrinsics(), "deoptimize").end();
-            builder.end();
-
+            builder.tree(createDeoptimize(builder));
             emitSpecializationListeners(builder, specialization.getNode());
 
             builder.startStatement();