Bug 1301400: Baseline Wasm Compiler: Part 5: Implement LoadI64 and StoreI64, r=lth
authorh4writer <hv1989@gmail.com>
Thu, 29 Sep 2016 22:33:22 +0200
changeset 315905 7d6daefd4e7963157897ebfefc5d16d8304b752c
parent 315904 90989a3b070d3c61961274e842c6ef305b84992a
child 315906 a878585ab51022ffd457d5b4e2a7686f0b72c3f7
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 5: Implement LoadI64 and StoreI64, r=lth
js/src/asmjs/WasmBaselineCompile.cpp
js/src/jit/arm/MacroAssembler-arm.h
js/src/jit/mips32/MacroAssembler-mips32.h
js/src/jit/x86/Assembler-x86.h
js/src/jit/x86/MacroAssembler-x86.h
--- a/js/src/asmjs/WasmBaselineCompile.cpp
+++ b/js/src/asmjs/WasmBaselineCompile.cpp
@@ -3009,23 +3009,27 @@ class BaseCompiler
         else
             masm.wasmLoad(access.accessType(), 0, srcAddr, dest.any());
 
         if (isAsmJSAccess(access))
             masm.append(MemoryAccess(before));
 # elif defined(JS_CODEGEN_X86)
         Operand srcAddr(ptr.reg, access.offset());
 
-        bool byteRegConflict = access.byteSize() == 1 && !singleByteRegs_.has(dest.i32().reg);
-        AnyRegister out = byteRegConflict ? AnyRegister(ScratchRegX86) : dest.any();
-
-        masm.wasmLoad(access.accessType(), 0, srcAddr, out);
-
-        if (byteRegConflict)
-            masm.mov(ScratchRegX86, dest.i32().reg);
+        if (dest.tag == AnyReg::I64) {
+            masm.wasmLoadI64(access.accessType(), srcAddr, dest.i64().reg);
+        } else {
+            bool byteRegConflict = access.byteSize() == 1 && !singleByteRegs_.has(dest.i32().reg);
+            AnyRegister out = byteRegConflict ? AnyRegister(ScratchRegX86) : dest.any();
+
+            masm.wasmLoad(access.accessType(), 0, srcAddr, out);
+
+            if (byteRegConflict)
+                masm.mov(ScratchRegX86, dest.i32().reg);
+        }
 # else
         MOZ_CRASH("Compiler bug: Unexpected platform.");
 # endif
 
         if (ool)
             masm.bind(ool->rejoin());
         return true;
     }
@@ -3049,25 +3053,31 @@ class BaseCompiler
         uint32_t before = masm.size();
         masm.wasmStore(access.accessType(), 0, src.any(), dstAddr);
 
         if (isCompilingAsmJS())
             masm.append(MemoryAccess(before));
 # elif defined(JS_CODEGEN_X86)
         Operand dstAddr(ptr.reg, access.offset());
 
-        AnyRegister value;
-        if (access.byteSize() == 1 && !singleByteRegs_.has(src.i32().reg)) {
-            masm.mov(src.i32().reg, ScratchRegX86);
-            value = AnyRegister(ScratchRegX86);
+        if (access.accessType() == Scalar::Int64) {
+            masm.wasmStoreI64(src.i64().reg, dstAddr);
         } else {
-            value = src.any();
+            AnyRegister value;
+            if (src.tag == AnyReg::I64) {
+                value = AnyRegister(src.i64().reg.low);
+            } else if (access.byteSize() == 1 && !singleByteRegs_.has(src.i32().reg)) {
+                masm.mov(src.i32().reg, ScratchRegX86);
+                value = AnyRegister(ScratchRegX86);
+            } else {
+                value = src.any();
+            }
+
+            masm.wasmStore(access.accessType(), 0, value, dstAddr);
         }
-
-        masm.wasmStore(access.accessType(), 0, value, dstAddr);
 # else
         MOZ_CRASH("Compiler bug: unexpected platform");
 # endif
 
         if (rejoin.used())
             masm.bind(&rejoin);
 
         return true;
@@ -5674,18 +5684,26 @@ BaseCompiler::emitLoad(ValType type, Sca
       case ValType::I32: {
         RegI32 rp = popI32();
         if (!load(access, rp, AnyReg(rp)))
             return false;
         pushI32(rp);
         break;
       }
       case ValType::I64: {
-        RegI32 rp = popI32();
-        RegI64 rv = needI64();
+        RegI64 rv;
+        RegI32 rp;
+#ifdef JS_CODEGEN_X86
+        rv = abiReturnRegI64;
+        needI64(rv);
+        rp = popI32();
+#else
+        rp = popI32();
+        rv = needI64();
+#endif
         if (!load(access, rp, AnyReg(rv)))
             return false;
         pushI64(rv);
         freeI32(rp);
         break;
       }
       case ValType::F32: {
         RegI32 rp = popI32();
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -930,18 +930,19 @@ class MacroAssemblerARMCompat : public M
 
     void load16ZeroExtend(const Address& address, Register dest);
     void load16ZeroExtend(const BaseIndex& src, Register dest);
 
     void load32(const Address& address, Register dest);
     void load32(const BaseIndex& address, Register dest);
     void load32(AbsoluteAddress address, Register dest);
     void load64(const Address& address, Register64 dest) {
-        load32(address, dest.low);
-        load32(Address(address.base, address.offset + 4), dest.high);
+        load32(Address(address.base, address.offset + INT64LOW_OFFSET), dest.low);
+        int32_t highOffset = (address.offset < 0) ? -int32_t(INT64HIGH_OFFSET) : INT64HIGH_OFFSET;
+        load32(Address(address.base, address.offset + highOffset), dest.high);
     }
 
     void loadPtr(const Address& address, Register dest);
     void loadPtr(const BaseIndex& src, Register dest);
     void loadPtr(AbsoluteAddress address, Register dest);
     void loadPtr(wasm::SymbolicAddress address, Register dest);
 
     void loadPrivate(const Address& address, Register dest);
--- a/js/src/jit/mips32/MacroAssembler-mips32.h
+++ b/js/src/jit/mips32/MacroAssembler-mips32.h
@@ -845,18 +845,19 @@ class MacroAssemblerMIPSCompat : public 
     void load16ZeroExtend(const Address& address, Register dest);
     void load16ZeroExtend(const BaseIndex& src, Register dest);
 
     void load32(const Address& address, Register dest);
     void load32(const BaseIndex& address, Register dest);
     void load32(AbsoluteAddress address, Register dest);
     void load32(wasm::SymbolicAddress address, Register dest);
     void load64(const Address& address, Register64 dest) {
-        load32(Address(address.base, address.offset + LOW_32_OFFSET), dest.low);
-        load32(Address(address.base, address.offset + HIGH_32_OFFSET), dest.high);
+        load32(Address(address.base, address.offset + INT64LOW_OFFSET), dest.low);
+        int32_t highOffset = (address.offset < 0) ? -int32_t(INT64HIGH_OFFSET) : INT64HIGH_OFFSET;
+        load32(Address(address.base, address.offset + highOffset), dest.high);
     }
 
     void loadPtr(const Address& address, Register dest);
     void loadPtr(const BaseIndex& src, Register dest);
     void loadPtr(AbsoluteAddress address, Register dest);
     void loadPtr(wasm::SymbolicAddress address, Register dest);
 
     void loadPrivate(const Address& address, Register dest);
--- a/js/src/jit/x86/Assembler-x86.h
+++ b/js/src/jit/x86/Assembler-x86.h
@@ -722,16 +722,46 @@ class Assembler : public AssemblerX86Sha
           case Operand::MEM_ADDRESS32:
             masm.movl_rm(src.encoding(), dest.address());
             break;
           default:
             MOZ_CRASH("unexpected operand kind");
         }
         return CodeOffset(masm.currentOffset());
     }
+    CodeOffset movlWithPatchLow(Register regLow, const Operand& dest) {
+        switch (dest.kind()) {
+          case Operand::MEM_REG_DISP: {
+            Address addr = dest.toAddress();
+            Operand low(addr.base, addr.offset + INT64LOW_OFFSET);
+            return movlWithPatch(regLow, low);
+          }
+          case Operand::MEM_ADDRESS32: {
+            Operand low(PatchedAbsoluteAddress(uint32_t(dest.address()) + INT64LOW_OFFSET));
+            return movlWithPatch(regLow, low);
+          }
+          default:
+            MOZ_CRASH("unexpected operand kind");
+        }
+    }
+    CodeOffset movlWithPatchHigh(Register regHigh, const Operand& dest) {
+        switch (dest.kind()) {
+          case Operand::MEM_REG_DISP: {
+            Address addr = dest.toAddress();
+            Operand high(addr.base, addr.offset + INT64HIGH_OFFSET);
+            return movlWithPatch(regHigh, high);
+          }
+          case Operand::MEM_ADDRESS32: {
+            Operand high(PatchedAbsoluteAddress(uint32_t(dest.address()) + INT64HIGH_OFFSET));
+            return movlWithPatch(regHigh, high);
+          }
+          default:
+            MOZ_CRASH("unexpected operand kind");
+        }
+    }
     CodeOffset vmovdWithPatch(FloatRegister src, const Operand& dest) {
         MOZ_ASSERT(HasSSE2());
         switch (dest.kind()) {
           case Operand::MEM_REG_DISP:
             masm.vmovd_rm_disp32(src.encoding(), dest.disp(), dest.base());
             break;
           case Operand::MEM_ADDRESS32:
             masm.vmovd_rm(src.encoding(), dest.address());
--- a/js/src/jit/x86/MacroAssembler-x86.h
+++ b/js/src/jit/x86/MacroAssembler-x86.h
@@ -621,18 +621,19 @@ class MacroAssemblerX86 : public MacroAs
     }
     void loadPrivate(const Address& src, Register dest) {
         movl(payloadOf(src), dest);
     }
     void load32(AbsoluteAddress address, Register dest) {
         movl(Operand(address), dest);
     }
     void load64(const Address& address, Register64 dest) {
-        movl(Operand(address), dest.low);
-        movl(Operand(Address(address.base, address.offset + 4)), dest.high);
+        movl(Operand(Address(address.base, address.offset + INT64LOW_OFFSET)), dest.low);
+        int32_t highOffset = (address.offset < 0) ? -int32_t(INT64HIGH_OFFSET) : INT64HIGH_OFFSET;
+        movl(Operand(Address(address.base, address.offset + highOffset)), dest.high);
     }
     template <typename T>
     void storePtr(ImmWord imm, T address) {
         movl(Imm32(imm.value), Operand(address));
     }
     template <typename T>
     void storePtr(ImmPtr imm, T address) {
         storePtr(ImmWord(uintptr_t(imm.value)), address);