# HG changeset patch # User Thomas Wuerthinger # Date 1367123126 -7200 # Node ID addc2a25d7279fad5f8d208f9a26590fdb9c522d # Parent ee8cd087a731982be16ffce174457269c6c3110f Implement merging of frame states if they differ at a merge that does not have its own frame state. diff -r ee8cd087a731 -r addc2a25d727 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java Sun Apr 28 02:03:34 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java Sun Apr 28 06:25:26 2013 +0200 @@ -24,6 +24,8 @@ import java.util.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; @@ -67,7 +69,8 @@ if (node instanceof DeoptimizingNode) { DeoptimizingNode deopt = (DeoptimizingNode) node; if (deopt.canDeoptimize() && deopt.getDeoptimizationState() == null) { - deopt.setDeoptimizationState(currentState.getFramestate()); + FrameState state = currentState.getFramestate(); + deopt.setDeoptimizationState(state); } } @@ -93,7 +96,7 @@ if (merge.stateAfter() != null) { return new FrameStateAssignmentState(merge.stateAfter()); } - return new FrameStateAssignmentState(singleFrameState(states)); + return new FrameStateAssignmentState(singleFrameState(merge, states)); } @Override @@ -125,15 +128,80 @@ return true; } - private static FrameState singleFrameState(List states) { - Iterator it = states.iterator(); - assert it.hasNext(); - FrameState first = it.next().getFramestate(); - while (it.hasNext()) { - if (first != it.next().getFramestate()) { + private static FrameState singleFrameState(MergeNode merge, List states) { + if (states.size() == 0) { + return null; + } + FrameState firstState = states.get(0).getFramestate(); + FrameState singleState = firstState; + if (singleState == null) { + return null; + } + int singleBci = singleState.bci; + for (int i = 1; i < states.size(); ++i) { + FrameState cur = states.get(i).getFramestate(); + if (cur == null) { return null; } + + if (cur != singleState) { + singleState = null; + } + + if (cur.bci != singleBci) { + singleBci = FrameState.INVALID_FRAMESTATE_BCI; + } + } - return first; + if (singleState != null) { + return singleState; + } + + if (singleBci != FrameState.INVALID_FRAMESTATE_BCI) { + FrameState outerState = firstState.outerFrameState(); + boolean duringCall = firstState.duringCall(); + boolean rethrowException = firstState.rethrowException(); + int stackSize = firstState.stackSize(); + int localsSize = firstState.localsSize(); + ResolvedJavaMethod method = firstState.method(); + FrameState newState = firstState.duplicate(); + for (int i = 1; i < states.size(); ++i) { + FrameState curState = states.get(i).getFramestate(); + assert curState.duringCall() == duringCall; + assert curState.rethrowException() == rethrowException; + assert curState.stackSize() == stackSize; + assert curState.localsSize() == localsSize; + assert curState.method() == method; + assert curState.outerFrameState() == outerState; + + for (int j = 0; j < localsSize + stackSize; ++j) { + ValueNode oldValue = newState.values().get(j); + ValueNode curValue = curState.values().get(j); + newState.values().set(j, merge(merge, oldValue, curValue, i)); + } + } + + Debug.log("Created artificial frame state with bci %d ", singleBci); + return newState; + } + return null; + } + + private static ValueNode merge(MergeNode merge, ValueNode oldValue, ValueNode newValue, int processedPreds) { + if (oldValue == newValue) { + return oldValue; + } + + if (oldValue instanceof PhiNode && ((PhiNode) oldValue).merge() == merge) { + ((PhiNode) oldValue).addInput(newValue); + return oldValue; + } else { + PhiNode newPhi = merge.graph().add(new PhiNode(oldValue.kind(), merge)); + for (int i = 0; i < processedPreds; ++i) { + newPhi.addInput(oldValue); + } + newPhi.addInput(newValue); + return newPhi; + } } }