changeset 6356:41fc19bd618d

adapt old EscapeAnalysisPhase to infrastructure changes
author Lukas Stadler <lukas.stadler@jku.at>
date Tue, 11 Sep 2012 14:48:24 +0200
parents 892d3c82febe
children 2d902712a3f3
files graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EscapeAnalysisTest.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java
diffstat 6 files changed, 94 insertions(+), 258 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EscapeAnalysisTest.java	Tue Sep 11 14:27:44 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EscapeAnalysisTest.java	Tue Sep 11 14:48:24 2012 +0200
@@ -127,7 +127,7 @@
                 new InliningPhase(null, runtime(), null, null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
                 Debug.dump(graph, "Graph");
-                new EscapeAnalysisPhase(null, runtime(), null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
+                new EscapeAnalysisPhase(null, runtime(), null).apply(graph);
                 Debug.dump(graph, "Graph");
                 int retCount = 0;
                 for (ReturnNode ret : graph.getNodes(ReturnNode.class)) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue Sep 11 14:27:44 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue Sep 11 14:48:24 2012 +0200
@@ -153,7 +153,7 @@
         }
 
         if (GraalOptions.EscapeAnalysis && !plan.isPhaseDisabled(EscapeAnalysisPhase.class)) {
-            new EscapeAnalysisPhase(target, runtime, assumptions, cache, plan, optimisticOpts).apply(graph);
+            new EscapeAnalysisPhase(target, runtime, assumptions).apply(graph);
         }
         if (GraalOptions.OptLoopTransform) {
             new LoopTransformHighPhase().apply(graph);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java	Tue Sep 11 14:27:44 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java	Tue Sep 11 14:48:24 2012 +0200
@@ -25,6 +25,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.graph.*;
 import com.oracle.graal.compiler.util.*;
@@ -153,9 +154,7 @@
             }
             assert node.objectStamp().isExactType();
             final VirtualObjectNode virtual = graph.add(new VirtualObjectNode(id, node.objectStamp().type(), escapeFields.length));
-            if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) {
-                TTY.println("new virtual object: " + virtual);
-            }
+            Debug.log("new virtual object: " + virtual);
             node.replaceAtUsages(virtual);
             FixedNode next = node.next();
             graph.removeFixed(node);
@@ -190,130 +189,25 @@
         }
     }
 
+    private final TargetDescription target;
+    private final GraalCodeCacheProvider runtime;
+    private final Assumptions assumptions;
 
     private int virtualIds = 0;
 
-
-    private final TargetDescription target;
-    private final GraalCodeCacheProvider runtime;
-    private final Assumptions assumptions;
-    private final GraphCache cache;
-    private final PhasePlan plan;
-    private final OptimisticOptimizations optimisticOpts;
-
-    public EscapeAnalysisPhase(TargetDescription target, GraalCodeCacheProvider runtime, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
+    public EscapeAnalysisPhase(TargetDescription target, GraalCodeCacheProvider runtime, Assumptions assumptions) {
         this.runtime = runtime;
         this.target = target;
         this.assumptions = assumptions;
-        this.cache = cache;
-        this.plan = plan;
-        this.optimisticOpts = optimisticOpts;
     }
 
-    private static class EscapeRecord {
-
-        public final Node node;
-        public final ArrayList<Node> escapesThrough = new ArrayList<>();
-        public double localWeight;
-
-        public EscapeRecord(Node node) {
-            this.node = node;
-        }
-
-        public void dump() {
-            TTY.print("node %s (%f) escapes through ", node, localWeight);
-            for (Node escape : escapesThrough) {
-                TTY.print("%s ", escape);
-            }
-            TTY.println();
-        }
-    }
-
-    private static Node escape(EscapeRecord record, Node usage) {
-        final Node node = record.node;
-        if (usage instanceof VirtualState) {
-            assert usage.inputs().contains(node);
-            return null;
-        } else {
-            if (usage instanceof FixedNode) {
-                record.localWeight += ((FixedNode) usage).probability();
-            }
-            if (usage instanceof IsNullNode) {
-                assert ((IsNullNode) usage).object() == node;
-                return null;
-            } else if (usage instanceof IsTypeNode) {
-                assert ((IsTypeNode) usage).objectClass() == node;
-                return null;
-            } else if (usage instanceof AccessMonitorNode) {
-                assert ((AccessMonitorNode) usage).object() == node;
-                return null;
-            } else if (usage instanceof LoadFieldNode) {
-                assert ((LoadFieldNode) usage).object() == node;
-                return null;
-            } else if (usage instanceof StoreFieldNode) {
-                StoreFieldNode x = (StoreFieldNode) usage;
-                // self-references do not escape
-                return x.value() == node ? x.object() : null;
-            } else if (usage instanceof LoadIndexedNode) {
-                LoadIndexedNode x = (LoadIndexedNode) usage;
-                if (x.index() == node) {
-                    return x.array();
-                } else {
-                    assert x.array() == node;
-                    return EscapeOp.isValidConstantIndex(x) ? null : x.array();
-                }
-            } else if (usage instanceof StoreIndexedNode) {
-                StoreIndexedNode x = (StoreIndexedNode) usage;
-                if (x.index() == node) {
-                    return x.array();
-                } else {
-                    assert x.array() == node || x.value() == node;
-                    // in order to not escape, the access needs to have a valid constant index and either a store into node or be self-referencing
-                    return EscapeOp.isValidConstantIndex(x) && x.value() != node ? null : x.array();
-                }
-            } else if (usage instanceof RegisterFinalizerNode) {
-                assert ((RegisterFinalizerNode) usage).object() == node;
-                return null;
-            } else if (usage instanceof ArrayLengthNode) {
-                assert ((ArrayLengthNode) usage).array() == node;
-                return null;
-            } else {
-                return usage;
-            }
-        }
-    }
-
-    @SuppressWarnings("unused")
-    private static void completeAnalysis(StructuredGraph graph) {
-        // TODO (lstadler): debugging code
-
-        TTY.println("================================================================");
-        for (Node node : graph.getNodes()) {
-            if (node != null && node instanceof FixedWithNextNode && node instanceof EscapeAnalyzable) {
-                EscapeOp op = ((EscapeAnalyzable) node).getEscapeOp();
-                if (op != null && op.canAnalyze(node)) {
-                    EscapeRecord record = new EscapeRecord(node);
-
-                    for (Node usage : node.usages()) {
-                        Node escapesThrough = escape(record, usage);
-                        if (escapesThrough != null && escapesThrough != node) {
-                            record.escapesThrough.add(escapesThrough);
-                        }
-                    }
-                    record.dump();
-                }
-            }
-        }
-    }
-
-
     @Override
     protected void run(StructuredGraph graph) {
         for (Node node : new GraphOrder(graph)) {
             if (node != null && node instanceof FixedWithNextNode && node instanceof EscapeAnalyzable) {
                 FixedWithNextNode fixedNode = (FixedWithNextNode) node;
                 EscapeOp op = ((EscapeAnalyzable) node).getEscapeOp();
-                if (op != null && op.canAnalyze(fixedNode)) {
+                if (op != null) {
                     try {
                         performAnalysis(graph, fixedNode, op);
                     } catch (GraalInternalError e) {
@@ -328,60 +222,27 @@
         if (!shouldAnalyze(node)) {
             return;
         }
-        Set<Node> exits = new HashSet<>();
-        Set<Invoke> invokes = new HashSet<>();
-        int iterations = 0;
-
-        int minimumWeight = getMinimumWeight(node);
-        do {
-            double weight = analyze(op, node, exits, invokes);
-            if (exits.size() != 0) {
-                if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) {
-                    TTY.println("%n####### escaping object: %s (%s)", node, node.stamp());
-                    if (GraalOptions.TraceEscapeAnalysis) {
-                        TTY.print("%d: new value: %s, weight %f, escapes at ", iterations, node, weight);
-                        for (Node n : exits) {
-                            TTY.print("%s, ", n);
-                        }
-                        for (Invoke n : invokes) {
-                            TTY.print("%s, ", n);
-                        }
-                        TTY.println();
-                    }
-                }
-                break;
-            }
-            if (invokes.size() == 0) {
+        HashSet<Node> exits = new HashSet<>();
+        HashSet<Invoke> invokes = new HashSet<>();
 
-                Debug.dump(graph, "Before escape %s", node);
-                Debug.log("!!!!!!!! non-escaping object: %s (%s)", node, node.stamp());
-                removeAllocation(graph, node, op);
-                Debug.dump(graph, "After escape", graph);
-                break;
-            }
-            if (weight < minimumWeight) {
-                if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) {
-                    TTY.println("####### possibly escaping object: %s (insufficient weight for inlining: %f)", node, weight);
+        analyze(node, exits, invokes);
+        if (exits.isEmpty() && invokes.isEmpty()) {
+            Debug.log("!!!!!!!! non-escaping object: %s (%s)", node, node.stamp());
+            removeAllocation(graph, node, op);
+            Debug.dump(graph, "After escape", graph);
+        } else {
+            Debug.log("%n####### escaping object: %s (%s)", node, node.stamp());
+            if (GraalOptions.TraceEscapeAnalysis) {
+                TTY.print(" escapes at ", node);
+                for (Node n : exits) {
+                    TTY.print("%s, ", n);
                 }
-                break;
-            }
-            if (!GraalOptions.Inline) {
-                break;
+                for (Invoke n : invokes) {
+                    TTY.print("%s, ", n);
+                }
+                TTY.println();
             }
-            if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) {
-                TTY.println("Trying inlining to get a non-escaping object for %s", node);
-            }
-            new InliningPhase(target, runtime, invokes, assumptions, cache, plan, optimisticOpts).apply(graph);
-            new DeadCodeEliminationPhase().apply(graph);
-            if (node.isDeleted()) {
-                if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) {
-                    TTY.println("!!!!!!!! object died while performing escape analysis: %s (%s)", node, node.stamp());
-                }
-                break;
-            }
-            exits.clear();
-            invokes.clear();
-        } while (iterations++ < 3);
+        }
     }
 
     protected void removeAllocation(StructuredGraph graph, FixedWithNextNode node, EscapeOp op) {
@@ -410,14 +271,9 @@
         return true;
     }
 
-    protected int getMinimumWeight(@SuppressWarnings("unused") FixedWithNextNode node) {
-        return GraalOptions.ForcedInlineEscapeWeight;
-    }
-
-    private static double analyze(EscapeOp op, Node node, Collection<Node> exits, Collection<Invoke> invokes) {
-        double weight = 0;
+    private static void analyze(Node node, HashSet<Node> exits, HashSet<Invoke> invokes) {
         for (Node usage : node.usages().snapshot()) {
-            boolean escapes = op.escape(node, usage);
+            boolean escapes = escape(node, usage);
             if (escapes) {
                 if (usage instanceof VirtualState) {
                     // nothing to do...
@@ -439,15 +295,73 @@
                     exits.add(usage);
                     break;
                 }
+            }
+        }
+    }
+
+    private static boolean escape(Node node, Node usage) {
+        if (usage instanceof IsNullNode) {
+            assert ((IsNullNode) usage).object() == node;
+            return false;
+        } else if (usage instanceof IsTypeNode) {
+            assert ((IsTypeNode) usage).objectClass() == node;
+            return false;
+        } else if (usage instanceof VirtualState) {
+            assert usage.inputs().contains(node);
+            return true;
+        } else if (usage instanceof AccessMonitorNode) {
+            assert ((AccessMonitorNode) usage).object() == node;
+            return false;
+        } else if (usage instanceof LoadFieldNode) {
+            assert ((LoadFieldNode) usage).object() == node;
+            return false;
+        } else if (usage instanceof StoreFieldNode) {
+            StoreFieldNode x = (StoreFieldNode) usage;
+            // self-references do escape
+            return x.value() == node; // TODO (thomaswue) Check if we can add this condition? && x.object() != node;
+        } else if (usage instanceof LoadIndexedNode) {
+            LoadIndexedNode x = (LoadIndexedNode) usage;
+            if (x.index() == node) {
+                return true;
             } else {
-                if (GraalOptions.ProbabilityAnalysis && usage instanceof FixedNode) {
-                    weight += ((FixedNode) usage).probability();
-                } else {
-                    weight++;
+                assert x.array() == node;
+                return !isValidConstantIndex(x);
+            }
+        } else if (usage instanceof StoreIndexedNode) {
+            StoreIndexedNode x = (StoreIndexedNode) usage;
+            if (x.index() == node) {
+                return true;
+            } else {
+                assert x.array() == node || x.value() == node;
+                // in order to not escape the access needs to have a valid constant index and either a store into node
+                // or self-referencing
+                return !isValidConstantIndex(x) || x.value() == node && x.array() != node;
+            }
+        } else if (usage instanceof RegisterFinalizerNode) {
+            assert ((RegisterFinalizerNode) usage).object() == node;
+            return false;
+        } else if (usage instanceof ArrayLengthNode) {
+            assert ((ArrayLengthNode) usage).array() == node;
+            return false;
+        } else if (usage instanceof ValueProxyNode) {
+            for (Node vpnUsage : usage.usages().snapshot()) {
+                if (escape(usage, vpnUsage)) {
+                    return true;
                 }
             }
+            return false;
+        } else {
+            return true;
         }
-        return weight;
     }
 
+    public static boolean isValidConstantIndex(AccessIndexedNode x) {
+        Constant index = x.index().asConstant();
+        if (x.array() instanceof NewArrayNode) {
+            Constant length = ((NewArrayNode) x.array()).dimension(0).asConstant();
+            return index != null && length != null && index.asInt() >= 0 && index.asInt() < length.asInt();
+        } else {
+            return false;
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Tue Sep 11 14:27:44 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Tue Sep 11 14:48:24 2012 +0200
@@ -102,13 +102,6 @@
     private static final EscapeOp ESCAPE = new EscapeOp() {
 
         @Override
-        public boolean canAnalyze(Node node) {
-            NewArrayNode x = (NewArrayNode) node;
-            Constant length = x.dimension(0).asConstant();
-            return length != null && length.asInt() >= 0 && length.asInt() < MaximumEscapeAnalysisArrayLength;
-        }
-
-        @Override
         public EscapeField[] fields(Node node) {
             NewArrayNode x = (NewArrayNode) node;
             assert x.elementType.arrayOf().isArrayClass();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Tue Sep 11 14:27:44 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Tue Sep 11 14:48:24 2012 +0200
@@ -78,11 +78,6 @@
 
     private static final EscapeOp ESCAPE = new EscapeOp() {
 
-        @Override
-        public boolean canAnalyze(Node node) {
-            return true;
-        }
-
         private void fillEscapeFields(ResolvedJavaType type, List<EscapeField> escapeFields) {
             if (type != null) {
                 fillEscapeFields(type.superType(), escapeFields);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java	Tue Sep 11 14:27:44 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java	Tue Sep 11 14:48:24 2012 +0200
@@ -32,79 +32,12 @@
 
 public abstract class EscapeOp {
 
-    public abstract boolean canAnalyze(Node node);
-
-    public boolean escape(Node node, Node usage) {
-        if (usage instanceof IsNullNode) {
-            assert ((IsNullNode) usage).object() == node;
-            return false;
-        } else if (usage instanceof IsTypeNode) {
-            assert ((IsTypeNode) usage).objectClass() == node;
-            return false;
-        } else if (usage instanceof VirtualState) {
-            assert usage.inputs().contains(node);
-            return true;
-        } else if (usage instanceof AccessMonitorNode) {
-            assert ((AccessMonitorNode) usage).object() == node;
-            return false;
-        } else if (usage instanceof LoadFieldNode) {
-            assert ((LoadFieldNode) usage).object() == node;
-            return false;
-        } else if (usage instanceof StoreFieldNode) {
-            StoreFieldNode x = (StoreFieldNode) usage;
-            // self-references do escape
-            return x.value() == node; // TODO (thomaswue) Check if we can add this condition? && x.object() != node;
-        } else if (usage instanceof LoadIndexedNode) {
-            LoadIndexedNode x = (LoadIndexedNode) usage;
-            if (x.index() == node) {
-                return true;
-            } else {
-                assert x.array() == node;
-                return !isValidConstantIndex(x);
-            }
-        } else if (usage instanceof StoreIndexedNode) {
-            StoreIndexedNode x = (StoreIndexedNode) usage;
-            if (x.index() == node) {
-                return true;
-            } else {
-                assert x.array() == node || x.value() == node;
-                // in order to not escape the access needs to have a valid constant index and either a store into node or self-referencing
-                return !isValidConstantIndex(x) || x.value() == node && x.array() != node;
-            }
-        } else if (usage instanceof RegisterFinalizerNode) {
-            assert ((RegisterFinalizerNode) usage).object() == node;
-            return false;
-        } else if (usage instanceof ArrayLengthNode) {
-            assert ((ArrayLengthNode) usage).array() == node;
-            return false;
-        } else if (usage instanceof ValueProxyNode) {
-            for (Node vpnUsage : usage.usages().snapshot()) {
-                if (escape(usage, vpnUsage)) {
-                    return true;
-                }
-            }
-            return false;
-        } else {
-            return true;
-        }
-    }
-
-    public static boolean isValidConstantIndex(AccessIndexedNode x) {
-        Constant index = x.index().asConstant();
-        if (x.array() instanceof NewArrayNode) {
-            Constant length = ((NewArrayNode) x.array()).dimension(0).asConstant();
-            return index != null && length != null && index.asInt() >= 0 && index.asInt() < length.asInt();
-        } else {
-            return false;
-        }
-    }
-
     public abstract EscapeField[] fields(Node node);
 
     public abstract ResolvedJavaType type(Node node);
 
     public void beforeUpdate(Node node, Node usage) {
-        // IsNonNullNode and IsTypeNode should have been eliminated by the CanonicalizerPhase, but we can't rely on this
+        // IsNullNode and IsTypeNode should have been eliminated by the CanonicalizerPhase, but we can't rely on this
         if (usage instanceof IsNullNode) {
             IsNullNode x = (IsNullNode) usage;
             ((StructuredGraph) x.graph()).replaceFloating(x, ConstantNode.forBoolean(false, node.graph()));
@@ -119,4 +52,5 @@
 
     public abstract int updateState(Node node, Node current, Map<Object, Integer> fieldIndex, ValueNode[] fieldState);
 
+
 }