changeset 10851:cea4beb67bfd

Merge
author Christos Kotselidis <christos.kotselidis@oracle.com>
date Mon, 22 Jul 2013 22:04:17 +0200
parents e7679ec4f27f (current diff) 4da2141fc40f (diff)
children df023d960636 5404cde63c43
files
diffstat 11 files changed, 117 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Mon Jul 22 22:03:53 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Mon Jul 22 22:04:17 2013 +0200
@@ -39,6 +39,8 @@
  */
 public class ConditionalEliminationTest extends GraalCompilerTest {
 
+    public static Object field;
+
     static class Entry {
 
         final String name;
@@ -108,7 +110,7 @@
                 }
             } else {
                 if (b == null) {
-                    return 3;
+                    return -3;
                 } else {
                     return 4;
                 }
@@ -196,4 +198,34 @@
         assertEquals(InvokeKind.Special, ((MethodCallTargetNode) invoke.callTarget()).invokeKind());
     }
 
+    public static void testTypeMergingSnippet(Object o, boolean b) {
+        if (b) {
+            if (!(o instanceof Double)) {
+                return;
+            }
+        } else {
+            if (!(o instanceof Integer)) {
+                return;
+            }
+        }
+
+        /*
+         * For this test the conditional elimination has to correctly merge the type information it
+         * has about o, so that it can remove the check on Number.
+         */
+        if (!(o instanceof Number)) {
+            field = o;
+        }
+    }
+
+    @Test
+    public void testTypeMerging() {
+        StructuredGraph graph = parse("testTypeMergingSnippet");
+        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new ConditionalEliminationPhase(runtime()).apply(graph);
+        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+
+        assertEquals(0, graph.getNodes().filter(StoreFieldNode.class).count());
+    }
+
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Mon Jul 22 22:03:53 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Mon Jul 22 22:04:17 2013 +0200
@@ -195,7 +195,7 @@
                 return null;
             }
 
-            PhiNode phi = graph.unique(new PhiNode(currentValue.kind(), block));
+            PhiNode phi = graph.add(new PhiNode(currentValue.kind(), block));
             for (int i = 0; i < block.phiPredecessorCount(); i++) {
                 phi.addInput(currentValue);
             }
@@ -290,7 +290,7 @@
         }
         assert !block.isPhiAtMerge(value) : "phi function for this block already created";
 
-        PhiNode phi = graph.unique(new PhiNode(value.kind(), block));
+        PhiNode phi = graph.add(new PhiNode(value.kind(), block));
         phi.addInput(value);
         return phi;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Mon Jul 22 22:03:53 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Mon Jul 22 22:04:17 2013 +0200
@@ -22,8 +22,11 @@
  */
 package com.oracle.graal.nodes.java;
 
+import java.lang.reflect.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -57,11 +60,15 @@
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         MetaAccessProvider runtime = tool.runtime();
-        if (tool.canonicalizeReads()) {
+        if (tool.canonicalizeReads() && runtime != null) {
             ConstantNode constant = asConstant(runtime);
             if (constant != null) {
                 return constant;
             }
+            PhiNode phi = asPhi(runtime);
+            if (phi != null) {
+                return phi;
+            }
         }
         return this;
     }
@@ -70,16 +77,34 @@
      * Gets a constant value for this load if possible.
      */
     public ConstantNode asConstant(MetaAccessProvider runtime) {
-        if (runtime != null) {
-            Constant constant = null;
-            if (isStatic()) {
-                constant = field().readConstantValue(null);
-            } else if (object().isConstant() && !object().isNullConstant()) {
-                constant = field().readConstantValue(object().asConstant());
+        Constant constant = null;
+        if (isStatic()) {
+            constant = field().readConstantValue(null);
+        } else if (object().isConstant() && !object().isNullConstant()) {
+            constant = field().readConstantValue(object().asConstant());
+        }
+        if (constant != null) {
+            return ConstantNode.forConstant(constant, runtime, graph());
+        }
+        return null;
+    }
+
+    private PhiNode asPhi(MetaAccessProvider runtime) {
+        if (!isStatic() && Modifier.isFinal(field.getModifiers()) && object() instanceof PhiNode && ((PhiNode) object()).values().filter(NodePredicates.isNotA(ConstantNode.class)).isEmpty()) {
+            PhiNode phi = (PhiNode) object();
+            Constant[] constants = new Constant[phi.valueCount()];
+            for (int i = 0; i < phi.valueCount(); i++) {
+                Constant constantValue = field().readConstantValue(phi.valueAt(i).asConstant());
+                if (constantValue == null) {
+                    return null;
+                }
+                constants[i] = constantValue;
             }
-            if (constant != null) {
-                return ConstantNode.forConstant(constant, runtime, graph());
+            PhiNode newPhi = graph().add(new PhiNode(stamp(), phi.merge()));
+            for (int i = 0; i < phi.valueCount(); i++) {
+                newPhi.addInput(ConstantNode.forConstant(constants[i], runtime, graph()));
             }
+            return newPhi;
         }
         return null;
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Jul 22 22:03:53 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Jul 22 22:04:17 2013 +0200
@@ -114,7 +114,7 @@
                         break;
                     }
                 }
-                if (type == null && type != node.objectStamp().type()) {
+                if (type != null && type != node.objectStamp().type()) {
                     newKnownTypes.put(node, type);
                 }
             }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Mon Jul 22 22:03:53 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Mon Jul 22 22:04:17 2013 +0200
@@ -609,7 +609,7 @@
 
             PhiNode returnValuePhi = null;
             if (invoke.asNode().kind() != Kind.Void) {
-                returnValuePhi = graph.unique(new PhiNode(invoke.asNode().kind(), returnMerge));
+                returnValuePhi = graph.add(new PhiNode(invoke.asNode().kind(), returnMerge));
             }
 
             MergeNode exceptionMerge = null;
@@ -622,7 +622,7 @@
 
                 FixedNode exceptionSux = exceptionEdge.next();
                 graph.addBeforeFixed(exceptionSux, exceptionMerge);
-                exceptionObjectPhi = graph.unique(new PhiNode(Kind.Object, exceptionMerge));
+                exceptionObjectPhi = graph.add(new PhiNode(Kind.Object, exceptionMerge));
                 exceptionMerge.setStateAfter(exceptionEdge.stateAfter().duplicateModified(invoke.stateAfter().bci, true, Kind.Object, exceptionObjectPhi));
             }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Mon Jul 22 22:03:53 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Mon Jul 22 22:04:17 2013 +0200
@@ -50,7 +50,7 @@
         this.originalInvokeCounter = compilationThreshold;
         this.rootNode.setCallTarget(this);
 
-        if (TruffleProfiling.getValue()) {
+        if (TruffleCallTargetProfiling.getValue()) {
             registerCallTarget(this);
         }
     }
@@ -75,7 +75,7 @@
 
     @Override
     public Object call(PackedFrame caller, Arguments args) {
-        if (TruffleProfiling.getValue()) {
+        if (TruffleCallTargetProfiling.getValue()) {
             callCount++;
         }
         if (CompilerDirectives.injectBranchProbability(CompilerDirectives.FASTPATH_PROBABILITY, compiledMethod != null)) {
@@ -138,7 +138,7 @@
                                     (timeCompilationFinished - timeCompilationStarted) / 1e6, (timePartialEvaluationFinished - timeCompilationStarted) / 1e6,
                                     (timeCompilationFinished - timePartialEvaluationFinished) / 1e6, nodeCountPartialEval, nodeCountLowered, codeSize);
                 }
-                if (TruffleProfiling.getValue()) {
+                if (TruffleCallTargetProfiling.getValue()) {
                     resetProfiling();
                 }
             }
@@ -237,16 +237,16 @@
             return inlined;
         }
 
-        private void printCallSiteInfo(InliningPolicy policy, List<InlinableCallSiteInfo> inlinableCallSites, String msg) {
+        private static void printCallSiteInfo(InliningPolicy policy, List<InlinableCallSiteInfo> inlinableCallSites, String msg) {
             for (InlinableCallSiteInfo candidate : inlinableCallSites) {
                 printCallSiteInfo(policy, candidate, msg);
             }
         }
 
-        private void printCallSiteInfo(InliningPolicy policy, InlinableCallSiteInfo callSite, String msg) {
+        private static void printCallSiteInfo(InliningPolicy policy, InlinableCallSiteInfo callSite, String msg) {
             String calls = String.format("%4s/%4s", callSite.getCallCount(), policy.callerInvocationCount);
             String nodes = String.format("%3s/%3s", callSite.getInlineNodeCount(), policy.callerNodeCount);
-            OUT.printf("[truffle] %-9s %-50s |Nodes %6s |Calls %6s %7.3f |into %s\n", msg, callSite.getCallSite(), nodes, calls, policy.metric(callSite), target.getRootNode());
+            OUT.printf("[truffle] %-9s %-50s |Nodes %6s |Calls %6s %7.3f |%s\n", msg, callSite.getCallSite(), nodes, calls, policy.metric(callSite), callSite.getCallSite().getCallTarget());
         }
 
         private static final class InliningPolicy {
@@ -405,7 +405,7 @@
 
     private static Map<OptimizedCallTarget, Integer> callTargets;
     static {
-        if (TruffleProfiling.getValue()) {
+        if (TruffleCallTargetProfiling.getValue()) {
             callTargets = new WeakHashMap<>();
 
             Runtime.getRuntime().addShutdownHook(new Thread() {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Mon Jul 22 22:03:53 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java	Mon Jul 22 22:04:17 2013 +0200
@@ -88,6 +88,6 @@
     @Option(help = "")
     public static final OptionValue<Boolean> TraceTruffleInliningDetails = new OptionValue<>(false);
     @Option(help = "")
-    public static final OptionValue<Boolean> TruffleProfiling = new StableOptionValue<>(false);
+    public static final OptionValue<Boolean> TruffleCallTargetProfiling = new StableOptionValue<>(false);
     // @formatter:on
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java	Mon Jul 22 22:03:53 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java	Mon Jul 22 22:04:17 2013 +0200
@@ -70,7 +70,7 @@
                 ValueNode cachedValue = state.getReadCache(object, store.field());
 
                 ValueNode value = state.getScalarAlias(store.value());
-                if (value == cachedValue) {
+                if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
                     effects.deleteFixedNode(store);
                     deleted = true;
                 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Mon Jul 22 22:03:53 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Mon Jul 22 22:04:17 2013 +0200
@@ -36,8 +36,8 @@
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.CacheEntry;
+import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.LoadCacheEntry;
 import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.ReadCacheEntry;
-import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.LoadCacheEntry;
 
 public class ReadEliminationClosure extends EffectsClosure<ReadEliminationBlockState> {
 
@@ -106,6 +106,8 @@
                 }
                 state.killReadCache(write.location().getLocationIdentity());
                 state.addCacheEntry(identifier, value);
+            } else {
+                state.killReadCache(write.location().getLocationIdentity());
             }
         } else if (node instanceof MemoryCheckpoint.Single) {
             processIdentity(state, ((MemoryCheckpoint.Single) node).getLocationIdentity());
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Mon Jul 22 22:03:53 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Mon Jul 22 22:04:17 2013 +0200
@@ -33,11 +33,6 @@
  */
 public abstract class Node implements Cloneable {
 
-    /**
-     * Utility constant representing an empty node array.
-     */
-    public static final Node[] EMPTY_ARRAY = new Node[0];
-
     private Node parent;
 
     private SourceSection sourceSection;
@@ -193,6 +188,22 @@
     }
 
     /**
+     * Checks if this node is properly adopted by a parent and can be replaced.
+     * 
+     * @return {@code true} if it is safe to replace this node.
+     */
+    public final boolean isReplaceable() {
+        if (getParent() != null) {
+            for (Node sibling : getParent().getChildren()) {
+                if (sibling == this) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
      * Intended to be implemented by subclasses of {@link Node} to receive a notification when the
      * node is rewritten. This method is invoked before the actual replace has happened.
      * 
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Mon Jul 22 22:03:53 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Mon Jul 22 22:04:17 2013 +0200
@@ -344,7 +344,11 @@
         for (long fieldOffset : nodeClass.childrenOffsets) {
             Node[] children = (Node[]) unsafe.getObject(node, fieldOffset);
             if (children != null) {
-                nodes.addAll(Arrays.asList(children));
+                for (Node child : children) {
+                    if (child != null) {
+                        nodes.add(child);
+                    }
+                }
             }
         }
 
@@ -545,23 +549,25 @@
     }
 
     public static int countNodes(Node root, Class<?> clazz) {
-        NodeCountVisitor nodeCount = new NodeCountVisitor(clazz);
+        NodeCountVisitor nodeCount = new NodeCountVisitor(root, clazz);
         root.accept(nodeCount);
         return nodeCount.nodeCount;
     }
 
     private static final class NodeCountVisitor implements NodeVisitor {
 
+        int nodeCount;
+        private final Node root;
         private final Class<?> clazz;
-        int nodeCount;
 
-        private NodeCountVisitor(Class<?> clazz) {
+        private NodeCountVisitor(Node root, Class<?> clazz) {
+            this.root = root;
             this.clazz = clazz;
         }
 
         @Override
         public boolean visit(Node node) {
-            if (node instanceof RootNode && nodeCount > 0) {
+            if (node instanceof RootNode && node != root) {
                 return false;
             }
             if (clazz == null || clazz.isInstance(node)) {
@@ -589,7 +595,7 @@
             p.print("  ");
         }
         if (parent == null) {
-            p.println(node.getClass().getSimpleName());
+            p.println(nodeName(node));
         } else {
             String fieldName = "unknownField";
             NodeField[] fields = NodeClass.get(parent.getClass()).fields;
@@ -611,7 +617,7 @@
             }
             p.print(fieldName);
             p.print(" = ");
-            p.println(node.getClass().getSimpleName());
+            p.println(nodeName(node));
         }
 
         for (Node child : node.getChildren()) {
@@ -649,7 +655,7 @@
             return;
         }
 
-        p.print(node.getClass().getSimpleName());
+        p.print(nodeName(node));
 
         ArrayList<NodeField> childFields = new ArrayList<>();
         String sep = "";
@@ -704,4 +710,7 @@
         }
     }
 
+    private static String nodeName(Node node) {
+        return node.getClass().getSimpleName();
+    }
 }