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 315893 58829d3beda3cb5c7c9e83ef370f8d0c1c0789d3
parent 315892 89f6b845f34749a796686f9e41cca9318f002338
child 315894 07b4fdd7588aab05136af8c7802d2737d50448ec
push id30757
push usercbook@mozilla.com
push dateFri, 30 Sep 2016 10:02:43 +0000
treeherdermozilla-central@5ffed033557e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslth
bugs1301400
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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();
 }