changeset 10703:7cdd4708b1aa

Merge
author Christos Kotselidis <christos.kotselidis@oracle.com>
date Thu, 11 Jul 2013 12:10:17 +0200
parents b95d42fdddca (current diff) 4109190a0da5 (diff)
children 84b944726df2
files
diffstat 17 files changed, 400 insertions(+), 228 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java	Thu Jul 11 12:09:36 2013 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java	Thu Jul 11 12:10:17 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 12:09:36 2013 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Thu Jul 11 12:10:17 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 12:09:36 2013 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Thu Jul 11 12:10:17 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 12:09:36 2013 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Thu Jul 11 12:10:17 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.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Thu Jul 11 12:09:36 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Thu Jul 11 12:10:17 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 12:09:36 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Thu Jul 11 12:10:17 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 12:09:36 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRuntime.java	Thu Jul 11 12:10:17 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 12:10:17 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/UnsafeArrayCopyNode.java	Thu Jul 11 12:09:36 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java	Thu Jul 11 12:10:17 2013 +0200
@@ -88,7 +88,7 @@
 
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
-        if (loweringType == LoweringType.AFTER_GUARDS) {
+        if (loweringType == LoweringType.AFTER_FSA) {
             UnsafeArrayCopySnippets.Templates templates = tool.getReplacements().getSnippetTemplateCache(UnsafeArrayCopySnippets.Templates.class);
             templates.lower(this);
         }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Thu Jul 11 12:09:36 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Thu Jul 11 12:10:17 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 12:09:36 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java	Thu Jul 11 12:10:17 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 12:09:36 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Thu Jul 11 12:10:17 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 12:09:36 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Thu Jul 11 12:10:17 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.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Thu Jul 11 12:09:36 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Thu Jul 11 12:10:17 2013 +0200
@@ -281,7 +281,7 @@
     }
 
     private static boolean checkArgumentStamps(StructuredGraph graph, NodeInputList<ValueNode> arguments) {
-        assert graph.getNodes(LocalNode.class).count() == arguments.count();
+        assert graph.getNodes(LocalNode.class).count() <= arguments.count();
         for (LocalNode localNode : graph.getNodes(LocalNode.class)) {
             Stamp newStamp = localNode.stamp().meet(arguments.get(localNode.index()).stamp());
             if (!newStamp.equals(localNode.stamp())) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Thu Jul 11 12:09:36 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Thu Jul 11 12:10:17 2013 +0200
@@ -1466,7 +1466,7 @@
 
             method.getAnnotationMirrors().add(new CodeAnnotationMirror(getContext().getTruffleTypes().getSlowPath()));
 
-            addInternalValueParameters(method, node.getGenericSpecialization(), false, false);
+            addInternalValueParameters(method, node.getGenericSpecialization(), node.needsFrame(), false);
             CodeTreeBuilder builder = method.createBuilder();
 
             String prefix = null;
@@ -2268,7 +2268,7 @@
             builder.end();
 
             builder.startReturn().startCall("super", EXECUTE_GENERIC_NAME);
-            addInternalValueParameterNames(builder, specialization, node.getGenericSpecialization(), null, false, true);
+            addInternalValueParameterNames(builder, specialization, node.getGenericSpecialization(), null, node.needsFrame(), true);
             builder.end().end();
 
             builder.end().startElseBlock();
@@ -2434,7 +2434,7 @@
                 emitEncounteredSynthetic(builder, specialization);
             } else if (specialization.isGeneric()) {
                 returnBuilder.startCall("super", EXECUTE_GENERIC_NAME);
-                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, false, true);
+                addInternalValueParameterNames(returnBuilder, specialization, specialization, null, node.needsFrame(), true);
                 returnBuilder.end();
             } else {
                 returnBuilder.tree(createTemplateMethodCall(returnBuilder, null, specialization, specialization, null));
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java	Thu Jul 11 12:09:36 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeData.java	Thu Jul 11 12:10:17 2013 +0200
@@ -78,6 +78,18 @@
         this.assumptions = splitSource.assumptions;
     }
 
+    public boolean needsFrame() {
+        for (SpecializationData specialization : specializations) {
+            if (!specialization.isReachable()) {
+                continue;
+            }
+            if (specialization.findParameter("frameValue") != null) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     public int getPolymorphicDepth() {
         return polymorphicDepth;
     }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Thu Jul 11 12:09:36 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java	Thu Jul 11 12:10:17 2013 +0200
@@ -41,8 +41,6 @@
 
 public class NodeParser extends TemplateParser<NodeData> {
 
-    private static final String FRAME_VALUE = "frameValue";
-
     public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Generic.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, SpecializationListener.class,
                     NodeContainer.class, NodeChild.class, NodeChildren.class, NodeId.class);
 
@@ -655,27 +653,6 @@
             }
         }
 
-        // remove frame parameter of generic if not needed
-        if (genericSpecialization != null) {
-            ActualParameter frame = genericSpecialization.findParameter(FRAME_VALUE);
-            if (frame != null) {
-                boolean frameUsed = false;
-                for (SpecializationData specialization : specializations) {
-                    if (!specialization.isReachable()) {
-                        continue;
-                    }
-                    frameUsed = specialization.findParameter(FRAME_VALUE) != null;
-                    if (frameUsed) {
-                        break;
-                    }
-                }
-
-                if (!frameUsed) {
-                    genericSpecialization.getParameters().remove(frame);
-                }
-            }
-        }
-
         if (node.getPolymorphicDepth() < 0) {
             node.setPolymorphicDepth(specializationCount - 1);
         }