Bug 1406336 - JS Jits: Fix load64() on 32-bit platforms, and centralize address arithmetic. r=nbp
authorLars T Hansen <lhansen@mozilla.com>
Fri, 06 Oct 2017 11:01:08 +0200
changeset 385365 8dd2fefd471b508a6233042abc5d2ed5b7b754a4
parent 385364 2ffd7a34aa10f072615044c0c84929358b11f318
child 385366 813d4e250712d296eb4b11b0b89e10ed6a94e3d4
push id32653
push userarchaeopteryx@coole-files.de
push dateTue, 10 Oct 2017 21:56:30 +0000
treeherdermozilla-central@e897e367d3bd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1406336
milestone58.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 1406336 - JS Jits: Fix load64() on 32-bit platforms, and centralize address arithmetic. r=nbp
js/src/jit/Registers.h
js/src/jit/arm/MacroAssembler-arm.h
js/src/jit/mips32/MacroAssembler-mips32.h
js/src/jit/shared/Assembler-shared.h
js/src/jit/x86/Assembler-x86.h
js/src/jit/x86/MacroAssembler-x86-inl.h
js/src/jit/x86/MacroAssembler-x86.cpp
js/src/jit/x86/MacroAssembler-x86.h
js/src/wasm/WasmBaselineCompile.cpp
js/src/wasm/WasmStubs.cpp
--- a/js/src/jit/Registers.h
+++ b/js/src/jit/Registers.h
@@ -130,17 +130,18 @@ Register::LiveAsIndexableSet<RegTypeName
 }
 
 template <> inline Register::SetType
 Register::AllocatableAsIndexableSet<RegTypeName::GPR>(SetType set)
 {
     return set;
 }
 
-#if defined(JS_NUNBOX32)
+#if JS_BITS_PER_WORD == 32
+// Note, some platform code depends on INT64LOW_OFFSET being zero.
 static const uint32_t INT64LOW_OFFSET = 0 * sizeof(int32_t);
 static const uint32_t INT64HIGH_OFFSET = 1 * sizeof(int32_t);
 #endif
 
 struct Register64
 {
 #ifdef JS_PUNBOX64
     Register reg;
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -1003,19 +1003,18 @@ 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(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);
+        load32(LowWord(address), dest.low);
+        load32(HighWord(address), 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);
@@ -1075,23 +1074,23 @@ class MacroAssemblerARMCompat : public M
 
     void store32(Register src, AbsoluteAddress address);
     void store32(Register src, const Address& address);
     void store32(Register src, const BaseIndex& address);
     void store32(Imm32 src, const Address& address);
     void store32(Imm32 src, const BaseIndex& address);
 
     void store64(Register64 src, Address address) {
-        store32(src.low, Address(address.base, address.offset + INT64LOW_OFFSET));
-        store32(src.high, Address(address.base, address.offset + INT64HIGH_OFFSET));
+        store32(src.low, LowWord(address));
+        store32(src.high, HighWord(address));
     }
 
     void store64(Imm64 imm, Address address) {
-        store32(imm.low(), Address(address.base, address.offset + INT64LOW_OFFSET));
-        store32(imm.hi(), Address(address.base, address.offset + INT64HIGH_OFFSET));
+        store32(imm.low(), LowWord(address));
+        store32(imm.hi(), HighWord(address));
     }
 
     void storePtr(ImmWord imm, const Address& address);
     void storePtr(ImmWord imm, const BaseIndex& address);
     void storePtr(ImmPtr imm, const Address& address);
     void storePtr(ImmPtr imm, const BaseIndex& address);
     void storePtr(ImmGCPtr imm, const Address& address);
     void storePtr(ImmGCPtr imm, const BaseIndex& address);
--- a/js/src/jit/mips32/MacroAssembler-mips32.h
+++ b/js/src/jit/mips32/MacroAssembler-mips32.h
@@ -853,19 +853,18 @@ 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 + 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);
+        load32(LowWord(address), dest.low);
+        load32(HighWord(address), 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/shared/Assembler-shared.h
+++ b/js/src/jit/shared/Assembler-shared.h
@@ -2,16 +2,17 @@
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef jit_shared_Assembler_shared_h
 #define jit_shared_Assembler_shared_h
 
+#include "mozilla/CheckedInt.h"
 #include "mozilla/PodOperations.h"
 
 #include <limits.h>
 
 #include "jit/AtomicOp.h"
 #include "jit/JitAllocPolicy.h"
 #include "jit/Label.h"
 #include "jit/Registers.h"
@@ -29,16 +30,18 @@
 // JS_SMALL_BRANCH means the range on a branch instruction
 // is smaller than the whole address space
 # define JS_SMALL_BRANCH
 #endif
 
 namespace js {
 namespace jit {
 
+using mozilla::CheckedInt;
+
 namespace Disassembler {
 class HeapAccess;
 } // namespace Disassembler
 
 static const uint32_t Simd128DataSize = 4 * sizeof(int32_t);
 static_assert(Simd128DataSize == 4 * sizeof(int32_t), "SIMD data should be able to contain int32x4");
 static_assert(Simd128DataSize == 4 * sizeof(float), "SIMD data should be able to contain float32x4");
 static_assert(Simd128DataSize == 2 * sizeof(double), "SIMD data should be able to contain float64x2");
@@ -293,32 +296,68 @@ struct Address
     int32_t offset;
 
     Address(Register base, int32_t offset) : base(base), offset(offset)
     { }
 
     Address() { mozilla::PodZero(this); }
 };
 
+#if JS_BITS_PER_WORD == 32
+
+static inline Address
+LowWord(const Address& address) {
+    CheckedInt<int32_t> offset = CheckedInt<int32_t>(address.offset) + INT64LOW_OFFSET;
+    MOZ_ALWAYS_TRUE(offset.isValid());
+    return Address(address.base, offset.value());
+}
+
+static inline Address
+HighWord(const Address& address) {
+    CheckedInt<int32_t> offset = CheckedInt<int32_t>(address.offset) + INT64HIGH_OFFSET;
+    MOZ_ALWAYS_TRUE(offset.isValid());
+    return Address(address.base, offset.value());
+}
+
+#endif
+
 // Specifies an address computed in the form of a register base, a register
 // index with a scale, and a constant, 32-bit offset.
 struct BaseIndex
 {
     Register base;
     Register index;
     Scale scale;
     int32_t offset;
 
     BaseIndex(Register base, Register index, Scale scale, int32_t offset = 0)
       : base(base), index(index), scale(scale), offset(offset)
     { }
 
     BaseIndex() { mozilla::PodZero(this); }
 };
 
+#if JS_BITS_PER_WORD == 32
+
+static inline BaseIndex
+LowWord(const BaseIndex& address) {
+    CheckedInt<int32_t> offset = CheckedInt<int32_t>(address.offset) + INT64LOW_OFFSET;
+    MOZ_ALWAYS_TRUE(offset.isValid());
+    return BaseIndex(address.base, address.index, address.scale, offset.value());
+}
+
+static inline BaseIndex
+HighWord(const BaseIndex& address) {
+    CheckedInt<int32_t> offset = CheckedInt<int32_t>(address.offset) + INT64HIGH_OFFSET;
+    MOZ_ALWAYS_TRUE(offset.isValid());
+    return BaseIndex(address.base, address.index, address.scale, offset.value());
+}
+
+#endif
+
 // A BaseIndex used to access Values.  Note that |offset| is *not* scaled by
 // sizeof(Value).  Use this *only* if you're indexing into a series of Values
 // that aren't object elements or object slots (for example, values on the
 // stack, values in an arguments object, &c.).  If you're indexing into an
 // object's elements or slots, don't use this directly!  Use
 // BaseObject{Element,Slot}Index instead.
 struct BaseValueIndex : BaseIndex
 {
--- a/js/src/jit/x86/Assembler-x86.h
+++ b/js/src/jit/x86/Assembler-x86.h
@@ -203,16 +203,34 @@ PatchJump(CodeLocationJump jump, CodeLoc
     X86Encoding::SetRel32(jump.raw(), label.raw());
 }
 static inline void
 PatchBackedge(CodeLocationJump& jump_, CodeLocationLabel label, JitZoneGroup::BackedgeTarget target)
 {
     PatchJump(jump_, label);
 }
 
+static inline Operand
+LowWord(const Operand& op) {
+    switch (op.kind()) {
+      case Operand::MEM_REG_DISP: return Operand(LowWord(op.toAddress()));
+      case Operand::MEM_SCALE:    return Operand(LowWord(op.toBaseIndex()));
+      default:                    MOZ_CRASH("Invalid operand type");
+    }
+}
+
+static inline Operand
+HighWord(const Operand& op) {
+    switch (op.kind()) {
+      case Operand::MEM_REG_DISP: return Operand(HighWord(op.toAddress()));
+      case Operand::MEM_SCALE:    return Operand(HighWord(op.toBaseIndex()));
+      default:                    MOZ_CRASH("Invalid operand type");
+    }
+}
+
 // Return operand from a JS -> JS call.
 static const ValueOperand JSReturnOperand = ValueOperand(JSReturnReg_Type, JSReturnReg_Data);
 
 class Assembler : public AssemblerX86Shared
 {
     void writeRelocation(JmpSrc src) {
         jumpRelocations_.writeUnsigned(src.offset());
     }
@@ -763,34 +781,30 @@ class Assembler : public AssemblerX86Sha
           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);
+            return movlWithPatch(regLow, LowWord(dest));
           }
           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);
+            return movlWithPatch(regHigh, HighWord(dest));
           }
           case Operand::MEM_ADDRESS32: {
             Operand high(PatchedAbsoluteAddress(uint32_t(dest.address()) + INT64HIGH_OFFSET));
             return movlWithPatch(regHigh, high);
           }
           default:
             MOZ_CRASH("unexpected operand kind");
         }
--- a/js/src/jit/x86/MacroAssembler-x86-inl.h
+++ b/js/src/jit/x86/MacroAssembler-x86-inl.h
@@ -945,57 +945,57 @@ MacroAssembler::truncateFloat32ToUInt64(
 {
     Label done;
 
     loadFloat32(src, floatTemp);
 
     truncateFloat32ToInt64(src, dest, temp);
 
     // For unsigned conversion the case of [INT64, UINT64] needs to get handle seperately.
-    load32(Address(dest.base, dest.offset + INT64HIGH_OFFSET), temp);
+    load32(HighWord(dest), temp);
     branch32(Assembler::Condition::NotSigned, temp, Imm32(0), &done);
 
     // Move the value inside INT64 range.
     storeFloat32(floatTemp, dest);
     loadConstantFloat32(double(int64_t(0x8000000000000000)), floatTemp);
     vaddss(Operand(dest), floatTemp, floatTemp);
     storeFloat32(floatTemp, dest);
     truncateFloat32ToInt64(dest, dest, temp);
 
-    load32(Address(dest.base, dest.offset + INT64HIGH_OFFSET), temp);
+    load32(HighWord(dest), temp);
     orl(Imm32(0x80000000), temp);
-    store32(temp, Address(dest.base, dest.offset + INT64HIGH_OFFSET));
+    store32(temp, HighWord(dest));
 
     bind(&done);
 }
 
 void
 MacroAssembler::truncateDoubleToUInt64(Address src, Address dest, Register temp,
                                        FloatRegister floatTemp)
 {
     Label done;
 
     loadDouble(src, floatTemp);
 
     truncateDoubleToInt64(src, dest, temp);
 
     // For unsigned conversion the case of [INT64, UINT64] needs to get handle seperately.
-    load32(Address(dest.base, dest.offset + INT64HIGH_OFFSET), temp);
+    load32(HighWord(dest), temp);
     branch32(Assembler::Condition::NotSigned, temp, Imm32(0), &done);
 
     // Move the value inside INT64 range.
     storeDouble(floatTemp, dest);
     loadConstantDouble(double(int64_t(0x8000000000000000)), floatTemp);
     vaddsd(Operand(dest), floatTemp, floatTemp);
     storeDouble(floatTemp, dest);
     truncateDoubleToInt64(dest, dest, temp);
 
-    load32(Address(dest.base, dest.offset + INT64HIGH_OFFSET), temp);
+    load32(HighWord(dest), temp);
     orl(Imm32(0x80000000), temp);
-    store32(temp, Address(dest.base, dest.offset + INT64HIGH_OFFSET));
+    store32(temp, HighWord(dest));
 
     bind(&done);
 }
 
 // ========================================================================
 // wasm support
 
 template <class L>
--- a/js/src/jit/x86/MacroAssembler-x86.cpp
+++ b/js/src/jit/x86/MacroAssembler-x86.cpp
@@ -763,40 +763,28 @@ MacroAssembler::wasmLoadI64(const wasm::
         break;
       case Scalar::Uint32:
         movl(srcAddr, out.low);
         append(access, loadOffset, framePushed());
 
         xorl(out.high, out.high);
         break;
       case Scalar::Int64: {
-        Operand low(eax);
-        Operand high(eax);
-
         if (srcAddr.kind() == Operand::MEM_SCALE) {
-            BaseIndex addr = srcAddr.toBaseIndex();
-
-            MOZ_RELEASE_ASSERT(addr.base != out.low && addr.index != out.low);
+            MOZ_RELEASE_ASSERT(srcAddr.toBaseIndex().base != out.low &&
+                               srcAddr.toBaseIndex().index != out.low);
+        }
+        if (srcAddr.kind() == Operand::MEM_REG_DISP)
+            MOZ_RELEASE_ASSERT(srcAddr.toAddress().base != out.low);
 
-            low = Operand(addr.base, addr.index, addr.scale, addr.offset + INT64LOW_OFFSET);
-            high = Operand(addr.base, addr.index, addr.scale, addr.offset + INT64HIGH_OFFSET);
-        } else {
-            Address addr = srcAddr.toAddress();
-
-            MOZ_RELEASE_ASSERT(addr.base != out.low);
-
-            low = Operand(addr.base, addr.offset + INT64LOW_OFFSET);
-            high = Operand(addr.base, addr.offset + INT64HIGH_OFFSET);
-        }
-
-        movl(low, out.low);
+        movl(LowWord(srcAddr), out.low);
         append(access, loadOffset, framePushed());
 
         loadOffset = size();
-        movl(high, out.high);
+        movl(HighWord(srcAddr), out.high);
         append(access, loadOffset, framePushed());
 
         break;
       }
       case Scalar::Float32:
       case Scalar::Float64:
       case Scalar::Float32x4:
       case Scalar::Int8x16:
@@ -877,34 +865,22 @@ MacroAssembler::wasmStore(const wasm::Me
 
 void
 MacroAssembler::wasmStoreI64(const wasm::MemoryAccessDesc& access, Register64 value, Operand dstAddr)
 {
     MOZ_ASSERT(!access.isAtomic());
     MOZ_ASSERT(!access.isSimd());
     MOZ_ASSERT(dstAddr.kind() == Operand::MEM_REG_DISP || dstAddr.kind() == Operand::MEM_SCALE);
 
-    Operand low(eax);
-    Operand high(eax);
-    if (dstAddr.kind() == Operand::MEM_SCALE) {
-        BaseIndex addr = dstAddr.toBaseIndex();
-        low = Operand(addr.base, addr.index, addr.scale, addr.offset + INT64LOW_OFFSET);
-        high = Operand(addr.base, addr.index, addr.scale, addr.offset + INT64HIGH_OFFSET);
-    } else {
-        Address addr = dstAddr.toAddress();
-        low = Operand(addr.base, addr.offset + INT64LOW_OFFSET);
-        high = Operand(addr.base, addr.offset + INT64HIGH_OFFSET);
-    }
-
     size_t storeOffset = size();
-    movl(value.low, low);
+    movl(value.low, LowWord(dstAddr));
     append(access, storeOffset, framePushed());
 
     storeOffset = size();
-    movl(value.high, high);
+    movl(value.high, HighWord(dstAddr));
     append(access, storeOffset, framePushed());
 }
 
 void
 MacroAssembler::wasmTruncateDoubleToUInt32(FloatRegister input, Register output, Label* oolEntry)
 {
     Label done;
     vcvttsd2si(input, output);
--- a/js/src/jit/x86/MacroAssembler-x86.h
+++ b/js/src/jit/x86/MacroAssembler-x86.h
@@ -582,20 +582,20 @@ class MacroAssemblerX86 : public MacroAs
         movl(Operand(address), dest);
     }
     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(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 load64(const T& address, Register64 dest) {
+        movl(Operand(LowWord(address)), dest.low);
+        movl(Operand(HighWord(address)), 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);
@@ -617,23 +617,24 @@ class MacroAssemblerX86 : public MacroAs
         movl(src, Operand(address));
     }
     void store32(Register src, AbsoluteAddress address) {
         movl(src, Operand(address));
     }
     void store16(Register src, AbsoluteAddress address) {
         movw(src, Operand(address));
     }
-    void store64(Register64 src, Address address) {
-        movl(src.low, Operand(Address(address.base, address.offset + INT64LOW_OFFSET)));
-        movl(src.high, Operand(Address(address.base, address.offset + INT64HIGH_OFFSET)));
+    template <typename T>
+    void store64(Register64 src, const T& address) {
+        movl(src.low, Operand(LowWord(address)));
+        movl(src.high, Operand(HighWord(address)));
     }
     void store64(Imm64 imm, Address address) {
-        movl(imm.low(), Operand(Address(address.base, address.offset + INT64LOW_OFFSET)));
-        movl(imm.hi(), Operand(Address(address.base, address.offset + INT64HIGH_OFFSET)));
+        movl(imm.low(), Operand(LowWord(address)));
+        movl(imm.hi(), Operand(HighWord(address)));
     }
 
     void setStackArg(Register reg, uint32_t arg) {
         movl(reg, Operand(esp, arg * sizeof(intptr_t)));
     }
 
     void boxDouble(FloatRegister src, const ValueOperand& dest, FloatRegister temp) {
         if (Assembler::HasSSE41()) {
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -2516,19 +2516,19 @@ class BaseCompiler
             ABIArg argLoc = call.abi.next(MIRType::Int64);
             if (argLoc.kind() == ABIArg::Stack) {
                 ScratchI32 scratch(*this);
 #if defined(JS_CODEGEN_X64)
                 loadI64(Register64(scratch), arg);
                 masm.movq(scratch, Operand(StackPointer, argLoc.offsetFromArgBase()));
 #elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM)
                 loadI64Low(scratch, arg);
-                masm.store32(scratch, Address(StackPointer, argLoc.offsetFromArgBase() + INT64LOW_OFFSET));
+                masm.store32(scratch, LowWord(Address(StackPointer, argLoc.offsetFromArgBase())));
                 loadI64High(scratch, arg);
-                masm.store32(scratch, Address(StackPointer, argLoc.offsetFromArgBase() + INT64HIGH_OFFSET));
+                masm.store32(scratch, HighWord(Address(StackPointer, argLoc.offsetFromArgBase())));
 #else
                 MOZ_CRASH("BaseCompiler platform hook: passArg I64");
 #endif
             } else {
                 loadI64(argLoc.gpr64(), arg);
             }
             break;
           }
--- a/js/src/wasm/WasmStubs.cpp
+++ b/js/src/wasm/WasmStubs.cpp
@@ -134,20 +134,20 @@ SetupABIArguments(MacroAssembler& masm, 
             switch (type) {
               case MIRType::Int32:
                 masm.load32(src, scratch);
                 masm.storePtr(scratch, Address(masm.getStackPointer(), iter->offsetFromArgBase()));
                 break;
               case MIRType::Int64: {
                 Register sp = masm.getStackPointer();
 #if JS_BITS_PER_WORD == 32
-                masm.load32(Address(src.base, src.offset + INT64LOW_OFFSET), scratch);
-                masm.store32(scratch, Address(sp, iter->offsetFromArgBase() + INT64LOW_OFFSET));
-                masm.load32(Address(src.base, src.offset + INT64HIGH_OFFSET), scratch);
-                masm.store32(scratch, Address(sp, iter->offsetFromArgBase() + INT64HIGH_OFFSET));
+                masm.load32(LowWord(src), scratch);
+                masm.store32(scratch, LowWord(Address(sp, iter->offsetFromArgBase())));
+                masm.load32(HighWord(src), scratch);
+                masm.store32(scratch, HighWord(Address(sp, iter->offsetFromArgBase())));
 #else
                 Register64 scratch64(scratch);
                 masm.load64(src, scratch64);
                 masm.store64(scratch64, Address(sp, iter->offsetFromArgBase()));
 #endif
                 break;
               }
               case MIRType::Double:
@@ -379,20 +379,20 @@ GenerateEntry(MacroAssembler& masm, cons
 static void
 StackCopy(MacroAssembler& masm, MIRType type, Register scratch, Address src, Address dst)
 {
     if (type == MIRType::Int32) {
         masm.load32(src, scratch);
         masm.store32(scratch, dst);
     } else if (type == MIRType::Int64) {
 #if JS_BITS_PER_WORD == 32
-        masm.load32(Address(src.base, src.offset + INT64LOW_OFFSET), scratch);
-        masm.store32(scratch, Address(dst.base, dst.offset + INT64LOW_OFFSET));
-        masm.load32(Address(src.base, src.offset + INT64HIGH_OFFSET), scratch);
-        masm.store32(scratch, Address(dst.base, dst.offset + INT64HIGH_OFFSET));
+        masm.load32(LowWord(src), scratch);
+        masm.store32(scratch, LowWord(dst));
+        masm.load32(HighWord(src), scratch);
+        masm.store32(scratch, HighWord(dst));
 #else
         Register64 scratch64(scratch);
         masm.load64(src, scratch64);
         masm.store64(scratch64, dst);
 #endif
     } else if (type == MIRType::Float32) {
         masm.loadFloat32(src, ScratchFloat32Reg);
         masm.storeFloat32(ScratchFloat32Reg, dst);