# HG changeset patch # User Lukas Stadler # Date 1309539637 -7200 # Node ID c3573103764ec3119cf3ab7fe486ed61b9512351 # Parent 883c2f14e7d0869578ae6c598af555afc919ea75 escape analysis debug info fixes diff -r 883c2f14e7d0 -r c3573103764e 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 18:37:54 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Fri Jul 01 19:00:37 2011 +0200 @@ -58,6 +58,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 = ____; diff -r 883c2f14e7d0 -r c3573103764e 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 18:37:54 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java Fri Jul 01 19:00:37 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 883c2f14e7d0 -r c3573103764e 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 18:37:54 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java Fri Jul 01 19:00:37 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 883c2f14e7d0 -r c3573103764e 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 18:37:54 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Fri Jul 01 19:00:37 2011 +0200 @@ -1624,10 +1624,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 883c2f14e7d0 -r c3573103764e 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 18:37:54 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewArray.java Fri Jul 01 19:00:37 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 883c2f14e7d0 -r c3573103764e 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 18:37:54 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java Fri Jul 01 19:00:37 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 883c2f14e7d0 -r c3573103764e 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 18:37:54 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java Fri Jul 01 19:00:37 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 883c2f14e7d0 -r c3573103764e 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 18:37:54 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java Fri Jul 01 19:00:37 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 883c2f14e7d0 -r c3573103764e 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 18:37:54 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java Fri Jul 01 19:00:37 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 883c2f14e7d0 -r c3573103764e 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 18:37:54 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java Fri Jul 01 19:00:37 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();