# HG changeset patch # User Gilles Duboscq # Date 1335521678 -7200 # Node ID a60d1ed97bd0cbbe9ad2defde967e4d4430de53b # Parent 46fb141ae20f503d614c43f017f5749db4fdd5b3 Fix a peeling-escape analysis related problem that was causin LinearScan bailouts (merge virtual chains when merging ends of the peeled code) LiveIn problems in LinearScan are back to GraalInternalError diff -r 46fb141ae20f -r a60d1ed97bd0 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Thu Apr 26 14:35:25 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Fri Apr 27 12:14:38 2012 +0200 @@ -846,7 +846,7 @@ TTY.println("startBlock-ID: " + startBlock.getId()); // bailout of if this occurs in product mode. - throw new CiBailout("liveIn set of first block must be empty"); + throw new GraalInternalError("liveIn set of first block must be empty"); } } diff -r 46fb141ae20f -r a60d1ed97bd0 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopTransformDataResolver.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopTransformDataResolver.java Thu Apr 26 14:35:25 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopTransformDataResolver.java Fri Apr 27 12:14:38 2012 +0200 @@ -29,6 +29,7 @@ import com.oracle.graal.graph.NodeClass.NodeClassIterator; import com.oracle.graal.graph.NodeClass.Position; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.PhiNode.PhiType; @@ -60,6 +61,7 @@ List newPhis = new LinkedList<>(); for (PhiNode phi : loopBegin.phis().snapshot()) { ValueNode first = null; + StructuredGraph graph = (StructuredGraph) loopBegin.graph(); if (loopBegin.loopEnds().count() == 1) { ValueNode b = phi.valueAt(loopBegin.loopEnds().first()); // back edge value first = prim(b); // corresponding value in the peel @@ -76,7 +78,7 @@ } } if (merge != null) { // found values of interest (backedge values that exist in the peel) - PhiNode firstPhi = loopBegin.graph().add(new PhiNode(phi.kind(), merge, phi.type())); + PhiNode firstPhi = graph.add(new PhiNode(phi.kind(), merge, phi.type())); for (EndNode end : merge.forwardEnds()) { LoopEndNode loopEnd = reverseEnds.get(end); ValueNode prim = prim(phi.valueAt(loopEnd)); @@ -85,10 +87,13 @@ } first = firstPhi; merge.stateAfter().replaceFirstInput(phi, firstPhi); // fix the merge's state after (see SuperBlock.mergeExits) + if (phi.type() == PhiType.Virtual) { + first = SuperBlock.mergeVirtualChain(graph, firstPhi, merge); + } } } if (first != null) { // create a new phi (we don't patch the old one since some usages of the old one may still be valid) - PhiNode newPhi = loopBegin.graph().add(new PhiNode(phi.kind(), loopBegin, phi.type())); + PhiNode newPhi = graph.add(new PhiNode(phi.kind(), loopBegin, phi.type())); newPhi.addInput(first); for (LoopEndNode end : loopBegin.orderedLoopEnds()) { newPhi.addInput(phi.valueAt(end)); diff -r 46fb141ae20f -r a60d1ed97bd0 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/SuperBlock.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/SuperBlock.java Thu Apr 26 14:35:25 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/SuperBlock.java Fri Apr 27 12:14:38 2012 +0200 @@ -185,8 +185,8 @@ replaceWith = phi; } else { assert vpn.type() == PhiType.Virtual; - VirtualObjectFieldNode vof = (VirtualObjectFieldNode) GraphUtil.unProxify(vpn); - VirtualObjectFieldNode newVof = (VirtualObjectFieldNode) GraphUtil.unProxify(newVpn); + ValueNode vof = GraphUtil.unProxify(vpn); + ValueNode newVof = GraphUtil.unProxify(newVpn); replaceWith = mergeVirtualChain(graph, vof, newVof, phi, earlyExit, newEarlyExit, merge); } } else { @@ -217,14 +217,14 @@ private static ValueNode mergeVirtualChain( StructuredGraph graph, - VirtualObjectFieldNode vof, - VirtualObjectFieldNode newVof, + ValueNode vof, + ValueNode newVof, PhiNode vPhi, BeginNode earlyExit, BeginNode newEarlyExit, MergeNode merge) { - VirtualObjectNode vObject = vof.object(); - assert newVof.object() == vObject; + VirtualObjectNode vObject = virtualObject(vof); + assert virtualObject(newVof) == vObject; ValueNode[] virtualState = virtualState(vof); ValueNode[] newVirtualState = virtualState(newVof); ValueNode chain = vPhi; @@ -250,8 +250,57 @@ return chain; } - private static ValueNode[] virtualState(VirtualObjectFieldNode vof) { - VirtualObjectNode vObj = vof.object(); + public static ValueNode mergeVirtualChain( + StructuredGraph graph, + PhiNode vPhi, + MergeNode merge) { + NodeInputList virtuals = vPhi.values(); + VirtualObjectNode vObject = virtualObject(virtuals.first()); + List virtualStates = new ArrayList<>(virtuals.size()); + for (ValueNode virtual : virtuals) { + virtualStates.add(virtualState(GraphUtil.unProxify(virtual))); + } + ValueNode chain = vPhi; + int stateLength = virtualStates.get(0).length; + for (int i = 0; i < stateLength; i++) { + ValueNode v = null; + boolean reconcile = false; + for (ValueNode[] state : virtualStates) { + if (v == null) { + v = state[i]; + } else if (v != state[i]) { + reconcile = true; + break; + } + assert v.kind() == state[i].kind(); + } + if (reconcile) { + PhiNode valuePhi = graph.add(new PhiNode(v.kind(), merge, PhiType.Value)); + for (ValueNode[] state : virtualStates) { + valuePhi.addInput(state[i]); + } + chain = graph.add(new VirtualObjectFieldNode(vObject, chain, valuePhi, i)); + } + } + return chain; + } + + private static VirtualObjectNode virtualObject(ValueNode vof) { + assert vof instanceof VirtualObjectFieldNode || (vof instanceof PhiNode && ((PhiNode) vof).type() == PhiType.Virtual) : vof; + ValueNode currentField = vof; + do { + if (currentField instanceof VirtualObjectFieldNode) { + return ((VirtualObjectFieldNode) currentField).object(); + } else { + assert currentField instanceof PhiNode && ((PhiNode) currentField).type() == PhiType.Virtual : currentField; + currentField = ((PhiNode) currentField).valueAt(0); + } + } while (currentField != null); + throw new GraalInternalError("Invalid virtual chain : cound not find virtual object from %s", vof); + } + + private static ValueNode[] virtualState(ValueNode vof) { + VirtualObjectNode vObj = virtualObject(vof); int fieldsCount = vObj.fieldsCount(); int dicovered = 0; ValueNode[] state = new ValueNode[fieldsCount];