changeset 12417:0b71e8b6418c

preliminary fix for MonitorExitNodes with AFTER_BCI
author Lukas Stadler <lukas.stadler@jku.at>
date Tue, 15 Oct 2013 11:31:23 +0200
parents 9ad59f7fd57e
children 8c53ba3efbc9
files graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java
diffstat 2 files changed, 29 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- 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;
--- 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();
+            }
         }
     }
 }