# HG changeset patch # User Thomas Wuerthinger # Date 1309541969 -7200 # Node ID 5c696a58e69296463f6656f42c000f1f6140509c # Parent a4b0c3df7f802e069951c04b537e32b882c959c3# Parent c3573103764ec3119cf3ab7fe486ed61b9512351 Merge. diff -r a4b0c3df7f80 -r 5c696a58e692 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalMetrics.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalMetrics.java Fri Jul 01 19:39:14 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalMetrics.java Fri Jul 01 19:39:29 2011 +0200 @@ -62,6 +62,7 @@ public static int FrameStatesCreated; public static int FrameStateValuesCreated; public static int NodesCanonicalized; + public static int LoopsPeeled; public static void print() { for (Entry m : map.entrySet()) { diff -r a4b0c3df7f80 -r 5c696a58e692 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Fri Jul 01 19:39:14 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Fri Jul 01 19:39:29 2011 +0200 @@ -59,6 +59,7 @@ public static boolean EscapeAnalysis = ____; public static int ForcedInlineEscapeWeight = 0; public static int MaximumEscapeAnalysisArrayLength = 32; + public static boolean PrintEscapeAnalysis = ____; // debugging settings public static boolean VerifyPointerMaps = ____; @@ -155,4 +156,5 @@ public static boolean OptGVN = true; public static boolean OptCanonicalizer = true; public static boolean OptLoops = true; + public static boolean LoopPeeling = ____; } diff -r a4b0c3df7f80 -r 5c696a58e692 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java Fri Jul 01 19:39:14 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java Fri Jul 01 19:39:29 2011 +0200 @@ -642,7 +642,7 @@ if (!liveKill.get(operandNum)) { liveGen.set(operandNum); if (GraalOptions.TraceLinearScanLevel >= 4) { - TTY.println(" Setting liveGen for value %s, LIR opId %d, operand %d because of state for " + op.toString(), Util.valueString(value), op.id(), operandNum); + TTY.println(" Setting liveGen for value %s, LIR opId %d, operand %d because of state for %s", Util.valueString(value), op.id(), operandNum, op); } } } else if (operand.isRegister()) { @@ -1270,17 +1270,9 @@ if (info != null) { info.state.forEachLiveStateValue(new ValueProcedure() { public void doValue(Value value) { - if (value instanceof VirtualObject) { - VirtualObject obj = (VirtualObject) value; - do { - doValue(obj.input()); - obj = obj.object(); - } while (obj != null); - } else { - CiValue operand = value.operand(); - if (operand.isVariableOrRegister()) { - addUse(operand, blockFrom, (opId + 1), RegisterPriority.None, null); - } + CiValue operand = value.operand(); + if (operand.isVariableOrRegister()) { + addUse(operand, blockFrom, (opId + 1), RegisterPriority.None, null); } } }); @@ -1899,6 +1891,7 @@ RiType type = obj.type(); EscapeField[] escapeFields = obj.fields(); CiValue[] values = new CiValue[escapeFields.length]; + int valuesFilled = 0; VirtualObject current = obj; do { @@ -1907,6 +1900,7 @@ if (escapeFields[i].representation() == current.field().representation()) { if (values[i] == null) { values[i] = toCiValue(opId, current.input()); + valuesFilled++; } found = true; break; @@ -1914,7 +1908,7 @@ } assert found : type + "." + current.field() + " not found"; current = current.object(); - } while (current != null); + } while (current != null && valuesFilled < values.length); for (int i = 0; i < escapeFields.length; i++) { assert values[i] != null : type + "." + escapeFields[i]; diff -r a4b0c3df7f80 -r 5c696a58e692 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java Fri Jul 01 19:39:14 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java Fri Jul 01 19:39:29 2011 +0200 @@ -264,14 +264,20 @@ Set nodeBits = bits.get(node); if (nodeBits != null) { for (String bit : nodeBits) { - stream.printf("

true

%n", bit); + stream.printf("

true

"); } } for (Entry entry : props.entrySet()) { String key = entry.getKey().toString(); String value = entry.getValue() == null ? "null" : entry.getValue().toString(); - stream.printf("

%s

%n", escape(key), escape(value)); + stream.print("

"); + stream.print(escape(value)); + stream.println("

"); } stream.println(" "); @@ -371,11 +377,50 @@ } private String escape(String s) { - s = s.replace("&", "&"); - s = s.replace("<", "<"); - s = s.replace(">", ">"); - s = s.replace("\"", """); - s = s.replace("'", "'"); - return s; + StringBuilder str = null; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + switch (c) { + case '&': + case '<': + case '>': + case '"': + case '\'': + if (str == null) { + str = new StringBuilder(); + str.append(s, 0, i); + } + switch(c) { + case '&': + str.append("&"); + break; + case '<': + str.append("<"); + break; + case '>': + str.append(">"); + break; + case '"': + str.append("""); + break; + case '\'': + str.append("'"); + break; + default: + assert false; + } + break; + default: + if (str != null) { + str.append(c); + } + break; + } + } + if (str == null) { + return s; + } else { + return str.toString(); + } } } diff -r a4b0c3df7f80 -r 5c696a58e692 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Fri Jul 01 19:39:14 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Fri Jul 01 19:39:29 2011 +0200 @@ -1645,10 +1645,18 @@ } private void walkVirtualObject(VirtualObject value) { - walkStateValue(value.input()); - if (value.object() != null) { - walkVirtualObject(value.object()); + if (value.input() instanceof Phi) { + assert !((Phi) value.input()).isDead(); } + HashSet fields = new HashSet(); + VirtualObject obj = value; + do { + if (!fields.contains(obj.field().representation())) { + fields.add(obj.field().representation()); + walkStateValue(obj.input()); + } + obj = obj.object(); + } while (obj != null); } protected LIRDebugInfo stateFor(Value x) { diff -r a4b0c3df7f80 -r 5c696a58e692 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewArray.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewArray.java Fri Jul 01 19:39:14 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewArray.java Fri Jul 01 19:39:29 2011 +0200 @@ -93,6 +93,13 @@ public abstract CiKind elementKind(); + @Override + public Map getDebugProperties() { + Map properties = super.getDebugProperties(); + properties.put("exactType", exactType()); + return properties; + } + @SuppressWarnings("unchecked") @Override public T lookup(Class clazz) { @@ -200,7 +207,7 @@ } @Override - public void updateState(Node node, Node current, Map fields, Map fieldState) { + public EscapeField updateState(Node node, Node current, Map fields, Map fieldState) { if (current instanceof AccessIndexed) { int index = ((AccessIndexed) current).index().asConstant().asInt(); EscapeField field = fields.get(index); @@ -220,9 +227,11 @@ fieldState.put(field, x.value()); assert x.usages().size() == 0; x.replaceAndDelete(x.next()); + return field; } } } + return null; } } } diff -r a4b0c3df7f80 -r 5c696a58e692 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java Fri Jul 01 19:39:14 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java Fri Jul 01 19:39:29 2011 +0200 @@ -87,6 +87,14 @@ } @Override + public Map getDebugProperties() { + Map properties = super.getDebugProperties(); + properties.put("instanceClass", instanceClass); + properties.put("cpi", cpi); + return properties; + } + + @Override public Node copy(Graph into) { NewInstance x = new NewInstance(instanceClass, cpi, constantPool, into); return x; @@ -187,7 +195,7 @@ } @Override - public void updateState(Node node, Node current, Map fields, Map fieldState) { + public EscapeField updateState(Node node, Node current, Map fields, Map fieldState) { if (current instanceof AccessField) { EscapeField field = fields.get(((AccessField) current).field()); if (current instanceof LoadField) { @@ -206,9 +214,11 @@ fieldState.put(field, x.value()); assert x.usages().size() == 0; x.replaceAndDelete(x.next()); + return field; } } } + return null; } } } diff -r a4b0c3df7f80 -r 5c696a58e692 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java Fri Jul 01 19:39:14 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java Fri Jul 01 19:39:29 2011 +0200 @@ -101,6 +101,7 @@ assert this.operand.isIllegal() : "operand cannot be set twice"; assert operand != null && operand.isLegal() : "operand must be legal"; assert operand.kind.stackKind() == this.kind; + assert !(this instanceof VirtualObject); this.operand = operand; } diff -r a4b0c3df7f80 -r 5c696a58e692 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java Fri Jul 01 19:39:14 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java Fri Jul 01 19:39:29 2011 +0200 @@ -30,6 +30,7 @@ import com.oracle.max.graal.compiler.gen.*; import com.oracle.max.graal.compiler.graph.*; import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.compiler.observer.*; import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.compiler.value.*; import com.oracle.max.graal.graph.*; @@ -41,11 +42,11 @@ public static class BlockExitState { - public final Map fieldState; + public final Map fieldState; public VirtualObject obj; public BlockExitState() { - this.fieldState = new HashMap(); + this.fieldState = new HashMap(); } } @@ -101,7 +102,7 @@ // TTY.println(); BlockExitState state = new BlockExitState(); - if (block == startBlock) { + if (/*block == startBlock ||*/ block.getPredecessors().size() == 0) { state.obj = null; for (EscapeField field : fields.values()) { Constant value = Constant.defaultForKind(field.kind(), graph); @@ -150,7 +151,10 @@ } while (current != block.lastNode()) { Node next = ((FixedNodeWithNext) current).next(); - op.updateState(node, current, fields, state.fieldState); + EscapeField changedField = op.updateState(node, current, fields, state.fieldState); + if (changedField != null) { + state.obj = new VirtualObject(state.obj, state.fieldState.get(changedField), changedField, type, escapeFields, graph); + } if (!current.isDeleted() && current instanceof StateSplit) { FrameState stateAfter = ((StateSplit) current).stateAfter(); if (stateAfter != null) { @@ -162,14 +166,14 @@ if (GraalOptions.TraceEscapeAnalysis) { TTY.print(" block end state: "); - for (Entry entry : state.fieldState.entrySet()) { + for (Entry entry : state.fieldState.entrySet()) { TTY.print("%s->%s ", entry.getKey().name(), entry.getValue()); } TTY.println(); } exitStates.put(block, state); } - }, startBlock); + }); for (Entry entry : phis.entrySet()) { Phi phi = entry.getKey(); @@ -208,7 +212,7 @@ } // the rest of the usages should be dead frame states... for (Node usage : new ArrayList(node.usages())) { - assert usage instanceof FrameState || usage instanceof VirtualObject; + assert usage instanceof FrameState || usage instanceof VirtualObject : "usage: " + usage; usage.inputs().replace(node, Node.Null); } @@ -231,8 +235,19 @@ } while (obj != null); } } - if (frameState.outerFrameState() != null) { - current = updateFrameState(frameState.outerFrameState(), current); + FrameState outer = frameState.outerFrameState(); + if (outer != null) { + boolean duplicate = false; + for (int i = 0; i < outer.inputs().size(); i++) { + if (outer.inputs().get(i) == node) { + duplicate = true; + } + } + if (duplicate) { + outer = outer.duplicate(outer.bci); + frameState.setOuterFrameState(outer); + } + current = updateFrameState(outer, current); } return current; } @@ -251,7 +266,8 @@ } private void process() { - for (Node usage : new ArrayList(node.usages())) { + ArrayList arrayList = new ArrayList(node.usages()); + for (Node usage : arrayList) { op.beforeUpdate(node, usage); } } @@ -267,10 +283,9 @@ @Override protected void run(Graph graph) { -// if (!compilation.method.holder().name().contains("jnt")) { +// if (compilation.method.holder().name().contains("oracle")) { // return; // } -// if (true) return; for (Node node : graph.getNodes()) { EscapeOp op = node.lookup(EscapeOp.class); if (op != null && op.canAnalyze(node)) { @@ -283,30 +298,39 @@ do { weight = analyze(op, node, exits, invokes); if (exits.size() != 0) { - if (GraalOptions.TraceEscapeAnalysis) { - TTY.println("####### escaping object: %d %s (%s) in %s", node.id(), node.shortName(), ((Value) node).exactType(), compilation.method); - TTY.print("%d: new value: %d %s, weight %d, escapes at ", iterations, node.id(), node.shortName(), weight); - for (Node n : exits) { - TTY.print("%d %s, ", n.id(), n.shortName()); + if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) { + TTY.println("%n####### escaping object: %d %s (%s) in %s", node.id(), node.shortName(), ((Value) node).exactType(), compilation.method); + if (GraalOptions.TraceEscapeAnalysis) { + TTY.print("%d: new value: %d %s, weight %d, escapes at ", iterations, node.id(), node.shortName(), weight); + for (Node n : exits) { + TTY.print("%d %s, ", n.id(), n.shortName()); + } + for (Node n : invokes) { + TTY.print("%d %s, ", n.id(), n.shortName()); + } + TTY.println(); } - for (Node n : invokes) { - TTY.print("%d %s, ", n.id(), n.shortName()); - } - TTY.println(); } break; } if (invokes.size() == 0) { - if (GraalOptions.TraceEscapeAnalysis) { - TTY.println("!!!!!!!! non-escaping object: %d %s (%s) in %s", node.id(), node.shortName(), ((Value) node).exactType(), compilation.method); + + if (compilation.compiler.isObserved()) { + compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "Before escape " + node.id(), graph, true, false)); + } + if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) { + TTY.println("%n!!!!!!!! non-escaping object: %d %s (%s) in %s", node.id(), node.shortName(), ((Value) node).exactType(), compilation.method); } new EscapementFixup(op, graph, node).apply(); new PhiSimplifier(graph); + if (compilation.compiler.isObserved()) { + compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After escape " + node.id(), graph, true, false)); + } break; } if (weight < minimumWeight) { - if (GraalOptions.TraceEscapeAnalysis) { - TTY.println("####### possibly escaping object: %d in %s (insufficient weight for inlining)", node.id(), compilation.method); + if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) { + TTY.println("%n####### possibly escaping object: %d in %s (insufficient weight for inlining)", node.id(), compilation.method); } break; } @@ -381,7 +405,7 @@ void beforeUpdate(Node node, Node usage); - void updateState(Node node, Node current, Map fields, Map fieldState); + EscapeField updateState(Node node, Node current, Map fields, Map fieldState); } } diff -r a4b0c3df7f80 -r 5c696a58e692 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java Fri Jul 01 19:39:14 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java Fri Jul 01 19:39:29 2011 +0200 @@ -24,6 +24,7 @@ import java.util.*; +import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.ir.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.compiler.util.LoopUtil.Loop; @@ -38,14 +39,24 @@ protected void run(Graph graph) { List loops = LoopUtil.computeLoops(graph); -// for (Loop loop : loops) { -// System.out.println("Peel loop : " + loop.loopBegin()); -// LoopUtil.peelLoop(loop); -// } -// loops = LoopUtil.computeLoops(graph); // TODO (gd) avoid recomputing loops - - for (Loop loop : loops) { - doLoopCounters(loop); + // TODO (gd) currently counter detection is disabled when loop peeling is active + if (GraalOptions.LoopPeeling) { +peeling: + for (Loop loop : loops) { + // System.out.println("Peel loop : " + loop.loopBegin()); + for (Node exit : loop.exits()) { + if (!(exit instanceof StateSplit) || ((StateSplit) exit).stateAfter() == null) { + // TODO (gd) can not do loop peeling if an exit has no state. see LoopUtil.findNearestMergableExitPoint + continue peeling; + } + } + LoopUtil.peelLoop(loop); + } + } else { +// loops = LoopUtil.computeLoops(graph); // TODO (gd) avoid recomputing loops + for (Loop loop : loops) { + doLoopCounters(loop); + } } } diff -r a4b0c3df7f80 -r 5c696a58e692 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java Fri Jul 01 19:39:14 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java Fri Jul 01 19:39:29 2011 +0200 @@ -408,7 +408,11 @@ } } + int cnt = 0; while (!workList.isEmpty()) { + if (cnt++ > blocks.size() * 10) { + throw new RuntimeException("(ls) endless loop in computeDominators?"); + } Block b = workList.remove(); List predecessors = b.getPredecessors(); diff -r a4b0c3df7f80 -r 5c696a58e692 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java Fri Jul 01 19:39:14 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java Fri Jul 01 19:39:29 2011 +0200 @@ -76,17 +76,19 @@ private static class PeelingResult { public final FixedNode begin; public final FixedNode end; - public final NodeMap exits; + public final NodeMap exits; + public final NodeBitMap unaffectedExits; public final NodeMap phis; public final NodeMap phiInits; public final NodeMap dataOut; - public PeelingResult(FixedNode begin, FixedNode end, NodeMap exits, NodeMap phis, NodeMap phiInits, NodeMap dataOut) { + public PeelingResult(FixedNode begin, FixedNode end, NodeMap exits, NodeMap phis, NodeMap phiInits, NodeMap dataOut, NodeBitMap unaffectedExits) { this.begin = begin; this.end = end; this.exits = exits; this.phis = phis; this.phiInits = phiInits; this.dataOut = dataOut; + this.unaffectedExits = unaffectedExits; } } @@ -230,7 +232,7 @@ return loopNodes; } - public static void ifDoWhileTransform(Loop loop, If split) { + public static void inverseLoop(Loop loop, If split) { assert loop.nodes().isMarked(split); FixedNode noExit = split.trueSuccessor(); FixedNode exit = split.falseSuccessor(); @@ -284,6 +286,7 @@ parent.exits = computeLoopExits(parent.loopBegin, parent.nodes); parent = parent.parent; } + GraalMetrics.LoopsPeeled++; } private static void rewirePeeling(PeelingResult peeling, Loop loop, FixedNode from) { @@ -329,79 +332,64 @@ } NodeMap> newExitValues = graph.createNodeMap(); List exitPoints = new LinkedList(); - for (Node exit : loop.exits()) { + for (Node exit : peeling.unaffectedExits) { exitPoints.add(exit); } - for (Entry entry : peeling.exits.entries()) { - Placeholder original = (Placeholder) entry.getKey(); - Placeholder newExit = entry.getValue(); - FixedNode next = original.next(); + for (Entry entry : peeling.exits.entries()) { + StateSplit original = (StateSplit) entry.getKey(); + StateSplit newExit = entry.getValue(); EndNode oEnd = new EndNode(graph); EndNode nEnd = new EndNode(graph); Merge merge = new Merge(graph); - merge.setNext(next); FrameState newState = newExit.stateAfter(); merge.addEnd(nEnd); - merge.setStateAfter(newState); - //newState.merge(merge, original.stateAfter()); merge.addEnd(oEnd); + merge.setStateAfter(newState.duplicate(newState.bci)); + merge.setNext(original.next()); original.setNext(oEnd); - newExit.setStateAfter(null); - newExit.replaceAndDelete(nEnd); - - exitPoints.add(nEnd); + newExit.setNext(nEnd); + exitPoints.add(original); + exitPoints.add(newExit); } - for (Entry entry : peeling.exits.entries()) { - Placeholder original = (Placeholder) entry.getKey(); + for (Entry entry : peeling.exits.entries()) { + StateSplit original = (StateSplit) entry.getKey(); EndNode oEnd = (EndNode) original.next(); Merge merge = oEnd.merge(); EndNode nEnd = merge.endAt(1 - merge.phiPredecessorIndex(oEnd)); FrameState newState = merge.stateAfter(); - NodeArray oInputs = original.stateAfter().inputs(); - NodeArray nInputs = newState.inputs(); - int oSize = oInputs.size(); - for (int i = 0; i < oSize; i++) { - Node newValue = nInputs.get(i); - Node originalValue = oInputs.get(i); - if (newValue != originalValue) { - NodeMap phiMap = newExitValues.get(originalValue); - if (phiMap == null) { - phiMap = graph.createNodeMap(); - newExitValues.set(originalValue, phiMap); - } - phiMap.set(original, (Value) originalValue); - phiMap.set(nEnd, (Value) newValue); + FrameState originalState = original.stateAfter(); + while (newState != null) { + assert originalState != null; + NodeArray oInputs = originalState.inputs(); + NodeArray nInputs = newState.inputs(); + int oSize = oInputs.size(); + for (int i = 1; i < oSize; i++) { // TODO (gd) start from 1 to avoid outer framestate, hacky.. + Node newValue = nInputs.get(i); + Node originalValue = oInputs.get(i); + if (newValue != originalValue) { + Node newExit = nEnd.singlePredecessor(); + NodeMap phiMap = newExitValues.get(originalValue); + if (phiMap == null) { + phiMap = graph.createNodeMap(); + newExitValues.set(originalValue, phiMap); + } + phiMap.set(original, (Value) originalValue); + phiMap.set(newExit, (Value) newValue); - phiMap = newExitValues.get(newValue); - if (phiMap == null) { - phiMap = graph.createNodeMap(); - newExitValues.set(newValue, phiMap); + phiMap = newExitValues.get(newValue); + if (phiMap == null) { + phiMap = graph.createNodeMap(); + newExitValues.set(newValue, phiMap); + } + phiMap.set(original, (Value) originalValue); + phiMap.set(nEnd, (Value) newValue); } - phiMap.set(original, (Value) originalValue); - phiMap.set(nEnd, (Value) newValue); } + newState = newState.outerFrameState(); + originalState = originalState.outerFrameState(); } - /*Placeholder original = (Placeholder) entry.getKey(); - Merge merge = ((EndNode) original.next()).merge(); - FrameState newState = merge.stateAfter(); - NodeArray oInputs = original.stateAfter().inputs(); - NodeArray nInputs = newState.inputs(); - int oSize = oInputs.size(); - for (int i = 0; i < oSize; i++) { - Node newValue = nInputs.get(i); - Node originalValue = oInputs.get(i); - if (newValue != originalValue && newValue instanceof Phi) { - Phi newPhi = (Phi) newValue; - assert newPhi.valueAt(1) == originalValue; - NodeMap phiMap = newExitValues.get(originalValue); - if (phiMap == null) { - phiMap = graph.createNodeMap(); - newExitValues.set(originalValue, phiMap); - } - phiMap.set(merge, newPhi); - } - }*/ + assert originalState == null; } for (Entry> entry : newExitValues.entries()) { Value original = (Value) entry.getKey(); @@ -567,15 +555,16 @@ clearWithState(loopBegin, marked); Map replacements = new HashMap(); NodeMap phis = graph.createNodeMap(); - NodeMap exits = graph.createNodeMap(); - + NodeMap exits = graph.createNodeMap(); + NodeBitMap unaffectedExits = graph.createNodeBitMap(); + NodeBitMap clonedExits = graph.createNodeBitMap(); for (Node exit : loop.exits()) { if (marked.isMarked(exit.singlePredecessor())) { - Placeholder pExit = (Placeholder) exit; - marked.mark(pExit.stateAfter()); - Placeholder p = new Placeholder(graph); - replacements.put(exit, p); - exits.set(exit, p); + StateSplit pExit = findNearestMergableExitPoint(exit, marked); + markWithState(pExit, marked); + clonedExits.mark(pExit); + } else { + unaffectedExits.mark(exit); } } @@ -587,7 +576,7 @@ marked.clear(n); } for (Node input : n.dataInputs()) { - if (!marked.isMarked(input) && (!(input instanceof Phi) || ((Phi) input).merge() != loopBegin)) { + if (!marked.isMarked(input) && (!(input instanceof Phi) || ((Phi) input).merge() != loopBegin) && replacements.get(input) == null) { replacements.put(input, input); } } @@ -602,6 +591,10 @@ Map duplicates = graph.addDuplicate(marked, replacements); + for (Node n : clonedExits) { + exits.set(n, (StateSplit) duplicates.get(n)); + } + NodeMap dataOut = graph.createNodeMap(); for (Node n : marked) { for (Node usage : n.dataUsages()) { @@ -628,7 +621,12 @@ FixedNode newBegin = (FixedNode) duplicates.get(loopBegin.next()); FixedNode newFrom = (FixedNode) duplicates.get(from == loopBegin.loopEnd() ? from.singlePredecessor() : from); - return new PeelingResult(newBegin, newFrom, exits, phis, phiInits, dataOut); + return new PeelingResult(newBegin, newFrom, exits, phis, phiInits, dataOut, unaffectedExits); + } + + private static StateSplit findNearestMergableExitPoint(Node exit, NodeBitMap marked) { + // TODO (gd) find appropriate point : will be useful if a loop exit goes "up" as a result of making a branch dead in the loop body + return (StateSplit) exit; } private static NodeBitMap inOrBefore(Loop loop) { @@ -686,8 +684,9 @@ map.mark(n); if (n instanceof StateSplit) { FrameState stateAfter = ((StateSplit) n).stateAfter(); - if (stateAfter != null) { + while (stateAfter != null) { map.mark(stateAfter); + stateAfter = stateAfter.outerFrameState(); } } } @@ -696,8 +695,9 @@ map.clear(n); if (n instanceof StateSplit) { FrameState stateAfter = ((StateSplit) n).stateAfter(); - if (stateAfter != null) { + while (stateAfter != null) { map.clear(stateAfter); + stateAfter = stateAfter.outerFrameState(); } } } diff -r a4b0c3df7f80 -r 5c696a58e692 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java Fri Jul 01 19:39:14 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java Fri Jul 01 19:39:29 2011 +0200 @@ -469,15 +469,31 @@ public void forEachLiveStateValue(ValueProcedure proc) { for (int i = 0; i < valuesSize(); i++) { Value value = valueAt(i); - if (value != null) { - proc.doValue(value); - } + visitLiveStateValue(value, proc); } if (outerFrameState() != null) { outerFrameState().forEachLiveStateValue(proc); } } + private void visitLiveStateValue(Value value, ValueProcedure proc) { + if (value != null) { + if (value instanceof VirtualObject) { + HashSet fields = new HashSet(); + VirtualObject obj = (VirtualObject) value; + do { + if (!fields.contains(obj.field().representation())) { + fields.add(obj.field().representation()); + visitLiveStateValue(obj.input(), proc); + } + obj = obj.object(); + } while (obj != null); + } else { + proc.doValue(value); + } + } + } + @Override public String toString() { return super.toString(); diff -r a4b0c3df7f80 -r 5c696a58e692 src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardGroupOrganizer.java --- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardGroupOrganizer.java Fri Jul 01 19:39:14 2011 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardGroupOrganizer.java Fri Jul 01 19:39:29 2011 +0200 @@ -51,7 +51,7 @@ List children = new ArrayList(); children.add(g); if(g.getGraphs().size() == 1) { - g.getGraphs().get(0).setName(g.getName() + " / " + g.getGraphs().get(0).getName()); + //g.getGraphs().get(0).setName(g.getName() + " / " + g.getGraphs().get(0).getName()); result.add(new Pair>("", children)); } else { Pair> p = new Pair>();