changeset 16232:e34bb128f227

Merge.
author Doug Simon <doug.simon@oracle.com>
date Wed, 25 Jun 2014 17:34:25 +0200
parents a47528fb2ea0 (diff) cc4b4fd5c484 (current diff)
children 68fb8e4d8043
files graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java
diffstat 9 files changed, 180 insertions(+), 100 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Wed Jun 25 16:55:01 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Wed Jun 25 17:34:25 2014 +0200
@@ -85,9 +85,11 @@
     private StructuredGraph parseAndProcess(String snippet) {
         StructuredGraph graph = parse(snippet);
         ParameterNode param = graph.getNodes(ParameterNode.class).first();
-        ConstantNode constant = ConstantNode.forInt(0, graph);
-        for (Node n : param.usages().filter(isNotA(FrameState.class)).snapshot()) {
-            n.replaceFirstInput(param, constant);
+        if (param != null) {
+            ConstantNode constant = ConstantNode.forInt(0, graph);
+            for (Node n : param.usages().filter(isNotA(FrameState.class)).snapshot()) {
+                n.replaceFirstInput(param, constant);
+            }
         }
         Map<Invoke, Double> hints = new HashMap<>();
         for (Invoke invoke : graph.getInvokes()) {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputList.java	Wed Jun 25 16:55:01 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputList.java	Wed Jun 25 17:34:25 2014 +0200
@@ -49,6 +49,12 @@
         this.self = self;
     }
 
+    public NodeInputList(Node self, Collection<? extends NodeInterface> elements) {
+        super(elements);
+        assert self.usages().isEmpty();
+        this.self = self;
+    }
+
     @Override
     protected void update(T oldNode, T newNode) {
         self.updateUsages(oldNode, newNode);
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Wed Jun 25 16:55:01 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Wed Jun 25 17:34:25 2014 +0200
@@ -77,6 +77,24 @@
         }
     }
 
+    protected NodeList(Collection<? extends NodeInterface> elements) {
+        if (elements == null || elements.isEmpty()) {
+            this.size = 0;
+            this.nodes = EMPTY_NODE_ARRAY;
+            this.initialSize = 0;
+        } else {
+            this.size = elements.size();
+            this.initialSize = elements.size();
+            this.nodes = new Node[elements.size()];
+            int i = 0;
+            for (NodeInterface n : elements) {
+                this.nodes[i] = n.asNode();
+                assert this.nodes[i] == null || !this.nodes[i].isDeleted();
+                i++;
+            }
+        }
+    }
+
     protected abstract void update(T oldNode, T newNode);
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMap.java	Wed Jun 25 17:34:25 2014 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, 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.graal.nodes;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.extended.*;
+
+/**
+ * Maps a {@linkplain LocationIdentity location} to the last node that (potentially) wrote to the
+ * location.
+ */
+public interface MemoryMap {
+
+    /**
+     * Gets the last node that that (potentially) wrote to {@code locationIdentity}.
+     */
+    MemoryNode getLastLocationAccess(LocationIdentity locationIdentity);
+
+    /**
+     * Gets the location identities in the domain of this map.
+     */
+    Collection<LocationIdentity> getLocations();
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java	Wed Jun 25 16:55:01 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,27 +1,7 @@
-/*
- * Copyright (c) 2013, 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.graal.nodes;
 
+import static com.oracle.graal.api.meta.LocationIdentity.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
@@ -29,17 +9,68 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Extension})
-public abstract class MemoryMapNode extends FloatingNode {
+public class MemoryMapNode extends FloatingNode implements MemoryMap, LIRLowerable {
+
+    private final List<LocationIdentity> locationIdentities;
+    @Input(InputType.Memory) private final NodeInputList<ValueNode> nodes;
 
-    public MemoryMapNode() {
+    private boolean checkOrder(Map<LocationIdentity, MemoryNode> mmap) {
+        for (int i = 0; i < locationIdentities.size(); i++) {
+            LocationIdentity locationIdentity = locationIdentities.get(i);
+            ValueNode n = nodes.get(i);
+            assertTrue(mmap.get(locationIdentity) == n, "iteration order of keys differs from values in input map");
+        }
+        return true;
+    }
+
+    public MemoryMapNode(Map<LocationIdentity, MemoryNode> mmap) {
         super(StampFactory.forVoid());
+        locationIdentities = new ArrayList<>(mmap.keySet());
+        nodes = new NodeInputList<>(this, mmap.values());
+        assert checkOrder(mmap);
     }
 
-    public abstract MemoryNode getLastLocationAccess(LocationIdentity locationIdentity);
+    public boolean isEmpty() {
+        if (locationIdentities.isEmpty()) {
+            return true;
+        }
+        if (locationIdentities.size() == 1) {
+            if (nodes.get(0) instanceof StartNode) {
+                return true;
+            }
+        }
+        return false;
+    }
 
-    public abstract Set<LocationIdentity> getLocations();
+    public MemoryNode getLastLocationAccess(LocationIdentity locationIdentity) {
+        if (locationIdentity == FINAL_LOCATION) {
+            return null;
+        } else {
+            int index = locationIdentities.indexOf(locationIdentity);
+            if (index == -1) {
+                index = locationIdentities.indexOf(ANY_LOCATION);
+            }
+            assert index != -1;
+            return (MemoryNode) nodes.get(index);
+        }
+    }
 
-    public abstract boolean replaceLastLocationAccess(MemoryNode oldNode, MemoryNode newNode);
+    public Collection<LocationIdentity> getLocations() {
+        return locationIdentities;
+    }
+
+    public Map<LocationIdentity, MemoryNode> toMap() {
+        HashMap<LocationIdentity, MemoryNode> res = new HashMap<>(locationIdentities.size());
+        for (int i = 0; i < nodes.size(); i++) {
+            res.put(locationIdentities.get(i), (MemoryNode) nodes.get(i));
+        }
+        return res;
+    }
+
+    public void generate(NodeLIRBuilderTool generator) {
+        // nothing to do...
+    }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Wed Jun 25 16:55:01 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Wed Jun 25 17:34:25 2014 +0200
@@ -42,7 +42,7 @@
         CREATE_FLOATING_READS
     }
 
-    public static class MemoryMapImpl extends MemoryMapNode {
+    public static class MemoryMapImpl implements MemoryMap {
 
         private final Map<LocationIdentity, MemoryNode> lastMemorySnapshot;
 
@@ -74,33 +74,13 @@
             }
         }
 
-        public boolean isEmpty() {
-            if (lastMemorySnapshot.size() == 0) {
-                return true;
-            }
-            if (lastMemorySnapshot.size() == 1) {
-                if (lastMemorySnapshot.get(ANY_LOCATION) instanceof StartNode) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
         @Override
-        public Set<LocationIdentity> getLocations() {
+        public Collection<LocationIdentity> getLocations() {
             return lastMemorySnapshot.keySet();
         }
 
-        @Override
-        public boolean replaceLastLocationAccess(MemoryNode oldNode, MemoryNode newNode) {
-            boolean replaced = false;
-            for (Map.Entry<LocationIdentity, MemoryNode> entry : lastMemorySnapshot.entrySet()) {
-                if (entry.getValue() == oldNode) {
-                    entry.setValue(newNode);
-                    replaced = true;
-                }
-            }
-            return replaced;
+        public Map<LocationIdentity, MemoryNode> getMap() {
+            return lastMemorySnapshot;
         }
     }
 
@@ -125,11 +105,11 @@
         }
     }
 
-    public static MemoryMapImpl mergeMemoryMaps(MergeNode merge, List<? extends MemoryMapNode> states) {
+    public static MemoryMapImpl mergeMemoryMaps(MergeNode merge, List<? extends MemoryMap> states) {
         MemoryMapImpl newState = new MemoryMapImpl();
 
         Set<LocationIdentity> keys = new HashSet<>();
-        for (MemoryMapNode other : states) {
+        for (MemoryMap other : states) {
             keys.addAll(other.getLocations());
         }
         assert !keys.contains(FINAL_LOCATION);
@@ -138,7 +118,7 @@
             int mergedStatesCount = 0;
             boolean isPhi = false;
             MemoryNode merged = null;
-            for (MemoryMapNode state : states) {
+            for (MemoryMap state : states) {
                 MemoryNode last = state.getLastLocationAccess(key);
                 if (isPhi) {
                     merged.asMemoryPhi().addInput(ValueNodeUtil.asNode(last));
@@ -243,7 +223,7 @@
             assert MemoryCheckpoint.TypeAssertion.correctType(node) : node;
 
             if (execmode == ExecutionMode.ANALYSIS_ONLY && node instanceof ReturnNode) {
-                ((ReturnNode) node).setMemoryMap(node.graph().unique(new MemoryMapImpl(state)));
+                ((ReturnNode) node).setMemoryMap(node.graph().unique(new MemoryMapNode(state.lastMemorySnapshot)));
             }
             return state;
         }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/NoDeadCodeVerifyHandler.java	Wed Jun 25 16:55:01 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/NoDeadCodeVerifyHandler.java	Wed Jun 25 17:34:25 2014 +0200
@@ -42,19 +42,22 @@
 
     // The options below will be removed once all phases clean up their own dead code.
 
+    private static final int OFF = 0;
+    private static final int INFO = 1;
+    private static final int VERBOSE = 2;
+    private static final int FATAL = 3;
+
     static class Options {
         // @formatter:off
-        @Option(help = "Enable NoDeadCodeVerifyHandler")
-        public static final OptionValue<Boolean> NDCV = new OptionValue<>(false);
-        @Option(help = "Issues caught by NoDeadCodeVerifyHandler raise an error")
-        public static final OptionValue<Boolean> NDCVFatal = new OptionValue<>(false);
+        @Option(help = "Run level for NoDeadCodeVerifyHandler (0 = off, 1 = info, 2 = verbose, 3 = fatal)")
+        public static final OptionValue<Integer> NDCV = new OptionValue<>(0);
         // @formatter:on
     }
 
     private static final Map<Class<?>, Boolean> discovered = new ConcurrentHashMap<>();
 
     public void verify(Object object, Object... context) {
-        if (NDCV.getValue()) {
+        if (NDCV.getValue() != OFF) {
             StructuredGraph graph = extract(StructuredGraph.class, object);
             BasePhase<?> phase = extract(BasePhase.class, context);
             if (graph != null) {
@@ -64,15 +67,19 @@
                 assert after.size() <= before.size();
                 if (before.size() != after.size()) {
                     before.removeAll(after);
-                    if (NDCVFatal.getValue() || discovered.put(phase.getClass(), Boolean.TRUE) == null) {
+                    if (discovered.put(phase.getClass(), Boolean.TRUE) == null) {
                         String message = extract(String.class, context);
                         String prefix = message == null ? "" : message + ": ";
                         String phaseClass = phase == null ? null : phase.getClass().getName();
                         GraalInternalError error = new GraalInternalError("%sfound dead nodes in %s (phase class=%s): %s", prefix, graph, phaseClass, before);
-                        if (NDCVFatal.getValue()) {
+                        if (NDCV.getValue() == INFO) {
+                            System.out.println(error.getMessage());
+                        } else if (NDCV.getValue() == VERBOSE) {
+                            error.printStackTrace(System.out);
+                        } else {
+                            assert NDCV.getValue() == FATAL;
                             throw error;
                         }
-                        error.printStackTrace(System.out);
                     }
                 }
             }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Wed Jun 25 16:55:01 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Wed Jun 25 17:34:25 2014 +0200
@@ -208,7 +208,7 @@
         }
 
         @Override
-        public void replace(ValueNode oldNode, ValueNode newNode, MemoryMapNode mmap) {
+        public void replace(ValueNode oldNode, ValueNode newNode, MemoryMap mmap) {
             assert newNode instanceof PhiNode;
             assert oldNode == instanceOf;
             newNode.inferStamp();
@@ -239,7 +239,7 @@
         }
 
         @Override
-        public void replace(ValueNode oldNode, ValueNode newNode, MemoryMapNode mmap) {
+        public void replace(ValueNode oldNode, ValueNode newNode, MemoryMap mmap) {
             assert newNode instanceof PhiNode;
             assert oldNode == instanceOf;
             newNode.inferStamp();
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Wed Jun 25 16:55:01 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Wed Jun 25 17:34:25 2014 +0200
@@ -35,6 +35,7 @@
 import java.util.*;
 import java.util.concurrent.*;
 import java.util.concurrent.atomic.*;
+import java.util.stream.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -677,38 +678,33 @@
 
         Debug.dump(snippet, "SnippetTemplate after fixing memory anchoring");
 
-        List<ReturnNode> returnNodes = new ArrayList<>(4);
-        List<MemoryMapNode> memMaps = new ArrayList<>(4);
         StartNode entryPointNode = snippet.start();
-        boolean anchorUsed = false;
-        for (ReturnNode retNode : snippet.getNodes(ReturnNode.class)) {
-            MemoryMapNode memMap = retNode.getMemoryMap();
-            anchorUsed |= memMap.replaceLastLocationAccess(snippetCopy.start(), memoryAnchor);
-            memMaps.add(memMap);
-            retNode.setMemoryMap(null);
-            returnNodes.add(retNode);
-            if (memMap.usages().isEmpty()) {
-                memMap.safeDelete();
-            }
-        }
-        if (memoryAnchor.usages().isEmpty() && !anchorUsed) {
+        if (memoryAnchor.usages().isEmpty()) {
             memoryAnchor.safeDelete();
         } else {
             snippetCopy.addAfterFixed(snippetCopy.start(), memoryAnchor);
         }
-        assert snippet.getNodes().filter(MemoryMapNode.class).isEmpty();
+        List<ReturnNode> returnNodes = snippet.getNodes(ReturnNode.class).snapshot();
         if (returnNodes.isEmpty()) {
             this.returnNode = null;
             this.memoryMap = null;
         } else if (returnNodes.size() == 1) {
             this.returnNode = returnNodes.get(0);
-            this.memoryMap = memMaps.get(0);
+            this.memoryMap = returnNode.getMemoryMap();
         } else {
             MergeNode merge = snippet.add(new MergeNode());
+            List<MemoryMapNode> memMaps = returnNodes.stream().map(n -> n.getMemoryMap()).collect(Collectors.toList());
             ValueNode returnValue = InliningUtil.mergeReturns(merge, returnNodes, null);
             this.returnNode = snippet.add(new ReturnNode(returnValue));
-            this.memoryMap = FloatingReadPhase.mergeMemoryMaps(merge, memMaps);
+            MemoryMapImpl mmap = FloatingReadPhase.mergeMemoryMaps(merge, memMaps);
+            this.memoryMap = snippet.unique(new MemoryMapNode(mmap.getMap()));
             merge.setNext(this.returnNode);
+
+            for (MemoryMapNode mm : memMaps) {
+                if (mm.isAlive()) {
+                    mm.safeDelete();
+                }
+            }
         }
 
         this.sideEffectNodes = curSideEffectNodes;
@@ -798,7 +794,7 @@
     private final ArrayList<Node> nodes;
 
     /**
-     * map of killing locations to memory checkpoints (nodes).
+     * Map of killing locations to memory checkpoints (nodes).
      */
     private final MemoryMapNode memoryMap;
 
@@ -897,7 +893,7 @@
         /**
          * Replaces all usages of {@code oldNode} with direct or indirect usages of {@code newNode}.
          */
-        void replace(ValueNode oldNode, ValueNode newNode, MemoryMapNode mmap);
+        void replace(ValueNode oldNode, ValueNode newNode, MemoryMap mmap);
     }
 
     /**
@@ -919,7 +915,7 @@
         }
 
         @Override
-        public void replace(ValueNode oldNode, ValueNode newNode, MemoryMapNode mmap) {
+        public void replace(ValueNode oldNode, ValueNode newNode, MemoryMap mmap) {
             if (mmap != null) {
                 for (Node usage : oldNode.usages().snapshot()) {
                     LocationIdentity identity = getLocationIdentity(usage);
@@ -961,12 +957,12 @@
             // no floating reads yet, ignore locations created while lowering
             return true;
         }
-        if (memoryMap == null || ((MemoryMapImpl) memoryMap).isEmpty()) {
-            // there're no kills in the snippet graph
+        if (memoryMap == null || memoryMap.isEmpty()) {
+            // there are no kills in the snippet graph
             return true;
         }
 
-        Set<LocationIdentity> kills = new HashSet<>(((MemoryMapImpl) memoryMap).getLocations());
+        Set<LocationIdentity> kills = new HashSet<>(memoryMap.getLocations());
 
         if (replacee instanceof MemoryCheckpoint.Single) {
             // check if some node in snippet graph also kills the same location
@@ -1010,10 +1006,10 @@
         return true;
     }
 
-    private class DuplicateMapper extends MemoryMapNode {
+    private class DuplicateMapper implements MemoryMap {
 
         private final Map<Node, Node> duplicates;
-        @Input private StartNode replaceeStart;
+        private StartNode replaceeStart;
 
         public DuplicateMapper(Map<Node, Node> duplicates, StartNode replaceeStart) {
             this.duplicates = duplicates;
@@ -1033,14 +1029,9 @@
         }
 
         @Override
-        public Set<LocationIdentity> getLocations() {
+        public Collection<LocationIdentity> getLocations() {
             return memoryMap.getLocations();
         }
-
-        @Override
-        public boolean replaceLastLocationAccess(MemoryNode oldNode, MemoryNode newNode) {
-            throw GraalInternalError.shouldNotReachHere();
-        }
     }
 
     /**
@@ -1134,7 +1125,7 @@
             if (returnNode != null && !(replacee instanceof ControlSinkNode)) {
                 ReturnNode returnDuplicate = (ReturnNode) duplicates.get(returnNode);
                 returnValue = returnDuplicate.result();
-                MemoryMapNode mmap = new DuplicateMapper(duplicates, replaceeGraph.start());
+                MemoryMap mmap = new DuplicateMapper(duplicates, replaceeGraph.start());
                 if (returnValue == null && replacee.usages().isNotEmpty() && replacee instanceof MemoryCheckpoint) {
                     replacer.replace(replacee, null, mmap);
                 } else {