# HG changeset patch # User Thomas Wuerthinger # Date 1309567564 -7200 # Node ID 4b63eb1197ca2abe578a9574112e518e577a9020 # Parent 5aeb62416609ca5eda0f0d84e0e5b3716ca200e6 Various fixes around escape analysis. diff -r 5aeb62416609 -r 4b63eb1197ca 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 21:07:29 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Sat Jul 02 02:46:04 2011 +0200 @@ -153,8 +153,8 @@ public static boolean CommentedAssembly = ____; public static boolean PrintLIRWithAssembly = ____; - public static boolean OptGVN = true; + public static boolean OptGVN = ____; public static boolean OptCanonicalizer = true; - public static boolean OptLoops = true; + public static boolean OptLoops = ____; public static boolean LoopPeeling = ____; } diff -r 5aeb62416609 -r 4b63eb1197ca 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 21:07:29 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java Sat Jul 02 02:46:04 2011 +0200 @@ -1914,12 +1914,6 @@ assert values[i] != null : type + "." + escapeFields[i]; } - if (GraalOptions.PrintEscapeAnalysis) { - for (int i = 0; i < values.length; i++) { - TTY.println("field " + escapeFields[i].name() + " offset=" + values[i]); - } - } - return CiVirtualObject.get(type, values, obj.id()); } diff -r 5aeb62416609 -r 4b63eb1197ca 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 21:07:29 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Sat Jul 02 02:46:04 2011 +0200 @@ -1613,6 +1613,9 @@ if (state == null) { return; } + + walkState(x, state.outerFrameState()); + for (int index = 0; index < state.stackSize(); index++) { Value value = state.stackAt(index); if (value != x) { diff -r 5aeb62416609 -r 4b63eb1197ca graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java Fri Jul 01 21:07:29 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java Sat Jul 02 02:46:04 2011 +0200 @@ -100,9 +100,13 @@ new DeadCodeEliminationPhase().apply(graph); } - if (GraalOptions.EscapeAnalysis/* && compilation.method.toString().contains("commonDominator")*/) { + if (GraalOptions.OptLoops) { + new LoopPhase().apply(graph); + } + + if (GraalOptions.EscapeAnalysis /*&& compilation.method.toString().contains("simplify")*/) { new EscapeAnalysisPhase(compilation, this).apply(graph); - new DeadCodeEliminationPhase().apply(graph); + // new DeadCodeEliminationPhase().apply(graph); new CanonicalizerPhase().apply(graph); new DeadCodeEliminationPhase().apply(graph); } @@ -110,12 +114,6 @@ if (GraalOptions.OptGVN) { new GlobalValueNumberingPhase().apply(graph); } -// -// new EscapeAnalysisPhase().apply(graph); - - if (GraalOptions.OptLoops) { - new LoopPhase().apply(graph); - } if (GraalOptions.Lower) { new LoweringPhase(compilation.runtime).apply(graph); diff -r 5aeb62416609 -r 4b63eb1197ca graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java Fri Jul 01 21:07:29 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java Sat Jul 02 02:46:04 2011 +0200 @@ -85,11 +85,7 @@ @Override public boolean valueEqual(Node i) { - if (i instanceof ArrayLength) { - ArrayLength o = (ArrayLength) i; - return array() == o.array(); - } - return false; + return i instanceof ArrayLength; } @Override diff -r 5aeb62416609 -r 4b63eb1197ca graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java Fri Jul 01 21:07:29 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java Sat Jul 02 02:46:04 2011 +0200 @@ -185,6 +185,11 @@ } @Override + public String toString() { + return super.toString() + target; + } + + @Override public Map getDebugProperties() { Map properties = super.getDebugProperties(); properties.put("opcode", Bytecodes.nameOf(opcode)); diff -r 5aeb62416609 -r 4b63eb1197ca 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 21:07:29 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewArray.java Sat Jul 02 02:46:04 2011 +0200 @@ -214,10 +214,7 @@ if (current instanceof LoadIndexed) { LoadIndexed x = (LoadIndexed) current; if (x.array() == node) { - for (Node usage : new ArrayList(x.usages())) { - assert fieldState.get(field) != null; - usage.inputs().replace(x, fieldState.get(field)); - } + x.replaceAtUsages(fieldState.get(field)); assert x.usages().size() == 0; x.replaceAndDelete(x.next()); } @@ -226,7 +223,10 @@ if (x.array() == node) { fieldState.put(field, x.value()); assert x.usages().size() == 0; - x.replaceAndDelete(x.next()); + WriteMemoryCheckpointNode checkpoint = new WriteMemoryCheckpointNode(x.graph()); + checkpoint.setStateAfter(x.stateAfter()); + checkpoint.setNext(x.next()); + x.replaceAndDelete(checkpoint); return field; } } diff -r 5aeb62416609 -r 4b63eb1197ca 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 21:07:29 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java Sat Jul 02 02:46:04 2011 +0200 @@ -202,9 +202,7 @@ LoadField x = (LoadField) current; if (x.object() == node) { assert fieldState.get(field) != null : field + ", " + ((AccessField) current).field() + ((AccessField) current).field().hashCode(); - for (Node usage : new ArrayList(x.usages())) { - usage.inputs().replace(x, fieldState.get(field)); - } + x.replaceAtUsages(fieldState.get(field)); assert x.usages().size() == 0; x.replaceAndDelete(x.next()); } @@ -213,7 +211,10 @@ if (x.object() == node) { fieldState.put(field, x.value()); assert x.usages().size() == 0; - x.replaceAndDelete(x.next()); + WriteMemoryCheckpointNode checkpoint = new WriteMemoryCheckpointNode(x.graph()); + checkpoint.setStateAfter(x.stateAfter()); + checkpoint.setNext(x.next()); + x.replaceAndDelete(checkpoint); return field; } } diff -r 5aeb62416609 -r 4b63eb1197ca graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRAssembler.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRAssembler.java Fri Jul 01 21:07:29 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRAssembler.java Sat Jul 02 02:46:04 2011 +0200 @@ -212,6 +212,7 @@ void emitOp1(LIROp1 op) { switch (op.code) { case Move: + assert !op.operand().isIllegal(); if (op.moveKind() == LIROp1.LIRMoveKind.Volatile) { emitVolatileMove(op.operand(), op.result(), op.kind, op.info); } else { diff -r 5aeb62416609 -r 4b63eb1197ca graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java Fri Jul 01 21:07:29 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java Sat Jul 02 02:46:04 2011 +0200 @@ -28,6 +28,7 @@ import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.gen.*; import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.graph.*; @@ -98,6 +99,29 @@ endNode.replaceAndDelete(loop.next()); loop.delete(); } + } else if (node instanceof Merge) { + for (Node n : node.usages()) { + if (n instanceof Phi) { + Phi phi = (Phi) n; + if (phi.usages().size() == 1 && phi.usages().get(0) instanceof VirtualObject) { + // (tw) This VirtualObject instance is implicitely dead, because the CFG to it (i.e. the store that produced it) is dead! => fix this in escape analysis + VirtualObject virtualObject = (VirtualObject) phi.usages().get(0); + virtualObject.replaceAndDelete(virtualObject.object()); + } + } + } + } + + + if (IdentifyBlocksPhase.isFixed(node)) { + for (Node n : new ArrayList(node.usages())) { + if (n instanceof VirtualObject) { + // (tw) This VirtualObject instance is implicitely dead, because the CFG to it (i.e. the + // store that produced it) is dead! => fix this in Escape analysis + VirtualObject virtualObject = (VirtualObject) n; + virtualObject.replaceAndDelete(virtualObject.object()); + } + } } } } @@ -113,7 +137,28 @@ private void deleteNodes() { for (Node node : graph.getNodes()) { if (!flood.isMarked(node)) { - node.unsafeDelete(); + for (int i = 0; i < node.inputs().size(); i++) { + node.inputs().set(i, Node.Null); + } + for (int i = 0; i < node.successors().size(); i++) { + node.successors().set(i, Node.Null); + } + } + } + for (Node node : graph.getNodes()) { + if (!flood.isMarked(node)) { + if (node.predecessors().size() > 0) { + for (Node pred : node.predecessors()) { + TTY.println("!PRED! " + pred + " (" + flood.isMarked(pred) + ")"); + for (int i=0; isucc: " + pred.successors().get(i)); + } + for (int i=0; iusage: " + pred.usages().get(i)); + } + } + } + node.delete(); } } } diff -r 5aeb62416609 -r 4b63eb1197ca 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 21:07:29 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java Sat Jul 02 02:46:04 2011 +0200 @@ -104,11 +104,6 @@ BlockExitState state = new BlockExitState(); if (/*block == startBlock ||*/ block.getPredecessors().size() == 0) { state.obj = null; - for (EscapeField field : fields.values()) { - Constant value = Constant.defaultForKind(field.kind(), graph); - state.fieldState.put(field, value); - state.obj = new VirtualObject(state.obj, value, field, type, escapeFields, graph); - } } else { List predecessors = block.getPredecessors(); Set mergedFields = new HashSet(); @@ -119,6 +114,7 @@ for (int i = 0; i < predecessors.size(); i++) { BlockExitState exitState = exitStates.get(predecessors.get(i)); if (exitState == null) { + // (tw) What about an object that is allocated in a loop. We are merging in the values of the old allocation?; Now solved by "if" below. mergedFields.addAll(fields.values()); state.obj = null; break; @@ -126,12 +122,23 @@ for (EscapeField field : fields.values()) { if (state.fieldState.get(field) == null) { state.fieldState.put(field, exitState.fieldState.get(field)); + if (i != 0) { + // We need to merge this field too! + mergedFields.add(field); + } } else if (state.fieldState.get(field) != exitState.fieldState.get(field)) { mergedFields.add(field); } } } } + if (block.firstNode() instanceof LoopBegin) { + if (predState.obj == null) { + state.obj = null; + mergedFields.clear(); + } + } + if (!mergedFields.isEmpty()) { assert block.firstNode() instanceof Merge : "unexpected: " + block.firstNode().shortName() + " " + block.firstNode().id(); for (EscapeField field : mergedFields) { @@ -151,15 +158,24 @@ } while (current != block.lastNode()) { Node next = ((FixedNodeWithNext) current).next(); - 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); + FrameState stateAfter = null; + if (current instanceof StateSplit) { + stateAfter = ((StateSplit) current).stateAfter(); } - if (!current.isDeleted() && current instanceof StateSplit) { - FrameState stateAfter = ((StateSplit) current).stateAfter(); - if (stateAfter != null) { - updateFrameState(stateAfter, state.obj); + if (current == node) { + for (EscapeField field : fields.values()) { + Constant value = Constant.defaultForKind(field.kind(), graph); + state.fieldState.put(field, value); + state.obj = new VirtualObject(state.obj, value, field, type, escapeFields, graph); } + } else { + 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 (stateAfter != null) { + updateFrameState(stateAfter, state.obj); } current = next; } @@ -187,13 +203,12 @@ BlockExitState exitState = exitStates.get(predecessors.get(i)); if (exitState.fieldState.get(field) != simple) { simple = null; + break; } } if (simple != null) { - for (Node usage : new ArrayList(phi.usages())) { - usage.inputs().replace(phi, simple); - } - phi.delete(); + // (tw) Should never be reached, because Phi verification fails here.. + phi.replaceAndDelete(simple); } else { for (int i = 0; i < predecessors.size(); i++) { BlockExitState exitState = exitStates.get(predecessors.get(i)); @@ -212,8 +227,14 @@ } // the rest of the usages should be dead frame states... for (Node usage : new ArrayList(node.usages())) { - assert usage instanceof FrameState || usage instanceof VirtualObject : "usage: " + usage; - usage.inputs().replace(node, Node.Null); + if (usage instanceof IsNonNull) { + usage.replaceAndDelete(Constant.forBoolean(true, graph)); + } else if (usage instanceof RegisterFinalizer) { + usage.replaceAndDelete(((RegisterFinalizer) usage).next()); + } else { + assert usage instanceof FrameState || usage instanceof VirtualObject : "usage: " + usage; + usage.inputs().replace(node, Node.Null); + } } if (node instanceof FixedNodeWithNext) { @@ -223,14 +244,14 @@ } } - private VirtualObject updateFrameState(FrameState frameState, VirtualObject current) { + private void updateFrameState(FrameState frameState, VirtualObject current) { for (int i = 0; i < frameState.inputs().size(); i++) { if (frameState.inputs().get(i) == node) { frameState.inputs().set(i, current); } else if (frameState.inputs().get(i) instanceof VirtualObject) { VirtualObject obj = (VirtualObject) frameState.inputs().get(i); do { - current = updateVirtualObject(obj, current); + updateVirtualObject(obj, current); obj = obj.object(); } while (obj != null); } @@ -243,26 +264,27 @@ duplicate = true; } } + // (tw) need to fully duplicate also if there is a reference to "node" in an outer framestate? + duplicate = true; if (duplicate) { outer = outer.duplicate(outer.bci); frameState.setOuterFrameState(outer); } - current = updateFrameState(outer, current); + updateFrameState(outer, current); } - return current; } - private VirtualObject updateVirtualObject(VirtualObject obj, VirtualObject current) { + private void updateVirtualObject(VirtualObject obj, VirtualObject current) { if (obj.input() == node) { + // (tw) don't we have similar issues here like in framestate dup? We are updating a shared data structure here.. obj.setInput(current); } else if (obj.input() instanceof VirtualObject) { VirtualObject obj2 = (VirtualObject) obj.input(); do { - current = updateVirtualObject(obj2, current); + updateVirtualObject(obj2, current); obj2 = obj2.object(); } while (obj2 != null); } - return current; } private void process() { @@ -283,9 +305,9 @@ @Override protected void run(Graph graph) { -// if (compilation.method.holder().name().contains("oracle")) { -// return; -// } + if (compilation.method.name().contains("removeEnd") || compilation.method.name().contains("emitCode")) { + return; + } for (Node node : graph.getNodes()) { EscapeOp op = node.lookup(EscapeOp.class); if (op != null && op.canAnalyze(node)) { diff -r 5aeb62416609 -r 4b63eb1197ca 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 21:07:29 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java Sat Jul 02 02:46:04 2011 +0200 @@ -124,8 +124,9 @@ // Either dead code or at a merge node => stop iteration. break; } + Node prev = currentNode; currentNode = currentNode.singlePredecessor(); - assert !currentNode.isDeleted(); + assert !currentNode.isDeleted() : prev + " " + currentNode; } } } diff -r 5aeb62416609 -r 4b63eb1197ca 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 21:07:29 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java Sat Jul 02 02:46:04 2011 +0200 @@ -129,8 +129,9 @@ * Gets a copy of this frame state. */ public FrameState duplicate(int bci) { - FrameState other = copy(bci); + FrameState other = new FrameState(method, bci, localsSize, stackSize, locksSize, rethrowException, graph()); other.inputs().setAll(inputs()); + other.setOuterFrameState(outerFrameState()); return other; } @@ -532,11 +533,6 @@ out.print("FrameState"); } - - private FrameState copy(int newBci) { - return new FrameState(method, newBci, localsSize, stackSize, locksSize, rethrowException, graph()); - } - @Override public String shortName() { return "FrameState@" + bci; diff -r 5aeb62416609 -r 4b63eb1197ca runavrora.sh --- a/runavrora.sh Fri Jul 01 21:07:29 2011 +0200 +++ b/runavrora.sh Sat Jul 02 02:46:04 2011 +0200 @@ -15,6 +15,6 @@ echo "DACAPO is not defined. It must point to a Dacapo benchmark directory." exit 1; fi -COMMAND="${JDK7}/bin/java -client -d64 -graal -Xms1g -Xmx2g -esa -classpath ${DACAPO}/dacapo-9.12-bach.jar -XX:-GraalBailoutIsFatal -G:-QuietBailout $* Harness --preserve -n 5 avrora" +COMMAND="${JDK7}/bin/java -client -d64 -graal -Xms1g -Xmx2g -esa -classpath ${DACAPO}/dacapo-9.12-bach.jar -XX:-GraalBailoutIsFatal -G:-QuietBailout $* Harness --preserve -n 20 avrora" echo $COMMAND $COMMAND diff -r 5aeb62416609 -r 4b63eb1197ca runjython.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/runjython.sh Sat Jul 02 02:46:04 2011 +0200 @@ -0,0 +1,20 @@ +#!/bin/bash +if [ -z "${JDK7}" ]; then + echo "JDK7 is not defined." + exit 1; +fi +if [ -z "${MAXINE}" ]; then + echo "MAXINE is not defined. It must point to a maxine repository directory." + exit 1; +fi +if [ -z "${GRAAL}" ]; then + echo "GRAAL is not defined. It must point to a maxine repository directory." + exit 1; +fi +if [ -z "${DACAPO}" ]; then + echo "DACAPO is not defined. It must point to a Dacapo benchmark directory." + exit 1; +fi +COMMAND="${JDK7}/bin/java -client -d64 -graal -Xms1g -Xmx2g -esa -classpath ${DACAPO}/dacapo-9.12-bach.jar -XX:-GraalBailoutIsFatal -G:-QuietBailout $* Harness --preserve -n 20 jython" +echo $COMMAND +$COMMAND diff -r 5aeb62416609 -r 4b63eb1197ca src/share/vm/runtime/deoptimization.cpp --- a/src/share/vm/runtime/deoptimization.cpp Fri Jul 01 21:07:29 2011 +0200 +++ b/src/share/vm/runtime/deoptimization.cpp Sat Jul 02 02:46:04 2011 +0200 @@ -889,6 +889,9 @@ KlassHandle k(((ConstantOopReadValue*) sv->klass())->value()()); Handle obj = sv->value(); assert(obj.not_null(), "reallocation was missed"); + if (TraceDeoptimization) { + tty->print_cr("reassign fields for object of type %s!", k->name()->as_C_string()); + } if (k->oop_is_instance()) { instanceKlass* ik = instanceKlass::cast(k());