changeset 19538:fac54d234f30

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Sun, 22 Feb 2015 17:17:45 +0100
parents 9d5003af91f5 (diff) 9299e71df12a (current diff)
children 34462e7f0278
files
diffstat 10 files changed, 798 insertions(+), 305 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Sun Feb 22 07:42:06 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Sun Feb 22 17:17:45 2015 +0100
@@ -42,7 +42,7 @@
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 
-public abstract class AbstractBytecodeParser<T extends KindProvider, F extends AbstractFrameStateBuilder<T, F>> {
+public abstract class AbstractBytecodeParser {
 
     static class Options {
         // @formatter:off
@@ -63,7 +63,7 @@
      */
     public static final int TRACELEVEL_STATE = 2;
 
-    protected F frameState;
+    protected HIRFrameStateBuilder frameState;
     protected BciBlock currentBlock;
 
     protected final BytecodeStream stream;
@@ -97,7 +97,7 @@
         assert metaAccess != null;
     }
 
-    public void setCurrentFrameState(F frameState) {
+    public void setCurrentFrameState(HIRFrameStateBuilder frameState) {
         this.frameState = frameState;
     }
 
@@ -114,7 +114,7 @@
     }
 
     public void storeLocal(Kind kind, int index) {
-        T value;
+        ValueNode value;
         if (kind == Kind.Object) {
             value = frameState.xpop();
             // astore and astore_<n> may be used to store a returnAddress (jsr)
@@ -134,13 +134,13 @@
      * @param type the unresolved type of the type check
      * @param object the object value whose type is being checked against {@code type}
      */
-    protected abstract void handleUnresolvedCheckCast(JavaType type, T object);
+    protected abstract void handleUnresolvedCheckCast(JavaType type, ValueNode object);
 
     /**
      * @param type the unresolved type of the type check
      * @param object the object value whose type is being checked against {@code type}
      */
-    protected abstract void handleUnresolvedInstanceOf(JavaType type, T object);
+    protected abstract void handleUnresolvedInstanceOf(JavaType type, ValueNode object);
 
     /**
      * @param type the type being instantiated
@@ -151,26 +151,26 @@
      * @param type the type of the array being instantiated
      * @param length the length of the array
      */
-    protected abstract void handleUnresolvedNewObjectArray(JavaType type, T length);
+    protected abstract void handleUnresolvedNewObjectArray(JavaType type, ValueNode length);
 
     /**
      * @param type the type being instantiated
      * @param dims the dimensions for the multi-array
      */
-    protected abstract void handleUnresolvedNewMultiArray(JavaType type, List<T> dims);
+    protected abstract void handleUnresolvedNewMultiArray(JavaType type, List<ValueNode> dims);
 
     /**
      * @param field the unresolved field
      * @param receiver the object containing the field or {@code null} if {@code field} is static
      */
-    protected abstract void handleUnresolvedLoadField(JavaField field, T receiver);
+    protected abstract void handleUnresolvedLoadField(JavaField field, ValueNode receiver);
 
     /**
      * @param field the unresolved field
      * @param value the value being stored to the field
      * @param receiver the object containing the field or {@code null} if {@code field} is static
      */
-    protected abstract void handleUnresolvedStoreField(JavaField field, T value, T receiver);
+    protected abstract void handleUnresolvedStoreField(JavaField field, ValueNode value, ValueNode receiver);
 
     /**
      * @param type
@@ -179,7 +179,7 @@
 
     // protected abstract void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKind);
 
-    // protected abstract DispatchBeginNode handleException(T exceptionObject, int bci);
+    // protected abstract DispatchBeginNode handleException(ValueNode exceptionObject, int bci);
 
     private void genLoadConstant(int cpi, int opcode) {
         Object con = lookupConstant(cpi, opcode);
@@ -200,24 +200,24 @@
         }
     }
 
-    protected abstract T genLoadIndexed(T index, T array, Kind kind);
+    protected abstract ValueNode genLoadIndexed(ValueNode index, ValueNode array, Kind kind);
 
     private void genLoadIndexed(Kind kind) {
         emitExplicitExceptions(frameState.peek(1), frameState.peek(0));
 
-        T index = frameState.ipop();
-        T array = frameState.apop();
+        ValueNode index = frameState.ipop();
+        ValueNode array = frameState.apop();
         frameState.push(kind.getStackKind(), append(genLoadIndexed(array, index, kind)));
     }
 
-    protected abstract T genStoreIndexed(T array, T index, Kind kind, T value);
+    protected abstract ValueNode genStoreIndexed(ValueNode array, ValueNode index, Kind kind, ValueNode value);
 
     private void genStoreIndexed(Kind kind) {
         emitExplicitExceptions(frameState.peek(2), frameState.peek(1));
 
-        T value = frameState.pop(kind.getStackKind());
-        T index = frameState.ipop();
-        T array = frameState.apop();
+        ValueNode value = frameState.pop(kind.getStackKind());
+        ValueNode index = frameState.ipop();
+        ValueNode array = frameState.apop();
         append(genStoreIndexed(array, index, kind, value));
     }
 
@@ -233,23 +233,23 @@
                 break;
             }
             case DUP: {
-                T w = frameState.xpop();
+                ValueNode w = frameState.xpop();
                 frameState.xpush(w);
                 frameState.xpush(w);
                 break;
             }
             case DUP_X1: {
-                T w1 = frameState.xpop();
-                T w2 = frameState.xpop();
+                ValueNode w1 = frameState.xpop();
+                ValueNode w2 = frameState.xpop();
                 frameState.xpush(w1);
                 frameState.xpush(w2);
                 frameState.xpush(w1);
                 break;
             }
             case DUP_X2: {
-                T w1 = frameState.xpop();
-                T w2 = frameState.xpop();
-                T w3 = frameState.xpop();
+                ValueNode w1 = frameState.xpop();
+                ValueNode w2 = frameState.xpop();
+                ValueNode w3 = frameState.xpop();
                 frameState.xpush(w1);
                 frameState.xpush(w3);
                 frameState.xpush(w2);
@@ -257,8 +257,8 @@
                 break;
             }
             case DUP2: {
-                T w1 = frameState.xpop();
-                T w2 = frameState.xpop();
+                ValueNode w1 = frameState.xpop();
+                ValueNode w2 = frameState.xpop();
                 frameState.xpush(w2);
                 frameState.xpush(w1);
                 frameState.xpush(w2);
@@ -266,9 +266,9 @@
                 break;
             }
             case DUP2_X1: {
-                T w1 = frameState.xpop();
-                T w2 = frameState.xpop();
-                T w3 = frameState.xpop();
+                ValueNode w1 = frameState.xpop();
+                ValueNode w2 = frameState.xpop();
+                ValueNode w3 = frameState.xpop();
                 frameState.xpush(w2);
                 frameState.xpush(w1);
                 frameState.xpush(w3);
@@ -277,10 +277,10 @@
                 break;
             }
             case DUP2_X2: {
-                T w1 = frameState.xpop();
-                T w2 = frameState.xpop();
-                T w3 = frameState.xpop();
-                T w4 = frameState.xpop();
+                ValueNode w1 = frameState.xpop();
+                ValueNode w2 = frameState.xpop();
+                ValueNode w3 = frameState.xpop();
+                ValueNode w4 = frameState.xpop();
                 frameState.xpush(w2);
                 frameState.xpush(w1);
                 frameState.xpush(w4);
@@ -290,8 +290,8 @@
                 break;
             }
             case SWAP: {
-                T w1 = frameState.xpop();
-                T w2 = frameState.xpop();
+                ValueNode w1 = frameState.xpop();
+                ValueNode w2 = frameState.xpop();
                 frameState.xpush(w1);
                 frameState.xpush(w2);
                 break;
@@ -301,27 +301,27 @@
         }
     }
 
-    protected abstract T genIntegerAdd(Kind kind, T x, T y);
+    protected abstract ValueNode genIntegerAdd(Kind kind, ValueNode x, ValueNode y);
 
-    protected abstract T genIntegerSub(Kind kind, T x, T y);
+    protected abstract ValueNode genIntegerSub(Kind kind, ValueNode x, ValueNode y);
 
-    protected abstract T genIntegerMul(Kind kind, T x, T y);
+    protected abstract ValueNode genIntegerMul(Kind kind, ValueNode x, ValueNode y);
 
-    protected abstract T genFloatAdd(Kind kind, T x, T y, boolean isStrictFP);
+    protected abstract ValueNode genFloatAdd(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP);
 
-    protected abstract T genFloatSub(Kind kind, T x, T y, boolean isStrictFP);
+    protected abstract ValueNode genFloatSub(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP);
 
-    protected abstract T genFloatMul(Kind kind, T x, T y, boolean isStrictFP);
+    protected abstract ValueNode genFloatMul(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP);
 
-    protected abstract T genFloatDiv(Kind kind, T x, T y, boolean isStrictFP);
+    protected abstract ValueNode genFloatDiv(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP);
 
-    protected abstract T genFloatRem(Kind kind, T x, T y, boolean isStrictFP);
+    protected abstract ValueNode genFloatRem(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP);
 
     private void genArithmeticOp(Kind result, int opcode) {
-        T y = frameState.pop(result);
-        T x = frameState.pop(result);
+        ValueNode y = frameState.pop(result);
+        ValueNode x = frameState.pop(result);
         boolean isStrictFP = method.isStrict();
-        T v;
+        ValueNode v;
         switch (opcode) {
             case IADD:
             case LADD:
@@ -361,14 +361,14 @@
         frameState.push(result, append(v));
     }
 
-    protected abstract T genIntegerDiv(Kind kind, T x, T y);
+    protected abstract ValueNode genIntegerDiv(Kind kind, ValueNode x, ValueNode y);
 
-    protected abstract T genIntegerRem(Kind kind, T x, T y);
+    protected abstract ValueNode genIntegerRem(Kind kind, ValueNode x, ValueNode y);
 
     private void genIntegerDivOp(Kind result, int opcode) {
-        T y = frameState.pop(result);
-        T x = frameState.pop(result);
-        T v;
+        ValueNode y = frameState.pop(result);
+        ValueNode x = frameState.pop(result);
+        ValueNode v;
         switch (opcode) {
             case IDIV:
             case LDIV:
@@ -384,22 +384,22 @@
         frameState.push(result, append(v));
     }
 
-    protected abstract T genNegateOp(T x);
+    protected abstract ValueNode genNegateOp(ValueNode x);
 
     private void genNegateOp(Kind kind) {
         frameState.push(kind, append(genNegateOp(frameState.pop(kind))));
     }
 
-    protected abstract T genLeftShift(Kind kind, T x, T y);
+    protected abstract ValueNode genLeftShift(Kind kind, ValueNode x, ValueNode y);
 
-    protected abstract T genRightShift(Kind kind, T x, T y);
+    protected abstract ValueNode genRightShift(Kind kind, ValueNode x, ValueNode y);
 
-    protected abstract T genUnsignedRightShift(Kind kind, T x, T y);
+    protected abstract ValueNode genUnsignedRightShift(Kind kind, ValueNode x, ValueNode y);
 
     private void genShiftOp(Kind kind, int opcode) {
-        T s = frameState.ipop();
-        T x = frameState.pop(kind);
-        T v;
+        ValueNode s = frameState.ipop();
+        ValueNode x = frameState.pop(kind);
+        ValueNode v;
         switch (opcode) {
             case ISHL:
             case LSHL:
@@ -419,16 +419,16 @@
         frameState.push(kind, append(v));
     }
 
-    protected abstract T genAnd(Kind kind, T x, T y);
+    protected abstract ValueNode genAnd(Kind kind, ValueNode x, ValueNode y);
 
-    protected abstract T genOr(Kind kind, T x, T y);
+    protected abstract ValueNode genOr(Kind kind, ValueNode x, ValueNode y);
 
-    protected abstract T genXor(Kind kind, T x, T y);
+    protected abstract ValueNode genXor(Kind kind, ValueNode x, ValueNode y);
 
     private void genLogicOp(Kind kind, int opcode) {
-        T y = frameState.pop(kind);
-        T x = frameState.pop(kind);
-        T v;
+        ValueNode y = frameState.pop(kind);
+        ValueNode x = frameState.pop(kind);
+        ValueNode v;
         switch (opcode) {
             case IAND:
             case LAND:
@@ -448,29 +448,29 @@
         frameState.push(kind, append(v));
     }
 
-    protected abstract T genNormalizeCompare(T x, T y, boolean isUnorderedLess);
+    protected abstract ValueNode genNormalizeCompare(ValueNode x, ValueNode y, boolean isUnorderedLess);
 
     private void genCompareOp(Kind kind, boolean isUnorderedLess) {
-        T y = frameState.pop(kind);
-        T x = frameState.pop(kind);
+        ValueNode y = frameState.pop(kind);
+        ValueNode x = frameState.pop(kind);
         frameState.ipush(append(genNormalizeCompare(x, y, isUnorderedLess)));
     }
 
-    protected abstract T genFloatConvert(FloatConvert op, T input);
+    protected abstract ValueNode genFloatConvert(FloatConvert op, ValueNode input);
 
     private void genFloatConvert(FloatConvert op, Kind from, Kind to) {
-        T input = frameState.pop(from.getStackKind());
+        ValueNode input = frameState.pop(from.getStackKind());
         frameState.push(to.getStackKind(), append(genFloatConvert(op, input)));
     }
 
-    protected abstract T genNarrow(T input, int bitCount);
+    protected abstract ValueNode genNarrow(ValueNode input, int bitCount);
 
-    protected abstract T genSignExtend(T input, int bitCount);
+    protected abstract ValueNode genSignExtend(ValueNode input, int bitCount);
 
-    protected abstract T genZeroExtend(T input, int bitCount);
+    protected abstract ValueNode genZeroExtend(ValueNode input, int bitCount);
 
     private void genSignExtend(Kind from, Kind to) {
-        T input = frameState.pop(from.getStackKind());
+        ValueNode input = frameState.pop(from.getStackKind());
         if (from != from.getStackKind()) {
             input = append(genNarrow(input, from.getBitCount()));
         }
@@ -478,7 +478,7 @@
     }
 
     private void genZeroExtend(Kind from, Kind to) {
-        T input = frameState.pop(from.getStackKind());
+        ValueNode input = frameState.pop(from.getStackKind());
         if (from != from.getStackKind()) {
             input = append(genNarrow(input, from.getBitCount()));
         }
@@ -486,45 +486,45 @@
     }
 
     private void genNarrow(Kind from, Kind to) {
-        T input = frameState.pop(from.getStackKind());
+        ValueNode input = frameState.pop(from.getStackKind());
         frameState.push(to.getStackKind(), append(genNarrow(input, to.getBitCount())));
     }
 
     private void genIncrement() {
         int index = getStream().readLocalIndex();
         int delta = getStream().readIncrement();
-        T x = frameState.loadLocal(index);
-        T y = appendConstant(JavaConstant.forInt(delta));
+        ValueNode x = frameState.loadLocal(index);
+        ValueNode y = appendConstant(JavaConstant.forInt(delta));
         frameState.storeLocal(index, append(genIntegerAdd(Kind.Int, x, y)));
     }
 
     protected abstract void genGoto();
 
-    protected abstract T genObjectEquals(T x, T y);
+    protected abstract ValueNode genObjectEquals(ValueNode x, ValueNode y);
 
-    protected abstract T genIntegerEquals(T x, T y);
+    protected abstract ValueNode genIntegerEquals(ValueNode x, ValueNode y);
 
-    protected abstract T genIntegerLessThan(T x, T y);
+    protected abstract ValueNode genIntegerLessThan(ValueNode x, ValueNode y);
 
-    protected abstract T genUnique(T x);
+    protected abstract ValueNode genUnique(ValueNode x);
 
-    protected abstract void genIf(T x, Condition cond, T y);
+    protected abstract void genIf(ValueNode x, Condition cond, ValueNode y);
 
     private void genIfZero(Condition cond) {
-        T y = appendConstant(JavaConstant.INT_0);
-        T x = frameState.ipop();
+        ValueNode y = appendConstant(JavaConstant.INT_0);
+        ValueNode x = frameState.ipop();
         genIf(x, cond, y);
     }
 
     private void genIfNull(Condition cond) {
-        T y = appendConstant(JavaConstant.NULL_POINTER);
-        T x = frameState.apop();
+        ValueNode y = appendConstant(JavaConstant.NULL_POINTER);
+        ValueNode x = frameState.apop();
         genIf(x, cond, y);
     }
 
     private void genIfSame(Kind kind, Condition cond) {
-        T y = frameState.pop(kind);
-        T x = frameState.pop(kind);
+        ValueNode y = frameState.pop(kind);
+        ValueNode x = frameState.pop(kind);
         // assert !x.isDeleted() && !y.isDeleted();
         genIf(x, cond, y);
     }
@@ -579,41 +579,40 @@
         }
     }
 
-    protected abstract T createCheckCast(ResolvedJavaType type, T object, JavaTypeProfile profileForTypeCheck, boolean forStoreCheck);
+    protected abstract ValueNode createCheckCast(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck, boolean forStoreCheck);
 
     private void genCheckCast() {
         int cpi = getStream().readCPI();
         JavaType type = lookupType(cpi, CHECKCAST);
-        T object = frameState.apop();
+        ValueNode object = frameState.apop();
         if (type instanceof ResolvedJavaType) {
             JavaTypeProfile profileForTypeCheck = getProfileForTypeCheck((ResolvedJavaType) type);
-            T checkCastNode = append(createCheckCast((ResolvedJavaType) type, object, profileForTypeCheck, false));
+            ValueNode checkCastNode = append(createCheckCast((ResolvedJavaType) type, object, profileForTypeCheck, false));
             frameState.apush(checkCastNode);
         } else {
             handleUnresolvedCheckCast(type, object);
         }
     }
 
-    protected abstract T createInstanceOf(ResolvedJavaType type, T object, JavaTypeProfile profileForTypeCheck);
+    protected abstract ValueNode createInstanceOf(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck);
 
-    protected abstract T genConditional(T x);
+    protected abstract ValueNode genConditional(ValueNode x);
 
     private void genInstanceOf() {
         int cpi = getStream().readCPI();
         JavaType type = lookupType(cpi, INSTANCEOF);
-        T object = frameState.apop();
+        ValueNode object = frameState.apop();
         if (type instanceof ResolvedJavaType) {
             ResolvedJavaType resolvedType = (ResolvedJavaType) type;
-            T instanceOfNode = createInstanceOf((ResolvedJavaType) type, object, getProfileForTypeCheck(resolvedType));
+            ValueNode instanceOfNode = createInstanceOf((ResolvedJavaType) type, object, getProfileForTypeCheck(resolvedType));
             frameState.ipush(append(genConditional(genUnique(instanceOfNode))));
         } else {
             handleUnresolvedInstanceOf(type, object);
         }
     }
 
-    protected abstract T createNewInstance(ResolvedJavaType type, boolean fillContents);
+    protected abstract ValueNode createNewInstance(ResolvedJavaType type, boolean fillContents);
 
-    @SuppressWarnings("unchecked")
     void genNewInstance(int cpi) {
         JavaType type = lookupType(cpi, NEW);
         if (type instanceof ResolvedJavaType && ((ResolvedJavaType) type).isInitialized()) {
@@ -621,7 +620,7 @@
             if (skippedExceptionTypes != null) {
                 for (ResolvedJavaType exceptionType : skippedExceptionTypes) {
                     if (exceptionType.isAssignableFrom((ResolvedJavaType) type)) {
-                        append((T) new DeoptimizeNode(DeoptimizationAction.None, TransferToInterpreter));
+                        append(new DeoptimizeNode(DeoptimizationAction.None, TransferToInterpreter));
                         return;
                     }
                 }
@@ -672,7 +671,7 @@
 
     private void genNewObjectArray(int cpi) {
         JavaType type = lookupType(cpi, ANEWARRAY);
-        T length = frameState.ipop();
+        ValueNode length = frameState.ipop();
         if (type instanceof ResolvedJavaType) {
             frameState.apush(append(createNewArray((ResolvedJavaType) type, length, true)));
         } else {
@@ -681,12 +680,12 @@
 
     }
 
-    protected abstract T createNewArray(ResolvedJavaType elementType, T length, boolean fillContents);
+    protected abstract ValueNode createNewArray(ResolvedJavaType elementType, ValueNode length, boolean fillContents);
 
     private void genNewMultiArray(int cpi) {
         JavaType type = lookupType(cpi, MULTIANEWARRAY);
         int rank = getStream().readUByte(bci() + 3);
-        List<T> dims = new ArrayList<>(Collections.nCopies(rank, null));
+        List<ValueNode> dims = new ArrayList<>(Collections.nCopies(rank, null));
         for (int i = rank - 1; i >= 0; i--) {
             dims.set(i, frameState.ipop());
         }
@@ -697,18 +696,18 @@
         }
     }
 
-    protected abstract T createNewMultiArray(ResolvedJavaType type, List<T> dims);
+    protected abstract ValueNode createNewMultiArray(ResolvedJavaType type, List<ValueNode> dims);
 
-    protected abstract T genLoadField(T receiver, ResolvedJavaField field);
+    protected abstract ValueNode genLoadField(ValueNode receiver, ResolvedJavaField field);
 
     private void genGetField(JavaField field) {
         emitExplicitExceptions(frameState.peek(0), null);
 
         Kind kind = field.getKind();
-        T receiver = frameState.apop();
+        ValueNode receiver = frameState.apop();
         if ((field instanceof ResolvedJavaField) && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) {
             LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getLoadFieldPlugin();
-            if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, (ValueNode) receiver, (ResolvedJavaField) field)) {
+            if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, receiver, (ResolvedJavaField) field)) {
                 appendOptimizedLoadField(kind, genLoadField(receiver, (ResolvedJavaField) field));
             }
         } else {
@@ -716,15 +715,15 @@
         }
     }
 
-    protected abstract void emitNullCheck(T receiver);
+    protected abstract void emitNullCheck(ValueNode receiver);
 
-    protected abstract void emitBoundsCheck(T index, T length);
+    protected abstract void emitBoundsCheck(ValueNode index, ValueNode length);
 
     private static final DebugMetric EXPLICIT_EXCEPTIONS = Debug.metric("ExplicitExceptions");
 
-    protected abstract T genArrayLength(T x);
+    protected abstract ValueNode genArrayLength(ValueNode x);
 
-    protected void emitExplicitExceptions(T receiver, T outOfBoundsIndex) {
+    protected void emitExplicitExceptions(ValueNode receiver, ValueNode outOfBoundsIndex) {
         assert receiver != null;
         if (graphBuilderConfig.omitAllExceptionEdges() || profilingInfo == null ||
                         (optimisticOpts.useExceptionProbabilityForOperations() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE && !GraalOptions.StressExplicitExceptionCode.getValue())) {
@@ -733,19 +732,19 @@
 
         emitNullCheck(receiver);
         if (outOfBoundsIndex != null) {
-            T length = append(genArrayLength(receiver));
+            ValueNode length = append(genArrayLength(receiver));
             emitBoundsCheck(outOfBoundsIndex, length);
         }
         EXPLICIT_EXCEPTIONS.increment();
     }
 
-    protected abstract T genStoreField(T receiver, ResolvedJavaField field, T value);
+    protected abstract ValueNode genStoreField(ValueNode receiver, ResolvedJavaField field, ValueNode value);
 
     private void genPutField(JavaField field) {
         emitExplicitExceptions(frameState.peek(1), null);
 
-        T value = frameState.pop(field.getKind().getStackKind());
-        T receiver = frameState.apop();
+        ValueNode value = frameState.pop(field.getKind().getStackKind());
+        ValueNode receiver = frameState.apop();
         if (field instanceof ResolvedJavaField && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) {
             appendOptimizedStoreField(genStoreField(receiver, (ResolvedJavaField) field, value));
         } else {
@@ -766,7 +765,7 @@
     }
 
     private void genPutStatic(JavaField field) {
-        T value = frameState.pop(field.getKind().getStackKind());
+        ValueNode value = frameState.pop(field.getKind().getStackKind());
         if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) {
             appendOptimizedStoreField(genStoreField(null, (ResolvedJavaField) field, value));
         } else {
@@ -774,13 +773,13 @@
         }
     }
 
-    protected void appendOptimizedStoreField(T store) {
+    protected void appendOptimizedStoreField(ValueNode store) {
         append(store);
     }
 
-    protected void appendOptimizedLoadField(Kind kind, T load) {
+    protected void appendOptimizedLoadField(Kind kind, ValueNode load) {
         // append the load to the instruction
-        T optimized = append(load);
+        ValueNode optimized = append(load);
         frameState.push(kind.getStackKind(), optimized);
     }
 
@@ -794,11 +793,11 @@
 
     protected abstract void genInvokeSpecial(JavaMethod target);
 
-    protected abstract void genReturn(T x);
+    protected abstract void genReturn(ValueNode x);
 
-    protected abstract T genMonitorEnter(T x);
+    protected abstract ValueNode genMonitorEnter(ValueNode x);
 
-    protected abstract T genMonitorExit(T x, T returnValue);
+    protected abstract ValueNode genMonitorExit(ValueNode x, ValueNode returnValue);
 
     protected abstract void genJsr(int dest);
 
@@ -843,7 +842,7 @@
 
     private void genSwitch(BytecodeSwitch bs) {
         int bci = bci();
-        T value = frameState.ipop();
+        ValueNode value = frameState.ipop();
 
         int nofCases = bs.numberOfCases();
         double[] keyProbabilities = switchProbability(nofCases + 1, bci);
@@ -861,7 +860,7 @@
         int[] keySuccessors = new int[nofCases + 1];
         int deoptSuccessorIndex = -1;
         int nextSuccessorIndex = 0;
-        boolean constantValue = ((ValueNode) value).isConstant();
+        boolean constantValue = value.isConstant();
         for (int i = 0; i < nofCases + 1; i++) {
             if (i < nofCases) {
                 keys[i] = bs.keyAt(i);
@@ -888,7 +887,7 @@
 
     }
 
-    protected abstract void genIntegerSwitch(T value, ArrayList<BciBlock> actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors);
+    protected abstract void genIntegerSwitch(ValueNode value, ArrayList<BciBlock> actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors);
 
     private static class SuccessorInfo {
 
@@ -901,9 +900,9 @@
         }
     }
 
-    protected abstract T appendConstant(JavaConstant constant);
+    protected abstract ValueNode appendConstant(JavaConstant constant);
 
-    protected abstract T append(T v);
+    protected abstract ValueNode append(ValueNode v);
 
     protected boolean isNeverExecutedCode(double probability) {
         return probability == 0 && optimisticOpts.removeNeverExecutedCode();
@@ -1182,7 +1181,7 @@
         return method;
     }
 
-    public F getFrameState() {
+    public HIRFrameStateBuilder getFrameState() {
         return frameState;
     }
 
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Sun Feb 22 07:42:06 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Sun Feb 22 17:17:45 2015 +0100
@@ -172,7 +172,7 @@
             private int peelIteration;
         }
 
-        public class BytecodeParser extends AbstractBytecodeParser<ValueNode, HIRFrameStateBuilder> implements GraphBuilderContext {
+        public class BytecodeParser extends AbstractBytecodeParser implements GraphBuilderContext {
 
             private BciBlockMapping blockMap;
             private LocalLiveness liveness;
@@ -642,8 +642,8 @@
                 return (ValueNode) currentGraph.unique((Node & ValueNumberable) x);
             }
 
-            protected ValueNode genIfNode(ValueNode condition, ValueNode falseSuccessor, ValueNode trueSuccessor, double d) {
-                return new IfNode((LogicNode) condition, (FixedNode) falseSuccessor, (FixedNode) trueSuccessor, d);
+            protected ValueNode genIfNode(LogicNode condition, FixedNode falseSuccessor, FixedNode trueSuccessor, double d) {
+                return new IfNode(condition, falseSuccessor, trueSuccessor, d);
             }
 
             @Override
@@ -1228,7 +1228,7 @@
                             }
                             lastLoopExit = loopExit;
                             Debug.log("Target %s Exits %s, scanning framestates...", targetBlock, loop);
-                            newState.insertLoopProxies(loopExit, (HIRFrameStateBuilder) getEntryState(loop, this.getCurrentDimension()));
+                            newState.insertLoopProxies(loopExit, getEntryState(loop, this.getCurrentDimension()));
                             loopExit.setStateAfter(newState.create(bci));
                         }
 
@@ -1239,7 +1239,7 @@
                 return new Target(target, state);
             }
 
-            private AbstractFrameStateBuilder<?, ?> getEntryState(BciBlock block, int dimension) {
+            private HIRFrameStateBuilder getEntryState(BciBlock block, int dimension) {
                 int id = block.id;
                 if (dimension == 0) {
                     return entryStateArray[id];
@@ -1248,9 +1248,9 @@
                 }
             }
 
-            private AbstractFrameStateBuilder<?, ?> getEntryStateMultiDimension(int dimension, int id) {
+            private HIRFrameStateBuilder getEntryStateMultiDimension(int dimension, int id) {
                 if (entryStateMatrix != null && dimension - 1 < entryStateMatrix.length) {
-                    AbstractFrameStateBuilder<?, ?>[] entryStateArrayEntry = entryStateMatrix[dimension - 1];
+                    HIRFrameStateBuilder[] entryStateArrayEntry = entryStateMatrix[dimension - 1];
                     if (entryStateArrayEntry == null) {
                         return null;
                     }
@@ -1342,10 +1342,10 @@
             }
 
             private FixedNode createTarget(BciBlock block, HIRFrameStateBuilder state) {
-                return createTarget(block, state, false);
+                return createTarget(block, state, false, false);
             }
 
-            private FixedNode createTarget(BciBlock block, HIRFrameStateBuilder state, boolean isGoto) {
+            private FixedNode createTarget(BciBlock block, HIRFrameStateBuilder state, boolean canReuseInstruction, boolean canReuseState) {
                 assert block != null && state != null;
                 assert !block.isExceptionEntry || state.stackSize() == 1;
 
@@ -1358,7 +1358,7 @@
                      * this block again.
                      */
                     FixedNode targetNode;
-                    if (isGoto && (block.getPredecessorCount() == 1 || !controlFlowSplit) && !block.isLoopHeader && (currentBlock.loops & ~block.loops) == 0) {
+                    if (canReuseInstruction && (block.getPredecessorCount() == 1 || !controlFlowSplit) && !block.isLoopHeader && (currentBlock.loops & ~block.loops) == 0) {
                         setFirstInstruction(block, operatingDimension, lastInstr);
                         lastInstr = null;
                     } else {
@@ -1367,7 +1367,7 @@
                     targetNode = getFirstInstruction(block, operatingDimension);
                     Target target = checkLoopExit(targetNode, block, state);
                     FixedNode result = target.fixed;
-                    HIRFrameStateBuilder currentEntryState = target.state == state ? state.copy() : target.state;
+                    HIRFrameStateBuilder currentEntryState = target.state == state ? (canReuseState ? state : state.copy()) : target.state;
                     setEntryState(block, operatingDimension, currentEntryState);
                     currentEntryState.clearNonLiveLocals(block, liveness, true);
 
@@ -1376,7 +1376,7 @@
                 }
 
                 // We already saw this block before, so we have to merge states.
-                if (!((HIRFrameStateBuilder) getEntryState(block, operatingDimension)).isCompatibleWith(state)) {
+                if (!getEntryState(block, operatingDimension).isCompatibleWith(state)) {
                     throw bailout("stacks do not match; bytecodes would not verify");
                 }
 
@@ -1389,7 +1389,7 @@
                     LoopBeginNode loopBegin = (LoopBeginNode) getFirstInstruction(block, operatingDimension);
                     Target target = checkLoopExit(currentGraph.add(new LoopEndNode(loopBegin)), block, state);
                     FixedNode result = target.fixed;
-                    ((HIRFrameStateBuilder) getEntryState(block, operatingDimension)).merge(loopBegin, target.state);
+                    getEntryState(block, operatingDimension).merge(loopBegin, target.state);
 
                     Debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result);
                     return result;
@@ -1430,7 +1430,7 @@
                 EndNode newEnd = currentGraph.add(new EndNode());
                 Target target = checkLoopExit(newEnd, block, state);
                 FixedNode result = target.fixed;
-                ((HIRFrameStateBuilder) getEntryState(block, operatingDimension)).merge(mergeNode, target.state);
+                getEntryState(block, operatingDimension).merge(mergeNode, target.state);
                 mergeNode.addForwardEnd(newEnd);
 
                 Debug.log("createTarget %s: merging state, result: %s", block, result);
@@ -1501,45 +1501,27 @@
 
             protected void processBlock(BytecodeParser parser, BciBlock block) {
                 // Ignore blocks that have no predecessors by the time their bytecodes are parsed
-                if (block == null || getFirstInstruction(block, this.getCurrentDimension()) == null) {
+                int currentDimension = this.getCurrentDimension();
+                FixedWithNextNode firstInstruction = getFirstInstruction(block, currentDimension);
+                if (firstInstruction == null) {
                     Debug.log("Ignoring block %s", block);
                     return;
                 }
-                try (Indent indent = Debug.logAndIndent("Parsing block %s  firstInstruction: %s  loopHeader: %b", block, getFirstInstruction(block, this.getCurrentDimension()), block.isLoopHeader)) {
+                try (Indent indent = Debug.logAndIndent("Parsing block %s  firstInstruction: %s  loopHeader: %b", block, firstInstruction, block.isLoopHeader)) {
 
-                    lastInstr = getFirstInstruction(block, this.getCurrentDimension());
-                    frameState = (HIRFrameStateBuilder) getEntryState(block, this.getCurrentDimension());
+                    lastInstr = firstInstruction;
+                    frameState = getEntryState(block, currentDimension);
                     parser.setCurrentFrameState(frameState);
                     currentBlock = block;
 
-                    if (lastInstr instanceof AbstractMergeNode) {
-
-                        AbstractMergeNode abstractMergeNode = (AbstractMergeNode) lastInstr;
-                        if (abstractMergeNode.stateAfter() == null) {
-                            int bci = block.startBci;
-                            if (block instanceof ExceptionDispatchBlock) {
-                                bci = ((ExceptionDispatchBlock) block).deoptBci;
-                            }
-                            abstractMergeNode.setStateAfter(frameState.create(bci));
-                        }
+                    if (firstInstruction instanceof AbstractMergeNode) {
+                        setMergeStateAfter(block, firstInstruction);
                     }
 
                     if (block == blockMap.getReturnBlock()) {
-                        Kind returnKind = method.getSignature().getReturnKind().getStackKind();
-                        ValueNode x = returnKind == Kind.Void ? null : frameState.pop(returnKind);
-                        assert frameState.stackSize() == 0;
-                        beforeReturn(x);
-                        this.returnValue = x;
-                        this.beforeReturnNode = this.lastInstr;
+                        handleReturnBlock();
                     } else if (block == blockMap.getUnwindBlock()) {
-                        if (currentDepth == 0) {
-                            frameState.setRethrowException(false);
-                            createUnwind();
-                        } else {
-                            ValueNode exception = frameState.apop();
-                            this.unwindValue = exception;
-                            this.beforeUnwindNode = this.lastInstr;
-                        }
+                        handleUnwindBlock();
                     } else if (block instanceof ExceptionDispatchBlock) {
                         createExceptionDispatch((ExceptionDispatchBlock) block);
                     } else {
@@ -1549,6 +1531,37 @@
                 }
             }
 
+            private void handleUnwindBlock() {
+                if (currentDepth == 0) {
+                    frameState.setRethrowException(false);
+                    createUnwind();
+                } else {
+                    ValueNode exception = frameState.apop();
+                    this.unwindValue = exception;
+                    this.beforeUnwindNode = this.lastInstr;
+                }
+            }
+
+            private void handleReturnBlock() {
+                Kind returnKind = method.getSignature().getReturnKind().getStackKind();
+                ValueNode x = returnKind == Kind.Void ? null : frameState.pop(returnKind);
+                assert frameState.stackSize() == 0;
+                beforeReturn(x);
+                this.returnValue = x;
+                this.beforeReturnNode = this.lastInstr;
+            }
+
+            private void setMergeStateAfter(BciBlock block, FixedWithNextNode firstInstruction) {
+                AbstractMergeNode abstractMergeNode = (AbstractMergeNode) firstInstruction;
+                if (abstractMergeNode.stateAfter() == null) {
+                    int bci = block.startBci;
+                    if (block instanceof ExceptionDispatchBlock) {
+                        bci = ((ExceptionDispatchBlock) block).deoptBci;
+                    }
+                    abstractMergeNode.setStateAfter(frameState.create(bci));
+                }
+            }
+
             /**
              * Remove loop header without loop ends. This can happen with degenerated loops like
              * this one:
@@ -1636,7 +1649,7 @@
             }
 
             private void appendGoto(BciBlock successor) {
-                FixedNode targetInstr = createTarget(successor, frameState, true);
+                FixedNode targetInstr = createTarget(successor, frameState, true, true);
                 if (lastInstr != null && lastInstr != targetInstr) {
                     lastInstr.setNext(targetInstr);
                 }
@@ -1788,17 +1801,107 @@
                 BciBlock trueBlock = currentBlock.getSuccessor(0);
                 BciBlock falseBlock = currentBlock.getSuccessor(1);
                 if (trueBlock == falseBlock) {
+                    // The target block is the same independent of the condition.
                     appendGoto(trueBlock);
                     return;
                 }
 
-                // the mirroring and negation operations get the condition into canonical form
-                boolean mirror = cond.canonicalMirror();
+                ValueNode a = x;
+                ValueNode b = y;
+
+                // Check whether the condition needs to mirror the operands.
+                if (cond.canonicalMirror()) {
+                    a = y;
+                    b = x;
+                }
+
+                // Create the logic node for the condition.
+                LogicNode condition = createLogicNode(cond, a, b);
+
+                // Check whether the condition needs to negate the result.
                 boolean negate = cond.canonicalNegate();
 
-                ValueNode a = mirror ? y : x;
-                ValueNode b = mirror ? x : y;
+                // Remove a logic negation node and fold it into the negate boolean.
+                if (condition instanceof LogicNegationNode) {
+                    LogicNegationNode logicNegationNode = (LogicNegationNode) condition;
+                    negate = !negate;
+                    condition = logicNegationNode.getValue();
+                }
+
+                if (condition instanceof LogicConstantNode) {
+                    genConstantTargetIf(trueBlock, falseBlock, negate, condition);
+                } else {
+                    if (condition.graph() == null) {
+                        condition = currentGraph.unique(condition);
+                    }
+
+                    // Need to get probability based on current bci.
+                    double probability = branchProbability();
+
+                    if (negate) {
+                        BciBlock tmpBlock = trueBlock;
+                        trueBlock = falseBlock;
+                        falseBlock = tmpBlock;
+                        probability = 1 - probability;
+                    }
+
+                    if (isNeverExecutedCode(probability)) {
+                        append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, true));
+                        appendGoto(falseBlock);
+                        return;
+                    } else if (isNeverExecutedCode(1 - probability)) {
+                        append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, false));
+                        appendGoto(trueBlock);
+                        return;
+                    }
 
+                    int oldBci = stream.currentBCI();
+                    int trueBlockInt = checkPositiveIntConstantPushed(trueBlock);
+                    if (trueBlockInt != -1) {
+                        int falseBlockInt = checkPositiveIntConstantPushed(falseBlock);
+                        if (falseBlockInt != -1) {
+                            if (tryGenConditionalForIf(trueBlock, falseBlock, condition, oldBci, trueBlockInt, falseBlockInt)) {
+                                return;
+                            }
+                        }
+                    }
+
+                    this.controlFlowSplit = true;
+                    FixedNode trueSuccessor = createTarget(trueBlock, frameState, false, false);
+                    FixedNode falseSuccessor = createTarget(falseBlock, frameState, false, true);
+                    ValueNode ifNode = genIfNode(condition, trueSuccessor, falseSuccessor, probability);
+                    append(ifNode);
+                }
+            }
+
+            private boolean tryGenConditionalForIf(BciBlock trueBlock, BciBlock falseBlock, LogicNode condition, int oldBci, int trueBlockInt, int falseBlockInt) {
+                if (gotoOrFallThroughAfterConstant(trueBlock) && gotoOrFallThroughAfterConstant(falseBlock) && trueBlock.getSuccessor(0) == falseBlock.getSuccessor(0)) {
+                    genConditionalForIf(trueBlock, condition, oldBci, trueBlockInt, falseBlockInt, false);
+                    return true;
+                } else if (this.currentDepth != 0 && returnAfterConstant(trueBlock) && returnAfterConstant(falseBlock)) {
+                    genConditionalForIf(trueBlock, condition, oldBci, trueBlockInt, falseBlockInt, true);
+                    return true;
+                }
+                return false;
+            }
+
+            private void genConditionalForIf(BciBlock trueBlock, LogicNode condition, int oldBci, int trueBlockInt, int falseBlockInt, boolean genReturn) {
+                ConstantNode trueValue = currentGraph.unique(ConstantNode.forInt(trueBlockInt));
+                ConstantNode falseValue = currentGraph.unique(ConstantNode.forInt(falseBlockInt));
+                ValueNode conditionalNode = ConditionalNode.create(condition, trueValue, falseValue);
+                if (conditionalNode.graph() == null) {
+                    conditionalNode = currentGraph.addOrUnique(conditionalNode);
+                }
+                if (genReturn) {
+                    this.genReturn(conditionalNode);
+                } else {
+                    frameState.push(Kind.Int, conditionalNode);
+                    appendGoto(trueBlock.getSuccessor(0));
+                    stream.setBCI(oldBci);
+                }
+            }
+
+            private LogicNode createLogicNode(Condition cond, ValueNode a, ValueNode b) {
                 LogicNode condition;
                 assert !a.getKind().isNumericFloat();
                 if (cond == Condition.EQ || cond == Condition.NE) {
@@ -1811,80 +1914,20 @@
                     assert a.getKind() != Kind.Object && !cond.isUnsigned();
                     condition = genIntegerLessThan(a, b);
                 }
-
-                if (condition instanceof LogicNegationNode) {
-                    LogicNegationNode logicNegationNode = (LogicNegationNode) condition;
-                    negate = !negate;
-                    condition = logicNegationNode.getValue();
-                }
-
-                if (condition instanceof LogicConstantNode) {
-                    LogicConstantNode constantLogicNode = (LogicConstantNode) condition;
-                    boolean value = constantLogicNode.getValue();
-                    if (negate) {
-                        value = !value;
-                    }
-                    BciBlock nextBlock = falseBlock;
-                    if (value) {
-                        nextBlock = trueBlock;
-                    }
-                    appendGoto(nextBlock);
-                } else {
-
-                    if (condition.graph() == null) {
-                        condition = currentGraph.unique(condition);
-                    }
-
-                    // Need to get probability based on current bci.
-                    double probability = branchProbability();
-
-                    int oldBci = stream.currentBCI();
-                    int trueBlockInt = checkPositiveIntConstantPushed(trueBlock);
-                    if (trueBlockInt != -1) {
-                        int falseBlockInt = checkPositiveIntConstantPushed(falseBlock);
-                        if (falseBlockInt != -1) {
+                return condition;
+            }
 
-                            boolean genReturn = false;
-                            boolean genConditional = false;
-                            if (gotoOrFallThroughAfterConstant(trueBlock) && gotoOrFallThroughAfterConstant(falseBlock) && trueBlock.getSuccessor(0) == falseBlock.getSuccessor(0)) {
-                                genConditional = true;
-                            } else if (this.currentDepth != 0 && returnAfterConstant(trueBlock) && returnAfterConstant(falseBlock)) {
-                                genReturn = true;
-                                genConditional = true;
-                            }
-
-                            if (genConditional) {
-                                ConstantNode trueValue = currentGraph.unique(ConstantNode.forInt(trueBlockInt));
-                                ConstantNode falseValue = currentGraph.unique(ConstantNode.forInt(falseBlockInt));
-                                if (negate) {
-                                    ConstantNode tmp = falseValue;
-                                    falseValue = trueValue;
-                                    trueValue = tmp;
-                                }
-                                ValueNode conditionalNode = ConditionalNode.create(condition, trueValue, falseValue);
-                                if (conditionalNode.graph() == null) {
-                                    conditionalNode = currentGraph.addOrUnique(conditionalNode);
-                                }
-                                if (genReturn) {
-                                    this.genReturn(conditionalNode);
-                                } else {
-                                    frameState.push(Kind.Int, conditionalNode);
-                                    appendGoto(trueBlock.getSuccessor(0));
-                                    stream.setBCI(oldBci);
-                                }
-                                return;
-                            }
-                        }
-                    }
-
-                    this.controlFlowSplit = true;
-
-                    ValueNode trueSuccessor = createBlockTarget(probability, trueBlock, frameState);
-                    ValueNode falseSuccessor = createBlockTarget(1 - probability, falseBlock, frameState);
-
-                    ValueNode ifNode = negate ? genIfNode(condition, falseSuccessor, trueSuccessor, 1 - probability) : genIfNode(condition, trueSuccessor, falseSuccessor, probability);
-                    append(ifNode);
+            private void genConstantTargetIf(BciBlock trueBlock, BciBlock falseBlock, boolean negate, LogicNode condition) {
+                LogicConstantNode constantLogicNode = (LogicConstantNode) condition;
+                boolean value = constantLogicNode.getValue();
+                if (negate) {
+                    value = !value;
                 }
+                BciBlock nextBlock = falseBlock;
+                if (value) {
+                    nextBlock = trueBlock;
+                }
+                appendGoto(nextBlock);
             }
 
             private int checkPositiveIntConstantPushed(BciBlock block) {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Sun Feb 22 07:42:06 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Sun Feb 22 17:17:45 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, 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
@@ -31,6 +31,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.java.BciBlockMapping.*;
 import com.oracle.graal.java.GraphBuilderPlugin.ParameterPlugin;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
@@ -38,11 +39,27 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.util.*;
 
-public class HIRFrameStateBuilder extends AbstractFrameStateBuilder<ValueNode, HIRFrameStateBuilder> {
+public final class HIRFrameStateBuilder {
 
     private static final ValueNode[] EMPTY_ARRAY = new ValueNode[0];
     private static final MonitorIdNode[] EMPTY_MONITOR_ARRAY = new MonitorIdNode[0];
 
+    protected final ResolvedJavaMethod method;
+    protected int stackSize;
+    protected final ValueNode[] locals;
+    protected final ValueNode[] stack;
+    protected ValueNode[] lockedObjects;
+
+    /**
+     * Specifies if asserting type checks are enabled.
+     */
+    protected final boolean checkTypes;
+
+    /**
+     * @see BytecodeFrame#rethrowException
+     */
+    protected boolean rethrowException;
+
     private MonitorIdNode[] monitorIds;
     private final StructuredGraph graph;
     private final Supplier<FrameState> outerFrameStateSupplier;
@@ -54,7 +71,11 @@
      * @param graph the target graph of Graal nodes created by the builder
      */
     public HIRFrameStateBuilder(ResolvedJavaMethod method, StructuredGraph graph, boolean checkTypes, Supplier<FrameState> outerFrameStateSupplier) {
-        super(method, checkTypes);
+        this.method = method;
+        this.locals = allocateArray(method.getMaxLocals());
+        this.stack = allocateArray(Math.max(1, method.getMaxStackSize()));
+        this.lockedObjects = allocateArray(0);
+        this.checkTypes = checkTypes;
 
         assert graph != null;
 
@@ -63,7 +84,7 @@
         this.outerFrameStateSupplier = outerFrameStateSupplier;
     }
 
-    public final void initializeFromArgumentsArray(ValueNode[] arguments) {
+    public void initializeFromArgumentsArray(ValueNode[] arguments) {
 
         int javaIndex = 0;
         int index = 0;
@@ -82,7 +103,7 @@
         }
     }
 
-    public final void initializeForMethodStart(boolean eagerResolve, ParameterPlugin parameterPlugin) {
+    public void initializeForMethodStart(boolean eagerResolve, ParameterPlugin parameterPlugin) {
 
         int javaIndex = 0;
         int index = 0;
@@ -128,7 +149,17 @@
     }
 
     private HIRFrameStateBuilder(HIRFrameStateBuilder other) {
-        super(other);
+        this.method = other.method;
+        this.stackSize = other.stackSize;
+        this.locals = other.locals.clone();
+        this.stack = other.stack.clone();
+        this.lockedObjects = other.lockedObjects.length == 0 ? other.lockedObjects : other.lockedObjects.clone();
+        this.rethrowException = other.rethrowException;
+        this.checkTypes = other.checkTypes;
+
+        assert locals.length == method.getMaxLocals();
+        assert stack.length == Math.max(1, method.getMaxStackSize());
+
         assert other.graph != null;
         graph = other.graph;
         monitorIds = other.monitorIds.length == 0 ? other.monitorIds : other.monitorIds.clone();
@@ -139,8 +170,7 @@
         assert lockedObjects.length == monitorIds.length;
     }
 
-    @Override
-    protected ValueNode[] allocateArray(int length) {
+    private static ValueNode[] allocateArray(int length) {
         return length == 0 ? EMPTY_ARRAY : new ValueNode[length];
     }
 
@@ -175,12 +205,10 @@
         return graph.add(new FrameState(outerFrameState, method, bci, locals, stack, stackSize, lockedObjects, Arrays.asList(monitorIds), rethrowException, false));
     }
 
-    @Override
     public HIRFrameStateBuilder copy() {
         return new HIRFrameStateBuilder(this);
     }
 
-    @Override
     public boolean isCompatibleWith(HIRFrameStateBuilder other) {
         assert method.equals(other.method) && graph == other.graph && localsSize() == other.localsSize() : "Can only compare frame states of the same method";
         assert lockedObjects.length == monitorIds.length && other.lockedObjects.length == other.monitorIds.length : "mismatch between lockedObjects and monitorIds";
@@ -210,10 +238,18 @@
         assert isCompatibleWith(other);
 
         for (int i = 0; i < localsSize(); i++) {
-            storeLocal(i, merge(localAt(i), other.localAt(i), block));
+            ValueNode curLocal = localAt(i);
+            ValueNode mergedLocal = merge(curLocal, other.localAt(i), block);
+            if (curLocal != mergedLocal) {
+                storeLocal(i, mergedLocal);
+            }
         }
         for (int i = 0; i < stackSize(); i++) {
-            storeStack(i, merge(stackAt(i), other.stackAt(i), block));
+            ValueNode curStack = stackAt(i);
+            ValueNode mergedStack = merge(curStack, other.stackAt(i), block);
+            if (curStack != mergedStack) {
+                storeStack(i, mergedStack);
+            }
         }
         for (int i = 0; i < lockedObjects.length; i++) {
             lockedObjects[i] = merge(lockedObjects[i], other.lockedObjects[i], block);
@@ -224,7 +260,6 @@
     private ValueNode merge(ValueNode currentValue, ValueNode otherValue, AbstractMergeNode block) {
         if (currentValue == null || currentValue.isDeleted()) {
             return null;
-
         } else if (block.isPhiAtMerge(currentValue)) {
             if (otherValue == null || otherValue.isDeleted() || currentValue.getKind() != otherValue.getKind()) {
                 propagateDelete((ValuePhiNode) currentValue);
@@ -232,26 +267,27 @@
             }
             ((PhiNode) currentValue).addInput(otherValue);
             return currentValue;
-
         } else if (currentValue != otherValue) {
             assert !(block instanceof LoopBeginNode) : "Phi functions for loop headers are create eagerly for changed locals and all stack slots";
             if (otherValue == null || otherValue.isDeleted() || currentValue.getKind() != otherValue.getKind()) {
                 return null;
             }
-
-            ValuePhiNode phi = graph.addWithoutUnique(new ValuePhiNode(currentValue.stamp().unrestricted(), block));
-            for (int i = 0; i < block.phiPredecessorCount(); i++) {
-                phi.addInput(currentValue);
-            }
-            phi.addInput(otherValue);
-            assert phi.valueCount() == block.phiPredecessorCount() + 1 : "valueCount=" + phi.valueCount() + " predSize= " + block.phiPredecessorCount();
-            return phi;
-
+            return createValuePhi(currentValue, otherValue, block);
         } else {
             return currentValue;
         }
     }
 
+    private ValuePhiNode createValuePhi(ValueNode currentValue, ValueNode otherValue, AbstractMergeNode block) {
+        ValuePhiNode phi = graph.addWithoutUnique(new ValuePhiNode(currentValue.stamp().unrestricted(), block));
+        for (int i = 0; i < block.phiPredecessorCount(); i++) {
+            phi.addInput(currentValue);
+        }
+        phi.addInput(otherValue);
+        assert phi.valueCount() == block.phiPredecessorCount() + 1;
+        return phi;
+    }
+
     private void propagateDelete(FloatingNode node) {
         assert node instanceof ValuePhiNode || node instanceof ProxyNode;
         if (node.isDeleted()) {
@@ -380,7 +416,6 @@
     /**
      * @return the current lock depth
      */
-    @Override
     public int lockDepth() {
         assert lockedObjects.length == monitorIds.length;
         return lockedObjects.length;
@@ -405,4 +440,433 @@
         }
         return false;
     }
+
+    public void clearNonLiveLocals(BciBlock block, LocalLiveness liveness, boolean liveIn) {
+        /*
+         * (lstadler) if somebody is tempted to remove/disable this clearing code: it's possible to
+         * remove it for normal compilations, but not for OSR compilations - otherwise dead object
+         * slots at the OSR entry aren't cleared. it is also not enough to rely on PiNodes with
+         * Kind.Illegal, because the conflicting branch might not have been parsed.
+         */
+        if (liveness == null) {
+            return;
+        }
+        if (liveIn) {
+            for (int i = 0; i < locals.length; i++) {
+                if (!liveness.localIsLiveIn(block, i)) {
+                    locals[i] = null;
+                }
+            }
+        } else {
+            for (int i = 0; i < locals.length; i++) {
+                if (!liveness.localIsLiveOut(block, i)) {
+                    locals[i] = null;
+                }
+            }
+        }
+    }
+
+    /**
+     * @see BytecodeFrame#rethrowException
+     */
+    public boolean rethrowException() {
+        return rethrowException;
+    }
+
+    /**
+     * @see BytecodeFrame#rethrowException
+     */
+    public void setRethrowException(boolean b) {
+        rethrowException = b;
+    }
+
+    /**
+     * Returns the size of the local variables.
+     *
+     * @return the size of the local variables
+     */
+    public int localsSize() {
+        return locals.length;
+    }
+
+    /**
+     * Gets the current size (height) of the stack.
+     */
+    public int stackSize() {
+        return stackSize;
+    }
+
+    /**
+     * Gets the value in the local variables at the specified index, without any sanity checking.
+     *
+     * @param i the index into the locals
+     * @return the instruction that produced the value for the specified local
+     */
+    public ValueNode localAt(int i) {
+        return locals[i];
+    }
+
+    /**
+     * Get the value on the stack at the specified stack index.
+     *
+     * @param i the index into the stack, with {@code 0} being the bottom of the stack
+     * @return the instruction at the specified position in the stack
+     */
+    public ValueNode stackAt(int i) {
+        return stack[i];
+    }
+
+    /**
+     * Gets the value in the lock at the specified index, without any sanity checking.
+     *
+     * @param i the index into the lock
+     * @return the instruction that produced the value for the specified lock
+     */
+    public ValueNode lockAt(int i) {
+        return lockedObjects[i];
+    }
+
+    public void storeLock(int i, ValueNode lock) {
+        lockedObjects[i] = lock;
+    }
+
+    /**
+     * Loads the local variable at the specified index, checking that the returned value is non-null
+     * and that two-stack values are properly handled.
+     *
+     * @param i the index of the local variable to load
+     * @return the instruction that produced the specified local
+     */
+    public ValueNode loadLocal(int i) {
+        ValueNode x = locals[i];
+        assert assertLoadLocal(i, x);
+        return x;
+    }
+
+    private boolean assertLoadLocal(int i, ValueNode x) {
+        assert x != null : i;
+        assert !checkTypes || (x.getKind().getSlotCount() == 1 || locals[i + 1] == null);
+        assert !checkTypes || (i == 0 || locals[i - 1] == null || locals[i - 1].getKind().getSlotCount() == 1);
+        return true;
+    }
+
+    /**
+     * Stores a given local variable at the specified index. If the value occupies two slots, then
+     * the next local variable index is also overwritten.
+     *
+     * @param i the index at which to store
+     * @param x the instruction which produces the value for the local
+     */
+    public void storeLocal(int i, ValueNode x) {
+        assert assertStoreLocal(x);
+        locals[i] = x;
+        if (x != null && x.getKind().needsTwoSlots()) {
+            // if this is a double word, then kill i+1
+            locals[i + 1] = null;
+        }
+        if (x != null && i > 0) {
+            ValueNode p = locals[i - 1];
+            if (p != null && p.getKind().needsTwoSlots()) {
+                // if there was a double word at i - 1, then kill it
+                locals[i - 1] = null;
+            }
+        }
+    }
+
+    private boolean assertStoreLocal(ValueNode x) {
+        assert x == null || !checkTypes || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal) : "unexpected value: " + x;
+        return true;
+    }
+
+    public void storeStack(int i, ValueNode x) {
+        assert assertStoreStack(i, x);
+        stack[i] = x;
+    }
+
+    private boolean assertStoreStack(int i, ValueNode x) {
+        assert x == null || (stack[i] == null || x.getKind() == stack[i].getKind()) : "Method does not handle changes from one-slot to two-slot values or non-alive values";
+        return true;
+    }
+
+    /**
+     * Pushes an instruction onto the stack with the expected type.
+     *
+     * @param kind the type expected for this instruction
+     * @param x the instruction to push onto the stack
+     */
+    public void push(Kind kind, ValueNode x) {
+        assert assertPush(kind, x);
+        xpush(x);
+        if (kind.needsTwoSlots()) {
+            xpush(null);
+        }
+    }
+
+    private boolean assertPush(Kind kind, ValueNode x) {
+        assert !checkTypes || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal);
+        assert x != null && (!checkTypes || x.getKind() == kind);
+        return true;
+    }
+
+    /**
+     * Pushes a value onto the stack without checking the type.
+     *
+     * @param x the instruction to push onto the stack
+     */
+    public void xpush(ValueNode x) {
+        assert assertXpush(x);
+        stack[stackSize++] = x;
+    }
+
+    private boolean assertXpush(ValueNode x) {
+        assert !checkTypes || (x == null || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal));
+        return true;
+    }
+
+    /**
+     * Pushes a value onto the stack and checks that it is an int.
+     *
+     * @param x the instruction to push onto the stack
+     */
+    public void ipush(ValueNode x) {
+        assert assertInt(x);
+        xpush(x);
+    }
+
+    /**
+     * Pushes a value onto the stack and checks that it is a float.
+     *
+     * @param x the instruction to push onto the stack
+     */
+    public void fpush(ValueNode x) {
+        assert assertFloat(x);
+        xpush(x);
+    }
+
+    /**
+     * Pushes a value onto the stack and checks that it is an object.
+     *
+     * @param x the instruction to push onto the stack
+     */
+    public void apush(ValueNode x) {
+        assert assertObject(x);
+        xpush(x);
+    }
+
+    /**
+     * Pushes a value onto the stack and checks that it is a long.
+     *
+     * @param x the instruction to push onto the stack
+     */
+    public void lpush(ValueNode x) {
+        assert assertLong(x);
+        xpush(x);
+        xpush(null);
+    }
+
+    /**
+     * Pushes a value onto the stack and checks that it is a double.
+     *
+     * @param x the instruction to push onto the stack
+     */
+    public void dpush(ValueNode x) {
+        assert assertDouble(x);
+        xpush(x);
+        xpush(null);
+    }
+
+    public void pushReturn(Kind kind, ValueNode x) {
+        if (kind != Kind.Void) {
+            push(kind.getStackKind(), x);
+        }
+    }
+
+    /**
+     * Pops an instruction off the stack with the expected type.
+     *
+     * @param kind the expected type
+     * @return the instruction on the top of the stack
+     */
+    public ValueNode pop(Kind kind) {
+        if (kind.needsTwoSlots()) {
+            xpop();
+        }
+        assert assertPop(kind);
+        return xpop();
+    }
+
+    private boolean assertPop(Kind kind) {
+        assert kind != Kind.Void;
+        ValueNode x = xpeek();
+        assert x != null && (!checkTypes || x.getKind() == kind);
+        return true;
+    }
+
+    /**
+     * Pops a value off of the stack without checking the type.
+     *
+     * @return x the instruction popped off the stack
+     */
+    public ValueNode xpop() {
+        return stack[--stackSize];
+    }
+
+    private ValueNode xpeek() {
+        return stack[stackSize - 1];
+    }
+
+    /**
+     * Pops a value off of the stack and checks that it is an int.
+     *
+     * @return x the instruction popped off the stack
+     */
+    public ValueNode ipop() {
+        assert assertIntPeek();
+        return xpop();
+    }
+
+    /**
+     * Pops a value off of the stack and checks that it is a float.
+     *
+     * @return x the instruction popped off the stack
+     */
+    public ValueNode fpop() {
+        assert assertFloatPeek();
+        return xpop();
+    }
+
+    /**
+     * Pops a value off of the stack and checks that it is an object.
+     *
+     * @return x the instruction popped off the stack
+     */
+    public ValueNode apop() {
+        assert assertObjectPeek();
+        return xpop();
+    }
+
+    /**
+     * Pops a value off of the stack and checks that it is a long.
+     *
+     * @return x the instruction popped off the stack
+     */
+    public ValueNode lpop() {
+        assert assertHighPeek();
+        xpop();
+        assert assertLongPeek();
+        return xpop();
+    }
+
+    /**
+     * Pops a value off of the stack and checks that it is a double.
+     *
+     * @return x the instruction popped off the stack
+     */
+    public ValueNode dpop() {
+        assert assertHighPeek();
+        xpop();
+        assert assertDoublePeek();
+        return xpop();
+    }
+
+    /**
+     * Pop the specified number of slots off of this stack and return them as an array of
+     * instructions.
+     *
+     * @return an array containing the arguments off of the stack
+     */
+    public ValueNode[] popArguments(int argSize) {
+        ValueNode[] result = allocateArray(argSize);
+        int newStackSize = stackSize;
+        for (int i = argSize - 1; i >= 0; i--) {
+            newStackSize--;
+            if (stack[newStackSize] == null) {
+                /* Two-slot value. */
+                newStackSize--;
+                assert stack[newStackSize].getKind().needsTwoSlots();
+            } else {
+                assert !checkTypes || (stack[newStackSize].getKind().getSlotCount() == 1);
+            }
+            result[i] = stack[newStackSize];
+        }
+        stackSize = newStackSize;
+        return result;
+    }
+
+    /**
+     * Peeks an element from the operand stack.
+     *
+     * @param argumentNumber The number of the argument, relative from the top of the stack (0 =
+     *            top). Long and double arguments only count as one argument, i.e., null-slots are
+     *            ignored.
+     * @return The peeked argument.
+     */
+    public ValueNode peek(int argumentNumber) {
+        int idx = stackSize() - 1;
+        for (int i = 0; i < argumentNumber; i++) {
+            if (stackAt(idx) == null) {
+                idx--;
+                assert stackAt(idx).getKind().needsTwoSlots();
+            }
+            idx--;
+        }
+        return stackAt(idx);
+    }
+
+    /**
+     * Clears all values on this stack.
+     */
+    public void clearStack() {
+        stackSize = 0;
+    }
+
+    private boolean assertLongPeek() {
+        return assertLong(xpeek());
+    }
+
+    private static boolean assertLong(ValueNode x) {
+        assert x != null && (x.getKind() == Kind.Long);
+        return true;
+    }
+
+    private boolean assertIntPeek() {
+        return assertInt(xpeek());
+    }
+
+    private static boolean assertInt(ValueNode x) {
+        assert x != null && (x.getKind() == Kind.Int);
+        return true;
+    }
+
+    private boolean assertFloatPeek() {
+        return assertFloat(xpeek());
+    }
+
+    private static boolean assertFloat(ValueNode x) {
+        assert x != null && (x.getKind() == Kind.Float);
+        return true;
+    }
+
+    private boolean assertObjectPeek() {
+        return assertObject(xpeek());
+    }
+
+    private boolean assertObject(ValueNode x) {
+        assert x != null && (!checkTypes || (x.getKind() == Kind.Object));
+        return true;
+    }
+
+    private boolean assertDoublePeek() {
+        return assertDouble(xpeek());
+    }
+
+    private static boolean assertDouble(ValueNode x) {
+        assert x != null && (x.getKind() == Kind.Double);
+        return true;
+    }
+
+    private boolean assertHighPeek() {
+        assert xpeek() == null;
+        return true;
+    }
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Sun Feb 22 07:42:06 2015 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Sun Feb 22 17:17:45 2015 +0100
@@ -32,6 +32,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.graph.*;
 import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure;
@@ -111,6 +112,12 @@
         };
         ReentrantBlockIterator.apply(closure, cfg.getStartBlock());
         assert VirtualUtil.assertNonReachable(graph, obsoleteNodes);
+        for (Node fixed : obsoleteNodes) {
+            if (fixed.isAlive()) {
+                fixed.replaceAtUsages(null);
+                GraphUtil.killWithUnusedFloatingInputs(fixed);
+            }
+        }
     }
 
     @Override
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Sun Feb 22 07:42:06 2015 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Sun Feb 22 17:17:45 2015 +0100
@@ -101,7 +101,7 @@
                     Debug.dump(graph, "after " + getName() + " iteration");
                 }
 
-                new DeadCodeEliminationPhase(Required).apply(graph);
+                new DeadCodeEliminationPhase(Optional).apply(graph);
 
                 Set<Node> changedNodes = listener.getNodes();
                 for (Node node : graph.getNodes()) {
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Sun Feb 22 07:42:06 2015 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Sun Feb 22 17:17:45 2015 +0100
@@ -130,23 +130,16 @@
      *
      * @param node The fixed node that should be deleted.
      */
-    public void deleteFixedNode(final FixedWithNextNode node) {
+    public void deleteNode(final Node node) {
         add("delete fixed node", (graph, obsoleteNodes) -> {
-            GraphUtil.unlinkFixedNode(node);
-            assert obsoleteNodes.add(node);
+            if (node instanceof FixedWithNextNode) {
+                GraphUtil.unlinkFixedNode((FixedWithNextNode) node);
+            }
+            obsoleteNodes.add(node);
         });
     }
 
     /**
-     * Removes the given fixed node from the control flow.
-     *
-     * @param node The fixed node that should be deleted.
-     */
-    public void unlinkFixedNode(final FixedWithNextNode node) {
-        add("unlink fixed node", graph -> GraphUtil.unlinkFixedNode(node));
-    }
-
-    /**
      * Replaces the given node at its usages without deleting it. If the current node is a fixed
      * node it will be disconnected from the control flow, so that it will be deleted by a
      * subsequent {@link DeadCodeEliminationPhase}
@@ -165,11 +158,9 @@
             }
             node.replaceAtUsages(replacement);
             if (node instanceof FixedWithNextNode) {
-                FixedNode next = ((FixedWithNextNode) node).next();
-                ((FixedWithNextNode) node).setNext(null);
-                node.replaceAtPredecessor(next);
-                assert obsoleteNodes.add(node);
+                GraphUtil.unlinkFixedNode((FixedWithNextNode) node);
             }
+            GraphUtil.killWithUnusedFloatingInputs(node);
         });
     }
 
@@ -194,13 +185,4 @@
             }
         });
     }
-
-    /**
-     * Performs a custom action.
-     *
-     * @param action The action that should be performed when the effects are applied.
-     */
-    public void customAction(final Runnable action) {
-        add("customAction", graph -> action.run());
-    }
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java	Sun Feb 22 07:42:06 2015 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java	Sun Feb 22 17:17:45 2015 +0100
@@ -94,7 +94,7 @@
             ValueNode value = getScalarAlias(store.value());
             boolean result = false;
             if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
-                effects.deleteFixedNode(store);
+                effects.deleteNode(store);
                 result = true;
             }
             state.killReadCache(store.field());
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Sun Feb 22 07:42:06 2015 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Sun Feb 22 17:17:45 2015 +0100
@@ -75,7 +75,7 @@
                     StoreFieldNode store = (StoreFieldNode) node;
                     ValueNode value = getScalarAlias(store.value());
                     if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
-                        effects.deleteFixedNode(store);
+                        effects.deleteNode(store);
                         deleted = true;
                     }
                     state.killReadCache(store.field());
@@ -108,7 +108,7 @@
 
                 ValueNode value = getScalarAlias(write.value());
                 if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
-                    effects.deleteFixedNode(write);
+                    effects.deleteNode(write);
                     deleted = true;
                 }
                 processIdentity(state, write.location().getLocationIdentity());
@@ -141,7 +141,7 @@
 
                     ValueNode value = getScalarAlias(write.value());
                     if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
-                        effects.deleteFixedNode(write);
+                        effects.deleteNode(write);
                         deleted = true;
                     }
                     processIdentity(state, write.getLocationIdentity());
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java	Sun Feb 22 07:42:06 2015 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java	Sun Feb 22 17:17:45 2015 +0100
@@ -62,7 +62,7 @@
         }
 
         for (Node node : obsoleteNodes) {
-            if (node instanceof FixedNode) {
+            if (node instanceof FixedNode && !node.isDeleted()) {
                 assert !flood.isMarked(node) : node;
             }
         }
@@ -87,7 +87,7 @@
         }
         boolean success = true;
         for (Node node : obsoleteNodes) {
-            if (flood.isMarked(node)) {
+            if (!node.isDeleted() && flood.isMarked(node)) {
                 TTY.println("offending node path:");
                 Node current = node;
                 TTY.print(current.toString());
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Sun Feb 22 07:42:06 2015 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java	Sun Feb 22 17:17:45 2015 +0100
@@ -117,9 +117,7 @@
     @Override
     public void replaceWithVirtual(VirtualObjectNode virtual) {
         closure.addAndMarkAlias(virtual, current);
-        if (current instanceof FixedWithNextNode) {
-            effects.deleteFixedNode((FixedWithNextNode) current);
-        }
+        effects.deleteNode(current);
         deleted = true;
     }
 
@@ -132,7 +130,7 @@
 
     @Override
     public void delete() {
-        effects.deleteFixedNode((FixedWithNextNode) current);
+        effects.deleteNode(current);
         deleted = true;
     }