# HG changeset patch # User Lukas Stadler # Date 1347529303 -7200 # Node ID adf0879a41c1977f2797de0ddd31e04cff64301e # Parent 4df5ec0f80820e2b4449e6c5b99ace03a65f9530 more escape analysis infrastructure: change EscapeOp behavior, make MaterializeObjectNodes roots for escape analysis diff -r 4df5ec0f8082 -r adf0879a41c1 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java --- 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); } diff -r 4df5ec0f8082 -r adf0879a41c1 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ea/PartialEscapeAnalysisPhase.java --- 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 { diff -r 4df5ec0f8082 -r adf0879a41c1 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MaterializeObjectNode.java --- 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 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 fieldIndex, ValueNode[] fieldState) { + throw new UnsupportedOperationException("MaterializeNode can only be escape analyzed using partial escape analysis"); + } + } } diff -r 4df5ec0f8082 -r adf0879a41c1 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java --- 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 fieldIndex, ValueNode[] fieldState) { + public int updateState(VirtualObjectNode virtualObject, Node current, Map 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; } - }; + + } } diff -r 4df5ec0f8082 -r adf0879a41c1 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java --- 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 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 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 fieldIndex, ValueNode[] fieldState) { + public int updateState(VirtualObjectNode node, Node current, Map fieldIndex, ValueNode[] fieldState) { if (current instanceof AccessFieldNode) { AccessFieldNode x = (AccessFieldNode) current; if (GraphUtil.unProxify(x.object()) == node) { @@ -134,5 +144,5 @@ } return -1; } - }; + } } diff -r 4df5ec0f8082 -r adf0879a41c1 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java --- 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 fieldIndex, ValueNode[] fieldState); - + public abstract int updateState(VirtualObjectNode virtualObject, Node current, Map fieldIndex, ValueNode[] fieldState); }