changeset 10696:062304c74353

merge.
author Christian Humer <christian.humer@gmail.com>
date Thu, 11 Jul 2013 01:56:42 +0200
parents 8c8e47cc101d (current diff) 31266ceb86ef (diff)
children 5c1afcee72ec
files
diffstat 20 files changed, 487 insertions(+), 254 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java	Thu Jul 11 01:55:54 2013 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java	Thu Jul 11 01:56:42 2013 +0200
@@ -25,6 +25,7 @@
 import static com.oracle.graal.sparc.SPARC.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.graph.*;
 
 public class SPARCAddress extends AbstractAddress {
 
@@ -34,7 +35,8 @@
     private static final int STACK_BIAS = 0x7ff;
 
     private final Register base;
-    private final int displacement; // need Register offset / displacement CompositeValue?
+    private final Register index;
+    private final int displacement;
 
     /**
      * Creates an {@link SPARCAddress} with given base register, no scaling and a given
@@ -45,17 +47,41 @@
      */
     public SPARCAddress(Register base, int displacement) {
         this.base = base;
+        this.index = Register.None;
         this.displacement = displacement;
     }
 
+    /**
+     * Creates an {@link SPARCAddress} with given base register, no scaling and a given index.
+     * 
+     * @param base the base register
+     * @param index the index register
+     */
+    public SPARCAddress(Register base, Register index) {
+        this.base = base;
+        this.index = index;
+        this.displacement = 0;
+    }
+
     @Override
     public String toString() {
         StringBuilder s = new StringBuilder();
         s.append("[");
+        String sep = "";
         if (!getBase().equals(Register.None)) {
             s.append(getBase());
+            sep = " + ";
         }
-        // later: displacement CompositeValue?
+        if (!getIndex().equals(Register.None)) {
+            s.append(sep).append(getIndex());
+            sep = " + ";
+        } else {
+            if (getDisplacement() < 0) {
+                s.append(" - ").append(-getDisplacement());
+            } else if (getDisplacement() > 0) {
+                s.append(sep).append(getDisplacement());
+            }
+        }
         s.append("]");
         return s.toString();
     }
@@ -69,9 +95,20 @@
     }
 
     /**
+     * @return Index register, the value of which is added to {@link #getBase}. If not present, is
+     *         denoted by {@link Register#None}.
+     */
+    public Register getIndex() {
+        return index;
+    }
+
+    /**
      * @return Optional additive displacement.
      */
     public int getDisplacement() {
+        if (!getIndex().equals(Register.None)) {
+            throw GraalInternalError.shouldNotReachHere("address has index register");
+        }
         // TODO Should we also hide the register save area size here?
         if (getBase() == sp || getBase() == fp) {
             return displacement + STACK_BIAS;
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Thu Jul 11 01:55:54 2013 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Thu Jul 11 01:56:42 2013 +0200
@@ -22,14 +22,14 @@
  */
 package com.oracle.graal.asm.sparc;
 
+import static com.oracle.graal.sparc.SPARC.*;
+
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.Kind;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
-import com.oracle.graal.hotspot.HotSpotGraalRuntime;
+import com.oracle.graal.hotspot.*;
 import com.oracle.graal.sparc.*;
 
-import static com.oracle.graal.sparc.SPARC.*;
-
 /**
  * This class implements an assembler that can encode most SPARC instructions.
  */
@@ -57,20 +57,66 @@
     // @formatter:on
     public static class Fmt00a {
 
+        private static final int OP_SHIFT = 30;
+        private static final int RD_SHIFT = 25;
+        private static final int OP2_SHIFT = 22;
+        private static final int IMM22_SHIFT = 0;
+
+        // @formatter:off
+        private static final int OP_MASK    = 0b11000000000000000000000000000000;
+        private static final int RD_MASK    = 0b00111110000000000000000000000000;
+        private static final int OP2_MASK   = 0b00000001110000000000000000000000;
+        private static final int IMM22_MASK = 0b00000000001111111111111111111111;
+        // @formatter:on
+
         private int rd;
         private int op2;
         private int imm22;
 
+        private Fmt00a(int rd, int op2, int imm22) {
+            this.rd = rd;
+            this.op2 = op2;
+            this.imm22 = imm22;
+            verify();
+        }
+
         public Fmt00a(Op2s op2, int imm22, Register rd) {
-            this.op2 = op2.getValue();
-            this.imm22 = imm22;
-            this.rd = rd.encoding();
+            this(rd.encoding(), op2.getValue(), hi22(imm22));
+        }
+
+        private int getInstructionBits() {
+            return Ops.BranchOp.getValue() << OP_SHIFT | rd << RD_SHIFT | op2 << OP2_SHIFT | (imm22 & IMM22_MASK) << IMM22_SHIFT;
+        }
+
+        public static Fmt00a read(SPARCAssembler masm, int pos) {
+            final int inst = masm.codeBuffer.getInt(pos);
+
+            // Make sure it's the right instruction:
+            final int op = (inst & OP_MASK) >> OP_SHIFT;
+            assert op == Ops.BranchOp.getValue();
+
+            // Get the instruction fields:
+            final int rd = (inst & RD_MASK) >> RD_SHIFT;
+            final int op2 = (inst & OP2_MASK) >> OP2_SHIFT;
+            final int imm22 = (inst & IMM22_MASK) >> IMM22_SHIFT;
+
+            return new Fmt00a(op2, imm22, rd);
+        }
+
+        public void write(SPARCAssembler masm, int pos) {
+            verify();
+            masm.codeBuffer.emitInt(getInstructionBits(), pos);
         }
 
         public void emit(SPARCAssembler masm) {
-            assert rd < 0x40;
-            assert op2 < 0x8;
-            masm.emitInt(Ops.BranchOp.getValue() << 30 | rd << 25 | op2 << 22 | (imm22 & 0x003fffff));
+            verify();
+            masm.emitInt(getInstructionBits());
+        }
+
+        public void verify() {
+            assert ((rd << RD_SHIFT) & RD_MASK) == (rd << RD_SHIFT);
+            assert ((op2 << OP2_SHIFT) & OP2_MASK) == (op2 << OP2_SHIFT);
+            assert ((imm22 << IMM22_SHIFT) & IMM22_MASK) == (imm22 << IMM22_SHIFT);
         }
     }
 
@@ -623,7 +669,7 @@
             assert ((i << I_SHIFT) & I_MASK) == (i << I_SHIFT);
             assert ((immAsi << IMM_ASI_SHIFT) & IMM_ASI_MASK) == (immAsi << IMM_ASI_SHIFT);
             assert ((rs2 << RS2_SHIFT) & RS2_MASK) == (rs2 << RS2_SHIFT);
-            assert isSimm13(simm13);
+            assert isSimm13(simm13) : String.format("simm13: %d (%x)", simm13, simm13);
         }
     }
 
@@ -1226,6 +1272,10 @@
         return min13 <= src && src <= max13;
     }
 
+    public static boolean isSimm13(long src) {
+        return NumUtil.isInt(src) && min13 <= src && src <= max13;
+    }
+
     public static final int hi22(int x) {
         return x >> 10;
     }
@@ -2866,15 +2916,31 @@
 
     public static class Stw extends Fmt11 {
 
+        public Stw(Register dst, Register src1, Register src2) {
+            super(Op3s.Stw, src1, src2, dst);
+        }
+
+        public Stw(Register dst, Register src1, int simm13) {
+            super(Op3s.Stw, src1, simm13, dst);
+        }
+
         public Stw(Register dst, SPARCAddress addr) {
-            super(Op3s.Stw, addr.getBase(), addr.getDisplacement(), dst);
+            this(dst, addr.getBase(), addr.getDisplacement());
         }
     }
 
     public static class Stx extends Fmt11 {
 
+        public Stx(Register dst, Register src1, Register src2) {
+            super(Op3s.Stx, src1, src2, dst);
+        }
+
+        public Stx(Register dst, Register src1, int simm13) {
+            super(Op3s.Stx, src1, simm13, dst);
+        }
+
         public Stx(Register dst, SPARCAddress addr) {
-            super(Op3s.Stx, addr.getBase(), addr.getDisplacement(), dst);
+            this(dst, addr.getBase(), addr.getDisplacement());
         }
     }
 
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Thu Jul 11 01:55:54 2013 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Thu Jul 11 01:56:42 2013 +0200
@@ -107,14 +107,10 @@
         }
     }
 
-    public static class Clr {
+    public static class Clr extends Or {
 
-        public Clr(SPARCAssembler asm, Register dst) {
-            new Or(g0, g0, dst).emit(asm);
-        }
-
-        public Clr(SPARCAssembler asm, SPARCAddress addr) {
-            new Stw(g0, addr).emit(asm);
+        public Clr(Register dst) {
+            super(g0, g0, dst);
         }
     }
 
@@ -279,12 +275,19 @@
         }
     }
 
-    @SuppressWarnings("unused")
     public static class Setuw {
 
-        public Setuw(SPARCAssembler masm, int value, Register dst) {
+        private int value;
+        private Register dst;
+
+        public Setuw(int value, Register dst) {
+            this.value = value;
+            this.dst = dst;
+        }
+
+        public void emit(SPARCMacroAssembler masm) {
             if (value == 0) {
-                new Clr(masm, dst);
+                new Clr(dst).emit(masm);
             } else if (-4095 <= value && value <= 4096) {
                 new Or(g0, value, dst).emit(masm);
             } else if (value >= 0 && ((value & 0x3FFF) == 0)) {
@@ -298,41 +301,54 @@
 
     public static class Setx {
 
-        public Setx(SPARCAssembler asm, long value, Register tmp, Register dst) {
+        private long value;
+        private Register tmp;
+        private Register dst;
+
+        public Setx(long value, Register tmp, Register dst) {
+            this.value = value;
+            this.tmp = tmp;
+            this.dst = dst;
+        }
+
+        public void emit(SPARCMacroAssembler masm) {
             int hi = (int) (value >> 32);
             int lo = (int) (value & ~0);
 
             if (isSimm13(lo) && value == lo) {
-                new Or(g0, lo, dst).emit(asm);
+                new Or(g0, lo, dst).emit(masm);
             } else if (hi == 0) {
-                new Sethi(lo, dst).emit(asm);   // hardware version zero-extends to upper 32
+                new Sethi(lo, dst).emit(masm);   // hardware version zero-extends to upper 32
                 if (lo10(lo) != 0) {
-                    new Or(dst, lo10(lo), dst).emit(asm);
+                    new Or(dst, lo10(lo), dst).emit(masm);
                 }
             } else if (hi == -1) {
-                new Sethi(~lo, dst).emit(asm);  // hardware version zero-extends to upper 32
-                new Xor(dst, lo10(lo) ^ ~lo10(~0), dst).emit(asm);
+                new Sethi(~lo, dst).emit(masm);  // hardware version zero-extends to upper 32
+                new Xor(dst, ~lo10(~0), dst).emit(masm);
+                new Add(dst, lo10(lo), dst).emit(masm);
             } else if (lo == 0) {
                 if (isSimm13(hi)) {
-                    new Or(g0, hi, dst).emit(asm);
+                    new Or(g0, hi, dst).emit(masm);
                 } else {
-                    new Sethi(hi, dst).emit(asm);   // hardware version zero-extends to upper 32
+                    new Sethi(hi, dst).emit(masm);   // hardware version zero-extends to upper 32
                     if (lo10(hi) != 0) {
-                        new Or(dst, lo10(hi), dst).emit(asm);
+                        new Or(dst, lo10(hi), dst).emit(masm);
                     }
                 }
-                new Sllx(dst, 32, dst).emit(asm);
+                new Sllx(dst, 32, dst).emit(masm);
             } else {
-                new Sethi(hi, tmp).emit(asm);
-                new Sethi(lo, dst).emit(asm); // macro assembler version sign-extends
+                // TODO Use the same logic as in MacroAssembler::internal_sethi, which doesn't need
+// a scratch register.
+                new Sethi(hi, tmp).emit(masm);
+                new Sethi(lo, dst).emit(masm); // macro assembler version sign-extends
                 if (lo10(hi) != 0) {
-                    new Or(tmp, lo10(hi), tmp).emit(asm);
+                    new Or(tmp, lo10(hi), tmp).emit(masm);
                 }
                 if (lo10(lo) != 0) {
-                    new Or(dst, lo10(lo), dst).emit(asm);
+                    new Or(dst, lo10(lo), dst).emit(masm);
                 }
-                new Sllx(tmp, 32, tmp).emit(asm);
-                new Or(dst, tmp, dst).emit(asm);
+                new Sllx(tmp, 32, tmp).emit(masm);
+                new Or(dst, tmp, dst).emit(masm);
             }
         }
     }
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Thu Jul 11 01:55:54 2013 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Thu Jul 11 01:56:42 2013 +0200
@@ -134,39 +134,22 @@
 
     @Override
     public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label) {
-        Variable x;
-        Value y;
-        Condition condition;
-        if (LIRValueUtil.isVariable(right)) {
-            x = load(right);
-            y = loadNonConst(left);
-            condition = cond.mirror();
-        } else {
-            x = load(left);
-            y = loadNonConst(right);
-            condition = cond;
-        }
+        boolean mirrored = emitCompare(left, right);
+        Condition finalCondition = mirrored ? cond.mirror() : cond;
         switch (left.getKind().getStackKind()) {
             case Int:
-                append(new CompareOp(ICMP, x, y));
-                append(new BranchOp(condition, label));
-                break;
             case Long:
-                append(new CompareOp(LCMP, x, y));
-                append(new BranchOp(condition, label));
+            case Object:
+                append(new BranchOp(finalCondition, label));
                 break;
-            case Float:
-                append(new CompareOp(FCMP, x, y));
-                append(new BranchOp(condition, label));
-                break;
-            case Double:
-                append(new CompareOp(DCMP, x, y));
-                append(new BranchOp(condition, label));
-                break;
-            case Object:
-                append(new CompareOp(ACMP, x, y));
-                append(new BranchOp(condition, label));
-                break;
+// case Float:
+// append(new CompareOp(FCMP, x, y));
+// append(new BranchOp(condition, label));
+// break;
+// case Double:
+// append(new CompareOp(DCMP, x, y));
+// append(new BranchOp(condition, label));
+// break;
             default:
                 throw GraalInternalError.shouldNotReachHere("" + left.getKind());
         }
@@ -376,8 +359,7 @@
             case Int:
                 return SPARCAssembler.isSimm13(c.asInt()) && !runtime.needsDataPatch(c);
             case Long:
-                // return NumUtil.isInt(c.asLong()) && !runtime.needsDataPatch(c);
-                throw new InternalError("NYI");
+                return SPARCAssembler.isSimm13(c.asLong()) && !runtime.needsDataPatch(c);
             case Object:
                 return c.isNull();
             default:
@@ -407,21 +389,23 @@
             baseRegister = asAllocatable(base);
         }
 
-        if (!Value.ILLEGAL.equals(index) && scale != 0) {
+        if (!index.equals(Value.ILLEGAL) && scale != 0) {
             if (isConstant(index)) {
                 finalDisp += asConstant(index).asLong() * scale;
             } else {
                 Value indexRegister;
                 if (scale != 1) {
-                    indexRegister = emitMul(index, Constant.forInt(scale));
+                    Variable longIndex = newVariable(Kind.Long);
+                    emitMove(longIndex, index);
+                    indexRegister = emitMul(longIndex, Constant.forLong(scale));
                 } else {
                     indexRegister = index;
                 }
 
-                if (Value.ILLEGAL.equals(baseRegister)) {
+                if (baseRegister.equals(Value.ILLEGAL)) {
                     baseRegister = asAllocatable(indexRegister);
                 } else {
-                    Variable newBase = newVariable(Kind.Int);
+                    Variable newBase = newVariable(Kind.Long);
                     emitMove(newBase, baseRegister);
                     baseRegister = newBase;
                     baseRegister = emitAdd(baseRegister, indexRegister);
@@ -807,11 +791,6 @@
     }
 
     @Override
-    public void visitSafepointNode(SafepointNode i) {
-        throw new InternalError("NYI");
-    }
-
-    @Override
     public void visitBreakpointNode(BreakpointNode node) {
         JavaType[] sig = new JavaType[node.arguments().size()];
         for (int i = 0; i < sig.length; i++) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Thu Jul 11 01:55:54 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Thu Jul 11 01:56:42 2013 +0200
@@ -75,7 +75,7 @@
                             if (field.getName().equals("x")) {
                                 Assert.assertTrue(rn.object() instanceof LocalNode);
                             } else {
-                                Assert.assertTrue(rn.object() instanceof UnsafeCastNode);
+                                Assert.assertTrue(rn.object().toString(), rn.object() instanceof PiNode);
                             }
                             counter++;
                         }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Thu Jul 11 01:55:54 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Thu Jul 11 01:56:42 2013 +0200
@@ -69,19 +69,26 @@
      */
     protected static void emitStackOverflowCheck(TargetMethodAssembler tasm, boolean afterFrameInit) {
         if (StackShadowPages.getValue() > 0) {
-            // SPARCMacroAssembler masm = (SPARCMacroAssembler) tasm.asm;
+            SPARCMacroAssembler masm = (SPARCMacroAssembler) tasm.asm;
             final int frameSize = tasm.frameMap.frameSize();
             if (frameSize > 0) {
                 int lastFramePage = frameSize / unsafe.pageSize();
                 // emit multiple stack bangs for methods with frames larger than a page
                 for (int i = 0; i <= lastFramePage; i++) {
-                    // int disp = (i + StackShadowPages.getValue()) * unsafe.pageSize();
-                    // if (afterFrameInit) {
-                    // disp -= frameSize;
-                    // }
+                    int disp = (i + StackShadowPages.getValue()) * unsafe.pageSize();
+                    if (afterFrameInit) {
+                        disp -= frameSize;
+                    }
                     tasm.blockComment("[stack overflow check]");
-                    // FIXME currently doesn't work; maybe frame size is wrong
-                    // new Ldx(new SPARCAddress(sp, -disp), g0).emit(masm);
+                    // Use SPARCAddress to get the final displacement including the stack bias.
+                    SPARCAddress address = new SPARCAddress(sp, -disp);
+                    if (SPARCAssembler.isSimm13(address.getDisplacement())) {
+                        new Stx(g0, address).emit(masm);
+                    } else {
+                        // TODO Can't use g3 as scratch here.
+                        new Setx(address.getDisplacement(), g3, g3).emit(masm);
+                        new Stx(g0, sp, g3).emit(masm);
+                    }
                 }
             }
         }
@@ -193,7 +200,7 @@
         if (unverifiedStub != null) {
             masm.bind(unverifiedStub);
 // SPARCCall.directJmp(tasm, asm, runtime().lookupForeignCall(IC_MISS_HANDLER));
-            throw new InternalError("g0 must be scratch register");
+            // throw new InternalError("g0 must be scratch register");
         }
     }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Thu Jul 11 01:55:54 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Thu Jul 11 01:56:42 2013 +0200
@@ -37,11 +37,25 @@
 
 public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSpotLIRGenerator {
 
-    public StackSlot deoptimizationRescueSlot;
+    private HotSpotRuntime runtime() {
+        return (HotSpotRuntime) runtime;
+    }
 
     public SPARCHotSpotLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, CallingConvention cc, LIR lir) {
         super(graph, runtime, target, frameMap, cc, lir);
-        // TODO Auto-generated constructor stub
+    }
+
+    /**
+     * The slot reserved for storing the original return address when a frame is marked for
+     * deoptimization. The return address slot in the callee is overwritten with the address of a
+     * deoptimization stub.
+     */
+    StackSlot deoptimizationRescueSlot;
+
+    @Override
+    public void visitSafepointNode(SafepointNode i) {
+        LIRFrameState info = state(i);
+        append(new SPARCSafepointOp(info, runtime().config, this));
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRuntime.java	Thu Jul 11 01:55:54 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRuntime.java	Thu Jul 11 01:56:42 2013 +0200
@@ -35,18 +35,15 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 
-//import com.oracle.graal.replacements.sparc.*;
-
 public class SPARCHotSpotRuntime extends HotSpotRuntime {
 
     public SPARCHotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime graalRuntime) {
         super(config, graalRuntime);
     }
 
-// private AMD64ConvertSnippets.Templates convertSnippets;
-
     @Override
     public void registerReplacements(Replacements replacements) {
         Kind word = graalRuntime.getTarget().wordKind;
@@ -60,23 +57,21 @@
         register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF, exceptionCc, NOT_REEXECUTABLE, ANY_LOCATION));
         register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF, exceptionCc, NOT_REEXECUTABLE, ANY_LOCATION));
 
-// convertSnippets = new AMD64ConvertSnippets.Templates(this, replacements,
-// graalRuntime.getTarget());
         super.registerReplacements(replacements);
     }
 
     @Override
     public void lower(Node n, LoweringTool tool) {
-// if (n instanceof ConvertNode) {
-// convertSnippets.lower((ConvertNode) n, tool);
-// } else {
-        super.lower(n, tool);
-// }
+        if (n instanceof ConvertNode) {
+            // ConvertNodes are handled in SPARCLIRGenerator.emitConvert
+        } else {
+            super.lower(n, tool);
+        }
     }
 
     @Override
     public Register threadRegister() {
-        throw new InternalError("NYI: SPARC: Define thread register.");
+        return g2;
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCSafepointOp.java	Thu Jul 11 01:56:42 2013 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011, 2013, 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.hotspot.sparc;
+
+import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
+import static com.oracle.graal.sparc.SPARC.*;
+import static com.oracle.graal.phases.GraalOptions.*;
+import sun.misc.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.bridge.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.sparc.*;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * Emits a safepoint poll.
+ */
+@Opcode("SAFEPOINT")
+public class SPARCSafepointOp extends SPARCLIRInstruction {
+
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    @State protected LIRFrameState state;
+    @Temp({OperandFlag.REG}) private AllocatableValue temp;
+
+    private final HotSpotVMConfig config;
+
+    public SPARCSafepointOp(LIRFrameState state, HotSpotVMConfig config, LIRGeneratorTool tool) {
+        this.state = state;
+        this.config = config;
+        temp = tool.newVariable(tool.target().wordKind);
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
+        final int pos = masm.codeBuffer.position();
+        final int offset = SafepointPollOffset.getValue() % unsafe.pageSize();
+        Register scratch = ((RegisterValue) temp).getRegister();
+        new Setx(config.safepointPollingAddress + offset, scratch, scratch).emit(masm);
+        tasm.recordMark(config.isPollingPageFar ? Marks.MARK_POLL_FAR : Marks.MARK_POLL_NEAR);
+        tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
+        new Ldx(new SPARCAddress(scratch, 0), g0).emit(masm);
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Thu Jul 11 01:55:54 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Thu Jul 11 01:56:42 2013 +0200
@@ -82,21 +82,12 @@
     private static final long VECTOR_SIZE = arrayIndexScale(Kind.Long);
 
     private static void checkedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) {
-        Object nonNullSrc = checkNonNull(src);
-        Object nonNullDest = checkNonNull(dest);
+        Object nonNullSrc = guardingNonNull(src);
+        Object nonNullDest = guardingNonNull(dest);
         checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length);
         UnsafeArrayCopyNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, baseKind);
     }
 
-    @Fold
-    private static Stamp nonNull() {
-        return StampFactory.objectNonNull();
-    }
-
-    public static Object checkNonNull(Object obj) {
-        return guardingPi(obj, isNull(obj), true, DeoptimizationReason.RuntimeConstraint, DeoptimizationAction.None, nonNull());
-    }
-
     public static int checkArrayType(Word hub) {
         int layoutHelper = readLayoutHelper(hub);
         if (layoutHelper >= 0) {
@@ -191,8 +182,8 @@
 
     @Snippet
     public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) {
-        Object nonNullSrc = checkNonNull(src);
-        Object nonNullDest = checkNonNull(dest);
+        Object nonNullSrc = guardingNonNull(src);
+        Object nonNullDest = guardingNonNull(dest);
         Word srcHub = loadHub(nonNullSrc);
         Word destHub = loadHub(nonNullDest);
         if (probability(FAST_PATH_PROBABILITY, srcHub.equal(destHub)) && probability(FAST_PATH_PROBABILITY, nonNullSrc != nonNullDest)) {
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Thu Jul 11 01:55:54 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Thu Jul 11 01:56:42 2013 +0200
@@ -517,7 +517,7 @@
                 rk = result.getKind();
                 xsk = x.getKind().getStackKind();
                 ysk = y.getKind().getStackKind();
-                assert rk == Kind.Int && xsk == Kind.Int && ysk == Kind.Int;
+                assert rk == Kind.Int && xsk == Kind.Int && ysk == Kind.Int : "opcode=" + opcode + ", rk=" + rk + ", xsk=" + xsk + ", ysk=" + ysk;
                 break;
             case LADD:
             case LSUB:
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java	Thu Jul 11 01:55:54 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java	Thu Jul 11 01:56:42 2013 +0200
@@ -72,8 +72,8 @@
                     new Cmp(asLongReg(x), asLongReg(y)).emit(masm);
                     break;
                 case ACMP:
-                    // masm.cmpptr(asObjectReg(x), asObjectReg(y));
-                    // break;
+// new Cmp(asObjectReg(x), asObjectReg(y)).emit(masm);
+// break;
                 case FCMP:
                     // masm.ucomiss(asFloatReg(x), asFloatReg(y));
                     // break;
@@ -96,9 +96,8 @@
                     break;
                 case ACMP:
                     if (((Constant) y).isNull()) {
-                        // masm.cmpq(asObjectReg(x), 0);
-                        // break;
-                        throw GraalInternalError.shouldNotReachHere();
+                        new Cmp(asObjectReg(x), 0).emit(masm);
+                        break;
                     } else {
                         throw GraalInternalError.shouldNotReachHere("Only null object constants are allowed in comparisons");
                     }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Thu Jul 11 01:55:54 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Thu Jul 11 01:56:42 2013 +0200
@@ -53,9 +53,12 @@
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
+            // FIXME Using xcc is wrong! It depends on the compare.
             switch (condition) {
+                case EQ:
+                    new Bpe(CC.Xcc, destination.label()).emit(masm);
+                    break;
                 case GT:
-                    // FIXME xcc is wrong! It depends on the compare.
                     new Bpg(CC.Xcc, destination.label()).emit(masm);
                     break;
                 default:
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Thu Jul 11 01:55:54 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Thu Jul 11 01:56:42 2013 +0200
@@ -23,27 +23,13 @@
 package com.oracle.graal.lir.sparc;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 import static com.oracle.graal.sparc.SPARC.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Lddf;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldf;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsb;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsh;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsw;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Lduw;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldx;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Membar;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Stb;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Sth;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Stw;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Stx;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setuw;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.MoveOp;
@@ -51,68 +37,6 @@
 
 public class SPARCMove {
 
-    public static class LoadOp extends SPARCLIRInstruction {
-
-        private final Kind kind;
-        @Def({REG}) protected AllocatableValue result;
-        @Use({COMPOSITE}) protected SPARCAddressValue address;
-        @State protected LIRFrameState state;
-
-        public LoadOp(Kind kind, AllocatableValue result, SPARCAddressValue address, LIRFrameState state) {
-            this.kind = kind;
-            this.result = result;
-            this.address = address;
-            this.state = state;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
-            SPARCAddress addr = address.toAddress();
-            switch (kind) {
-                case Byte:
-                    new Ldsb(addr, asRegister(result)).emit(masm);
-                    break;
-                case Short:
-                    new Ldsh(addr, asRegister(result)).emit(masm);
-                    break;
-                case Char:
-                    new Lduw(addr, asRegister(result)).emit(masm);
-                    break;
-                case Int:
-                    new Ldsw(addr, asRegister(result)).emit(masm);
-                    break;
-                case Long:
-                    new Ldx(addr, asRegister(result)).emit(masm);
-                    break;
-                case Float:
-                    new Ldf(addr, asRegister(result)).emit(masm);
-                    break;
-                case Double:
-                    new Lddf(addr, asRegister(result)).emit(masm);
-                    break;
-                case Object:
-                    new Ldx(addr, asRegister(result)).emit(masm);
-                    break;
-                default:
-                    throw GraalInternalError.shouldNotReachHere();
-            }
-        }
-    }
-
-    public static class MembarOp extends SPARCLIRInstruction {
-
-        private final int barriers;
-
-        public MembarOp(final int barriers) {
-            this.barriers = barriers;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
-            new Membar(barriers).emit(masm);
-        }
-    }
-
     @Opcode("MOVE")
     public static class MoveToRegOp extends SPARCLIRInstruction implements MoveOp {
 
@@ -167,6 +91,86 @@
         }
     }
 
+    public abstract static class MemOp extends SPARCLIRInstruction {
+
+        protected final Kind kind;
+        @Use({COMPOSITE}) protected SPARCAddressValue address;
+        @State protected LIRFrameState state;
+
+        public MemOp(Kind kind, SPARCAddressValue address, LIRFrameState state) {
+            this.kind = kind;
+            this.address = address;
+            this.state = state;
+        }
+
+        protected abstract void emitMemAccess(SPARCMacroAssembler masm);
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
+            if (state != null) {
+                tasm.recordImplicitException(masm.codeBuffer.position(), state);
+            }
+            emitMemAccess(masm);
+        }
+    }
+
+    public static class LoadOp extends MemOp {
+
+        @Def({REG}) protected AllocatableValue result;
+
+        public LoadOp(Kind kind, AllocatableValue result, SPARCAddressValue address, LIRFrameState state) {
+            super(kind, address, state);
+            this.result = result;
+        }
+
+        @Override
+        public void emitMemAccess(SPARCMacroAssembler masm) {
+            SPARCAddress addr = address.toAddress();
+            switch (kind) {
+                case Byte:
+                    new Ldsb(addr, asRegister(result)).emit(masm);
+                    break;
+                case Short:
+                    new Ldsh(addr, asRegister(result)).emit(masm);
+                    break;
+                case Char:
+                    new Lduw(addr, asRegister(result)).emit(masm);
+                    break;
+                case Int:
+                    new Ldsw(addr, asRegister(result)).emit(masm);
+                    break;
+                case Long:
+                    new Ldx(addr, asRegister(result)).emit(masm);
+                    break;
+                case Float:
+                    new Ldf(addr, asRegister(result)).emit(masm);
+                    break;
+                case Double:
+                    new Lddf(addr, asRegister(result)).emit(masm);
+                    break;
+                case Object:
+                    new Ldx(addr, asRegister(result)).emit(masm);
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    public static class MembarOp extends SPARCLIRInstruction {
+
+        private final int barriers;
+
+        public MembarOp(final int barriers) {
+            this.barriers = barriers;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
+            new Membar(barriers).emit(masm);
+        }
+    }
+
     public static class NullCheckOp extends SPARCLIRInstruction {
 
         @Use({REG}) protected AllocatableValue input;
@@ -201,22 +205,17 @@
         }
     }
 
-    public static class StoreOp extends SPARCLIRInstruction {
+    public static class StoreOp extends MemOp {
 
-        private final Kind kind;
-        @Use({COMPOSITE}) protected SPARCAddressValue address;
         @Use({REG}) protected AllocatableValue input;
-        @State protected LIRFrameState state;
 
         public StoreOp(Kind kind, SPARCAddressValue address, AllocatableValue input, LIRFrameState state) {
-            this.kind = kind;
-            this.address = address;
+            super(kind, address, state);
             this.input = input;
-            this.state = state;
         }
 
         @Override
-        public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
+        public void emitMemAccess(SPARCMacroAssembler masm) {
             assert isRegister(input);
             SPARCAddress addr = address.toAddress();
             switch (kind) {
@@ -318,27 +317,26 @@
         }
     }
 
-    @SuppressWarnings("unused")
     private static void const2reg(TargetMethodAssembler tasm, SPARCMacroAssembler masm, Value result, Constant input) {
         switch (input.getKind().getStackKind()) {
             case Int:
                 if (tasm.runtime.needsDataPatch(input)) {
                     tasm.recordDataReferenceInCode(input, 0, true);
                 }
-                new Setuw(masm, input.asInt(), asRegister(result));
+                new Setuw(input.asInt(), asRegister(result)).emit(masm);
                 break;
             case Long:
                 if (tasm.runtime.needsDataPatch(input)) {
                     tasm.recordDataReferenceInCode(input, 0, true);
                 }
-                new Setx(masm, input.asLong(), null, asRegister(result));
+                new Setx(input.asLong(), null, asRegister(result)).emit(masm);
                 break;
             case Object:
                 if (input.isNull()) {
-                    new Setx(masm, 0x0L, null, asRegister(result));
+                    new Clr(asRegister(result)).emit(masm);
                 } else if (tasm.target.inlineObjects) {
                     tasm.recordDataReferenceInCode(input, 0, true);
-                    new Setx(masm, 0xDEADDEADDEADDEADL, null, asRegister(result));
+                    new Setx(0xDEADDEADDEADDEADL, null, asRegister(result)).emit(masm);
                 } else {
                     throw new InternalError("NYI");
                 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Thu Jul 11 01:55:54 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Thu Jul 11 01:56:42 2013 +0200
@@ -46,13 +46,24 @@
         return object;
     }
 
-    public GuardingPiNode(ValueNode object) {
+    /**
+     * Constructor for {@link #guardingNonNull(Object)} node intrinsic.
+     */
+    private GuardingPiNode(ValueNode object) {
         this(object, object.graph().unique(new IsNullNode(object)), true, DeoptimizationReason.NullCheckException, DeoptimizationAction.None, object.stamp().join(StampFactory.objectNonNull()));
     }
 
+    /**
+     * Creates a guarding pi node.
+     * 
+     * @param object the object whose type is refined if this guard succeeds
+     * @param condition the condition to test
+     * @param negateCondition the guard succeeds if {@code condition != negateCondition}
+     * @param stamp the refined type of the object if the guard succeeds
+     */
     public GuardingPiNode(ValueNode object, ValueNode condition, boolean negateCondition, DeoptimizationReason reason, DeoptimizationAction action, Stamp stamp) {
-        super(object.stamp().join(stamp));
-        assert stamp() != null;
+        super(stamp);
+        assert stamp != null;
         this.object = object;
         this.condition = (LogicNode) condition;
         this.reason = reason;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Thu Jul 11 01:55:54 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Thu Jul 11 01:56:42 2013 +0200
@@ -22,9 +22,13 @@
  */
 package com.oracle.graal.nodes.java;
 
+import static com.oracle.graal.api.code.DeoptimizationAction.*;
+import static com.oracle.graal.api.meta.DeoptimizationReason.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -62,9 +66,48 @@
         return forStoreCheck;
     }
 
+    /**
+     * Lowers a {@link CheckCastNode} to a {@link GuardingPiNode}. That is:
+     * 
+     * <pre>
+     * 1: A a = ...
+     * 2: B b = (B) a;
+     * </pre>
+     * 
+     * is lowered to:
+     * 
+     * <pre>
+     * 1: A a = ...
+     * 2: B b = guardingPi(a == null || a instanceof B, a, stamp(B))
+     * </pre>
+     * 
+     * or if a is known to be non-null:
+     * 
+     * <pre>
+     * 1: A a = ...
+     * 2: B b = guardingPi(a instanceof B, a, stamp(B, non-null))
+     * </pre>
+     * 
+     * Note: we use {@link Graph#add} as opposed to {@link Graph#unique} for the new
+     * {@link InstanceOfNode} to maintain the invariant checked by
+     * {@code LoweringPhase.checkUsagesAreScheduled()}.
+     */
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
-        tool.getRuntime().lower(this, tool);
+        InstanceOfNode typeTest = graph().add(new InstanceOfNode(type, object, profile));
+        Stamp stamp = object.stamp().join(StampFactory.declared(type));
+        ValueNode condition;
+        if (stamp == null) {
+            // This is a check cast that will always fail
+            condition = LogicConstantNode.contradiction(graph());
+            stamp = StampFactory.declared(type);
+        } else if (object.stamp().nonNull()) {
+            condition = typeTest;
+        } else {
+            condition = graph().unique(new LogicDisjunctionNode(graph().unique(new IsNullNode(object)), typeTest));
+        }
+        GuardingPiNode checkedObject = graph().add(new GuardingPiNode(object, condition, false, forStoreCheck ? ArrayStoreException : ClassCastException, InvalidateReprofile, stamp));
+        graph().replaceFixedWithFixed(this, checkedObject);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Thu Jul 11 01:55:54 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Thu Jul 11 01:56:42 2013 +0200
@@ -116,7 +116,8 @@
     @Override
     public boolean verify() {
         for (Node usage : usages()) {
-            assertTrue(usage instanceof IfNode || usage instanceof FixedGuardNode || usage instanceof ConditionalNode, "unsupported usage: ", usage);
+            assertTrue(usage instanceof IfNode || usage instanceof FixedGuardNode || usage instanceof GuardingPiNode || usage instanceof ConditionalNode || usage instanceof LogicBinaryNode,
+                            "unsupported usage: %s", usage);
         }
         return super.verify();
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Thu Jul 11 01:55:54 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Thu Jul 11 01:56:42 2013 +0200
@@ -1441,7 +1441,8 @@
         if (firstParam.kind() == Kind.Object && !firstParam.objectStamp().nonNull()) {
             assert !firstParam.objectStamp().alwaysNull();
             IsNullNode condition = graph.unique(new IsNullNode(firstParam));
-            GuardingPiNode nonNullReceiver = graph.add(new GuardingPiNode(firstParam, condition, true, NullCheckException, InvalidateReprofile, objectNonNull()));
+            Stamp stamp = firstParam.stamp().join(objectNonNull());
+            GuardingPiNode nonNullReceiver = graph.add(new GuardingPiNode(firstParam, condition, true, NullCheckException, InvalidateReprofile, stamp));
             graph.addBeforeFixed(invoke.asNode(), nonNullReceiver);
             callTarget.replaceFirstInput(firstParam, nonNullReceiver);
             return nonNullReceiver;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Thu Jul 11 01:55:54 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Thu Jul 11 01:56:42 2013 +0200
@@ -253,11 +253,34 @@
                 }
 
                 if (node instanceof Lowerable) {
+                    assert checkUsagesAreScheduled(node);
                     ((Lowerable) node).lower(loweringTool, loweringType);
                 }
 
                 loweringTool.setLastFixedNode((FixedWithNextNode) nextNode.predecessor());
             }
         }
+
+        /**
+         * Checks that all usages of a floating, lowerable node are scheduled.
+         * <p>
+         * Given that the lowering of such nodes may introduce fixed nodes, they must be lowered in
+         * the context of a usage that dominates all other usages. The fixed nodes resulting from
+         * lowering are attached to the fixed node context of the dominating usage. This ensures the
+         * post-lowering graph still has a valid schedule.
+         * 
+         * @param node a {@link Lowerable} node
+         */
+        private boolean checkUsagesAreScheduled(Node node) {
+            if (node instanceof FloatingNode) {
+                for (Node usage : node.usages()) {
+                    if (usage instanceof ScheduledNode) {
+                        Block usageBlock = schedule.getCFG().blockFor(usage);
+                        assert usageBlock != null : node.graph() + ": cannot lower floatable node " + node + " that has non-scheduled usage " + usage;
+                    }
+                }
+            }
+            return true;
+        }
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Thu Jul 11 01:55:54 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Thu Jul 11 01:56:42 2013 +0200
@@ -65,13 +65,12 @@
     public void lower(FloatingNode instanceOf, LoweringTool tool) {
         assert instanceOf instanceof InstanceOfNode || instanceOf instanceof InstanceOfDynamicNode;
         List<Node> usages = instanceOf.usages().snapshot();
-        int nUsages = usages.size();
 
         Instantiation instantiation = new Instantiation();
         for (Node usage : usages) {
             final StructuredGraph graph = (StructuredGraph) usage.graph();
 
-            InstanceOfUsageReplacer replacer = createReplacer(instanceOf, tool, nUsages, instantiation, usage, graph);
+            InstanceOfUsageReplacer replacer = createReplacer(instanceOf, instantiation, usage, graph);
 
             if (instantiation.isInitialized()) {
                 // No need to re-instantiate the snippet - just re-use its result
@@ -91,18 +90,15 @@
     /**
      * Gets the specific replacer object used to replace the usage of an instanceof node with the
      * result of an instantiated instanceof snippet.
-     * 
-     * @param nUsages
-     * @param tool
      */
-    protected InstanceOfUsageReplacer createReplacer(FloatingNode instanceOf, LoweringTool tool, int nUsages, Instantiation instantiation, Node usage, final StructuredGraph graph) {
+    protected InstanceOfUsageReplacer createReplacer(FloatingNode instanceOf, Instantiation instantiation, Node usage, final StructuredGraph graph) {
         InstanceOfUsageReplacer replacer;
-        if (usage instanceof IfNode || usage instanceof FixedGuardNode) {
-            replacer = new IfUsageReplacer(instantiation, ConstantNode.forInt(1, graph), ConstantNode.forInt(0, graph), instanceOf, (FixedNode) usage);
+        if (usage instanceof IfNode || usage instanceof FixedGuardNode || usage instanceof LogicBinaryNode || usage instanceof GuardingPiNode) {
+            replacer = new NonMaterializationUsageReplacer(instantiation, ConstantNode.forInt(1, graph), ConstantNode.forInt(0, graph), instanceOf, usage);
         } else {
             assert usage instanceof ConditionalNode : "unexpected usage of " + instanceOf + ": " + usage;
             ConditionalNode c = (ConditionalNode) usage;
-            replacer = new ConditionalUsageReplacer(instantiation, c.trueValue(), c.falseValue(), instanceOf, c);
+            replacer = new MaterializationUsageReplacer(instantiation, c.trueValue(), c.falseValue(), instanceOf, c);
         }
         return replacer;
     }
@@ -192,14 +188,14 @@
     }
 
     /**
-     * Replaces an {@link IfNode} usage of an {@link InstanceOfNode} or
-     * {@link InstanceOfDynamicNode}.
+     * Replaces the usage of an {@link InstanceOfNode} or {@link InstanceOfDynamicNode} that does
+     * not materialize the result of the type test.
      */
-    public static class IfUsageReplacer extends InstanceOfUsageReplacer {
+    public static class NonMaterializationUsageReplacer extends InstanceOfUsageReplacer {
 
-        private final FixedNode usage;
+        private final Node usage;
 
-        public IfUsageReplacer(Instantiation instantiation, ValueNode trueValue, ValueNode falseValue, FloatingNode instanceOf, FixedNode usage) {
+        public NonMaterializationUsageReplacer(Instantiation instantiation, ValueNode trueValue, ValueNode falseValue, FloatingNode instanceOf, Node usage) {
             super(instantiation, instanceOf, trueValue, falseValue);
             this.usage = usage;
         }
@@ -211,14 +207,6 @@
 
         @Override
         public void replace(ValueNode oldNode, ValueNode newNode) {
-            if (newNode.isConstant()) {
-                LogicConstantNode logicConstant = LogicConstantNode.forBoolean(newNode.asConstant().asInt() != 0, newNode.graph());
-                usage.replaceFirstInput(oldNode, logicConstant);
-                // PrintStream out = System.out;
-                // out.println(newNode.graph() + ": " + this);
-                GraalInternalError.shouldNotReachHere(instanceOf.graph().toString());
-                return;
-            }
             assert newNode instanceof PhiNode;
             assert oldNode == instanceOf;
             newNode.inferStamp();
@@ -228,14 +216,14 @@
     }
 
     /**
-     * Replaces a {@link ConditionalNode} usage of an {@link InstanceOfNode} or
-     * {@link InstanceOfDynamicNode}.
+     * Replaces the usage of an {@link InstanceOfNode} or {@link InstanceOfDynamicNode} that does
+     * materializes the result of the type test.
      */
-    public static class ConditionalUsageReplacer extends InstanceOfUsageReplacer {
+    public static class MaterializationUsageReplacer extends InstanceOfUsageReplacer {
 
         public final ConditionalNode usage;
 
-        public ConditionalUsageReplacer(Instantiation instantiation, ValueNode trueValue, ValueNode falseValue, FloatingNode instanceOf, ConditionalNode usage) {
+        public MaterializationUsageReplacer(Instantiation instantiation, ValueNode trueValue, ValueNode falseValue, FloatingNode instanceOf, ConditionalNode usage) {
             super(instantiation, instanceOf, trueValue, falseValue);
             this.usage = usage;
         }
@@ -251,14 +239,6 @@
 
         @Override
         public void replace(ValueNode oldNode, ValueNode newNode) {
-            if (newNode.isConstant()) {
-                LogicConstantNode logicConstant = LogicConstantNode.forBoolean(newNode.asConstant().asInt() != 0, newNode.graph());
-                usage.replaceFirstInput(oldNode, logicConstant);
-                // PrintStream out = System.out;
-                // out.println(newNode.graph() + ": " + this);
-                GraalInternalError.shouldNotReachHere(instanceOf.graph().toString());
-                return;
-            }
             assert newNode instanceof PhiNode;
             assert oldNode == instanceOf;
             newNode.inferStamp();