changeset 14747:a836fed0e270

Merge
author Christian Wimmer <christian.wimmer@oracle.com>
date Tue, 25 Mar 2014 13:50:28 -0700
parents 7544068e1a91 (current diff) c5ee41cf9823 (diff)
children 483d05bf77a7 6b29befc7f38
files graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RawDataValue.java graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java
diffstat 40 files changed, 321 insertions(+), 376 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RawDataValue.java	Tue Mar 25 13:32:32 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2011, 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.api.code;
-
-import java.util.*;
-
-import com.oracle.graal.api.meta.*;
-
-/**
- * Represents some raw data.
- */
-public final class RawDataValue extends Value {
-
-    private static final long serialVersionUID = 7947228462156566360L;
-
-    private final byte[] data;
-
-    public RawDataValue(PlatformKind kind, byte[] data) {
-        super(kind);
-        this.data = data;
-    }
-
-    public byte[] getData() {
-        return data;
-    }
-
-    @Override
-    public String toString() {
-        Formatter ret = new Formatter();
-        ret.format("data[");
-        boolean first = true;
-        for (byte b : data) {
-            ret.format(first ? "%02X" : " %02X", b);
-            first = false;
-        }
-        return ret.format("]").toString();
-    }
-
-    @Override
-    public int hashCode() {
-        return Arrays.hashCode(data);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj instanceof RawDataValue) {
-            RawDataValue other = (RawDataValue) obj;
-            return Arrays.equals(data, other.data);
-        } else {
-            return false;
-        }
-    }
-}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java	Tue Mar 25 13:50:28 2014 -0700
@@ -90,16 +90,6 @@
         return ((RegisterValue) value).getRegister();
     }
 
-    public static boolean isRawData(Value value) {
-        assert value != null;
-        return value instanceof RawDataValue;
-    }
-
-    public static RawDataValue asRawData(Value value) {
-        assert value != null;
-        return (RawDataValue) value;
-    }
-
     public static Register asIntReg(Value value) {
         if (value.getKind() != Kind.Int) {
             throw new InternalError("needed Int got: " + value.getKind());
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Tue Mar 25 13:50:28 2014 -0700
@@ -60,6 +60,7 @@
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.ReturnOp;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.StrategySwitchOp;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.TableSwitchOp;
+import com.oracle.graal.lir.amd64.AMD64Move.LeaDataOp;
 import com.oracle.graal.lir.amd64.AMD64Move.LeaOp;
 import com.oracle.graal.lir.amd64.AMD64Move.ZeroExtendLoadOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MembarOp;
@@ -158,6 +159,10 @@
         append(createMove(dst, src));
     }
 
+    public void emitData(AllocatableValue dst, byte[] data) {
+        append(new LeaDataOp(dst, data));
+    }
+
     @Override
     public AMD64AddressValue emitAddress(Value base, long displacement, Value index, int scale) {
         AllocatableValue baseRegister;
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Tue Mar 25 13:50:28 2014 -0700
@@ -115,6 +115,10 @@
         }
     }
 
+    public void emitData(AllocatableValue dst, byte[] data) {
+        throw GraalInternalError.unimplemented();
+    }
+
     protected HSAILAddressValue asAddressValue(Value address) {
         if (address instanceof HSAILAddressValue) {
             return (HSAILAddressValue) address;
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Tue Mar 25 13:50:28 2014 -0700
@@ -208,6 +208,11 @@
     }
 
     @Override
+    public void emitData(AllocatableValue dst, byte[] data) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    @Override
     public PTXAddressValue emitAddress(Value base, long displacement, Value index, int scale) {
         AllocatableValue baseRegister;
         long finalDisp = displacement;
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Tue Mar 25 13:50:28 2014 -0700
@@ -132,6 +132,11 @@
     }
 
     @Override
+    public void emitData(AllocatableValue dst, byte[] data) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    @Override
     public SPARCAddressValue emitAddress(Value base, long displacement, Value index, int scale) {
         AllocatableValue baseRegister;
         long finalDisp = displacement;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Tue Mar 25 13:50:28 2014 -0700
@@ -368,18 +368,29 @@
         return false;
     }
 
+    private static FrameState getFrameState(DeoptimizingNode deopt) {
+        if (deopt instanceof DeoptimizingNode.DeoptBefore) {
+            return ((DeoptimizingNode.DeoptBefore) deopt).stateBefore();
+        } else if (deopt instanceof DeoptimizingNode.DeoptDuring) {
+            return ((DeoptimizingNode.DeoptDuring) deopt).stateDuring();
+        } else {
+            assert deopt instanceof DeoptimizingNode.DeoptAfter;
+            return ((DeoptimizingNode.DeoptAfter) deopt).stateAfter();
+        }
+    }
+
     public LIRFrameState state(DeoptimizingNode deopt) {
         if (!deopt.canDeoptimize()) {
             return null;
         }
-        return stateFor(deopt.getDeoptimizationState());
+        return stateFor(getFrameState(deopt));
     }
 
     public LIRFrameState stateWithExceptionEdge(DeoptimizingNode deopt, LabelRef exceptionEdge) {
         if (!deopt.canDeoptimize()) {
             return null;
         }
-        return stateForWithExceptionEdge(deopt.getDeoptimizationState(), exceptionEdge);
+        return stateForWithExceptionEdge(getFrameState(deopt), exceptionEdge);
     }
 
     public LIRFrameState stateFor(FrameState state) {
@@ -910,7 +921,7 @@
         LIRFrameState state = null;
         if (linkage.canDeoptimize()) {
             if (info != null) {
-                state = stateFor(info.getDeoptimizationState());
+                state = stateFor(getFrameState(info));
             } else {
                 assert needOnlyOopMaps();
                 state = new LIRFrameState(null, null, null);
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java	Tue Mar 25 13:50:28 2014 -0700
@@ -250,7 +250,7 @@
 
         ValueNode[] launchArgsArray = args.values().toArray(new ValueNode[args.size()]);
         ForeignCallNode result = append(new ForeignCallNode(providers.getForeignCalls(), CALL_KERNEL, launchArgsArray));
-        result.setDeoptimizationState(fs);
+        result.setStateAfter(fs);
 
         InvokeNode getObjectResult = null;
         ValueNode returnValue;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java	Tue Mar 25 13:50:28 2014 -0700
@@ -22,12 +22,11 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
 
 /**
@@ -43,17 +42,28 @@
     }
 
     public void generate(LIRGenerator gen) {
-        gen.setResult(this, gen.emitMove(new RawDataValue(gen.target().wordKind, toCString(string))));
+        gen.setResult(this, emitCString(gen, string));
+    }
+
+    public static AllocatableValue emitCString(LIRGeneratorTool gen, String value) {
+        AllocatableValue dst = gen.newVariable(gen.target().wordKind);
+        gen.emitData(dst, toCString(value));
+        return dst;
     }
 
     /**
-     * Converts a String to a null terminated byte array suitable for use as a C string value.
+     * Converts a string to a null terminated byte array of ASCII characters.
+     * 
+     * @param s a String that must only contain ASCII characters
      */
-    public static byte[] toCString(String value) {
-        byte[] bytes = value.getBytes();
-        byte[] nulTerminated = Arrays.copyOf(bytes, bytes.length + 1);
-        nulTerminated[bytes.length] = 0;
-        return nulTerminated;
+    public static byte[] toCString(String s) {
+        byte[] bytes = new byte[s.length() + 1];
+        for (int i = 0; i < s.length(); i++) {
+            assert s.charAt(i) < 128 : "non-ascii string: " + s;
+            bytes[i] = (byte) s.charAt(i);
+        }
+        bytes[s.length()] = 0;
+        return bytes;
     }
 
     @NodeIntrinsic(setStampFromReturnType = true)
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java	Tue Mar 25 13:50:28 2014 -0700
@@ -25,7 +25,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 
-public class G1PreWriteBarrier extends WriteBarrier implements DeoptimizingNode {
+public class G1PreWriteBarrier extends WriteBarrier implements DeoptimizingNode.DeoptBefore {
 
     @Input private FrameState deoptimizationState;
     private final boolean nullCheck;
@@ -55,17 +55,13 @@
     }
 
     @Override
-    public FrameState getDeoptimizationState() {
+    public FrameState stateBefore() {
         return deoptimizationState;
     }
 
     @Override
-    public void setDeoptimizationState(FrameState state) {
+    public void setStateBefore(FrameState state) {
         updateUsages(deoptimizationState, state);
         deoptimizationState = state;
     }
-
-    public FrameState getState() {
-        return deoptimizationState;
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Tue Mar 25 13:50:28 2014 -0700
@@ -52,10 +52,10 @@
     @Override
     public void generate(LIRGenerator gen) {
         String whereString;
-        if (getState() != null) {
+        if (stateBefore() != null) {
             String nl = CodeUtil.NEW_LINE;
             StringBuilder sb = new StringBuilder("in compiled code associated with frame state:");
-            FrameState fs = getState();
+            FrameState fs = stateBefore();
             while (fs != null) {
                 MetaUtil.appendLocation(sb.append(nl).append("\t"), fs.method(), fs.bci);
                 fs = fs.outerFrameState();
@@ -65,8 +65,8 @@
             ResolvedJavaMethod method = graph().method();
             whereString = "in compiled code for " + (method == null ? graph().toString() : format("%H.%n(%p)", method));
         }
-        Value whereArg = new RawDataValue(gen.target().wordKind, toCString(whereString));
-        Value formatArg = new RawDataValue(gen.target().wordKind, toCString(format));
+        Value whereArg = emitCString(gen, whereString);
+        Value formatArg = emitCString(gen, format);
 
         ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(VMErrorNode.VM_ERROR);
         gen.emitForeignCall(linkage, null, whereArg, formatArg, gen.operand(value));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java	Tue Mar 25 13:50:28 2014 -0700
@@ -68,9 +68,9 @@
 
     protected static void addG1PreWriteBarrier(FixedAccessNode node, ValueNode object, ValueNode value, LocationNode location, boolean doLoad, boolean nullCheck, StructuredGraph graph) {
         G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(object, value, location, doLoad, nullCheck));
-        preBarrier.setDeoptimizationState(node.getDeoptimizationState());
+        preBarrier.setStateBefore(node.stateBefore());
         node.setNullCheck(false);
-        node.setDeoptimizationState(null);
+        node.setStateBefore(null);
         graph.addBeforeFixed(node, preBarrier);
     }
 
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Tue Mar 25 13:50:28 2014 -0700
@@ -310,6 +310,23 @@
         }
     }
 
+    public static class LeaDataOp extends AMD64LIRInstruction {
+
+        @Def({REG}) protected AllocatableValue result;
+        private final byte[] data;
+
+        public LeaDataOp(AllocatableValue result, byte[] data) {
+            this.result = result;
+            this.data = data;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            RawData rawData = new RawData(data, 16);
+            masm.leaq(asRegister(result), (AMD64Address) crb.recordDataReferenceInCode(rawData));
+        }
+    }
+
     public static class StackLeaOp extends AMD64LIRInstruction {
 
         @Def({REG}) protected AllocatableValue result;
@@ -409,13 +426,6 @@
             } else {
                 throw GraalInternalError.shouldNotReachHere();
             }
-        } else if (isRawData(input)) {
-            if (isRegister(result)) {
-                RawData rawData = new RawData(asRawData(input).getData(), 16);
-                masm.leaq(asRegister(result), (AMD64Address) crb.recordDataReferenceInCode(rawData));
-            } else {
-                throw GraalInternalError.shouldNotReachHere();
-            }
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Tue Mar 25 13:50:28 2014 -0700
@@ -26,7 +26,6 @@
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 import static com.oracle.graal.sparc.SPARC.*;
 
-import com.oracle.graal.api.code.CompilationResult.RawData;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
@@ -390,13 +389,6 @@
             } else {
                 throw GraalInternalError.shouldNotReachHere();
             }
-        } else if (isRawData(input)) {
-            if (isRegister(result)) {
-                RawData rawData = new RawData(asRawData(input).getData(), 16);
-                throw GraalInternalError.unimplemented("Emitting raw data: " + rawData);
-            } else {
-                throw GraalInternalError.shouldNotReachHere();
-            }
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Tue Mar 25 13:50:28 2014 -0700
@@ -237,7 +237,6 @@
         if ((isVariable(value) && flags.contains(OperandFlag.REG)) ||
             (isRegister(value) && flags.contains(OperandFlag.REG)) ||
             (isStackSlot(value) && flags.contains(OperandFlag.STACK)) ||
-            (isRawData(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) ||
             (isConstant(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) ||
             (isIllegal(value) && flags.contains(OperandFlag.ILLEGAL))) {
             return value;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java	Tue Mar 25 13:50:28 2014 -0700
@@ -30,11 +30,9 @@
  * This node represents an unconditional explicit request for immediate deoptimization.
  * 
  * After this node, execution will continue using a fallback execution engine (such as an
- * interpreter) at the position described by the {@link #getDeoptimizationState() deoptimization
- * state}.
- * 
+ * interpreter) at the position described by the {@link #stateBefore() deoptimization state}.
  */
-public abstract class AbstractDeoptimizeNode extends ControlSinkNode implements IterableNodeType, DeoptimizingNode {
+public abstract class AbstractDeoptimizeNode extends ControlSinkNode implements IterableNodeType, DeoptimizingNode.DeoptBefore {
 
     @Input private FrameState deoptState;
 
@@ -48,20 +46,16 @@
     }
 
     @Override
-    public FrameState getDeoptimizationState() {
+    public FrameState stateBefore() {
         return deoptState;
     }
 
     @Override
-    public void setDeoptimizationState(FrameState f) {
+    public void setStateBefore(FrameState f) {
         updateUsages(deoptState, f);
         deoptState = f;
     }
 
-    public FrameState getState() {
-        return deoptState;
-    }
-
     public abstract ValueNode getActionAndReason(MetaAccessProvider metaAccess);
 
     public abstract ValueNode getSpeculation(MetaAccessProvider metaAccess);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Tue Mar 25 13:50:28 2014 -0700
@@ -86,7 +86,7 @@
         FixedNode next = next();
         setNext(null);
         DeoptimizeNode deopt = graph().add(new DeoptimizeNode(action, reason));
-        deopt.setDeoptimizationState(getDeoptimizationState());
+        deopt.setStateBefore(stateBefore());
         IfNode ifNode;
         AbstractBeginNode noDeoptSuccessor;
         if (negated) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java	Tue Mar 25 13:50:28 2014 -0700
@@ -41,10 +41,6 @@
         stateAfter = x;
     }
 
-    public FrameState getState() {
-        return stateAfter();
-    }
-
     public boolean hasSideEffect() {
         return true;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Tue Mar 25 13:50:28 2014 -0700
@@ -24,7 +24,7 @@
 
 import com.oracle.graal.nodes.type.*;
 
-public abstract class DeoptimizingFixedWithNextNode extends FixedWithNextNode implements DeoptimizingNode {
+public abstract class DeoptimizingFixedWithNextNode extends FixedWithNextNode implements DeoptimizingNode.DeoptBefore {
 
     @Input(notDataflow = true) private FrameState deoptState;
 
@@ -33,17 +33,13 @@
     }
 
     @Override
-    public FrameState getDeoptimizationState() {
+    public FrameState stateBefore() {
         return deoptState;
     }
 
     @Override
-    public void setDeoptimizationState(FrameState f) {
+    public void setStateBefore(FrameState f) {
         updateUsages(deoptState, f);
         deoptState = f;
     }
-
-    public FrameState getState() {
-        return deoptState;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java	Tue Mar 25 13:50:28 2014 -0700
@@ -35,14 +35,46 @@
     boolean canDeoptimize();
 
     /**
-     * Gets the deoptimization information associated with this node if any.
+     * Interface for nodes that need a {@link FrameState} for deoptimizing to a point before their
+     * execution.
      */
-    FrameState getDeoptimizationState();
+    public interface DeoptBefore extends DeoptimizingNode {
+
+        /**
+         * Sets the {@link FrameState} describing the program state before the execution of this
+         * node.
+         */
+        void setStateBefore(FrameState state);
+
+        FrameState stateBefore();
+    }
+
+    /**
+     * Interface for nodes that need a {@link FrameState} for deoptimizing to a point after their
+     * execution.
+     */
+    public interface DeoptAfter extends DeoptimizingNode, StateSplit {
+    }
 
     /**
-     * Sets the deoptimization information associated with this node.
-     * 
-     * @param state the {@link FrameState} which represents the deoptimization information
+     * Interface for nodes that need a special {@link FrameState} for deoptimizing during their
+     * execution (e.g. {@link Invoke}).
      */
-    void setDeoptimizationState(FrameState state);
+    public interface DeoptDuring extends DeoptimizingNode, StateSplit {
+
+        FrameState stateDuring();
+
+        /**
+         * Sets the {@link FrameState} describing the program state during the execution of this
+         * node.
+         */
+        void setStateDuring(FrameState state);
+
+        /**
+         * Compute the {@link FrameState} describing the program state during the execution of this
+         * node from an input {@link FrameState} describing the program state after finishing the
+         * execution of this node.
+         */
+        void computeStateDuring(FrameState stateAfter);
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Tue Mar 25 13:50:28 2014 -0700
@@ -66,7 +66,7 @@
             DeoptimizeNode newDeopt = graph().add(
                             new DeoptimizeNode(tool.getMetaAccess().decodeDeoptAction(constant), tool.getMetaAccess().decodeDeoptReason(constant), tool.getMetaAccess().decodeDebugId(constant),
                                             speculationConstant));
-            newDeopt.setDeoptimizationState(getDeoptimizationState());
+            newDeopt.setStateBefore(stateBefore());
             return newDeopt;
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Tue Mar 25 13:50:28 2014 -0700
@@ -52,7 +52,7 @@
                 }
 
                 DeoptimizeNode deopt = graph().add(new DeoptimizeNode(getAction(), getReason()));
-                deopt.setDeoptimizationState(getDeoptimizationState());
+                deopt.setStateBefore(stateBefore());
                 setNext(deopt);
             }
             this.replaceAtUsages(null);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Tue Mar 25 13:50:28 2014 -0700
@@ -51,7 +51,7 @@
 
     @Override
     public boolean verify() {
-        return getState() != null && super.verify();
+        return state != null && super.verify();
     }
 
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Tue Mar 25 13:50:28 2014 -0700
@@ -26,7 +26,7 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 
-public interface Invoke extends StateSplit, Lowerable, DeoptimizingNode, GuardedNode {
+public interface Invoke extends StateSplit, Lowerable, DeoptimizingNode.DeoptDuring, GuardedNode {
 
     FixedNode next();
 
@@ -38,10 +38,6 @@
 
     FixedNode asNode();
 
-    FrameState stateDuring();
-
-    FrameState stateAfter();
-
     Node predecessor();
 
     void intrinsify(Node node);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Tue Mar 25 13:50:28 2014 -0700
@@ -133,17 +133,6 @@
     }
 
     @Override
-    public FrameState stateDuring() {
-        FrameState stateAfter = stateAfter();
-        if (stateAfter == null) {
-            return null;
-        }
-        FrameState stateDuring = stateAfter.duplicateModified(bci(), stateAfter.rethrowException(), getKind());
-        stateDuring.setDuringCall(true);
-        return stateDuring;
-    }
-
-    @Override
     public void intrinsify(Node node) {
         assert !(node instanceof ValueNode) || (((ValueNode) node).getKind() == Kind.Void) == (getKind() == Kind.Void);
         CallTargetNode call = callTarget;
@@ -174,18 +163,21 @@
     }
 
     @Override
-    public FrameState getDeoptimizationState() {
-        if (deoptState == null) {
-            FrameState stateDuring = stateDuring();
-            updateUsages(deoptState, stateDuring);
-            deoptState = stateDuring;
-        }
+    public FrameState stateDuring() {
         return deoptState;
     }
 
     @Override
-    public void setDeoptimizationState(FrameState f) {
-        throw new IllegalStateException("Cannot set deoptimization state " + f + " for invoke " + this);
+    public void setStateDuring(FrameState stateDuring) {
+        updateUsages(deoptState, stateDuring);
+        deoptState = stateDuring;
+    }
+
+    @Override
+    public void computeStateDuring(FrameState stateAfter) {
+        FrameState stateDuring = stateAfter.duplicateModified(bci(), stateAfter.rethrowException(), getKind());
+        stateDuring.setDuringCall(true);
+        setStateDuring(stateDuring);
     }
 
     @Override
@@ -198,14 +190,4 @@
         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	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Tue Mar 25 13:50:28 2014 -0700
@@ -155,13 +155,6 @@
         return LocationIdentity.ANY_LOCATION;
     }
 
-    public FrameState stateDuring() {
-        FrameState tempStateAfter = stateAfter();
-        FrameState stateDuring = tempStateAfter.duplicateModified(bci(), tempStateAfter.rethrowException(), getKind());
-        stateDuring.setDuringCall(true);
-        return stateDuring;
-    }
-
     @Override
     public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
         Map<Object, Object> debugProperties = super.getDebugProperties(map);
@@ -219,18 +212,21 @@
     }
 
     @Override
-    public FrameState getDeoptimizationState() {
-        if (deoptState == null) {
-            FrameState stateDuring = stateDuring();
-            updateUsages(deoptState, stateDuring);
-            deoptState = stateDuring;
-        }
+    public FrameState stateDuring() {
         return deoptState;
     }
 
     @Override
-    public void setDeoptimizationState(FrameState f) {
-        throw new IllegalStateException();
+    public void setStateDuring(FrameState stateDuring) {
+        updateUsages(deoptState, stateDuring);
+        deoptState = stateDuring;
+    }
+
+    @Override
+    public void computeStateDuring(FrameState tempStateAfter) {
+        FrameState stateDuring = tempStateAfter.duplicateModified(bci(), tempStateAfter.rethrowException(), getKind());
+        stateDuring.setDuringCall(true);
+        setStateDuring(stateDuring);
     }
 
     @Override
@@ -244,16 +240,6 @@
         this.guard = guard;
     }
 
-    @Override
-    public FrameState getState() {
-        if (deoptState != null) {
-            assert stateAfter() == null;
-            return deoptState;
-        } else {
-            return stateAfter();
-        }
-    }
-
     public MemoryCheckpoint asMemoryCheckpoint() {
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Tue Mar 25 13:50:28 2014 -0700
@@ -35,7 +35,7 @@
  * Node for a {@linkplain ForeignCallDescriptor foreign} call.
  */
 @NodeInfo(nameTemplate = "ForeignCall#{p#descriptor/s}")
-public class ForeignCallNode extends AbstractMemoryCheckpoint implements LIRLowerable, DeoptimizingNode, MemoryCheckpoint.Multi {
+public class ForeignCallNode extends AbstractMemoryCheckpoint implements LIRLowerable, DeoptimizingNode.DeoptDuring, MemoryCheckpoint.Multi {
 
     @Input private final NodeInputList<ValueNode> arguments;
     private final ForeignCallsProvider foreignCalls;
@@ -101,32 +101,25 @@
     }
 
     @Override
-    public FrameState getDeoptimizationState() {
-        if (deoptState != null) {
-            return deoptState;
-        } else if (stateAfter() != null && canDeoptimize()) {
-            FrameState stateDuring = stateAfter();
-            if ((stateDuring.stackSize() > 0 && stateDuring.stackAt(stateDuring.stackSize() - 1) == this) || (stateDuring.stackSize() > 1 && stateDuring.stackAt(stateDuring.stackSize() - 2) == this)) {
-                stateDuring = stateDuring.duplicateModified(stateDuring.bci, stateDuring.rethrowException(), this.getKind());
-            }
-            setDeoptimizationState(stateDuring);
-            return stateDuring;
-        }
-        return null;
+    public FrameState stateDuring() {
+        return deoptState;
     }
 
     @Override
-    public void setDeoptimizationState(FrameState f) {
-        updateUsages(deoptState, f);
-        assert deoptState == null && canDeoptimize() : "shouldn't assign deoptState to " + this;
-        deoptState = f;
+    public void setStateDuring(FrameState stateDuring) {
+        updateUsages(deoptState, stateDuring);
+        deoptState = stateDuring;
     }
 
     @Override
-    public void setStateAfter(FrameState x) {
-        if (hasSideEffect()) {
-            super.setStateAfter(x);
+    public void computeStateDuring(FrameState stateAfter) {
+        FrameState stateDuring;
+        if ((stateAfter.stackSize() > 0 && stateAfter.stackAt(stateAfter.stackSize() - 1) == this) || (stateAfter.stackSize() > 1 && stateAfter.stackAt(stateAfter.stackSize() - 2) == this)) {
+            stateDuring = stateAfter.duplicateModified(stateAfter.bci, stateAfter.rethrowException(), this.getKind());
+        } else {
+            stateDuring = stateAfter;
         }
+        setStateDuring(stateDuring);
     }
 
     @Override
@@ -141,14 +134,4 @@
     public boolean canDeoptimize() {
         return foreignCalls.canDeoptimize(descriptor);
     }
-
-    @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/WriteNode.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Tue Mar 25 13:50:28 2014 -0700
@@ -46,16 +46,6 @@
         return stateAfter;
     }
 
-    @Override
-    public FrameState getState() {
-        if (stateAfter != null) {
-            assert super.getState() == null;
-            return stateAfter;
-        } else {
-            return super.getState();
-        }
-    }
-
     public void setStateAfter(FrameState x) {
         assert x == null || x.isAlive() : "frame state must be in a graph";
         updateUsages(stateAfter, x);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Tue Mar 25 13:50:28 2014 -0700
@@ -33,9 +33,9 @@
  * 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 AbstractMemoryCheckpoint implements MemoryCheckpoint, DeoptimizingNode {
+public abstract class AccessMonitorNode extends AbstractMemoryCheckpoint implements MemoryCheckpoint, DeoptimizingNode.DeoptBefore, DeoptimizingNode.DeoptAfter {
 
-    @Input private FrameState deoptState;
+    @Input private FrameState stateBefore;
     @Input private ValueNode object;
     @Input private MonitorIdNode monitorId;
 
@@ -44,21 +44,14 @@
         return true;
     }
 
-    @Override
-    public FrameState getDeoptimizationState() {
-        return deoptState;
+    public FrameState stateBefore() {
+        return stateBefore;
     }
 
     @Override
-    public void setDeoptimizationState(FrameState f) {
-        updateUsages(deoptState, f);
-        deoptState = f;
-    }
-
-    @Override
-    public FrameState getState() {
-        assert deoptState == null || stateAfter() == null;
-        return deoptState == null ? stateAfter() : deoptState;
+    public void setStateBefore(FrameState f) {
+        updateUsages(stateBefore, f);
+        stateBefore = f;
     }
 
     public ValueNode object() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Tue Mar 25 13:50:28 2014 -0700
@@ -34,7 +34,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 Canonicalizable, LIRLowerable, Virtualizable, DeoptimizingNode {
+public final class RegisterFinalizerNode extends AbstractStateSplit implements Canonicalizable, LIRLowerable, Virtualizable, DeoptimizingNode.DeoptAfter {
 
     public static final ForeignCallDescriptor REGISTER_FINALIZER = new ForeignCallDescriptor("registerFinalizer", void.class, Object.class);
 
@@ -96,17 +96,6 @@
         return true;
     }
 
-    @Override
-    public FrameState getDeoptimizationState() {
-        return deoptState;
-    }
-
-    @Override
-    public void setDeoptimizationState(FrameState f) {
-        updateUsages(deoptState, f);
-        deoptState = f;
-    }
-
     @SuppressWarnings("unused")
     @NodeIntrinsic
     public static void register(Object thisObj) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Tue Mar 25 13:50:28 2014 -0700
@@ -59,6 +59,14 @@
 
     void emitMove(AllocatableValue dst, Value src);
 
+    /**
+     * Emits an op that loads the address of some raw data.
+     * 
+     * @param dst the variable into which the address is loaded
+     * @param data the data to be installed with the generated code
+     */
+    void emitData(AllocatableValue dst, byte[] data);
+
     Value emitAddress(Value base, long displacement, Value index, int scale);
 
     Value emitAddress(StackSlot slot);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeWithState.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeWithState.java	Tue Mar 25 13:50:28 2014 -0700
@@ -24,25 +24,11 @@
 
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import static com.oracle.graal.nodes.StructuredGraph.GuardsStage.*;
 
 /**
  * Interface for nodes which have {@link FrameState} nodes as input.
- * <p>
- * Some node can implement more than one interface which requires a {@link FrameState} input (e.g.
- * {@link DeoptimizingNode} and {@link StateSplit}). Since this interface can only report one
- * FrameState, such nodes must ensure they only maintain a link to at most one FrameState at all
- * times. Usually this is not a problem because FrameStates are associated only with StateSplit
- * nodes before the {@link #AFTER_FSA} stage and only with DeoptimizingNodes after.
- * 
  */
 public interface NodeWithState {
-    /**
-     * Gets the {@link FrameState} associated with this node.
-     * 
-     * @return the {@link FrameState} associated with this node
-     */
-    FrameState getState();
 
     Node asNode();
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Tue Mar 25 13:50:28 2014 -0700
@@ -82,7 +82,7 @@
                 }
             }
             if (obsoletes != null) {
-                ((DynamicDeoptimizeNode) ((MergeNode) target).next()).setDeoptimizationState(fs);
+                ((DynamicDeoptimizeNode) ((MergeNode) target).next()).setStateBefore(fs);
                 for (AbstractDeoptimizeNode obsolete : obsoletes) {
                     obsolete.safeDelete();
                 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Tue Mar 25 13:50:28 2014 -0700
@@ -49,24 +49,41 @@
 
         @Override
         protected FrameState processNode(FixedNode node, FrameState currentState) {
-            if (node instanceof DeoptimizingNode) {
-                DeoptimizingNode deopt = (DeoptimizingNode) node;
-                if (deopt.canDeoptimize() && deopt.getDeoptimizationState() == null) {
+            if (node instanceof DeoptimizingNode.DeoptBefore) {
+                DeoptimizingNode.DeoptBefore deopt = (DeoptimizingNode.DeoptBefore) node;
+                if (deopt.canDeoptimize() && deopt.stateBefore() == null) {
                     GraalInternalError.guarantee(currentState != null, "no FrameState at DeoptimizingNode %s", deopt);
-                    deopt.setDeoptimizationState(currentState);
+                    deopt.setStateBefore(currentState);
                 }
             }
 
+            FrameState newState = currentState;
             if (node instanceof StateSplit) {
                 StateSplit stateSplit = (StateSplit) node;
                 FrameState stateAfter = stateSplit.stateAfter();
                 if (stateAfter != null) {
-                    FrameState newState = stateAfter;
+                    newState = stateAfter;
                     stateSplit.setStateAfter(null);
-                    return newState;
                 }
             }
-            return currentState;
+
+            if (node instanceof DeoptimizingNode.DeoptDuring) {
+                DeoptimizingNode.DeoptDuring deopt = (DeoptimizingNode.DeoptDuring) node;
+                if (deopt.canDeoptimize()) {
+                    GraalInternalError.guarantee(newState != null, "no FrameState at DeoptimizingNode %s", deopt);
+                    deopt.computeStateDuring(newState);
+                }
+            }
+
+            if (node instanceof DeoptimizingNode.DeoptAfter) {
+                DeoptimizingNode.DeoptAfter deopt = (DeoptimizingNode.DeoptAfter) node;
+                if (deopt.canDeoptimize() && deopt.stateAfter() == null) {
+                    GraalInternalError.guarantee(newState != null, "no FrameState at DeoptimizingNode %s", deopt);
+                    deopt.setStateAfter(newState);
+                }
+            }
+
+            return newState;
         }
 
         @Override
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Tue Mar 25 13:50:28 2014 -0700
@@ -76,7 +76,7 @@
         AbstractBeginNode nonTrappingContinuation = ifNode.falseSuccessor();
         AbstractBeginNode trappingContinuation = ifNode.trueSuccessor();
         NullCheckNode trappingNullCheck = deopt.graph().add(new NullCheckNode(isNullNode.object()));
-        trappingNullCheck.setDeoptimizationState(deopt.getDeoptimizationState());
+        trappingNullCheck.setStateBefore(deopt.stateBefore());
         deopt.graph().replaceSplit(ifNode, trappingNullCheck, nonTrappingContinuation);
 
         GraphUtil.killCFG(trappingContinuation);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Tue Mar 25 13:50:28 2014 -0700
@@ -966,14 +966,18 @@
             return;
         }
 
-        FrameState state = null;
+        FrameState stateAfter = null;
+        if (i instanceof StateSplit) {
+            stateAfter = ((StateSplit) i).stateAfter();
+        }
+
         for (Node input : i.inputs()) {
             if (input instanceof FrameState) {
-                assert state == null;
-                state = (FrameState) input;
+                if (input != stateAfter) {
+                    addUnscheduledToLatestSorting(b, (FrameState) input, sortedInstructions, visited, reads, beforeLastLocation);
+                }
             } else {
                 addToLatestSorting(b, (ScheduledNode) input, sortedInstructions, visited, reads, beforeLastLocation);
-
             }
         }
 
@@ -991,7 +995,7 @@
 
         addToLatestSorting(b, (ScheduledNode) i.predecessor(), sortedInstructions, visited, reads, beforeLastLocation);
         visited.mark(i);
-        addUnscheduledToLatestSorting(b, state, sortedInstructions, visited, reads, beforeLastLocation);
+        addUnscheduledToLatestSorting(b, stateAfter, sortedInstructions, visited, reads, beforeLastLocation);
 
         // Now predecessors and inputs are scheduled => we can add this node.
         if (!sortedInstructions.contains(i)) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java	Tue Mar 25 13:50:28 2014 -0700
@@ -175,7 +175,7 @@
             for (Node returnSideEffect : returnSideEffects) {
                 if (!unwindSideEffects.contains(returnSideEffect) && !maskedSideEffects.contains(returnSideEffect)) {
                     StateSplit split = (StateSplit) returnSideEffect;
-                    if (split.getState() != null) {
+                    if (split.stateAfter() != null) {
                         split.setStateAfter(graph.add(new FrameState(FrameState.AFTER_BCI)));
                     }
                 }
@@ -184,7 +184,7 @@
             for (Node unwindSideEffect : unwindSideEffects) {
                 if (!returnSideEffects.contains(unwindSideEffect) && !maskedSideEffects.contains(unwindSideEffect)) {
                     StateSplit split = (StateSplit) unwindSideEffect;
-                    if (split.getState() != null) {
+                    if (split.stateAfter() != null) {
                         split.setStateAfter(graph.add(new FrameState(FrameState.AFTER_EXCEPTION_BCI)));
                     }
                 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Mar 25 13:50:28 2014 -0700
@@ -728,8 +728,8 @@
     private final ArrayList<StateSplit> sideEffectNodes;
 
     /**
-     * Nodes that inherit the {@link DeoptimizingNode#getDeoptimizationState()} from the replacee
-     * during instantiation.
+     * Nodes that inherit a deoptimization {@link FrameState} from the replacee during
+     * instantiation.
      */
     private final ArrayList<DeoptimizingNode> deoptNodes;
 
@@ -1024,11 +1024,50 @@
 
             if (replacee instanceof DeoptimizingNode) {
                 DeoptimizingNode replaceeDeopt = (DeoptimizingNode) replacee;
-                FrameState state = replaceeDeopt.getDeoptimizationState();
+
+                FrameState stateBefore = null;
+                FrameState stateDuring = null;
+                FrameState stateAfter = null;
+                if (replaceeDeopt.canDeoptimize()) {
+                    if (replaceeDeopt instanceof DeoptimizingNode.DeoptBefore) {
+                        stateBefore = ((DeoptimizingNode.DeoptBefore) replaceeDeopt).stateBefore();
+                    }
+                    if (replaceeDeopt instanceof DeoptimizingNode.DeoptDuring) {
+                        stateDuring = ((DeoptimizingNode.DeoptDuring) replaceeDeopt).stateDuring();
+                    }
+                    if (replaceeDeopt instanceof DeoptimizingNode.DeoptAfter) {
+                        stateAfter = ((DeoptimizingNode.DeoptAfter) replaceeDeopt).stateAfter();
+                    }
+                }
+
                 for (DeoptimizingNode deoptNode : deoptNodes) {
                     DeoptimizingNode deoptDup = (DeoptimizingNode) duplicates.get(deoptNode);
-                    assert replaceeDeopt.canDeoptimize() || !deoptDup.canDeoptimize();
-                    deoptDup.setDeoptimizationState(state);
+                    if (deoptDup.canDeoptimize()) {
+                        if (deoptDup instanceof DeoptimizingNode.DeoptBefore) {
+                            ((DeoptimizingNode.DeoptBefore) deoptDup).setStateBefore(stateBefore);
+                        }
+                        if (deoptDup instanceof DeoptimizingNode.DeoptDuring) {
+                            DeoptimizingNode.DeoptDuring deoptDupDuring = (DeoptimizingNode.DeoptDuring) deoptDup;
+                            if (stateDuring != null) {
+                                deoptDupDuring.setStateDuring(stateDuring);
+                            } else if (stateAfter != null) {
+                                deoptDupDuring.computeStateDuring(stateAfter);
+                            } else if (stateBefore != null) {
+                                assert !deoptDupDuring.hasSideEffect() : "can't use stateBefore as stateDuring for state split " + deoptDupDuring;
+                                deoptDupDuring.setStateDuring(stateBefore);
+                            }
+                        }
+                        if (deoptDup instanceof DeoptimizingNode.DeoptAfter) {
+                            DeoptimizingNode.DeoptAfter deoptDupAfter = (DeoptimizingNode.DeoptAfter) deoptDup;
+                            if (stateAfter != null) {
+                                deoptDupAfter.setStateAfter(stateAfter);
+                            } else {
+                                assert !deoptDupAfter.hasSideEffect() : "can't use stateBefore as stateAfter for state split " + deoptDupAfter;
+                                deoptDupAfter.setStateAfter(stateBefore);
+                            }
+
+                        }
+                    }
                 }
             }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleExpansionLogger.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleExpansionLogger.java	Tue Mar 25 13:50:28 2014 -0700
@@ -43,7 +43,7 @@
     }
 
     public void preExpand(MethodCallTargetNode callTarget, StructuredGraph inliningGraph) {
-        ResolvedJavaMethod sourceMethod = callTarget.invoke().getState().method();
+        ResolvedJavaMethod sourceMethod = callTarget.invoke().stateAfter().method();
 
         int sourceMethodBci = callTarget.invoke().bci();
         ResolvedJavaMethod targetMethod = callTarget.targetMethod();
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Tue Mar 25 13:32:32 2014 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Tue Mar 25 13:50:28 2014 -0700
@@ -132,75 +132,78 @@
     }
 
     private void processNodeWithState(NodeWithState nodeWithState, final BlockT state, final GraphEffectList effects) {
-        FrameState frameState = nodeWithState.getState();
-        if (frameState != null) {
-            if (frameState.usages().count() > 1) {
-                nodeWithState.asNode().replaceFirstInput(frameState, frameState.copyWithInputs());
-                frameState = nodeWithState.getState();
-            }
-            final Set<ObjectState> virtual = new ArraySet<>();
-            frameState.applyToNonVirtual(new NodeClosure<ValueNode>() {
+        for (Node input : nodeWithState.asNode().inputs()) {
+            if (input instanceof FrameState) {
+                FrameState frameState = (FrameState) input;
+                if (frameState.usages().count() > 1) {
+                    FrameState copy = (FrameState) frameState.copyWithInputs();
+                    nodeWithState.asNode().replaceFirstInput(frameState, copy);
+                    frameState = copy;
+                }
+                final Set<ObjectState> virtual = new ArraySet<>();
+                frameState.applyToNonVirtual(new NodeClosure<ValueNode>() {
 
-                @Override
-                public void apply(Node usage, ValueNode value) {
-                    ObjectState valueObj = getObjectState(state, value);
-                    if (valueObj != null) {
-                        virtual.add(valueObj);
-                        effects.replaceFirstInput(usage, value, valueObj.virtual);
-                    } else if (value instanceof VirtualObjectNode) {
-                        ObjectState virtualObj = null;
-                        for (ObjectState obj : state.getStates()) {
-                            if (value == obj.virtual) {
-                                virtualObj = obj;
-                                break;
+                    @Override
+                    public void apply(Node usage, ValueNode value) {
+                        ObjectState valueObj = getObjectState(state, value);
+                        if (valueObj != null) {
+                            virtual.add(valueObj);
+                            effects.replaceFirstInput(usage, value, valueObj.virtual);
+                        } else if (value instanceof VirtualObjectNode) {
+                            ObjectState virtualObj = null;
+                            for (ObjectState obj : state.getStates()) {
+                                if (value == obj.virtual) {
+                                    virtualObj = obj;
+                                    break;
+                                }
+                            }
+                            if (virtualObj != null) {
+                                virtual.add(virtualObj);
                             }
                         }
-                        if (virtualObj != null) {
-                            virtual.add(virtualObj);
-                        }
+                    }
+                });
+                for (ObjectState obj : state.getStates()) {
+                    if (obj.isVirtual() && obj.hasLocks()) {
+                        virtual.add(obj);
                     }
                 }
-            });
-            for (ObjectState obj : state.getStates()) {
-                if (obj.isVirtual() && obj.hasLocks()) {
-                    virtual.add(obj);
-                }
-            }
 
-            ArrayDeque<ObjectState> queue = new ArrayDeque<>(virtual);
-            while (!queue.isEmpty()) {
-                ObjectState obj = queue.removeLast();
-                if (obj.isVirtual()) {
-                    for (ValueNode field : obj.getEntries()) {
-                        if (field instanceof VirtualObjectNode) {
-                            ObjectState fieldObj = state.getObjectState((VirtualObjectNode) field);
-                            if (fieldObj.isVirtual() && !virtual.contains(fieldObj)) {
-                                virtual.add(fieldObj);
-                                queue.addLast(fieldObj);
+                ArrayDeque<ObjectState> queue = new ArrayDeque<>(virtual);
+                while (!queue.isEmpty()) {
+                    ObjectState obj = queue.removeLast();
+                    if (obj.isVirtual()) {
+                        for (ValueNode field : obj.getEntries()) {
+                            if (field instanceof VirtualObjectNode) {
+                                ObjectState fieldObj = state.getObjectState((VirtualObjectNode) field);
+                                if (fieldObj.isVirtual() && !virtual.contains(fieldObj)) {
+                                    virtual.add(fieldObj);
+                                    queue.addLast(fieldObj);
+                                }
                             }
                         }
                     }
                 }
-            }
-            for (ObjectState obj : virtual) {
-                EscapeObjectState v;
-                if (obj.isVirtual()) {
-                    ValueNode[] fieldState = obj.getEntries().clone();
-                    for (int i = 0; i < fieldState.length; i++) {
-                        ObjectState valueObj = getObjectState(state, fieldState[i]);
-                        if (valueObj != null) {
-                            if (valueObj.isVirtual()) {
-                                fieldState[i] = valueObj.virtual;
-                            } else {
-                                fieldState[i] = valueObj.getMaterializedValue();
+                for (ObjectState obj : virtual) {
+                    EscapeObjectState v;
+                    if (obj.isVirtual()) {
+                        ValueNode[] fieldState = obj.getEntries().clone();
+                        for (int i = 0; i < fieldState.length; i++) {
+                            ObjectState valueObj = getObjectState(state, fieldState[i]);
+                            if (valueObj != null) {
+                                if (valueObj.isVirtual()) {
+                                    fieldState[i] = valueObj.virtual;
+                                } else {
+                                    fieldState[i] = valueObj.getMaterializedValue();
+                                }
                             }
                         }
+                        v = new VirtualObjectState(obj.virtual, fieldState);
+                    } else {
+                        v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue());
                     }
-                    v = new VirtualObjectState(obj.virtual, fieldState);
-                } else {
-                    v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue());
+                    effects.addVirtualMapping(frameState, v);
                 }
-                effects.addVirtualMapping(frameState, v);
             }
         }
     }