# HG changeset patch # User Lukas Stadler # Date 1381829483 -7200 # Node ID 0b71e8b6418c677aeef2635938ff012a72442900 # Parent 9ad59f7fd57e871f6017f7e959f58a10eacebc11 preliminary fix for MonitorExitNodes with AFTER_BCI diff -r 9ad59f7fd57e -r 0b71e8b6418c graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Oct 14 19:46:29 2013 -0700 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Oct 15 11:31:23 2013 +0200 @@ -1218,12 +1218,12 @@ return monitorEnter; } - private MonitorExitNode genMonitorExit(ValueNode x) { + private MonitorExitNode genMonitorExit(ValueNode x, ValueNode returnValue) { ValueNode lockedObject = frameState.popLock(); if (GraphUtil.originalValue(lockedObject) != GraphUtil.originalValue(x)) { throw new BailoutException("unbalanced monitors: mismatch at monitorexit, %s != %s", GraphUtil.originalValue(x), GraphUtil.originalValue(lockedObject)); } - MonitorExitNode monitorExit = append(new MonitorExitNode(x, frameState.lockDepth())); + MonitorExitNode monitorExit = append(new MonitorExitNode(x, returnValue, frameState.lockDepth())); return monitorExit; } @@ -1619,7 +1619,7 @@ assert frameState.stackSize() == 1 : frameState; ValueNode exception = frameState.apop(); append(new FixedGuardNode(currentGraph.unique(new IsNullNode(exception)), NullCheckException, InvalidateReprofile, true)); - synchronizedEpilogue(FrameState.AFTER_EXCEPTION_BCI); + synchronizedEpilogue(FrameState.AFTER_EXCEPTION_BCI, null); append(new UnwindNode(exception)); } @@ -1628,7 +1628,7 @@ ValueNode x = returnKind == Kind.Void ? null : frameState.pop(returnKind); assert frameState.stackSize() == 0; - synchronizedEpilogue(FrameState.AFTER_BCI); + synchronizedEpilogue(FrameState.AFTER_BCI, x); if (frameState.lockDepth() != 0) { throw new BailoutException("unbalanced monitors"); } @@ -1640,9 +1640,9 @@ append(new ReturnNode(x)); } - private void synchronizedEpilogue(int bci) { + private void synchronizedEpilogue(int bci, ValueNode returnValue) { if (Modifier.isSynchronized(method.getModifiers())) { - MonitorExitNode monitorExit = genMonitorExit(methodSynchronizedObject); + MonitorExitNode monitorExit = genMonitorExit(methodSynchronizedObject, returnValue); monitorExit.setStateAfter(frameState.create(bci)); assert !frameState.rethrowException(); } @@ -2002,7 +2002,7 @@ case CHECKCAST : genCheckCast(); break; case INSTANCEOF : genInstanceOf(); break; case MONITORENTER : genMonitorEnter(frameState.apop()); break; - case MONITOREXIT : genMonitorExit(frameState.apop()); break; + case MONITOREXIT : genMonitorExit(frameState.apop(), null); break; case MULTIANEWARRAY : genNewMultiArray(stream.readCPI()); break; case IFNULL : genIfNull(Condition.EQ); break; case IFNONNULL : genIfNull(Condition.NE); break; diff -r 9ad59f7fd57e -r 0b71e8b6418c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Mon Oct 14 19:46:29 2013 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Tue Oct 15 11:31:23 2013 +0200 @@ -34,17 +34,24 @@ public final class MonitorExitNode extends AccessMonitorNode implements Virtualizable, Lowerable, IterableNodeType, MonitorExit, MemoryCheckpoint.Single, MonitorReference { private int lockDepth; + @Input private ValueNode escapedReturnValue; /** * Creates a new MonitorExitNode. * * @param object the instruction produces the object value */ - public MonitorExitNode(ValueNode object, int lockDepth) { + public MonitorExitNode(ValueNode object, ValueNode escapedReturnValue, int lockDepth) { super(object); + this.escapedReturnValue = escapedReturnValue; this.lockDepth = lockDepth; } + public void setEscapedReturnValue(ValueNode x) { + updateUsages(escapedReturnValue, x); + this.escapedReturnValue = x; + } + @Override public LocationIdentity getLocationIdentity() { return LocationIdentity.ANY_LOCATION; @@ -65,11 +72,20 @@ @Override public void virtualize(VirtualizerTool tool) { - State state = tool.getObjectState(object()); - if (state != null && state.getState() == EscapeState.Virtual && state.getVirtualObject().hasIdentity()) { - int removedLock = state.removeLock(); - assert removedLock == getLockDepth(); - tool.delete(); + /* + * The last MonitorExitNode of a synchronized method cannot be removed anyway, and we need + * it to materialize the return value. + * + * TODO: replace this with correct handling of AFTER_BCI frame states in the runtime. + */ + if (stateAfter().bci != FrameState.AFTER_BCI) { + setEscapedReturnValue(null); + State state = tool.getObjectState(object()); + if (state != null && state.getState() == EscapeState.Virtual && state.getVirtualObject().hasIdentity()) { + int removedLock = state.removeLock(); + assert removedLock == getLockDepth(); + tool.delete(); + } } } }