changeset 16454:973b5704b95d

GraphEffectList rework (with lambdas)
author Lukas Stadler <lukas.stadler@oracle.com>
date Thu, 10 Jul 2014 14:30:10 +0200
parents 2824f2d25339
children 59fdea1f9e36
files graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectList.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java
diffstat 4 files changed, 167 insertions(+), 249 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectList.java	Thu Jul 10 14:23:45 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectList.java	Thu Jul 10 14:30:10 2014 +0200
@@ -25,6 +25,8 @@
 import java.lang.reflect.*;
 import java.util.*;
 
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 
@@ -34,47 +36,27 @@
  */
 public class EffectList implements Iterable<EffectList.Effect> {
 
-    public abstract static class Effect {
-
-        public boolean isVisible() {
+    public interface Effect {
+        default boolean isVisible() {
             return true;
         }
 
-        @Override
-        public String toString() {
-            StringBuilder str = new StringBuilder();
-            for (Field field : getClass().getDeclaredFields()) {
-                String name = field.getName();
-                if (name.contains("$")) {
-                    name = name.substring(name.indexOf('$') + 1);
-                }
-                if (!Modifier.isStatic(field.getModifiers()) && !name.equals("0")) {
-                    try {
-                        field.setAccessible(true);
-                        str.append(str.length() > 0 ? ", " : "").append(name).append("=").append(format(field.get(this)));
-                    } catch (SecurityException | IllegalAccessException e) {
-                        throw new RuntimeException(e);
-                    }
-                }
-            }
-            return name() + " [" + str + "]";
+        void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes);
+    }
+
+    public interface SimpleEffect extends Effect {
+        default void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
+            apply(graph);
         }
 
-        private static String format(Object object) {
-            if (object != null && Object[].class.isAssignableFrom(object.getClass())) {
-                return Arrays.toString((Object[]) object);
-            }
-            return "" + object;
-        }
-
-        public abstract String name();
-
-        public abstract void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes);
+        void apply(StructuredGraph graph);
     }
 
     private static final Effect[] EMPTY_ARRAY = new Effect[0];
+    private static final String[] EMPTY_STRING_ARRAY = new String[0];
 
     private Effect[] effects = EMPTY_ARRAY;
+    private String[] names = EMPTY_STRING_ARRAY;
     private int size;
 
     private void enlarge(int elements) {
@@ -84,26 +66,31 @@
                 length = Math.max(length * 2, 4);
             }
             effects = Arrays.copyOf(effects, length);
+            if (Debug.isEnabled()) {
+                names = Arrays.copyOf(names, length);
+            }
         }
     }
 
-    public void add(Effect effect) {
-        assert effect != null;
-        enlarge(1);
-        effects[size++] = effect;
+    public void add(String name, SimpleEffect effect) {
+        add(name, (Effect) effect);
     }
 
-    public void addAll(Collection<? extends Effect> list) {
-        enlarge(list.size());
-        for (Effect effect : list) {
-            assert effect != null;
-            effects[size++] = effect;
+    public void add(String name, Effect effect) {
+        assert effect != null;
+        enlarge(1);
+        if (Debug.isEnabled()) {
+            names[size] = name;
         }
+        effects[size++] = effect;
     }
 
     public void addAll(EffectList list) {
         enlarge(list.size);
         System.arraycopy(list.effects, 0, effects, size, list.size);
+        if (Debug.isEnabled()) {
+            System.arraycopy(list.names, 0, names, size, list.size);
+        }
         size += list.size;
     }
 
@@ -112,6 +99,10 @@
         enlarge(list.size);
         System.arraycopy(effects, position, effects, position + list.size, size - position);
         System.arraycopy(list.effects, 0, effects, position, list.size);
+        if (Debug.isEnabled()) {
+            System.arraycopy(names, position, names, position + list.size, size - position);
+            System.arraycopy(list.names, 0, names, position, list.size);
+        }
         size += list.size;
     }
 
@@ -167,15 +158,65 @@
         return size == 0;
     }
 
+    public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
+        for (int i = 0; i < size(); i++) {
+            Effect effect = effects[i];
+            try {
+                effect.apply(graph, obsoleteNodes);
+            } catch (Throwable t) {
+                StringBuilder str = new StringBuilder();
+                toString(str, i);
+                throw new GraalInternalError(t).addContext("effect", str);
+            }
+            if (effect.isVisible() && Debug.isLogEnabled()) {
+                StringBuilder str = new StringBuilder();
+                toString(str, i);
+                Debug.log("    %s", str);
+            }
+        }
+    }
+
+    private void toString(StringBuilder str, int i) {
+        Effect effect = effects[i];
+        str.append(getName(i)).append(" [");
+        boolean first = true;
+        for (Field field : effect.getClass().getDeclaredFields()) {
+            try {
+                field.setAccessible(true);
+                str.append(first ? "" : ", ").append(format(field.get(effect)));
+                first = false;
+            } catch (SecurityException | IllegalAccessException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        str.append(']');
+    }
+
+    private static String format(Object object) {
+        if (object != null && Object[].class.isAssignableFrom(object.getClass())) {
+            return Arrays.toString((Object[]) object);
+        }
+        return "" + object;
+    }
+
     @Override
     public String toString() {
         StringBuilder str = new StringBuilder();
         for (int i = 0; i < size(); i++) {
             Effect effect = get(i);
             if (effect.isVisible()) {
-                str.append(effect).append('\n');
+                toString(str, i);
+                str.append('\n');
             }
         }
         return str.toString();
     }
+
+    private String getName(int i) {
+        if (Debug.isEnabled()) {
+            return names[i];
+        } else {
+            return "";
+        }
+    }
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Thu Jul 10 14:23:45 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Thu Jul 10 14:30:10 2014 +0200
@@ -38,7 +38,6 @@
 import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure;
 import com.oracle.graal.phases.graph.ReentrantBlockIterator.LoopInfo;
 import com.oracle.graal.phases.schedule.*;
-import com.oracle.graal.virtual.phases.ea.EffectList.Effect;
 
 public abstract class EffectsClosure<BlockT extends EffectsBlockState<BlockT>> extends EffectsPhase.Closure<BlockT> {
 
@@ -81,12 +80,7 @@
             private void apply(GraphEffectList effects, Object context) {
                 if (!effects.isEmpty()) {
                     Debug.log(" ==== effects for %s", context);
-                    for (Effect effect : effects) {
-                        effect.apply(graph, obsoleteNodes);
-                        if (effect.isVisible()) {
-                            Debug.log("    %s", effect);
-                        }
-                    }
+                    effects.apply(graph, obsoleteNodes);
                     if (TraceEscapeAnalysis.getValue()) {
                         Debug.dump(graph, EffectsClosure.this.getClass().getSimpleName() + " - after processing %s", context);
                     }
@@ -228,6 +222,11 @@
         @SuppressWarnings("unused")
         protected void commitEnds(List<BlockT> states) {
         }
+
+        @Override
+        public String toString() {
+            return "MergeProcessor@" + merge;
+        }
     }
 
     public void addScalarAlias(ValueNode node, ValueNode alias) {
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Thu Jul 10 14:23:45 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Thu Jul 10 14:30:10 2014 +0200
@@ -26,9 +26,7 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.debug.*;
-import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.common.*;
@@ -36,35 +34,15 @@
 public class GraphEffectList extends EffectList {
 
     public void addCounterBefore(final String group, final String name, final int increment, final boolean addContext, final FixedNode position) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "addCounterBefore";
-            }
+        add("add counter", graph -> DynamicCounterNode.addCounterBefore(group, name, increment, addContext, position));
+    }
 
-            @Override
-            public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                assert position.isAlive();
-                DynamicCounterNode.addCounterBefore(group, name, increment, addContext, position);
-            }
-        });
+    public void addCounterAfter(final String group, final String name, final int increment, final boolean addContext, final FixedWithNextNode position) {
+        add("add counter after", graph -> DynamicCounterNode.addCounterBefore(group, name, increment, addContext, position.next()));
     }
 
     public void addWeakCounterCounterBefore(final String group, final String name, final int increment, final boolean addContext, final ValueNode checkedValue, final FixedNode position) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "addWeakCounterBefore";
-            }
-
-            @Override
-            public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                assert position.isAlive();
-                WeakCounterNode.addCounterBefore(group, name, increment, addContext, checkedValue, position);
-            }
-        });
+        add("add weak counter", graph -> WeakCounterNode.addCounterBefore(group, name, increment, addContext, checkedValue, position));
     }
 
     /**
@@ -75,18 +53,9 @@
      * @param position The fixed node before which the node should be added.
      */
     public void addFixedNodeBefore(final FixedWithNextNode node, final FixedNode position) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "addFixedNodeBefore";
-            }
-
-            @Override
-            public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                assert !node.isAlive() && !node.isDeleted() && position.isAlive();
-                graph.addBeforeFixed(position, graph.add(node));
-            }
+        add("add fixed node", graph -> {
+            assert !node.isAlive() && !node.isDeleted() && position.isAlive();
+            graph.addBeforeFixed(position, graph.add(node));
         });
     }
 
@@ -95,20 +64,8 @@
      *
      * @param node The floating node to be added.
      */
-    public void addFloatingNode(final ValueNode node, final String cause) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "addFloatingNode " + cause;
-            }
-
-            @Override
-            public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                assert !node.isAlive() && !node.isDeleted() : node + " " + cause;
-                graph.addWithoutUnique(node);
-            }
-        });
+    public void addFloatingNode(final ValueNode node, @SuppressWarnings("unused") final String cause) {
+        add("add floating node", graph -> graph.addWithoutUnique(node));
     }
 
     /**
@@ -118,18 +75,9 @@
      * @param value The value that will be added to the phi node.
      */
     public void addPhiInput(final PhiNode node, final ValueNode value) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "addPhiInput";
-            }
-
-            @Override
-            public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                assert node.isAlive() && value.isAlive() : node + " " + value;
-                node.addInput(value);
-            }
+        add("add phi input", graph -> {
+            assert node.isAlive() && value.isAlive() : node + " " + value;
+            node.addInput(value);
         });
     }
 
@@ -142,18 +90,9 @@
      * @param value The new value for the phi input.
      */
     public void initializePhiInput(final PhiNode node, final int index, final ValueNode value) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "setPhiInput";
-            }
-
-            @Override
-            public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                assert node.isAlive() && value.isAlive() && index >= 0;
-                node.initializeValueAt(index, value);
-            }
+        add("set phi input", (graph, obsoleteNodes) -> {
+            assert node.isAlive() && value.isAlive() && index >= 0;
+            node.initializeValueAt(index, value);
         });
     }
 
@@ -165,13 +104,7 @@
      * @param state The virtual object state to add.
      */
     public void addVirtualMapping(final FrameState node, final EscapeObjectState state) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "addVirtualMapping";
-            }
-
+        add("add virtual mapping", new Effect() {
             @Override
             public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
                 assert node.isAlive() && !state.isAlive() && !state.isDeleted();
@@ -197,20 +130,19 @@
      * @param node The fixed node that should be deleted.
      */
     public void deleteFixedNode(final FixedWithNextNode node) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "deleteFixedNode";
-            }
+        add("delete fixed node", (graph, obsoleteNodes) -> {
+            GraphUtil.unlinkFixedNode(node);
+            assert obsoleteNodes.add(node);
+        });
+    }
 
-            @Override
-            public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                assert node.isAlive();
-                GraphUtil.unlinkFixedNode(node);
-                assert obsoleteNodes.add(node);
-            }
-        });
+    /**
+     * Removes the given fixed node from the control flow.
+     *
+     * @param node The fixed node that should be deleted.
+     */
+    public void unlinkFixedNode(final FixedWithNextNode node) {
+        add("unlink fixed node", graph -> GraphUtil.unlinkFixedNode(node));
     }
 
     /**
@@ -224,25 +156,18 @@
      *
      */
     public void replaceAtUsages(final ValueNode node, final ValueNode replacement) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "replaceAtUsages";
+        add("replace at usages", (graph, obsoleteNodes) -> {
+            assert node.isAlive() && replacement.isAlive();
+            if (replacement instanceof FixedWithNextNode && ((FixedWithNextNode) replacement).next() == null) {
+                assert node instanceof FixedNode;
+                graph.addBeforeFixed((FixedNode) node, (FixedWithNextNode) replacement);
             }
-
-            @Override
-            public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                assert node.isAlive() && replacement.isAlive();
-                if (replacement instanceof FixedWithNextNode && ((FixedWithNextNode) replacement).next() == null) {
-                    assert node instanceof FixedNode;
-                    graph.addBeforeFixed((FixedNode) node, (FixedWithNextNode) replacement);
-                }
-                node.replaceAtUsages(replacement);
-                if (node instanceof FixedWithNextNode) {
-                    GraphUtil.unlinkFixedNode((FixedWithNextNode) node);
-                    assert obsoleteNodes.add(node);
-                }
+            node.replaceAtUsages(replacement);
+            if (node instanceof FixedWithNextNode) {
+                FixedNode next = ((FixedWithNextNode) node).next();
+                ((FixedWithNextNode) node).setNext(null);
+                node.replaceAtPredecessor(next);
+                assert obsoleteNodes.add(node);
             }
         });
     }
@@ -255,13 +180,7 @@
      * @param newInput The value to replace with.
      */
     public void replaceFirstInput(final Node node, final Node oldInput, final Node newInput) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "replaceFirstInput";
-            }
-
+        add("replace first input", new Effect() {
             @Override
             public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
                 assert node.isAlive() && oldInput.isAlive() && newInput.isAlive();
@@ -281,83 +200,6 @@
      * @param action The action that should be performed when the effects are applied.
      */
     public void customAction(final Runnable action) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "customAction";
-            }
-
-            @Override
-            public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                action.run();
-            }
-        });
-    }
-
-    /**
-     * Add the materialization node to the graph's control flow at the given position, and then sets
-     * its values.
-     *
-     * @param position The fixed node before which the materialization node should be added.
-     * @param objects The allocated objects.
-     * @param locks The lock depths for each object.
-     * @param values The values (field, elements) of all objects.
-     * @param otherAllocations A list of allocations that need to be added before the rest (used for
-     *            boxing allocations).
-     */
-    public void addMaterializationBefore(final FixedNode position, final List<AllocatedObjectNode> objects, final List<List<MonitorIdNode>> locks, final List<ValueNode> values,
-                    final List<ValueNode> otherAllocations) {
-        add(new Effect() {
-
-            @Override
-            public String name() {
-                return "addMaterializationBefore";
-            }
-
-            @Override
-            public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
-                for (ValueNode otherAllocation : otherAllocations) {
-                    graph.addWithoutUnique(otherAllocation);
-                    if (otherAllocation instanceof FixedWithNextNode) {
-                        graph.addBeforeFixed(position, (FixedWithNextNode) otherAllocation);
-                    } else {
-                        assert otherAllocation instanceof FloatingNode;
-                    }
-                }
-                if (!objects.isEmpty()) {
-                    CommitAllocationNode commit;
-                    if (position.predecessor() instanceof CommitAllocationNode) {
-                        commit = (CommitAllocationNode) position.predecessor();
-                    } else {
-                        commit = graph.add(new CommitAllocationNode());
-                        graph.addBeforeFixed(position, commit);
-                    }
-                    for (AllocatedObjectNode obj : objects) {
-                        graph.addWithoutUnique(obj);
-                        commit.getVirtualObjects().add(obj.getVirtualObject());
-                        obj.setCommit(commit);
-                    }
-                    commit.getValues().addAll(values);
-                    for (List<MonitorIdNode> monitorIds : locks) {
-                        commit.addLocks(monitorIds);
-                    }
-
-                    assert commit.usages().filter(AllocatedObjectNode.class).count() == commit.usages().count();
-                    List<AllocatedObjectNode> materializedValues = commit.usages().filter(AllocatedObjectNode.class).snapshot();
-                    for (int i = 0; i < commit.getValues().size(); i++) {
-                        if (materializedValues.contains(commit.getValues().get(i))) {
-                            commit.getValues().set(i, ((AllocatedObjectNode) commit.getValues().get(i)).getVirtualObject());
-                        }
-                    }
-
-                }
-            }
-
-            @Override
-            public boolean isVisible() {
-                return true;
-            }
-        });
+        add("customAction", graph -> action.run());
     }
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java	Thu Jul 10 14:23:45 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeBlockState.java	Thu Jul 10 14:30:10 2014 +0200
@@ -27,6 +27,7 @@
 import java.util.*;
 
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.Virtualizable.EscapeState;
 import com.oracle.graal.nodes.virtual.*;
@@ -75,7 +76,42 @@
         List<ValueNode> otherAllocations = new ArrayList<>(2);
         materializeWithCommit(fixed, virtual, objects, locks, values, otherAllocations, state);
 
-        materializeEffects.addMaterializationBefore(fixed, objects, locks, values, otherAllocations);
+        materializeEffects.add("materializeBefore", (graph, obsoleteNodes) -> {
+            for (ValueNode otherAllocation : otherAllocations) {
+                graph.addWithoutUnique(otherAllocation);
+                if (otherAllocation instanceof FixedWithNextNode) {
+                    graph.addBeforeFixed(fixed, (FixedWithNextNode) otherAllocation);
+                } else {
+                    assert otherAllocation instanceof FloatingNode;
+                }
+            }
+            if (!objects.isEmpty()) {
+                CommitAllocationNode commit;
+                if (fixed.predecessor() instanceof CommitAllocationNode) {
+                    commit = (CommitAllocationNode) fixed.predecessor();
+                } else {
+                    commit = graph.add(new CommitAllocationNode());
+                    graph.addBeforeFixed(fixed, commit);
+                }
+                for (AllocatedObjectNode obj : objects) {
+                    graph.addWithoutUnique(obj);
+                    commit.getVirtualObjects().add(obj.getVirtualObject());
+                    obj.setCommit(commit);
+                }
+                commit.getValues().addAll(values);
+                for (List<MonitorIdNode> monitorIds : locks) {
+                    commit.addLocks(monitorIds);
+                }
+
+                assert commit.usages().filter(AllocatedObjectNode.class).count() == commit.usages().count();
+                List<AllocatedObjectNode> materializedValues = commit.usages().filter(AllocatedObjectNode.class).snapshot();
+                for (int i = 0; i < commit.getValues().size(); i++) {
+                    if (materializedValues.contains(commit.getValues().get(i))) {
+                        commit.getValues().set(i, ((AllocatedObjectNode) commit.getValues().get(i)).getVirtualObject());
+                    }
+                }
+            }
+        });
     }
 
     private void materializeWithCommit(FixedNode fixed, VirtualObjectNode virtual, List<AllocatedObjectNode> objects, List<List<MonitorIdNode>> locks, List<ValueNode> values,