changeset 18971:e349dfa54db1

Simplifications in PEA.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Tue, 27 Jan 2015 16:01:48 +0100
parents edf3a7fdd067
children b648ac155f1b
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java
diffstat 4 files changed, 167 insertions(+), 112 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Tue Jan 27 14:54:55 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Tue Jan 27 16:01:48 2015 +0100
@@ -458,8 +458,10 @@
 
     @Override
     public void applyToNonVirtual(NodeClosure<? super ValueNode> closure) {
-        for (ValueNode value : values.nonNull()) {
-            closure.apply(this, value);
+        for (ValueNode value : values) {
+            if (value != null) {
+                closure.apply(this, value);
+            }
         }
 
         if (monitorIds != null) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java	Tue Jan 27 14:54:55 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java	Tue Jan 27 16:01:48 2015 +0100
@@ -32,9 +32,9 @@
 @NodeInfo(allowedUsageTypes = {InputType.State})
 public abstract class VirtualState extends Node {
 
-    public interface NodeClosure<T extends Node> {
+    public abstract static class NodeClosure<T extends Node> {
 
-        void apply(Node usage, T node);
+        public abstract void apply(Node usage, T node);
     }
 
     public interface VirtualClosure {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Tue Jan 27 14:54:55 2015 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Tue Jan 27 16:01:48 2015 +0100
@@ -163,6 +163,7 @@
 
                         if (pendingStateAfter != null && node instanceof FixedNode) {
                             pendingStateAfter.applyToNonVirtual(new NodeClosure<Node>() {
+                                @Override
                                 public void apply(Node usage, Node nonVirtualNode) {
                                     assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode : nonVirtualNode + " not available at virtualstate " + usage +
                                                     " before " + node + " in block " + block + " \n" + list;
@@ -196,8 +197,11 @@
                             for (Node input : node.inputs()) {
                                 if (input != stateAfter) {
                                     if (input instanceof FrameState) {
-                                        ((FrameState) input).applyToNonVirtual((usage, nonVirtual) -> {
-                                            assert currentState.isMarked(nonVirtual) : nonVirtual + " not available at " + node + " in block " + block + "\n" + list;
+                                        ((FrameState) input).applyToNonVirtual(new VirtualState.NodeClosure<Node>() {
+                                            @Override
+                                            public void apply(Node usage, Node nonVirtual) {
+                                                assert currentState.isMarked(nonVirtual) : nonVirtual + " not available at " + node + " in block " + block + "\n" + list;
+                                            }
                                         });
                                     } else {
                                         assert currentState.isMarked(input) || input instanceof VirtualObjectNode : input + " not available at " + node + " in block " + block + "\n" + list;
@@ -220,6 +224,7 @@
                     }
                     if (pendingStateAfter != null) {
                         pendingStateAfter.applyToNonVirtual(new NodeClosure<Node>() {
+                            @Override
                             public void apply(Node usage, Node nonVirtualNode) {
                                 assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode : nonVirtualNode + " not available at virtualstate " + usage +
                                                 " at end of block " + block + " \n" + list;
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Tue Jan 27 14:54:55 2015 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Tue Jan 27 16:01:48 2015 +0100
@@ -56,6 +56,38 @@
     private final NodeBitMap usages;
     private final VirtualizerToolImpl tool;
 
+    private final class CollectVirtualObjectsClosure extends NodeClosure<ValueNode> {
+        private final Set<ObjectState> virtual;
+        private final GraphEffectList effects;
+        private final BlockT state;
+
+        private CollectVirtualObjectsClosure(Set<ObjectState> virtual, GraphEffectList effects, BlockT state) {
+            this.virtual = virtual;
+            this.effects = effects;
+            this.state = state;
+        }
+
+        @Override
+        public void apply(Node usage, ValueNode value) {
+            ObjectState valueObj = getObjectState(state, value);
+            if (valueObj != null) {
+                virtual.add(valueObj);
+                effects.replaceFirstInput(usage, value, valueObj.virtual);
+            } else if (value instanceof VirtualObjectNode) {
+                ObjectState virtualObj = null;
+                for (ObjectState obj : state.getStates()) {
+                    if (value == obj.virtual) {
+                        virtualObj = obj;
+                        break;
+                    }
+                }
+                if (virtualObj != null) {
+                    virtual.add(virtualObj);
+                }
+            }
+        }
+    }
+
     /**
      * Final subclass of PartialEscapeClosure, for performance and to make everything behave nicely
      * with generics.
@@ -109,10 +141,12 @@
         }
         if (isMarked) {
             for (Node input : node.inputs()) {
-                ObjectState obj = getObjectState(state, input);
-                if (obj != null) {
-                    VirtualUtil.trace("replacing input %s at %s: %s", input, node, obj);
-                    replaceWithMaterialized(input, node, insertBefore, state, obj, effects, METRIC_MATERIALIZATIONS_UNHANDLED);
+                if (input instanceof ValueNode) {
+                    ObjectState obj = getObjectState(state, (ValueNode) input);
+                    if (obj != null) {
+                        VirtualUtil.trace("replacing input %s at %s: %s", input, node, obj);
+                        replaceWithMaterialized(input, node, insertBefore, state, obj, effects, METRIC_MATERIALIZATIONS_UNHANDLED);
+                    }
                 }
             }
             if (node instanceof NodeWithState) {
@@ -124,76 +158,76 @@
 
     private void processNodeWithState(NodeWithState nodeWithState, final BlockT state, final GraphEffectList effects) {
         for (FrameState fs : nodeWithState.states()) {
-            FrameState frameState = fs;
-            if (frameState.getUsageCount() > 1) {
-                // Can happen for example from inlined snippets with multiple state split nodes.
-                FrameState copy = (FrameState) frameState.copyWithInputs();
-                nodeWithState.asNode().replaceFirstInput(frameState, copy);
-                frameState = copy;
-            }
-            final Set<ObjectState> virtual = new ArraySet<>();
-            frameState.applyToNonVirtual(new NodeClosure<ValueNode>() {
+            FrameState frameState = getUniqueFramestate(nodeWithState, fs);
+            Set<ObjectState> virtual = new ArraySet<>();
+            frameState.applyToNonVirtual(new CollectVirtualObjectsClosure(virtual, effects, state));
+            collectLockedVirtualObjects(state, virtual);
+            collectReferencedVirtualObjects(state, virtual);
+            addVirtualMappings(state, effects, frameState, virtual);
+        }
+    }
+
+    private static FrameState getUniqueFramestate(NodeWithState nodeWithState, FrameState frameState) {
+        if (frameState.getUsageCount() > 1) {
+            // Can happen for example from inlined snippets with multiple state split nodes.
+            FrameState copy = (FrameState) frameState.copyWithInputs();
+            nodeWithState.asNode().replaceFirstInput(frameState, copy);
+            return copy;
+        }
+        return frameState;
+    }
 
-                @Override
-                public void apply(Node usage, ValueNode value) {
-                    ObjectState valueObj = getObjectState(state, value);
-                    if (valueObj != null) {
-                        virtual.add(valueObj);
-                        effects.replaceFirstInput(usage, value, valueObj.virtual);
-                    } else if (value instanceof VirtualObjectNode) {
-                        ObjectState virtualObj = null;
-                        for (ObjectState obj : state.getStates()) {
-                            if (value == obj.virtual) {
-                                virtualObj = obj;
-                                break;
-                            }
-                        }
-                        if (virtualObj != null) {
-                            virtual.add(virtualObj);
-                        }
-                    }
-                }
-            });
-            for (ObjectState obj : state.getStates()) {
-                if (obj.isVirtual() && obj.hasLocks()) {
-                    virtual.add(obj);
-                }
+    private void addVirtualMappings(final BlockT state, final GraphEffectList effects, FrameState frameState, Set<ObjectState> virtual) {
+        for (ObjectState obj : virtual) {
+            EscapeObjectState v;
+            if (obj.isVirtual()) {
+                v = createVirtualObjectState(state, obj);
+            } else {
+                v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue());
             }
+            effects.addVirtualMapping(frameState, v);
+        }
+    }
 
-            ArrayDeque<ObjectState> queue = new ArrayDeque<>(virtual);
-            while (!queue.isEmpty()) {
-                ObjectState obj = queue.removeLast();
-                if (obj.isVirtual()) {
-                    for (ValueNode field : obj.getEntries()) {
-                        if (field instanceof VirtualObjectNode) {
-                            ObjectState fieldObj = state.getObjectState((VirtualObjectNode) field);
-                            if (fieldObj.isVirtual() && !virtual.contains(fieldObj)) {
-                                virtual.add(fieldObj);
-                                queue.addLast(fieldObj);
-                            }
+    private void collectReferencedVirtualObjects(final BlockT state, final Set<ObjectState> virtual) {
+        ArrayDeque<ObjectState> queue = new ArrayDeque<>(virtual);
+        while (!queue.isEmpty()) {
+            ObjectState obj = queue.removeLast();
+            if (obj.isVirtual()) {
+                for (ValueNode entry : obj.getEntries()) {
+                    if (entry instanceof VirtualObjectNode) {
+                        ObjectState fieldObj = state.getObjectState((VirtualObjectNode) entry);
+                        if (fieldObj.isVirtual() && !virtual.contains(fieldObj)) {
+                            virtual.add(fieldObj);
+                            queue.addLast(fieldObj);
                         }
                     }
                 }
             }
-            for (ObjectState obj : virtual) {
-                EscapeObjectState v;
-                if (obj.isVirtual()) {
-                    ValueNode[] fieldState = obj.getEntries().clone();
-                    for (int i = 0; i < fieldState.length; i++) {
-                        ObjectState valueObj = getObjectState(state, fieldState[i]);
-                        if (valueObj != null) {
-                            if (valueObj.isVirtual()) {
-                                fieldState[i] = valueObj.virtual;
-                            } else {
-                                fieldState[i] = valueObj.getMaterializedValue();
-                            }
-                        }
-                    }
-                    v = new VirtualObjectState(obj.virtual, fieldState);
+        }
+    }
+
+    private EscapeObjectState createVirtualObjectState(final BlockT state, ObjectState obj) {
+        EscapeObjectState v;
+        ValueNode[] fieldState = obj.getEntries().clone();
+        for (int i = 0; i < fieldState.length; i++) {
+            ObjectState valueObj = getObjectState(state, fieldState[i]);
+            if (valueObj != null) {
+                if (valueObj.isVirtual()) {
+                    fieldState[i] = valueObj.virtual;
                 } else {
-                    v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue());
+                    fieldState[i] = valueObj.getMaterializedValue();
                 }
-                effects.addVirtualMapping(frameState, v);
+            }
+        }
+        v = new VirtualObjectState(obj.virtual, fieldState);
+        return v;
+    }
+
+    private void collectLockedVirtualObjects(final BlockT state, final Set<ObjectState> virtual) {
+        for (ObjectState obj : state.getStates()) {
+            if (obj.isVirtual() && obj.hasLocks()) {
+                virtual.add(obj);
             }
         }
     }
@@ -222,44 +256,51 @@
 
     @Override
     protected void processLoopExit(LoopExitNode exitNode, BlockT initialState, BlockT exitState, GraphEffectList effects) {
-        Map<VirtualObjectNode, ProxyNode> proxies = Node.newMap();
-
-        for (ProxyNode proxy : exitNode.proxies()) {
-            ObjectState obj = getObjectState(exitState, proxy.value());
-            if (obj != null) {
-                proxies.put(obj.virtual, proxy);
+        if (exitNode.graph().hasValueProxies()) {
+            Map<VirtualObjectNode, ProxyNode> proxies = Node.newMap();
+            for (ProxyNode proxy : exitNode.proxies()) {
+                ObjectState obj = getObjectState(exitState, proxy.value());
+                if (obj != null) {
+                    proxies.put(obj.virtual, proxy);
+                }
             }
-        }
-        if (exitNode.graph().hasValueProxies()) {
             for (ObjectState obj : exitState.getStates()) {
                 ObjectState initialObj = initialState.getObjectStateOptional(obj.virtual);
                 if (obj.isVirtual()) {
-                    for (int i = 0; i < obj.getEntries().length; i++) {
-                        ValueNode value = obj.getEntry(i);
-                        if (!(value instanceof VirtualObjectNode || value.isConstant())) {
-                            if (exitNode.loopBegin().isPhiAtMerge(value) || initialObj == null || !initialObj.isVirtual() || initialObj.getEntry(i) != value) {
-                                ProxyNode proxy = new ValueProxyNode(value, exitNode);
-                                obj.setEntry(i, proxy);
-                                effects.addFloatingNode(proxy, "virtualProxy");
-                            }
-                        }
-                    }
+                    processVirtualAtLoopExit(exitNode, effects, obj, initialObj);
                 } else {
-                    if (initialObj == null || initialObj.isVirtual()) {
-                        ProxyNode proxy = proxies.get(obj.virtual);
-                        if (proxy == null) {
-                            proxy = new ValueProxyNode(obj.getMaterializedValue(), exitNode);
-                            effects.addFloatingNode(proxy, "proxy");
-                        } else {
-                            effects.replaceFirstInput(proxy, proxy.value(), obj.getMaterializedValue());
-                            // nothing to do - will be handled in processNode
-                        }
-                        obj.updateMaterializedValue(proxy);
-                    } else {
-                        if (initialObj.getMaterializedValue() == obj.getMaterializedValue()) {
-                            Debug.log("materialized value changes within loop: %s vs. %s at %s", initialObj.getMaterializedValue(), obj.getMaterializedValue(), exitNode);
-                        }
-                    }
+                    processMaterializedAtLoopExit(exitNode, effects, proxies, obj, initialObj);
+                }
+            }
+        }
+    }
+
+    private static void processMaterializedAtLoopExit(LoopExitNode exitNode, GraphEffectList effects, Map<VirtualObjectNode, ProxyNode> proxies, ObjectState obj, ObjectState initialObj) {
+        if (initialObj == null || initialObj.isVirtual()) {
+            ProxyNode proxy = proxies.get(obj.virtual);
+            if (proxy == null) {
+                proxy = new ValueProxyNode(obj.getMaterializedValue(), exitNode);
+                effects.addFloatingNode(proxy, "proxy");
+            } else {
+                effects.replaceFirstInput(proxy, proxy.value(), obj.getMaterializedValue());
+                // nothing to do - will be handled in processNode
+            }
+            obj.updateMaterializedValue(proxy);
+        } else {
+            if (initialObj.getMaterializedValue() == obj.getMaterializedValue()) {
+                Debug.log("materialized value changes within loop: %s vs. %s at %s", initialObj.getMaterializedValue(), obj.getMaterializedValue(), exitNode);
+            }
+        }
+    }
+
+    private static void processVirtualAtLoopExit(LoopExitNode exitNode, GraphEffectList effects, ObjectState obj, ObjectState initialObj) {
+        for (int i = 0; i < obj.getEntries().length; i++) {
+            ValueNode value = obj.getEntry(i);
+            if (!(value instanceof VirtualObjectNode || value.isConstant())) {
+                if (exitNode.loopBegin().isPhiAtMerge(value) || initialObj == null || !initialObj.isVirtual() || initialObj.getEntry(i) != value) {
+                    ProxyNode proxy = new ValueProxyNode(value, exitNode);
+                    obj.setEntry(i, proxy);
+                    effects.addFloatingNode(proxy, "virtualProxy");
                 }
             }
         }
@@ -322,10 +363,7 @@
             super.merge(states);
 
             // calculate the set of virtual objects that exist in all predecessors
-            Set<VirtualObjectNode> virtualObjTemp = Node.newSet(states.get(0).getVirtualObjects());
-            for (int i = 1; i < states.size(); i++) {
-                virtualObjTemp.retainAll(states.get(i).getVirtualObjects());
-            }
+            Set<VirtualObjectNode> virtualObjTemp = intersectVirtualObjects(states);
 
             ObjectState[] objStates = new ObjectState[states.size()];
             boolean materialized;
@@ -361,8 +399,10 @@
                             mergeEffects.addFloatingNode(materializedValuePhi, "materializedPhi");
                             for (int i = 0; i < objStates.length; i++) {
                                 ObjectState obj = objStates[i];
-                                Block predecessor = mergeBlock.getPredecessors().get(i);
-                                materialized |= ensureMaterialized(states.get(i), obj, predecessor.getEndNode(), blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_MERGE);
+                                if (obj.isVirtual()) {
+                                    Block predecessor = mergeBlock.getPredecessors().get(i);
+                                    materialized |= ensureMaterialized(states.get(i), obj, predecessor.getEndNode(), blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_MERGE);
+                                }
                                 afterMergeEffects.addPhiInput(materializedValuePhi, obj.getMaterializedValue());
                             }
                             newState.addObject(object, new ObjectState(object, materializedValuePhi, EscapeState.Materialized, null));
@@ -383,6 +423,14 @@
             } while (materialized);
         }
 
+        private Set<VirtualObjectNode> intersectVirtualObjects(List<BlockT> states) {
+            Set<VirtualObjectNode> virtualObjTemp = Node.newSet(states.get(0).getVirtualObjects());
+            for (int i = 1; i < states.size(); i++) {
+                virtualObjTemp.retainAll(states.get(i).getVirtualObjects());
+            }
+            return virtualObjTemp;
+        }
+
         /**
          * Try to merge multiple virtual object states into a single object state. If the incoming
          * object states are compatible, then this method will create PhiNodes for the object's
@@ -628,8 +676,8 @@
         }
     }
 
-    public ObjectState getObjectState(PartialEscapeBlockState<?> state, Node value) {
-        if (value == null || value instanceof VirtualState) {
+    public ObjectState getObjectState(PartialEscapeBlockState<?> state, ValueNode value) {
+        if (value == null) {
             return null;
         }
         if (value.isAlive() && !aliases.isNew(value)) {