changeset 11796:9c4c197aa6e8

Merge.
author Doug Simon <doug.simon@oracle.com>
date Wed, 25 Sep 2013 21:25:06 +0200
parents 56c3ec12a79c (current diff) 45e8bf81205d (diff)
children 65dbed1fdf46
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractCallNode.java
diffstat 30 files changed, 173 insertions(+), 116 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Wed Sep 25 21:25:06 2013 +0200
@@ -890,6 +890,6 @@
 
     @Override
     public void visitInfopointNode(InfopointNode i) {
-        append(new InfopointOp(stateFor(i.stateAfter(), DeoptimizationReason.None), i.reason));
+        append(new InfopointOp(stateFor(i.getState(), DeoptimizationReason.None), i.reason));
     }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Wed Sep 25 21:25:06 2013 +0200
@@ -122,7 +122,7 @@
         if (state.outerFrameState() != null) {
             caller = computeFrameForState(state.outerFrameState());
         }
-        assert state.bci != FrameState.UNKNOWN_BCI : "bci == " + state.bci;
+        assert state.bci >= FrameState.BEFORE_BCI : "bci == " + state.bci;
         return new BytecodeFrame(caller, state.method(), state.bci, state.rethrowException(), state.duringCall(), values, numLocals, numStack, numLocks);
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Sep 25 21:25:06 2013 +0200
@@ -616,7 +616,15 @@
 
     @Override
     public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) {
-        LIRFrameState state = !linkage.canDeoptimize() ? null : stateFor(info.getDeoptimizationState(), info.getDeoptimizationReason());
+        LIRFrameState state = null;
+        if (linkage.canDeoptimize()) {
+            if (info != null) {
+                state = stateFor(info.getDeoptimizationState(), info.getDeoptimizationReason());
+            } else {
+                assert needOnlyOopMaps();
+                state = new LIRFrameState(null, null, null, (short) -1);
+            }
+        }
 
         // move the arguments into the correct location
         CallingConvention linkageCc = linkage.getOutgoingCallingConvention();
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Sep 25 21:25:06 2013 +0200
@@ -36,6 +36,7 @@
 import com.oracle.graal.asm.amd64.AMD64Address.Scale;
 import com.oracle.graal.compiler.amd64.*;
 import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.CompareAndSwapCompressedOp;
@@ -242,7 +243,7 @@
         Variable result;
 
         if (linkage.canDeoptimize()) {
-            assert info != null;
+            assert info != null || stub != null;
             append(new AMD64HotSpotCRuntimeCallPrologueOp());
             result = super.emitForeignCall(linkage, info, args);
             append(new AMD64HotSpotCRuntimeCallEpilogueOp());
@@ -522,4 +523,13 @@
         append(new CondMoveOp(result, Condition.EQ, load(Constant.TRUE), Constant.FALSE));
         setResult(node, result);
     }
+
+    @Override
+    public void visitInfopointNode(InfopointNode i) {
+        if (i.getState() != null && i.getState().bci == FrameState.AFTER_BCI) {
+            Debug.log("Ignoring InfopointNode for AFTER_BCI");
+        } else {
+            super.visitInfopointNode(i);
+        }
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java	Wed Sep 25 21:25:06 2013 +0200
@@ -70,4 +70,8 @@
     public DeoptimizationReason getDeoptimizationReason() {
         return DeoptimizationReason.NullCheckException;
     }
+
+    public FrameState getState() {
+        return deoptimizationState;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java	Wed Sep 25 21:25:06 2013 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.hotspot.nodes;
 
 import com.oracle.graal.api.code.*;
-
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -35,11 +34,10 @@
  * Node for a {@linkplain ForeignCallDescriptor foreign} call from within a stub.
  */
 @NodeInfo(nameTemplate = "StubForeignCall#{p#descriptor/s}")
-public class StubForeignCallNode extends FixedWithNextNode implements DeoptimizingNode, LIRLowerable, MemoryCheckpoint.Multi {
+public class StubForeignCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Multi {
 
     @Input private final NodeInputList<ValueNode> arguments;
     private final MetaAccessProvider runtime;
-    @Input private FrameState deoptState;
 
     private final ForeignCallDescriptor descriptor;
 
@@ -72,7 +70,7 @@
         assert graph().start() instanceof StubStartNode;
         ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(descriptor);
         Value[] operands = operands(gen);
-        Value result = gen.emitForeignCall(linkage, this, operands);
+        Value result = gen.emitForeignCall(linkage, null, operands);
         if (result != null) {
             gen.setResult(this, result);
         }
@@ -85,23 +83,4 @@
         }
         return super.toString(verbosity);
     }
-
-    @Override
-    public boolean canDeoptimize() {
-        return false;
-    }
-
-    @Override
-    public FrameState getDeoptimizationState() {
-        return null;
-    }
-
-    @Override
-    public void setDeoptimizationState(FrameState state) {
-    }
-
-    @Override
-    public DeoptimizationReason getDeoptimizationReason() {
-        return null;
-    }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Sep 25 21:25:06 2013 +0200
@@ -216,17 +216,14 @@
             lastInstr = genMonitorEnter(methodSynchronizedObject);
         }
         frameState.clearNonLiveLocals(blockMap.startBlock.localsLiveIn);
+        ((StateSplit) lastInstr).setStateAfter(frameState.create(0));
 
         if (graphBuilderConfig.eagerInfopointMode()) {
-            ((StateSplit) lastInstr).setStateAfter(frameState.create(0));
-            InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.METHOD_START));
+            InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.METHOD_START, frameState.create(0)));
             lastInstr.setNext(ipn);
             lastInstr = ipn;
         }
 
-        // finish the start block
-        ((StateSplit) lastInstr).setStateAfter(frameState.create(0));
-
         currentBlock = blockMap.startBlock;
         blockMap.startBlock.entryState = frameState;
         if (blockMap.startBlock.isLoopHeader) {
@@ -1636,8 +1633,7 @@
         }
 
         if (graphBuilderConfig.eagerInfopointMode()) {
-            InfopointNode ipn = append(new InfopointNode(InfopointReason.METHOD_END));
-            ipn.setStateAfter(frameState.create(FrameState.AFTER_BCI));
+            append(new InfopointNode(InfopointReason.METHOD_END, frameState.create(FrameState.AFTER_BCI)));
         }
 
         append(new ReturnNode(x));
@@ -1752,8 +1748,7 @@
             if (graphBuilderConfig.eagerInfopointMode() && lnt != null) {
                 currentLineNumber = lnt.getLineNumber(bci);
                 if (currentLineNumber != previousLineNumber) {
-                    InfopointNode ipn = append(new InfopointNode(InfopointReason.LINE_NUMBER));
-                    ipn.setStateAfter(frameState.create(bci));
+                    append(new InfopointNode(InfopointReason.LINE_NUMBER, frameState.create(bci)));
                     previousLineNumber = currentLineNumber;
                 }
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java	Wed Sep 25 21:25:06 2013 +0200
@@ -185,4 +185,8 @@
             throw new UnsupportedOperationException();
         }
     }
+
+    public FrameState getState() {
+        return stateAfter();
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java	Wed Sep 25 21:25:06 2013 +0200
@@ -41,6 +41,10 @@
         stateAfter = x;
     }
 
+    public FrameState getState() {
+        return stateAfter();
+    }
+
     public boolean hasSideEffect() {
         return true;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Wed Sep 25 21:25:06 2013 +0200
@@ -86,4 +86,8 @@
     public DeoptimizationReason getDeoptimizationReason() {
         return reason;
     }
+
+    public FrameState getState() {
+        return deoptState;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Wed Sep 25 21:25:06 2013 +0200
@@ -42,4 +42,8 @@
         updateUsages(deoptState, f);
         deoptState = f;
     }
+
+    public FrameState getState() {
+        return deoptState;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java	Wed Sep 25 21:25:06 2013 +0200
@@ -23,11 +23,12 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.spi.*;
 
 /**
  * Interface implemented by nodes which need deoptimization information.
  */
-public interface DeoptimizingNode {
+public interface DeoptimizingNode extends NodeWithState {
 
     /**
      * Determines if this node needs deoptimization information.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Wed Sep 25 21:25:06 2013 +0200
@@ -29,13 +29,15 @@
 /**
  * Nodes of this type are inserted into the graph to denote points of interest to debugging.
  */
-public class InfopointNode extends AbstractStateSplit implements LIRLowerable {
+public class InfopointNode extends FixedWithNextNode implements LIRLowerable, NodeWithState {
 
     public final InfopointReason reason;
+    @Input private FrameState state;
 
-    public InfopointNode(InfopointReason reason) {
+    public InfopointNode(InfopointReason reason, FrameState state) {
         super(StampFactory.forVoid());
         this.reason = reason;
+        this.state = state;
     }
 
     @Override
@@ -43,24 +45,13 @@
         generator.visitInfopointNode(this);
     }
 
-    @Override
-    public boolean hasSideEffect() {
-        return false;
-    }
-
-    @Override
-    public void setStateAfter(FrameState state) {
-        // shield this node from frame state removal
-        // TODO turn InfopointNode into a FixedWithNextNode subclass with a self-maintained
-        // FrameState that is correctly dealt with by scheduling and partial escape analysis
-        if (state != null) {
-            super.setStateAfter(state);
-        }
+    public FrameState getState() {
+        return state;
     }
 
     @Override
     public boolean verify() {
-        return stateAfter() != null && super.verify();
+        return getState() != null && super.verify();
     }
 
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Wed Sep 25 21:25:06 2013 +0200
@@ -35,7 +35,7 @@
  * The {@code InvokeNode} represents all kinds of method calls.
  */
 @NodeInfo(nameTemplate = "Invoke#{p#targetMethod/s}")
-public final class InvokeNode extends AbstractStateSplit implements StateSplit, Invoke, LIRLowerable, MemoryCheckpoint.Single {
+public final class InvokeNode extends AbstractStateSplit implements Invoke, LIRLowerable, MemoryCheckpoint.Single {
 
     @Input private CallTargetNode callTarget;
     @Input private FrameState deoptState;
@@ -203,4 +203,14 @@
         updateUsages(this.guard == null ? null : this.guard.asNode(), guard == null ? null : guard.asNode());
         this.guard = guard;
     }
+
+    @Override
+    public FrameState getState() {
+        if (deoptState != null) {
+            assert stateAfter() == null;
+            return deoptState;
+        } else {
+            return super.getState();
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Sep 25 21:25:06 2013 +0200
@@ -248,4 +248,14 @@
         updateUsages(this.guard == null ? null : this.guard.asNode(), guard == null ? null : guard.asNode());
         this.guard = guard;
     }
+
+    @Override
+    public FrameState getState() {
+        if (deoptState != null) {
+            assert stateAfter() == null;
+            return deoptState;
+        } else {
+            return stateAfter();
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StateSplit.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StateSplit.java	Wed Sep 25 21:25:06 2013 +0200
@@ -22,10 +22,12 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.nodes.spi.*;
+
 /**
  * A state split is a node that may have a frame state associated with it.
  */
-public interface StateSplit {
+public interface StateSplit extends NodeWithState {
 
     /**
      * Gets the state of the JVM frame after execution of this node.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractCallNode.java	Wed Sep 25 12:22:07 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.extended;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
-
-public abstract class AbstractCallNode extends AbstractStateSplit implements StateSplit {
-
-    @Input private final NodeInputList<ValueNode> arguments;
-
-    public AbstractCallNode(Stamp stamp, ValueNode[] arguments) {
-        super(stamp);
-        this.arguments = new NodeInputList<>(this, arguments);
-    }
-
-    public NodeInputList<ValueNode> arguments() {
-        return arguments;
-    }
-
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Wed Sep 25 21:25:06 2013 +0200
@@ -95,6 +95,10 @@
         return barrierType;
     }
 
+    public FrameState getState() {
+        return deoptState;
+    }
+
     @Override
     public boolean isCompressible() {
         return compressible;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Wed Sep 25 21:25:06 2013 +0200
@@ -133,4 +133,14 @@
     public DeoptimizationReason getDeoptimizationReason() {
         return null;
     }
+
+    @Override
+    public FrameState getState() {
+        if (deoptState != null) {
+            assert stateAfter() == null;
+            return deoptState;
+        } else {
+            return super.getState();
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Wed Sep 25 21:25:06 2013 +0200
@@ -107,6 +107,10 @@
         return unsafeStoreNode;
     }
 
+    public FrameState getState() {
+        return stateAfter;
+    }
+
     // specialized on value type until boxing/unboxing is sorted out in intrinsification
 
     @SuppressWarnings("unused")
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Wed Sep 25 21:25:06 2013 +0200
@@ -33,7 +33,7 @@
  * The Java bytecode specification allows non-balanced locking. Graal does not handle such cases and
  * throws a {@link BailoutException} instead during graph building.
  */
-public abstract class AccessMonitorNode extends AbstractStateSplit implements StateSplit, MemoryCheckpoint {
+public abstract class AccessMonitorNode extends AbstractStateSplit implements MemoryCheckpoint {
 
     @Input private ValueNode object;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Wed Sep 25 21:25:06 2013 +0200
@@ -34,7 +34,7 @@
  * Represents an atomic compare-and-swap operation The result is a boolean that contains whether the
  * value matched the expected value.
  */
-public class CompareAndSwapNode extends AbstractStateSplit implements StateSplit, Lowerable, MemoryCheckpoint.Single {
+public class CompareAndSwapNode extends AbstractStateSplit implements Lowerable, MemoryCheckpoint.Single {
 
     @Input private ValueNode object;
     @Input private ValueNode offset;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Wed Sep 25 21:25:06 2013 +0200
@@ -32,7 +32,7 @@
  * This node is used to perform the finalizer registration at the end of the java.lang.Object
  * constructor.
  */
-public final class RegisterFinalizerNode extends AbstractStateSplit implements StateSplit, Canonicalizable, LIRLowerable, Virtualizable, DeoptimizingNode {
+public final class RegisterFinalizerNode extends AbstractStateSplit implements Canonicalizable, LIRLowerable, Virtualizable, DeoptimizingNode {
 
     public static final ForeignCallDescriptor REGISTER_FINALIZER = new ForeignCallDescriptor("registerFinalizer", void.class, Object.class);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Wed Sep 25 21:25:06 2013 +0200
@@ -79,4 +79,8 @@
             }
         }
     }
+
+    public FrameState getState() {
+        return stateAfter;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Wed Sep 25 21:25:06 2013 +0200
@@ -81,4 +81,8 @@
             }
         }
     }
+
+    public FrameState getState() {
+        return stateAfter;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeWithState.java	Wed Sep 25 21:25:06 2013 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.spi;
+
+import com.oracle.graal.nodes.*;
+
+public interface NodeWithState {
+    FrameState getState();
+}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Wed Sep 25 21:25:06 2013 +0200
@@ -36,6 +36,7 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.graph.*;
@@ -785,7 +786,7 @@
                     if (!(usage instanceof FrameState)) {
                         throw new SchedulingError(usage.toString());
                     }
-                    if (!(unscheduledUsage instanceof StateSplit || unscheduledUsage instanceof DeoptimizingNode)) {
+                    if (!(unscheduledUsage instanceof NodeWithState)) {
                         throw new SchedulingError(unscheduledUsage.toString());
                     }
                     // Otherwise: Put the input into the same block as the usage.
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetFrameStateCleanupPhase.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetFrameStateCleanupPhase.java	Wed Sep 25 21:25:06 2013 +0200
@@ -57,7 +57,8 @@
                 StateSplit stateSplit = (StateSplit) node;
                 FrameState frameState = stateSplit.stateAfter();
                 if (frameState != null) {
-                    if (stateSplit.hasSideEffect()) {
+                    // the stateSplit == currentState case comes from merge handling
+                    if (stateSplit.hasSideEffect() || stateSplit == currentState) {
                         stateSplit.setStateAfter(createInvalidFrameState(node));
                         state = stateSplit;
                     } else if (hasInvalidState(state)) {
@@ -78,7 +79,19 @@
 
         @Override
         protected StateSplit merge(MergeNode merge, List<StateSplit> states) {
-            return merge;
+            boolean invalid = false;
+            for (StateSplit state : states) {
+                if (state != null && state.stateAfter() != null && state.stateAfter().bci == FrameState.INVALID_FRAMESTATE_BCI) {
+                    invalid = true;
+                    state.setStateAfter(merge.graph().add(new FrameState(FrameState.AFTER_BCI)));
+                }
+            }
+            if (invalid) {
+                // at the next processNode call, stateSplit == currentState == merge
+                return merge;
+            } else {
+                return null;
+            }
         }
 
         @Override
@@ -103,7 +116,8 @@
         }
 
         private static boolean hasInvalidState(StateSplit state) {
-            return state != null && state.stateAfter() != null && state.stateAfter().bci == FrameState.INVALID_FRAMESTATE_BCI;
+            assert state == null || (state.stateAfter() != null && state.stateAfter().bci == FrameState.INVALID_FRAMESTATE_BCI) : state + " " + state.stateAfter();
+            return state != null;
         }
 
         private static FrameState createInvalidFrameState(FixedNode node) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Wed Sep 25 21:25:06 2013 +0200
@@ -141,13 +141,11 @@
             if (call.targetMethod() != getTargetMethod()) {
                 throw new GraalInternalError("unexpected invoke %s in snippet", getClass().getSimpleName());
             }
-            if (invoke.stateAfter().bci == FrameState.INVALID_FRAMESTATE_BCI) {
-                InvokeNode newInvoke = snippetGraph.add(new InvokeNode(invoke.callTarget(), getBci()));
-                newInvoke.setStateAfter(snippetGraph.add(new FrameState(FrameState.AFTER_BCI)));
-                snippetGraph.replaceFixedWithFixed((InvokeNode) invoke.asNode(), newInvoke);
-            } else {
-                assert invoke.stateAfter().bci == FrameState.AFTER_BCI : invoke;
-            }
+            assert invoke.stateAfter().bci == FrameState.AFTER_BCI;
+            // Here we need to fix the bci of the invoke
+            InvokeNode newInvoke = snippetGraph.add(new InvokeNode(invoke.callTarget(), getBci()));
+            newInvoke.setStateAfter(invoke.stateAfter());
+            snippetGraph.replaceFixedWithFixed((InvokeNode) invoke.asNode(), newInvoke);
         }
     }
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Wed Sep 25 12:22:07 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Wed Sep 25 21:25:06 2013 +0200
@@ -111,13 +111,18 @@
             return !(node instanceof CommitAllocationNode || node instanceof AllocatedObjectNode);
         }
         if (isMarked) {
-            if (node instanceof StateSplit) {
-                StateSplit split = (StateSplit) node;
-                FrameState stateAfter = split.stateAfter();
+            if (node instanceof NodeWithState) {
+                NodeWithState nodeWithState = (NodeWithState) node;
+                FrameState stateAfter = nodeWithState.getState();
                 if (stateAfter != null) {
                     if (stateAfter.usages().count() > 1) {
-                        stateAfter = (FrameState) stateAfter.copyWithInputs();
-                        split.setStateAfter(stateAfter);
+                        if (nodeWithState instanceof StateSplit) {
+                            StateSplit split = (StateSplit) nodeWithState;
+                            stateAfter = (FrameState) stateAfter.copyWithInputs();
+                            split.setStateAfter(stateAfter);
+                        } else {
+                            throw GraalInternalError.shouldNotReachHere();
+                        }
                     }
                     final HashSet<ObjectState> virtual = new HashSet<>();
                     stateAfter.applyToNonVirtual(new NodeClosure<ValueNode>() {