# HG changeset patch # User Lukas Stadler # Date 1347459764 -7200 # Node ID ccdf43a092040795ecfeae6a6898a870d73a589b # Parent e5203e5843fc99e906d9309239c484a6cfde4024 PartialEscapeAnalysis: fix for bailout, better metrics, small renaming diff -r e5203e5843fc -r ccdf43a09204 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/DeadCodeEliminationPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/DeadCodeEliminationPhase.java Wed Sep 12 12:57:27 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/DeadCodeEliminationPhase.java Wed Sep 12 16:22:44 2012 +0200 @@ -29,6 +29,9 @@ public class DeadCodeEliminationPhase extends Phase { + // Metrics + private static final DebugMetric metricNodesRemoved = Debug.metric("NodesRemoved"); + private NodeFlood flood; @Override @@ -101,6 +104,7 @@ } for (Node node : graph.getNodes()) { if (!flood.isMarked(node)) { + metricNodesRemoved.increment(); node.safeDelete(); } } diff -r e5203e5843fc -r ccdf43a09204 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 Wed Sep 12 12:57:27 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ea/PartialEscapeAnalysisPhase.java Wed Sep 12 16:22:44 2012 +0200 @@ -68,11 +68,13 @@ // Metrics private static final DebugMetric metricAllocationRemoved = Debug.metric("AllocationRemoved"); + private static final DebugMetric metricAllocationFieldsRemoved = Debug.metric("AllocationFieldsRemoved"); private static final DebugMetric metricStoreRemoved = Debug.metric("StoreRemoved"); private static final DebugMetric metricLoadRemoved = Debug.metric("LoadRemoved"); private static final DebugMetric metricLockRemoved = Debug.metric("LockRemoved"); private static final DebugMetric metricOtherRemoved = Debug.metric("OtherRemoved"); private static final DebugMetric metricMaterializations = Debug.metric("Materializations"); + private static final DebugMetric metricMaterializationFields = Debug.metric("MaterializationFields"); private static final ValueNode DUMMY_NODE = new ValueNode(null) { }; @@ -96,20 +98,22 @@ private final boolean changeGraph; + private final HashSet allocations; private final ArrayList obsoleteNodes = new ArrayList<>(); private int virtualIds = 0; - public EscapeAnalysisIteration(StructuredGraph graph, SchedulePhase schedule, MetaAccessProvider runtime, boolean changeGraph) { + public EscapeAnalysisIteration(StructuredGraph graph, SchedulePhase schedule, MetaAccessProvider runtime, HashSet allocations, boolean changeGraph) { this.graph = graph; this.schedule = schedule; this.runtime = runtime; + this.allocations = allocations; this.changeGraph = changeGraph; this.visitedNodes = graph.createNodeBitMap(); this.usages = graph.createNodeBitMap(); } public void run() { - new MyIterator(graph, schedule.getCFG().getStartBlock()).apply(); + new PartialEscapeIterator(graph, schedule.getCFG().getStartBlock()).apply(); if (changeGraph) { Debug.dump(graph, "after PartialEscapeAnalysis"); @@ -192,15 +196,15 @@ } } - private class MyState implements MergeableBlockState { + private class BlockState implements MergeableBlockState { private final HashMap recordStates = new HashMap<>(); private final HashMap recordAliases = new HashMap<>(); - public MyState() { + public BlockState() { } - public MyState(MyState other) { + public BlockState(BlockState other) { for (Map.Entry entry : other.recordStates.entrySet()) { recordStates.put(entry.getKey(), entry.getValue().clone()); } @@ -220,8 +224,8 @@ } @Override - public MyState clone() { - return new MyState(this); + public BlockState clone() { + return new BlockState(this); } public void materializeBefore(FixedNode fixed, EscapeRecord record) { @@ -271,9 +275,10 @@ } MaterializeObjectNode materialize = graph.add(new MaterializeObjectNode(record.type, record.fields)); - metricMaterializations.increment(); materialize.setProbability(fixed.probability()); ValueNode[] fieldState = obj.fieldState; + metricMaterializations.increment(); + metricMaterializationFields.add(fieldState.length); obj.fieldState = null; obj.materializedValue = materialize; deferred.add(record); @@ -343,14 +348,14 @@ } } - private class MyIterator extends PostOrderBlockIterator { + private class PartialEscapeIterator extends PostOrderBlockIterator { - public MyIterator(StructuredGraph graph, Block start) { - super(graph, start, new MyState()); + public PartialEscapeIterator(StructuredGraph graph, Block start) { + super(graph, start, new BlockState()); } @Override - protected void processBlock(Block block, MyState state) { + protected void processBlock(Block block, BlockState state) { trace("\nBlock: %s (", block); List nodeList = schedule.getBlockToNodesMap().get(block); @@ -360,13 +365,12 @@ if (node instanceof EscapeAnalyzable) { op = ((EscapeAnalyzable) node).getEscapeOp(); } - -// if (op != null) { -// String typeName = op.type(node).toString(); -// if (typeName.contains("ArrayList") || typeName.contains("Object") || typeName.contains("$")) { -// op = null; -// } -// } + if (op != null) { + // only escape analyze allocations that were escape analyzed during the first iteration + if (changeGraph && !allocations.contains(node)) { + op = null; + } + } if (op != null) { changed = true; @@ -380,11 +384,14 @@ 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 { + allocations.add((ValueNode) node); } state.addRecord(record, new ObjectState(record, fieldState, 0)); state.addAndMarkAlias(record, (ValueNode) node); virtualIds++; - metricAllocationRemoved.increment(); } else { visitedNodes.mark(node); @@ -419,7 +426,7 @@ trace(")\n end state: %s\n", state); } - private void processNode(final ValueNode node, FixedNode insertBefore, final MyState state) { + private void processNode(final ValueNode node, FixedNode insertBefore, final BlockState state) { boolean usageFound = false; if (node instanceof PiNode || node instanceof ValueProxyNode) { ValueNode value = node instanceof PiNode ? ((PiNode) node).object() : ((ValueProxyNode) node).value(); @@ -457,9 +464,9 @@ assert obj != null : x; if (changeGraph) { graph.replaceFloating(x, graph.unique(ConstantNode.forBoolean(false, graph))); + metricOtherRemoved.increment(); } usageFound = true; - metricOtherRemoved.increment(); } else if (node instanceof IsTypeNode) { throw new GraalInternalError("a newly created object can never be an object hub"); } else if (node instanceof AccessMonitorNode) { @@ -504,7 +511,9 @@ graph.removeFixed(x); } } - metricLoadRemoved.increment(); + if (changeGraph) { + metricLoadRemoved.increment(); + } } else { if (changeGraph) { x.replaceFirstInput(x.object(), obj.materializedValue); @@ -526,8 +535,8 @@ obj.fieldState[index] = value; if (changeGraph) { graph.removeFixed(x); + metricStoreRemoved.increment(); } - metricStoreRemoved.increment(); } else { if (changeGraph) { x.replaceFirstInput(object, obj.materializedValue); @@ -566,7 +575,9 @@ graph.removeFixed(x); } } - metricLoadRemoved.increment(); + if (changeGraph) { + metricLoadRemoved.increment(); + } } } else { if (changeGraph) { @@ -592,8 +603,8 @@ arrayObj.fieldState[index] = value; if (changeGraph) { graph.removeFixed(x); + metricStoreRemoved.increment(); } - metricStoreRemoved.increment(); } } else { if (changeGraph) { @@ -621,9 +632,9 @@ assert obj != null : x; if (changeGraph) { graph.replaceFixedWithFloating(x, ConstantNode.forInt(obj.record.fields.length, graph)); + metricOtherRemoved.increment(); } usageFound = true; - metricOtherRemoved.increment(); } else if (node instanceof ReadHubNode) { ReadHubNode x = (ReadHubNode) node; ObjectState obj = state.objectState(x.object()); @@ -631,9 +642,9 @@ if (changeGraph) { ConstantNode hub = ConstantNode.forConstant(obj.record.type.getEncoding(Representation.ObjectHub), runtime, graph); graph.replaceFixedWithFloating(x, hub); + metricOtherRemoved.increment(); } usageFound = true; - metricOtherRemoved.increment(); } else if (node instanceof ReturnNode) { ReturnNode x = (ReturnNode) node; ObjectState obj = state.objectState(x.result()); @@ -777,7 +788,7 @@ } } - private void ensureMaterialized(MyState state, ObjectState obj, FixedNode materializeBefore) { + private void ensureMaterialized(BlockState state, ObjectState obj, FixedNode materializeBefore) { assert obj != null; if (obj.materializedValue == null) { state.materializeBefore(materializeBefore, obj.record); @@ -785,14 +796,14 @@ assert obj.materializedValue != null; } - private void replaceWithMaterialized(ValueNode value, FixedNode usage, MyState state, ObjectState obj) { + private void replaceWithMaterialized(ValueNode value, FixedNode usage, BlockState state, ObjectState obj) { ensureMaterialized(state, obj, usage); if (changeGraph) { usage.replaceFirstInput(value, obj.materializedValue); } } - private void replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, MyState state, ObjectState obj) { + private void replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, BlockState state, ObjectState obj) { ensureMaterialized(state, obj, materializeBefore); if (changeGraph) { usage.replaceFirstInput(value, obj.materializedValue); @@ -800,12 +811,12 @@ } @Override - protected MyState merge(MergeNode merge, List states) { - MyState newState = new MyState(); + protected BlockState merge(MergeNode merge, List states) { + BlockState newState = new BlockState(); newState.recordAliases.putAll(states.get(0).recordAliases); for (int i = 1; i < states.size(); i++) { - MyState state = states.get(i); + BlockState state = states.get(i); for (Map.Entry entry : states.get(0).recordAliases.entrySet()) { if (state.recordAliases.containsKey(entry.getKey())) { assert state.recordAliases.get(entry.getKey()) == entry.getValue(); @@ -828,7 +839,7 @@ if (resultState == null || resultState.materializedValue == null) { int virtual = 0; int lockCount = states.get(0).objectState(record).lockCount; - for (MyState state : states) { + for (BlockState state : states) { ObjectState obj = state.objectState(record); if (obj.materializedValue == null) { virtual++; @@ -839,7 +850,7 @@ if (virtual < states.size()) { ValueNode materializedValuePhi = changeGraph ? graph.add(new PhiNode(Kind.Object, merge)) : DUMMY_NODE; for (int i = 0; i < states.size(); i++) { - MyState state = states.get(i); + BlockState state = states.get(i); ObjectState obj = state.objectState(record); materialized |= obj.materializedValue == null; ensureMaterialized(state, obj, merge.forwardEndAt(i)); @@ -855,7 +866,7 @@ boolean[] phiCreated = new boolean[values.length]; int mismatch = 0; for (int i = 1; i < states.size(); i++) { - MyState state = states.get(i); + BlockState state = states.get(i); ValueNode[] fields = state.objectState(record).fieldState; for (int index = 0; index < values.length; index++) { if (!phiCreated[index] && values[index] != fields[index]) { @@ -869,7 +880,7 @@ } if (mismatch > 0) { for (int i = 0; i < states.size(); i++) { - MyState state = states.get(i); + BlockState state = states.get(i); ValueNode[] fields = state.objectState(record).fieldState; for (int index = 0; index < values.length; index++) { if (phiCreated[index]) { @@ -907,7 +918,7 @@ return newState; } - private boolean processPhi(MyState newState, MergeNode merge, PhiNode phi, List states) { + private boolean processPhi(BlockState newState, MergeNode merge, PhiNode phi, List states) { assert states.size() == phi.valueCount(); int virtualInputs = 0; boolean materialized = false; @@ -972,8 +983,8 @@ } @Override - protected MyState loopBegin(LoopBeginNode loopBegin, MyState beforeLoopState) { - MyState state = beforeLoopState; + protected BlockState loopBegin(LoopBeginNode loopBegin, BlockState beforeLoopState) { + BlockState state = beforeLoopState; for (ObjectState obj : state.states()) { if (obj.fieldState != null) { for (int i = 0; obj.fieldState != null && i < obj.fieldState.length; i++) { @@ -1016,13 +1027,13 @@ } @Override - protected MyState loopEnds(LoopBeginNode loopBegin, MyState loopBeginState, List loopEndStates) { - MyState state = loopBeginState.clone(); + protected BlockState loopEnds(LoopBeginNode loopBegin, BlockState loopBeginState, List loopEndStates) { + BlockState state = loopBeginState.clone(); List loopEnds = loopBegin.orderedLoopEnds(); for (ObjectState obj : state.states()) { if (obj.fieldState != null) { Iterator iter = loopEnds.iterator(); - for (MyState loopEndState : loopEndStates) { + for (BlockState loopEndState : loopEndStates) { LoopEndNode loopEnd = iter.next(); ObjectState endObj = loopEndState.objectState(obj.record); if (endObj.fieldState == null) { @@ -1053,7 +1064,7 @@ } else { assert phi.valueCount() == loopEndStates.size() + 1; for (int i = 0; i < loopEndStates.size(); i++) { - MyState loopEndState = loopEndStates.get(i); + BlockState loopEndState = loopEndStates.get(i); ObjectState obj = loopEndState.objectState(phi.valueAt(i + 1)); if (obj != null) { ensureMaterialized(loopEndState, obj, loopEnds.get(i)); @@ -1068,7 +1079,7 @@ } @Override - protected MyState afterSplit(FixedNode node, MyState oldState) { + protected BlockState afterSplit(FixedNode node, BlockState oldState) { return oldState.clone(); } } @@ -1088,16 +1099,17 @@ @Override protected void run(StructuredGraph graph) { + HashSet allocations = new HashSet<>(); SchedulePhase schedule = new SchedulePhase(); schedule.apply(graph, false); try { - new EscapeAnalysisIteration(graph, schedule, runtime, false).run(); + new EscapeAnalysisIteration(graph, schedule, runtime, allocations, false).run(); } catch (BailoutException e) { // do nothing if the if the escape analysis bails out during the analysis iteration... return; } try { - new EscapeAnalysisIteration(graph, schedule, runtime, true).run(); + new EscapeAnalysisIteration(graph, schedule, runtime, allocations, true).run(); new CanonicalizerPhase(target, runtime, assumptions).apply(graph); } catch (BailoutException e) { throw new GraalInternalError(e);