Bug 1301400: Baseline Wasm Compiler: Part 1: Basic changes to support int64 ops in x86, r=lth
authorh4writer <hv1989@gmail.com>
Thu, 29 Sep 2016 22:33:22 +0200
changeset 315901 58829d3beda3cb5c7c9e83ef370f8d0c1c0789d3
parent 315900 89f6b845f34749a796686f9e41cca9318f002338
child 315902 07b4fdd7588aab05136af8c7802d2737d50448ec
push id20634
push usercbook@mozilla.com
push dateFri, 30 Sep 2016 10:10:13 +0000
treeherderfx-team@afe79b010d13 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslth
bugs1301400
milestone52.0a1
Bug 1301400: Baseline Wasm Compiler: Part 1: Basic changes to support int64 ops in x86, r=lth
js/src/asmjs/WasmBaselineCompile.cpp
js/src/jit/Registers.h
js/src/jit/x86-shared/Assembler-x86-shared.h
--- a/js/src/asmjs/WasmBaselineCompile.cpp
+++ b/js/src/asmjs/WasmBaselineCompile.cpp
@@ -254,17 +254,17 @@ class BaseCompiler
     // The strongly typed register wrappers have saved my bacon a few
     // times; though they are largely redundant they stay, for now.
 
     // TODO / INVESTIGATE: Things would probably be simpler if these
     // inherited from Register, Register64, and FloatRegister.
 
     struct RegI32
     {
-        RegI32() {}
+        RegI32() : reg(Register::Invalid()) {}
         explicit RegI32(Register reg) : reg(reg) {}
         Register reg;
         bool operator==(const RegI32& that) { return reg == that.reg; }
         bool operator!=(const RegI32& that) { return reg != that.reg; }
     };
 
     struct RegI64
     {
@@ -856,21 +856,17 @@ class BaseCompiler
     Vector<Stk, 8, SystemAllocPolicy> stk_;
 
     Stk& push() {
         stk_.infallibleEmplaceBack(Stk());
         return stk_.back();
     }
 
     Register64 invalidRegister64() {
-#ifdef JS_PUNBOX64
-        return Register64(Register::Invalid());
-#else
-        MOZ_CRASH("BaseCompiler platform hook: invalidRegister64");
-#endif
+        return Register64::Invalid();
     }
 
     RegI32 invalidI32() {
         return RegI32(Register::Invalid());
     }
 
     RegI64 invalidI64() {
         return RegI64(invalidRegister64());
@@ -884,31 +880,45 @@ class BaseCompiler
 #ifdef JS_PUNBOX64
         return RegI32(r.reg.reg);
 #else
         return RegI32(r.reg.low);
 #endif
     }
 
     RegI64 fromI32(RegI32 r) {
+        MOZ_ASSERT(!isAvailable(r.reg));
 #ifdef JS_PUNBOX64
         return RegI64(Register64(r.reg));
 #else
-        return RegI64(Register64(needI32().reg, r.reg)); // TODO: BUG if sync is called.
+        RegI32 high = needI32();
+        return RegI64(Register64(high.reg, r.reg));
 #endif
     }
 
     void freeI32(RegI32 r) {
         freeGPR(r.reg);
     }
 
     void freeI64(RegI64 r) {
         freeInt64(r.reg);
     }
 
+    void freeI64Except(RegI64 r, RegI32 except) {
+#ifdef JS_PUNBOX64
+        MOZ_ASSERT(r.reg.reg == except.reg);
+#else
+        MOZ_ASSERT(r.reg.high == except.reg || r.reg.low == except.reg);
+        freeI64(r);
+        needI32(except);
+#endif
+
+
+    }
+
     void freeF64(RegF64 r) {
         freeFPU(r.reg);
     }
 
     void freeF32(RegF32 r) {
         freeFPU(r.reg);
     }
 
@@ -925,17 +935,17 @@ class BaseCompiler
         allocGPR(specific.reg);
     }
 
     // TODO / OPTIMIZE: need2xI32() can be optimized along with needI32()
     // to avoid sync().
 
     void need2xI32(RegI32 r0, RegI32 r1) {
         needI32(r0);
-        needI32(r1); // TODO: BUG if sync is called.
+        needI32(r1);
     }
 
     MOZ_MUST_USE
     RegI64 needI64() {
         if (!hasInt64())
             sync();            // TODO / OPTIMIZE: improve this
         return RegI64(allocInt64());
     }
@@ -943,17 +953,17 @@ class BaseCompiler
     void needI64(RegI64 specific) {
         if (!isAvailable(specific.reg))
             sync();            // TODO / OPTIMIZE: improve this
         allocInt64(specific.reg);
     }
 
     void need2xI64(RegI64 r0, RegI64 r1) {
         needI64(r0);
-        needI64(r1); // TODO: BUG if sync is called.
+        needI64(r1);
     }
 
     MOZ_MUST_USE
     RegF32 needF32() {
         if (!hasFPU<MIRType::Float32>())
             sync();            // TODO / OPTIMIZE: improve this
         return RegF32(allocFPU<MIRType::Float32>());
     }
@@ -993,21 +1003,17 @@ class BaseCompiler
     }
 
     void moveF32(RegF32 src, RegF32 dest) {
         if (src != dest)
             masm.moveFloat32(src.reg, dest.reg);
     }
 
     void setI64(int64_t v, RegI64 r) {
-#ifdef JS_PUNBOX64
         masm.move64(Imm64(v), r.reg);
-#else
-        MOZ_CRASH("BaseCompiler platform hook: setI64");
-#endif
     }
 
     void loadConstI32(Register r, Stk& src) {
         masm.mov(ImmWord((uint32_t)src.i32val() & 0xFFFFFFFFU), r);
     }
 
     void loadMemI32(Register r, Stk& src) {
         loadFromFrameI32(r, src.offs());
@@ -1165,31 +1171,31 @@ class BaseCompiler
               }
               case Stk::LocalI64: {
                 ScratchI32 scratch(*this);
 #ifdef JS_PUNBOX64
                 loadI64(Register64(scratch), v);
                 masm.Push(scratch);
 #else
                 int32_t offset = frameOffsetFromSlot(v.slot(), MIRType::Int64);
-                loadFromFrameI32(scratch, offset + INT64LOW_OFFSET);
+                loadFromFrameI32(scratch, offset - INT64HIGH_OFFSET);
                 masm.Push(scratch);
-                loadFromFrameI32(scratch, offset + INT64HIGH_OFFSET);
+                loadFromFrameI32(scratch, offset - INT64LOW_OFFSET);
                 masm.Push(scratch);
 #endif
                 v.setOffs(Stk::MemI64, masm.framePushed());
                 break;
               }
               case Stk::RegisterI64: {
 #ifdef JS_PUNBOX64
                 masm.Push(v.i64reg().reg.reg);
                 freeI64(v.i64reg());
 #else
+                masm.Push(v.i64reg().reg.high);
                 masm.Push(v.i64reg().reg.low);
-                masm.Push(v.i64reg().reg.high);
                 freeI64(v.i64reg());
 #endif
                 v.setOffs(Stk::MemI64, masm.framePushed());
                 break;
               }
               case Stk::LocalF64: {
                 ScratchF64 scratch(*this);
                 loadF64(scratch, v);
@@ -1253,23 +1259,19 @@ class BaseCompiler
 
     void pushI32(RegI32 r) {
         MOZ_ASSERT(!isAvailable(r.reg));
         Stk& x = push();
         x.setI32Reg(r);
     }
 
     void pushI64(RegI64 r) {
-#ifdef JS_PUNBOX64
-        MOZ_ASSERT(!isAvailable(r.reg.reg));
+        MOZ_ASSERT(!isAvailable(r.reg));
         Stk& x = push();
         x.setI64Reg(r);
-#else
-        MOZ_CRASH("BaseCompiler platform hook: pushI64");
-#endif
     }
 
     void pushF64(RegF64 r) {
         MOZ_ASSERT(!isAvailable(r.reg));
         Stk& x = push();
         x.setF64Reg(r);
     }
 
@@ -2247,21 +2249,17 @@ class BaseCompiler
 #endif
     }
 
     void captureReturnedI32(RegI32 dest) {
         moveI32(RegI32(ReturnReg), dest);
     }
 
     void captureReturnedI64(RegI64 dest) {
-#ifdef JS_PUNBOX64
         moveI64(RegI64(ReturnReg64), dest);
-#else
-        MOZ_CRASH("BaseCompiler platform hook: captureReturnedI64");
-#endif
     }
 
     void captureReturnedF32(const FunctionCall& call, RegF32 dest) {
 #ifdef JS_CODEGEN_X86
         if (call.builtinCall_) {
             masm.reserveStack(sizeof(float));
             Operand op(esp, 0);
             masm.fstp32(op);
@@ -2294,21 +2292,17 @@ class BaseCompiler
 
     void returnI32(RegI32 r) {
         moveI32(r, RegI32(ReturnReg));
         popStackBeforeBranch(ctl_[0].framePushed);
         masm.jump(&returnLabel_);
     }
 
     void returnI64(RegI64 r) {
-#ifdef JS_PUNBOX64
-        moveI64(r, RegI64(Register64(ReturnReg)));
-#else
-        MOZ_CRASH("BaseCompiler platform hook: returnI64");
-#endif
+        moveI64(r, RegI64(Register64(ReturnReg64)));
         popStackBeforeBranch(ctl_[0].framePushed);
         masm.jump(&returnLabel_);
     }
 
     void returnF64(RegF64 r) {
         moveF64(r, RegF64(ReturnDoubleReg));
         popStackBeforeBranch(ctl_[0].framePushed);
         masm.jump(&returnLabel_);
@@ -3744,17 +3738,17 @@ BaseCompiler::emitMaxF64()
 }
 
 void
 BaseCompiler::emitCopysignF32()
 {
     RegF32 r0, r1;
     pop2xF32(&r0, &r1);
     RegI32 i0 = needI32();
-    RegI32 i1 = needI32(); // TODO: BUG if sync is called.
+    RegI32 i1 = needI32();
     masm.moveFloat32ToGPR(r0.reg, i0.reg);
     masm.moveFloat32ToGPR(r1.reg, i1.reg);
     masm.and32(Imm32(INT32_MAX), i0.reg);
     masm.and32(Imm32(INT32_MIN), i1.reg);
     masm.or32(i1.reg, i0.reg);
     masm.moveGPRToFloat32(i0.reg, r0.reg);
     freeI32(i0);
     freeI32(i1);
--- a/js/src/jit/Registers.h
+++ b/js/src/jit/Registers.h
@@ -119,32 +119,30 @@ struct Register64
     {}
     bool operator ==(Register64 other) const {
         return reg == other.reg;
     }
     bool operator !=(Register64 other) const {
         return reg != other.reg;
     }
     static Register64 Invalid() {
-        Register64 r(Register::Invalid());
-        return r;
+        return Register64(Register::Invalid());
     }
 #else
     constexpr Register64(Register h, Register l)
       : high(h), low(l)
     {}
     bool operator ==(Register64 other) const {
         return high == other.high && low == other.low;
     }
     bool operator !=(Register64 other) const {
         return high != other.high || low != other.low;
     }
     static Register64 Invalid() {
-        Register64 r(Register::Invalid(), Register::Invalid());
-        return r;
+        return Register64(Register::Invalid(), Register::Invalid());
     }
 #endif
 };
 
 class RegisterDump
 {
   public:
     typedef mozilla::Array<Registers::RegisterContent, Registers::Total> GPRArray;
--- a/js/src/jit/x86-shared/Assembler-x86-shared.h
+++ b/js/src/jit/x86-shared/Assembler-x86-shared.h
@@ -162,19 +162,18 @@ class Operand
         return reinterpret_cast<void*>(disp_);
     }
 
     bool containsReg(Register r) const {
         switch (kind()) {
           case REG:          return r.encoding() == reg();
           case MEM_REG_DISP: return r.encoding() == base();
           case MEM_SCALE:    return r.encoding() == base() || r.encoding() == index();
-          default: MOZ_CRASH("Unexpected Operand kind");
+          default:           return false;
         }
-        return false;
     }
 };
 
 inline Imm32
 Imm64::firstHalf() const
 {
     return low();
 }