changeset 6393:adf0879a41c1

more escape analysis infrastructure: change EscapeOp behavior, make MaterializeObjectNodes roots for escape analysis
author Lukas Stadler <lukas.stadler@jku.at>
date Thu, 13 Sep 2012 11:41:43 +0200
parents 4df5ec0f8082
children 466e6ceebfed
files graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ea/PartialEscapeAnalysisPhase.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MaterializeObjectNode.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, 122 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java	Thu Sep 13 11:29:18 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java	Thu Sep 13 11:41:43 2012 +0200
@@ -143,12 +143,12 @@
 
         private void process() {
             for (Node usage : node.usages().snapshot()) {
-                op.beforeUpdate(node, usage);
+                op.beforeUpdate(usage);
             }
         }
 
         public void removeAllocation() {
-            escapeFields = op.fields(node);
+            escapeFields = op.fields();
             for (int i = 0; i < escapeFields.length; i++) {
                 fields.put(escapeFields[i].representation(), i);
             }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ea/PartialEscapeAnalysisPhase.java	Thu Sep 13 11:29:18 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ea/PartialEscapeAnalysisPhase.java	Thu Sep 13 11:41:43 2012 +0200
@@ -375,15 +375,12 @@
                 if (op != null) {
                     changed = true;
                     trace("{{%s}} ", node);
-                    ResolvedJavaType type = op.type(node);
-                    EscapeField[] fields = op.fields(node);
+                    ResolvedJavaType type = op.type();
+                    EscapeField[] fields = op.fields();
                     VirtualObjectNode virtualObject = changeGraph ? graph.add(new VirtualObjectNode(virtualIds, type, fields.length)) : null;
                     EscapeRecord record = new EscapeRecord(type, fields, virtualObject);
-                    ValueNode[] fieldState = new ValueNode[fields.length];
+                    ValueNode[] fieldState = changeGraph ? op.fieldState() : new ValueNode[fields.length];
                     if (changeGraph) {
-                        for (int i = 0; i < fields.length; i++) {
-                            fieldState[i] = ConstantNode.defaultForKind(fields[i].type().kind(), virtualObject.graph());
-                        }
                         metricAllocationRemoved.increment();
                         metricAllocationFieldsRemoved.add(fieldState.length);
                     } else {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MaterializeObjectNode.java	Thu Sep 13 11:29:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MaterializeObjectNode.java	Thu Sep 13 11:41:43 2012 +0200
@@ -22,14 +22,17 @@
  */
 package com.oracle.graal.nodes.java;
 
+import java.util.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.virtual.*;
 
 @NodeInfo(nameTemplate = "Materialize {p#type/s}")
-public final class MaterializeObjectNode extends FixedWithNextNode implements Lowerable, Node.IterableNodeType, Canonicalizable {
+public final class MaterializeObjectNode extends FixedWithNextNode implements EscapeAnalyzable, Lowerable, Node.IterableNodeType, Canonicalizable {
 
     @Input private final NodeInputList<ValueNode> values;
     private final ResolvedJavaType type;
@@ -100,4 +103,37 @@
             return this;
         }
     }
+
+    @Override
+    public EscapeOp getEscapeOp() {
+        return new EscapeOpImpl();
+    }
+
+    private final class EscapeOpImpl extends EscapeOp {
+
+        @Override
+        public ResolvedJavaType type() {
+            return type;
+        }
+
+        @Override
+        public EscapeField[] fields() {
+            return fields;
+        }
+
+        @Override
+        public ValueNode[] fieldState() {
+            return values.toArray(new ValueNode[values.size()]);
+        }
+
+        @Override
+        public void beforeUpdate(Node usage) {
+            throw new UnsupportedOperationException("MaterializeNode can only be escape analyzed using partial escape analysis");
+        }
+
+        @Override
+        public int updateState(VirtualObjectNode node, Node current, Map<Object, Integer> fieldIndex, ValueNode[] fieldState) {
+            throw new UnsupportedOperationException("MaterializeNode can only be escape analyzed using partial escape analysis");
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Thu Sep 13 11:29:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java	Thu Sep 13 11:41:43 2012 +0200
@@ -30,6 +30,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.nodes.virtual.*;
 
 /**
  * The {@code NewArrayNode} class is the base of all instructions that allocate arrays.
@@ -85,58 +86,65 @@
         return 1;
     }
 
-    public EscapeOp getEscapeOp() {
-        Constant constantLength = length().asConstant();
-        if (constantLength != null && constantLength.asInt() >= 0 && constantLength.asInt() < MaximumEscapeAnalysisArrayLength) {
-            return ESCAPE;
-        } else {
-            return null;
-        }
-    }
-
     @Override
     public void lower(LoweringTool tool) {
         tool.getRuntime().lower(this, tool);
     }
 
-    private static final EscapeOp ESCAPE = new EscapeOp() {
+    @Override
+    public EscapeOp getEscapeOp() {
+        Constant constantLength = length().asConstant();
+        if (constantLength != null && constantLength.asInt() >= 0 && constantLength.asInt() < MaximumEscapeAnalysisArrayLength) {
+            return new EscapeOpImpl();
+        } else {
+            return null;
+        }
+    }
+
+    private final class EscapeOpImpl extends EscapeOp {
 
         @Override
-        public EscapeField[] fields(Node node) {
-            NewArrayNode x = (NewArrayNode) node;
-            assert x.elementType.arrayOf().isArrayClass();
-            int length = x.dimension(0).asConstant().asInt();
-            EscapeField[] fields = new EscapeField[length];
-            for (int i = 0; i < length; i++) {
+        public ResolvedJavaType type() {
+            return elementType.arrayOf();
+        }
+
+        @Override
+        public EscapeField[] fields() {
+            int constantLength = dimension(0).asConstant().asInt();
+            EscapeField[] fields = new EscapeField[constantLength];
+            for (int i = 0; i < constantLength; i++) {
                 Integer representation = i;
-                fields[i] = new EscapeField(Integer.toString(i), representation, ((NewArrayNode) node).elementType());
+                fields[i] = new EscapeField(Integer.toString(i), representation, elementType());
             }
             return fields;
         }
 
         @Override
-        public ResolvedJavaType type(Node node) {
-            NewArrayNode x = (NewArrayNode) node;
-            return x.elementType.arrayOf();
+        public ValueNode[] fieldState() {
+            ValueNode[] state = new ValueNode[dimension(0).asConstant().asInt()];
+            for (int i = 0; i < state.length; i++) {
+                state[i] = ConstantNode.defaultForKind(elementType().kind(), graph());
+            }
+            return state;
         }
 
         @Override
-        public void beforeUpdate(Node node, Node usage) {
+        public void beforeUpdate(Node usage) {
             if (usage instanceof ArrayLengthNode) {
                 ArrayLengthNode x = (ArrayLengthNode) usage;
-                StructuredGraph graph = (StructuredGraph) node.graph();
-                x.replaceAtUsages(((NewArrayNode) node).dimension(0));
+                StructuredGraph graph = (StructuredGraph) graph();
+                x.replaceAtUsages(dimension(0));
                 graph.removeFixed(x);
             } else {
-                super.beforeUpdate(node, usage);
+                beforeUpdate(NewArrayNode.this, usage);
             }
         }
 
         @Override
-        public int updateState(Node node, Node current, Map<Object, Integer> fieldIndex, ValueNode[] fieldState) {
+        public int updateState(VirtualObjectNode virtualObject, Node current, Map<Object, Integer> fieldIndex, ValueNode[] fieldState) {
             if (current instanceof AccessIndexedNode) {
                 AccessIndexedNode x = (AccessIndexedNode) current;
-                if (GraphUtil.unProxify(x.array()) == node) {
+                if (GraphUtil.unProxify(x.array()) == virtualObject) {
                     int index = ((AccessIndexedNode) current).index().asConstant().asInt();
                     StructuredGraph graph = (StructuredGraph) x.graph();
                     if (current instanceof LoadIndexedNode) {
@@ -151,5 +159,6 @@
             }
             return -1;
         }
-    };
+
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Thu Sep 13 11:29:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java	Thu Sep 13 11:41:43 2012 +0200
@@ -30,6 +30,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.nodes.virtual.*;
 
 /**
  * The {@code NewInstanceNode} represents the allocation of an instance class object.
@@ -72,11 +73,17 @@
         gen.visitNewInstance(this);
     }
 
+    @Override
     public EscapeOp getEscapeOp() {
-        return instanceClass == null ? null : ESCAPE;
+        return instanceClass == null ? null : new EscapeOpImpl();
     }
 
-    private static final EscapeOp ESCAPE = new EscapeOp() {
+    private final class EscapeOpImpl extends EscapeOp {
+
+        @Override
+        public ResolvedJavaType type() {
+            return instanceClass();
+        }
 
         private void fillEscapeFields(ResolvedJavaType type, List<EscapeField> escapeFields) {
             if (type != null) {
@@ -90,32 +97,35 @@
         }
 
         @Override
-        public ResolvedJavaType type(Node node) {
-            NewInstanceNode x = (NewInstanceNode) node;
-            return x.instanceClass();
-        }
-
-        @Override
-        public EscapeField[] fields(Node node) {
-            NewInstanceNode x = (NewInstanceNode) node;
-            assert !x.instanceClass().isArrayClass();
+        public EscapeField[] fields() {
+            assert !instanceClass().isArrayClass();
             List<EscapeField> escapeFields = new ArrayList<>();
-            fillEscapeFields(x.instanceClass(), escapeFields);
+            fillEscapeFields(instanceClass(), escapeFields);
             return escapeFields.toArray(new EscapeField[escapeFields.size()]);
         }
 
         @Override
-        public void beforeUpdate(Node node, Node usage) {
+        public ValueNode[] fieldState() {
+            EscapeField[] fields = fields();
+            ValueNode[] state = new ValueNode[fields.length];
+            for (int i = 0; i < state.length; i++) {
+                state[i] = ConstantNode.defaultForKind(fields[i].type().kind(), graph());
+            }
+            return state;
+        }
+
+        @Override
+        public void beforeUpdate(Node usage) {
             if (usage instanceof RegisterFinalizerNode) {
                 RegisterFinalizerNode x = (RegisterFinalizerNode) usage;
                 ((StructuredGraph) x.graph()).removeFixed(x);
             } else {
-                super.beforeUpdate(node, usage);
+                super.beforeUpdate(NewInstanceNode.this, usage);
             }
         }
 
         @Override
-        public int updateState(Node node, Node current, Map<Object, Integer> fieldIndex, ValueNode[] fieldState) {
+        public int updateState(VirtualObjectNode node, Node current, Map<Object, Integer> fieldIndex, ValueNode[] fieldState) {
             if (current instanceof AccessFieldNode) {
                 AccessFieldNode x = (AccessFieldNode) current;
                 if (GraphUtil.unProxify(x.object()) == node) {
@@ -134,5 +144,5 @@
             }
             return -1;
         }
-    };
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java	Thu Sep 13 11:29:18 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java	Thu Sep 13 11:41:43 2012 +0200
@@ -29,14 +29,28 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.virtual.*;
 
 public abstract class EscapeOp {
 
-    public abstract EscapeField[] fields(Node node);
+    /**
+     * Returns the type of object that is created by the associated node.
+     */
+    public abstract ResolvedJavaType type();
 
-    public abstract ResolvedJavaType type(Node node);
+    /**
+     * Returns all the fields that the objects create by the associated node have.
+     */
+    public abstract EscapeField[] fields();
 
-    public void beforeUpdate(Node node, Node usage) {
+    /**
+     * Returns the initial value of all fields, in the same order as {@link #fields()}.
+     */
+    public abstract ValueNode[] fieldState();
+
+    public abstract void beforeUpdate(Node usage);
+
+    protected static void beforeUpdate(Node node, Node usage) {
         // 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;
@@ -50,7 +64,6 @@
         }
     }
 
-    public abstract int updateState(Node node, Node current, Map<Object, Integer> fieldIndex, ValueNode[] fieldState);
-
+    public abstract int updateState(VirtualObjectNode virtualObject, Node current, Map<Object, Integer> fieldIndex, ValueNode[] fieldState);
 
 }