Bug 1245112 - Part 6: Move MacroAssembler::branchTest32 into generic macro assembler. r=nbp
authorTooru Fujisawa <arai_a@mac.com>
Mon, 15 Feb 2016 23:01:48 +0900
changeset 331317 f433eabad0eecdaf0d895e68fae7f3501dd52c04
parent 331316 50fc6edd4906bfebdf4dc932a634a281850eadb6
child 331318 38551974573c53bf0f4d47eb18c1dd56c1d3a734
push id10956
push userjolesen@mozilla.com
push dateTue, 16 Feb 2016 19:12:12 +0000
reviewersnbp
bugs1245112
milestone47.0a1
Bug 1245112 - Part 6: Move MacroAssembler::branchTest32 into generic macro assembler. r=nbp
js/src/jit/MacroAssembler-inl.h
js/src/jit/MacroAssembler.h
js/src/jit/arm/MacroAssembler-arm-inl.h
js/src/jit/arm/MacroAssembler-arm.h
js/src/jit/arm64/MacroAssembler-arm64-inl.h
js/src/jit/arm64/MacroAssembler-arm64.h
js/src/jit/mips-shared/MacroAssembler-mips-shared-inl.h
js/src/jit/mips32/MacroAssembler-mips32.h
js/src/jit/mips64/MacroAssembler-mips64.h
js/src/jit/none/MacroAssembler-none.h
js/src/jit/x64/MacroAssembler-x64-inl.h
js/src/jit/x64/MacroAssembler-x64.h
js/src/jit/x64/Trampoline-x64.cpp
js/src/jit/x86-shared/MacroAssembler-x86-shared-inl.h
js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
js/src/jit/x86-shared/MacroAssembler-x86-shared.h
js/src/jit/x86/MacroAssembler-x86-inl.h
js/src/jit/x86/MacroAssembler-x86.h
--- a/js/src/jit/MacroAssembler-inl.h
+++ b/js/src/jit/MacroAssembler-inl.h
@@ -315,16 +315,117 @@ void
 MacroAssembler::addPtr(ImmPtr imm, Register dest)
 {
     addPtr(ImmWord(uintptr_t(imm.value)), dest);
 }
 
 //}}} check_macroassembler_style
 // ===============================================================
 
+template <class L>
+void
+MacroAssembler::branchIfFalseBool(Register reg, L label)
+{
+    // Note that C++ bool is only 1 byte, so ignore the higher-order bits.
+    branchTest32(Assembler::Zero, reg, Imm32(0xFF), label);
+}
+
+void
+MacroAssembler::branchIfTrueBool(Register reg, Label* label)
+{
+    // Note that C++ bool is only 1 byte, so ignore the higher-order bits.
+    branchTest32(Assembler::NonZero, reg, Imm32(0xFF), label);
+}
+
+void
+MacroAssembler::branchIfRope(Register str, Label* label)
+{
+    Address flags(str, JSString::offsetOfFlags());
+    static_assert(JSString::ROPE_FLAGS == 0, "Rope type flags must be 0");
+    branchTest32(Assembler::Zero, flags, Imm32(JSString::TYPE_FLAGS_MASK), label);
+}
+
+void
+MacroAssembler::branchLatin1String(Register string, Label* label)
+{
+    branchTest32(Assembler::NonZero, Address(string, JSString::offsetOfFlags()),
+                 Imm32(JSString::LATIN1_CHARS_BIT), label);
+}
+
+void
+MacroAssembler::branchTwoByteString(Register string, Label* label)
+{
+    branchTest32(Assembler::Zero, Address(string, JSString::offsetOfFlags()),
+                 Imm32(JSString::LATIN1_CHARS_BIT), label);
+}
+
+void
+MacroAssembler::branchIfFunctionHasNoScript(Register fun, Label* label)
+{
+    // 16-bit loads are slow and unaligned 32-bit loads may be too so
+    // perform an aligned 32-bit load and adjust the bitmask accordingly.
+    MOZ_ASSERT(JSFunction::offsetOfNargs() % sizeof(uint32_t) == 0);
+    MOZ_ASSERT(JSFunction::offsetOfFlags() == JSFunction::offsetOfNargs() + 2);
+    Address address(fun, JSFunction::offsetOfNargs());
+    int32_t bit = IMM32_16ADJ(JSFunction::INTERPRETED);
+    branchTest32(Assembler::Zero, address, Imm32(bit), label);
+}
+
+void
+MacroAssembler::branchIfInterpreted(Register fun, Label* label)
+{
+    // 16-bit loads are slow and unaligned 32-bit loads may be too so
+    // perform an aligned 32-bit load and adjust the bitmask accordingly.
+    MOZ_ASSERT(JSFunction::offsetOfNargs() % sizeof(uint32_t) == 0);
+    MOZ_ASSERT(JSFunction::offsetOfFlags() == JSFunction::offsetOfNargs() + 2);
+    Address address(fun, JSFunction::offsetOfNargs());
+    int32_t bit = IMM32_16ADJ(JSFunction::INTERPRETED);
+    branchTest32(Assembler::NonZero, address, Imm32(bit), label);
+}
+
+void
+MacroAssembler::branchTestNeedsIncrementalBarrier(Condition cond, Label* label)
+{
+    MOZ_ASSERT(cond == Zero || cond == NonZero);
+    CompileZone* zone = GetJitContext()->compartment->zone();
+    AbsoluteAddress needsBarrierAddr(zone->addressOfNeedsIncrementalBarrier());
+    branchTest32(cond, needsBarrierAddr, Imm32(0x1), label);
+}
+
+void
+MacroAssembler::branchTestObjectTruthy(bool truthy, Register objReg, Register scratch,
+                                       Label* slowCheck, Label* checked)
+{
+    // The branches to out-of-line code here implement a conservative version
+    // of the JSObject::isWrapper test performed in EmulatesUndefined.  If none
+    // of the branches are taken, we can check class flags directly.
+    loadObjClass(objReg, scratch);
+    Address flags(scratch, Class::offsetOfFlags());
+
+    branchTestClassIsProxy(true, scratch, slowCheck);
+
+    Condition cond = truthy ? Assembler::Zero : Assembler::NonZero;
+    branchTest32(cond, flags, Imm32(JSCLASS_EMULATES_UNDEFINED), checked);
+}
+
+void
+MacroAssembler::branchTestClassIsProxy(bool proxy, Register clasp, Label* label)
+{
+    branchTest32(proxy ? Assembler::NonZero : Assembler::Zero,
+                 Address(clasp, Class::offsetOfFlags()),
+                 Imm32(JSCLASS_IS_PROXY), label);
+}
+
+void
+MacroAssembler::branchTestObjectIsProxy(bool proxy, Register object, Register scratch, Label* label)
+{
+    loadObjClass(object, scratch);
+    branchTestClassIsProxy(proxy, scratch, label);
+}
+
 void
 MacroAssembler::branchFunctionKind(Condition cond, JSFunction::FunctionKind kind, Register fun,
                                    Register scratch, Label* label)
 {
     // 16-bit loads are slow and unaligned 32-bit loads may be too so
     // perform an aligned 32-bit load and adjust the bitmask accordingly.
     MOZ_ASSERT(JSFunction::offsetOfNargs() % sizeof(uint32_t) == 0);
     MOZ_ASSERT(JSFunction::offsetOfFlags() == JSFunction::offsetOfNargs() + 2);
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -836,16 +836,24 @@ class MacroAssembler : public MacroAssem
 
     inline void branchPtr(Condition cond, wasm::SymbolicAddress lhs, Register rhs, Label* label)
         DEFINED_ON(arm, arm64, mips_shared, x86, x64);
 
     // This function compares a Value (lhs) which is having a private pointer
     // boxed inside a js::Value, with a raw pointer (rhs).
     inline void branchPrivatePtr(Condition cond, const Address& lhs, Register rhs, Label* label) PER_ARCH;
 
+    template <class L>
+    inline void branchTest32(Condition cond, Register lhs, Register rhs, L label) PER_SHARED_ARCH;
+    template <class L>
+    inline void branchTest32(Condition cond, Register lhs, Imm32 rhs, L label) PER_SHARED_ARCH;
+    inline void branchTest32(Condition cond, const Address& lhs, Imm32 rhh, Label* label) PER_SHARED_ARCH;
+    inline void branchTest32(Condition cond, const AbsoluteAddress& lhs, Imm32 rhs, Label* label)
+        DEFINED_ON(arm, arm64, mips_shared, x86, x64);
+
     inline void branchTestPtr(Condition cond, Register lhs, Register rhs, Label* label) PER_SHARED_ARCH;
     inline void branchTestPtr(Condition cond, Register lhs, Imm32 rhs, Label* label) PER_SHARED_ARCH;
     inline void branchTestPtr(Condition cond, const Address& lhs, Imm32 rhs, Label* label) PER_SHARED_ARCH;
 
     inline void branchTest64(Condition cond, Register64 lhs, Register64 rhs, Register temp,
                              Label* label) PER_ARCH;
 
     //}}} check_macroassembler_style
@@ -900,26 +908,20 @@ class MacroAssembler : public MacroAssem
           case MIRType_MagicHole: return branchTestMagic(cond, val, label);
           default:
             MOZ_CRASH("Bad MIRType");
         }
     }
 
     // Branches to |label| if |reg| is false. |reg| should be a C++ bool.
     template <class L>
-    void branchIfFalseBool(Register reg, L label) {
-        // Note that C++ bool is only 1 byte, so ignore the higher-order bits.
-        branchTest32(Assembler::Zero, reg, Imm32(0xFF), label);
-    }
+    inline void branchIfFalseBool(Register reg, L label);
 
     // Branches to |label| if |reg| is true. |reg| should be a C++ bool.
-    void branchIfTrueBool(Register reg, Label* label) {
-        // Note that C++ bool is only 1 byte, so ignore the higher-order bits.
-        branchTest32(Assembler::NonZero, reg, Imm32(0xFF), label);
-    }
+    inline void branchIfTrueBool(Register reg, Label* label);
 
     void loadObjPrivate(Register obj, uint32_t nfixed, Register dest) {
         loadPtr(Address(obj, NativeObject::getPrivateDataOffset(nfixed)), dest);
     }
 
     void loadObjProto(Register obj, Register dest) {
         loadPtr(Address(obj, JSObject::offsetOfGroup()), dest);
         loadPtr(Address(dest, ObjectGroup::offsetOfProto()), dest);
@@ -927,30 +929,20 @@ class MacroAssembler : public MacroAssem
 
     void loadStringLength(Register str, Register dest) {
         load32(Address(str, JSString::offsetOfLength()), dest);
     }
 
     void loadStringChars(Register str, Register dest);
     void loadStringChar(Register str, Register index, Register output);
 
-    void branchIfRope(Register str, Label* label) {
-        Address flags(str, JSString::offsetOfFlags());
-        static_assert(JSString::ROPE_FLAGS == 0, "Rope type flags must be 0");
-        branchTest32(Assembler::Zero, flags, Imm32(JSString::TYPE_FLAGS_MASK), label);
-    }
+    inline void branchIfRope(Register str, Label* label);
 
-    void branchLatin1String(Register string, Label* label) {
-        branchTest32(Assembler::NonZero, Address(string, JSString::offsetOfFlags()),
-                     Imm32(JSString::LATIN1_CHARS_BIT), label);
-    }
-    void branchTwoByteString(Register string, Label* label) {
-        branchTest32(Assembler::Zero, Address(string, JSString::offsetOfFlags()),
-                     Imm32(JSString::LATIN1_CHARS_BIT), label);
-    }
+    inline void branchLatin1String(Register string, Label* label);
+    inline void branchTwoByteString(Register string, Label* label);
 
     void loadJSContext(Register dest) {
         loadPtr(AbsoluteAddress(GetJitContext()->runtime->addressOfJSContext()), dest);
     }
     void loadJitActivation(Register dest) {
         loadPtr(AbsoluteAddress(GetJitContext()->runtime->addressOfActivation()), dest);
     }
 
@@ -1059,34 +1051,18 @@ class MacroAssembler : public MacroAssem
             storeCallResultValue(dest.typedReg());
     }
 
     template <typename T>
     Register extractString(const T& source, Register scratch) {
         return extractObject(source, scratch);
     }
 
-    void branchIfFunctionHasNoScript(Register fun, Label* label) {
-        // 16-bit loads are slow and unaligned 32-bit loads may be too so
-        // perform an aligned 32-bit load and adjust the bitmask accordingly.
-        MOZ_ASSERT(JSFunction::offsetOfNargs() % sizeof(uint32_t) == 0);
-        MOZ_ASSERT(JSFunction::offsetOfFlags() == JSFunction::offsetOfNargs() + 2);
-        Address address(fun, JSFunction::offsetOfNargs());
-        int32_t bit = IMM32_16ADJ(JSFunction::INTERPRETED);
-        branchTest32(Assembler::Zero, address, Imm32(bit), label);
-    }
-    void branchIfInterpreted(Register fun, Label* label) {
-        // 16-bit loads are slow and unaligned 32-bit loads may be too so
-        // perform an aligned 32-bit load and adjust the bitmask accordingly.
-        MOZ_ASSERT(JSFunction::offsetOfNargs() % sizeof(uint32_t) == 0);
-        MOZ_ASSERT(JSFunction::offsetOfFlags() == JSFunction::offsetOfNargs() + 2);
-        Address address(fun, JSFunction::offsetOfNargs());
-        int32_t bit = IMM32_16ADJ(JSFunction::INTERPRETED);
-        branchTest32(Assembler::NonZero, address, Imm32(bit), label);
-    }
+    inline void branchIfFunctionHasNoScript(Register fun, Label* label);
+    inline void branchIfInterpreted(Register fun, Label* label);
 
     void branchIfNotInterpretedConstructor(Register fun, Register scratch, Label* label);
 
     inline void bumpKey(Int32Key* key, int diff);
 
     void storeKey(const Int32Key& key, const Address& dest) {
         if (key.isRegister())
             store32(key.reg(), dest);
@@ -1097,22 +1073,17 @@ class MacroAssembler : public MacroAssem
     template<typename T>
     void branchKey(Condition cond, const T& length, const Int32Key& key, Label* label) {
         if (key.isRegister())
             branch32(cond, length, key.reg(), label);
         else
             branch32(cond, length, Imm32(key.constant()), label);
     }
 
-    void branchTestNeedsIncrementalBarrier(Condition cond, Label* label) {
-        MOZ_ASSERT(cond == Zero || cond == NonZero);
-        CompileZone* zone = GetJitContext()->compartment->zone();
-        AbsoluteAddress needsBarrierAddr(zone->addressOfNeedsIncrementalBarrier());
-        branchTest32(cond, needsBarrierAddr, Imm32(0x1), label);
-    }
+    inline void branchTestNeedsIncrementalBarrier(Condition cond, Label* label);
 
     template <typename T>
     void callPreBarrier(const T& address, MIRType type) {
         Label done;
 
         if (type == MIRType_Value)
             branchTestGCThing(Assembler::NotEqual, address, &done);
 
@@ -1291,43 +1262,22 @@ class MacroAssembler : public MacroAssem
     // This checks for identical pointers, atoms and length and fails for everything else.
     void compareStrings(JSOp op, Register left, Register right, Register result,
                         Label* fail);
 
   public:
     // Generates code used to complete a bailout.
     void generateBailoutTail(Register scratch, Register bailoutInfo);
 
-    void branchTestObjectTruthy(bool truthy, Register objReg, Register scratch,
-                                Label* slowCheck, Label* checked)
-    {
-        // The branches to out-of-line code here implement a conservative version
-        // of the JSObject::isWrapper test performed in EmulatesUndefined.  If none
-        // of the branches are taken, we can check class flags directly.
-        loadObjClass(objReg, scratch);
-        Address flags(scratch, Class::offsetOfFlags());
-
-        branchTestClassIsProxy(true, scratch, slowCheck);
+    inline void branchTestObjectTruthy(bool truthy, Register objReg, Register scratch,
+                                       Label* slowCheck, Label* checked);
 
-        Condition cond = truthy ? Assembler::Zero : Assembler::NonZero;
-        branchTest32(cond, flags, Imm32(JSCLASS_EMULATES_UNDEFINED), checked);
-    }
+    inline void branchTestClassIsProxy(bool proxy, Register clasp, Label* label);
 
-    void branchTestClassIsProxy(bool proxy, Register clasp, Label* label)
-    {
-        branchTest32(proxy ? Assembler::NonZero : Assembler::Zero,
-                     Address(clasp, Class::offsetOfFlags()),
-                     Imm32(JSCLASS_IS_PROXY), label);
-    }
-
-    void branchTestObjectIsProxy(bool proxy, Register object, Register scratch, Label* label)
-    {
-        loadObjClass(object, scratch);
-        branchTestClassIsProxy(proxy, scratch, label);
-    }
+    inline void branchTestObjectIsProxy(bool proxy, Register object, Register scratch, Label* label);
 
     inline void branchFunctionKind(Condition cond, JSFunction::FunctionKind kind, Register fun,
                                    Register scratch, Label* label);
 
   public:
 #ifndef JS_CODEGEN_ARM64
     // StackPointer manipulation functions.
     // On ARM64, the StackPointer is implemented as two synchronized registers.
--- a/js/src/jit/arm/MacroAssembler-arm-inl.h
+++ b/js/src/jit/arm/MacroAssembler-arm-inl.h
@@ -570,16 +570,57 @@ MacroAssembler::branchPtr(Condition cond
 }
 
 void
 MacroAssembler::branchPrivatePtr(Condition cond, const Address& lhs, Register rhs, Label* label)
 {
     branchPtr(cond, lhs, rhs, label);
 }
 
+template <class L>
+void
+MacroAssembler::branchTest32(Condition cond, Register lhs, Register rhs, L label)
+{
+    MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
+    // x86 likes test foo, foo rather than cmp foo, #0.
+    // Convert the former into the latter.
+    if (lhs == rhs && (cond == Zero || cond == NonZero))
+        ma_cmp(lhs, Imm32(0));
+    else
+        ma_tst(lhs, rhs);
+    ma_b(label, cond);
+}
+
+template <class L>
+void
+MacroAssembler::branchTest32(Condition cond, Register lhs, Imm32 rhs, L label)
+{
+    MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
+    ma_tst(lhs, rhs);
+    ma_b(label, cond);
+}
+
+void
+MacroAssembler::branchTest32(Condition cond, const Address& lhs, Imm32 rhs, Label* label)
+{
+    // branchTest32 will use ScratchRegister.
+    AutoRegisterScope scratch2(*this, secondScratchReg_);
+    load32(lhs, scratch2);
+    branchTest32(cond, scratch2, rhs, label);
+}
+
+void
+MacroAssembler::branchTest32(Condition cond, const AbsoluteAddress& lhs, Imm32 rhs, Label* label)
+{
+    // branchTest32 will use ScratchRegister.
+    AutoRegisterScope scratch2(*this, secondScratchReg_);
+    load32(lhs, scratch2);
+    branchTest32(cond, scratch2, rhs, label);
+}
+
 void
 MacroAssembler::branchTestPtr(Condition cond, Register lhs, Register rhs, Label* label)
 {
     branchTest32(cond, lhs, rhs, label);
 }
 
 void
 MacroAssembler::branchTestPtr(Condition cond, Register lhs, Imm32 rhs, Label* label)
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -831,45 +831,16 @@ class MacroAssemblerARMCompat : public M
     void branchTestDoubleTruthy(bool truthy, FloatRegister reg, Label* label) {
         Condition c = testDoubleTruthy(truthy, reg);
         ma_b(label, c);
     }
     void branchTestStringTruthy(bool truthy, const ValueOperand& value, Label* label) {
         Condition c = testStringTruthy(truthy, value);
         ma_b(label, c);
     }
-    template <class L>
-    void branchTest32(Condition cond, Register lhs, Register rhs, L label) {
-        MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
-        // x86 likes test foo, foo rather than cmp foo, #0.
-        // Convert the former into the latter.
-        if (lhs == rhs && (cond == Zero || cond == NonZero))
-            ma_cmp(lhs, Imm32(0));
-        else
-            ma_tst(lhs, rhs);
-        ma_b(label, cond);
-    }
-    template <class L>
-    void branchTest32(Condition cond, Register lhs, Imm32 imm, L label) {
-        MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
-        ma_tst(lhs, imm);
-        ma_b(label, cond);
-    }
-    void branchTest32(Condition cond, const Address& address, Imm32 imm, Label* label) {
-        // branchTest32 will use ScratchRegister.
-        AutoRegisterScope scratch2(asMasm(), secondScratchReg_);
-        load32(address, scratch2);
-        branchTest32(cond, scratch2, imm, label);
-    }
-    void branchTest32(Condition cond, AbsoluteAddress address, Imm32 imm, Label* label) {
-        // branchTest32 will use ScratchRegister.
-        AutoRegisterScope scratch2(asMasm(), secondScratchReg_);
-        load32(address, scratch2);
-        branchTest32(cond, scratch2, imm, label);
-    }
     void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) {
         ma_sub(imm, lhs, SetCC);
         as_b(label, cond);
     }
     void moveValue(const Value& val, Register type, Register data);
 
     CodeOffsetJump jumpWithPatch(RepatchLabel* label, Condition cond = Always,
                                  Label* documentation = nullptr);
--- a/js/src/jit/arm64/MacroAssembler-arm64-inl.h
+++ b/js/src/jit/arm64/MacroAssembler-arm64-inl.h
@@ -647,16 +647,58 @@ MacroAssembler::branchPrivatePtr(Conditi
     const Register scratch = temps.AcquireX().asUnsized();
     if (rhs != scratch)
         movePtr(rhs, scratch);
     // Instead of unboxing lhs, box rhs and do direct comparison with lhs.
     rshiftPtr(Imm32(1), scratch);
     branchPtr(cond, lhs, scratch, label);
 }
 
+template <class L>
+void
+MacroAssembler::branchTest32(Condition cond, Register lhs, Register rhs, L label)
+{
+    MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
+    // x86 prefers |test foo, foo| to |cmp foo, #0|.
+    // Convert the former to the latter for ARM.
+    if (lhs == rhs && (cond == Zero || cond == NonZero))
+        cmp32(lhs, Imm32(0));
+    else
+        test32(lhs, rhs);
+    B(label, cond);
+}
+
+template <class L>
+void
+MacroAssembler::branchTest32(Condition cond, Register lhs, Imm32 rhs, L label)
+{
+    MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
+    test32(lhs, rhs);
+    B(label, cond);
+}
+
+void
+MacroAssembler::branchTest32(Condition cond, const Address& lhs, Imm32 rhs, Label* label)
+{
+    vixl::UseScratchRegisterScope temps(this);
+    const Register scratch = temps.AcquireX().asUnsized();
+    MOZ_ASSERT(scratch != lhs.base);
+    load32(lhs, scratch);
+    branchTest32(cond, scratch, rhs, label);
+}
+
+void
+MacroAssembler::branchTest32(Condition cond, const AbsoluteAddress& lhs, Imm32 rhs, Label* label)
+{
+    vixl::UseScratchRegisterScope temps(this);
+    const Register scratch = temps.AcquireX().asUnsized();
+    load32(lhs, scratch);
+    branchTest32(cond, scratch, rhs, label);
+}
+
 void
 MacroAssembler::branchTestPtr(Condition cond, Register lhs, Register rhs, Label* label)
 {
     Tst(ARMRegister(lhs, 64), Operand(ARMRegister(rhs, 64)));
     B(label, cond);
 }
 
 void
--- a/js/src/jit/arm64/MacroAssembler-arm64.h
+++ b/js/src/jit/arm64/MacroAssembler-arm64.h
@@ -1350,46 +1350,16 @@ class MacroAssemblerCompat : public vixl
         B(label, cond);
     }
     void branch(JitCode* target) {
         syncStackPtr();
         BufferOffset loc = b(-1); // The jump target will be patched by executableCopy().
         addPendingJump(loc, ImmPtr(target->raw()), Relocation::JITCODE);
     }
 
-    template <class L>
-    void branchTest32(Condition cond, Register lhs, Register rhs, L label) {
-        MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
-        // x86 prefers |test foo, foo| to |cmp foo, #0|.
-        // Convert the former to the latter for ARM.
-        if (lhs == rhs && (cond == Zero || cond == NonZero))
-            cmp32(lhs, Imm32(0));
-        else
-            test32(lhs, rhs);
-        B(label, cond);
-    }
-    template <class L>
-    void branchTest32(Condition cond, Register lhs, Imm32 imm, L label) {
-        MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
-        test32(lhs, imm);
-        B(label, cond);
-    }
-    void branchTest32(Condition cond, const Address& address, Imm32 imm, Label* label) {
-        vixl::UseScratchRegisterScope temps(this);
-        const Register scratch = temps.AcquireX().asUnsized();
-        MOZ_ASSERT(scratch != address.base);
-        load32(address, scratch);
-        branchTest32(cond, scratch, imm, label);
-    }
-    void branchTest32(Condition cond, AbsoluteAddress address, Imm32 imm, Label* label) {
-        vixl::UseScratchRegisterScope temps(this);
-        const Register scratch = temps.AcquireX().asUnsized();
-        loadPtr(address, scratch);
-        branchTest32(cond, scratch, imm, label);
-    }
     CodeOffsetJump jumpWithPatch(RepatchLabel* label, Condition cond = Always,
                                  Label* documentation = nullptr)
     {
         ARMBuffer::PoolEntry pe;
         BufferOffset load_bo;
         BufferOffset branch_bo;
 
         // Does not overwrite condition codes from the caller.
--- a/js/src/jit/mips-shared/MacroAssembler-mips-shared-inl.h
+++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared-inl.h
@@ -340,16 +340,51 @@ MacroAssembler::branchPtr(Condition cond
 
 void
 MacroAssembler::branchPtr(Condition cond, wasm::SymbolicAddress lhs, Register rhs, Label* label)
 {
     loadPtr(lhs, SecondScratchReg);
     branchPtr(cond, SecondScratchReg, rhs, label);
 }
 
+template <class L>
+void
+MacroAssembler::branchTest32(Condition cond, Register lhs, Register rhs, L label)
+{
+    MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
+    if (lhs == rhs) {
+        ma_b(lhs, rhs, label, cond);
+    } else {
+        as_and(ScratchRegister, lhs, rhs);
+        ma_b(ScratchRegister, ScratchRegister, label, cond);
+    }
+}
+
+template <class L>
+void
+MacroAssembler::branchTest32(Condition cond, Register lhs, Imm32 rhs, L label)
+{
+    ma_li(ScratchRegister, rhs);
+    branchTest32(cond, lhs, ScratchRegister, label);
+}
+
+void
+MacroAssembler::branchTest32(Condition cond, const Address& lhs, Imm32 rhs, Label* label)
+{
+    load32(lhs, SecondScratchReg);
+    branchTest32(cond, SecondScratchReg, rhs, label);
+}
+
+void
+MacroAssembler::branchTest32(Condition cond, const AbsoluteAddress& lhs, Imm32 rhs, Label* label)
+{
+    load32(lhs, ScratchRegister);
+    branchTest32(cond, ScratchRegister, rhs, label);
+}
+
 void
 MacroAssembler::branchTestPtr(Condition cond, Register lhs, Register rhs, Label* label)
 {
     MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
     if (lhs == rhs) {
         ma_b(lhs, rhs, label, cond);
     } else {
         as_and(ScratchRegister, lhs, rhs);
--- a/js/src/jit/mips32/MacroAssembler-mips32.h
+++ b/js/src/jit/mips32/MacroAssembler-mips32.h
@@ -432,37 +432,16 @@ class MacroAssemblerMIPSCompat : public 
     void branchTestInt32Truthy(bool b, const ValueOperand& value, Label* label);
 
     void branchTestStringTruthy(bool b, const ValueOperand& value, Label* label);
 
     void branchTestDoubleTruthy(bool b, FloatRegister value, Label* label);
 
     void branchTestBooleanTruthy(bool b, const ValueOperand& operand, Label* label);
 
-    void branchTest32(Condition cond, Register lhs, Register rhs, Label* label) {
-        MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
-        if (lhs == rhs) {
-            ma_b(lhs, rhs, label, cond);
-        } else {
-            as_and(ScratchRegister, lhs, rhs);
-            ma_b(ScratchRegister, ScratchRegister, label, cond);
-        }
-    }
-    void branchTest32(Condition cond, Register lhs, Imm32 imm, Label* label) {
-        ma_li(ScratchRegister, imm);
-        branchTest32(cond, lhs, ScratchRegister, label);
-    }
-    void branchTest32(Condition cond, const Address& address, Imm32 imm, Label* label) {
-        load32(address, SecondScratchReg);
-        branchTest32(cond, SecondScratchReg, imm, label);
-    }
-    void branchTest32(Condition cond, AbsoluteAddress address, Imm32 imm, Label* label) {
-        load32(address, ScratchRegister);
-        branchTest32(cond, ScratchRegister, imm, label);
-    }
     inline void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label);
 
     // higher level tag testing code
     Operand ToPayload(Operand base);
     Address ToPayload(Address base) {
         return ToPayload(Operand(base)).toAddress();
     }
 
--- a/js/src/jit/mips64/MacroAssembler-mips64.h
+++ b/js/src/jit/mips64/MacroAssembler-mips64.h
@@ -473,37 +473,16 @@ class MacroAssemblerMIPS64Compat : publi
     void branchTestInt32Truthy(bool b, const ValueOperand& value, Label* label);
 
     void branchTestStringTruthy(bool b, const ValueOperand& value, Label* label);
 
     void branchTestDoubleTruthy(bool b, FloatRegister value, Label* label);
 
     void branchTestBooleanTruthy(bool b, const ValueOperand& operand, Label* label);
 
-    void branchTest32(Condition cond, Register lhs, Register rhs, Label* label) {
-        MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
-        if (lhs == rhs) {
-            ma_b(lhs, rhs, label, cond);
-        } else {
-            as_and(ScratchRegister, lhs, rhs);
-            ma_b(ScratchRegister, ScratchRegister, label, cond);
-        }
-    }
-    void branchTest32(Condition cond, Register lhs, Imm32 imm, Label* label) {
-        ma_li(ScratchRegister, imm);
-        branchTest32(cond, lhs, ScratchRegister, label);
-    }
-    void branchTest32(Condition cond, const Address& address, Imm32 imm, Label* label) {
-        load32(address, SecondScratchReg);
-        branchTest32(cond, SecondScratchReg, imm, label);
-    }
-    void branchTest32(Condition cond, AbsoluteAddress address, Imm32 imm, Label* label) {
-        load32(address, ScratchRegister);
-        branchTest32(cond, ScratchRegister, imm, label);
-    }
     inline void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label);
 
     // higher level tag testing code
     Address ToPayload(Address value) {
         return value;
     }
 
     void moveValue(const Value& val, Register dest);
--- a/js/src/jit/none/MacroAssembler-none.h
+++ b/js/src/jit/none/MacroAssembler-none.h
@@ -239,17 +239,16 @@ class MacroAssemblerNone : public Assemb
     template <typename T, typename S> void branchTestValue(Condition, T, S, Label*) { MOZ_CRASH(); }
     void testNullSet(Condition, ValueOperand, Register) { MOZ_CRASH(); }
     void testObjectSet(Condition, ValueOperand, Register) { MOZ_CRASH(); }
     void testUndefinedSet(Condition, ValueOperand, Register) { MOZ_CRASH(); }
 
     template <typename T, typename S> void cmpPtrSet(Condition, T, S, Register) { MOZ_CRASH(); }
     template <typename T, typename S> void cmp32Set(Condition, T, S, Register) { MOZ_CRASH(); }
 
-    template <typename T, typename S, typename L> void branchTest32(Condition, T, S, L) { MOZ_CRASH(); }
     template <typename T, typename S> void branchAdd32(Condition, T, S, Label*) { MOZ_CRASH(); }
     template <typename T, typename S> void branchSub32(Condition, T, S, Label*) { MOZ_CRASH(); }
     template <typename T, typename S> void branchDouble(DoubleCondition, T, S, Label*) { MOZ_CRASH(); }
     template <typename T, typename S> void branchFloat(DoubleCondition, T, S, Label*) { MOZ_CRASH(); }
     template <typename T, typename S> void decBranchPtr(Condition, T, S, Label*) { MOZ_CRASH(); }
     template <typename T, typename S> void mov(T, S) { MOZ_CRASH(); }
     template <typename T, typename S> void movq(T, S) { MOZ_CRASH(); }
     template <typename T, typename S> void movePtr(T, S) { MOZ_CRASH(); }
--- a/js/src/jit/x64/MacroAssembler-x64-inl.h
+++ b/js/src/jit/x64/MacroAssembler-x64-inl.h
@@ -294,16 +294,29 @@ MacroAssembler::branchPrivatePtr(Conditi
     if (rhs != scratch)
         movePtr(rhs, scratch);
     // Instead of unboxing lhs, box rhs and do direct comparison with lhs.
     rshiftPtr(Imm32(1), scratch);
     branchPtr(cond, lhs, scratch, label);
 }
 
 void
+MacroAssembler::branchTest32(Condition cond, const AbsoluteAddress& lhs, Imm32 rhs, Label* label)
+{
+    if (X86Encoding::IsAddressImmediate(lhs.addr)) {
+        test32(Operand(lhs), rhs);
+    } else {
+        ScratchRegisterScope scratch(*this);
+        mov(ImmPtr(lhs.addr), scratch);
+        test32(Operand(scratch, 0), rhs);
+    }
+    j(cond, label);
+}
+
+void
 MacroAssembler::branchTest64(Condition cond, Register64 lhs, Register64 rhs, Register temp,
                              Label* label)
 {
     branchTestPtr(cond, lhs.reg, rhs.reg, label);
 }
 
 //}}} check_macroassembler_style
 // ===============================================================
--- a/js/src/jit/x64/MacroAssembler-x64.h
+++ b/js/src/jit/x64/MacroAssembler-x64.h
@@ -37,17 +37,16 @@ class MacroAssemblerX64 : public MacroAs
   private:
     // Perform a downcast. Should be removed by Bug 996602.
     MacroAssembler& asMasm();
     const MacroAssembler& asMasm() const;
 
     void bindOffsets(const MacroAssemblerX86Shared::UsesVector&);
 
   public:
-    using MacroAssemblerX86Shared::branchTest32;
     using MacroAssemblerX86Shared::load32;
     using MacroAssemblerX86Shared::store32;
 
     MacroAssemblerX64()
     {
     }
 
     // The buffer is about to be linked, make sure any constant pools or excess
@@ -522,27 +521,16 @@ class MacroAssemblerX64 : public MacroAs
         cmpPtr(lhs, rhs);
         emitSet(cond, dest);
     }
 
     /////////////////////////////////////////////////////////////////
     // Common interface.
     /////////////////////////////////////////////////////////////////
 
-    void branchTest32(Condition cond, AbsoluteAddress address, Imm32 imm, Label* label) {
-        if (X86Encoding::IsAddressImmediate(address.addr)) {
-            test32(Operand(address), imm);
-        } else {
-            ScratchRegisterScope scratch(asMasm());
-            mov(ImmPtr(address.addr), scratch);
-            test32(Operand(scratch, 0), imm);
-        }
-        j(cond, label);
-    }
-
     template <typename T, typename S>
     inline void branchPtrImpl(Condition cond, const T& lhs, const S& rhs, Label* label);
 
     CodeOffsetJump jumpWithPatch(RepatchLabel* label, Label* documentation = nullptr) {
         JmpSrc src = jmpSrc(label);
         return CodeOffsetJump(size(), addPatchableJump(src, Relocation::HARDCODED));
     }
 
--- a/js/src/jit/x64/Trampoline-x64.cpp
+++ b/js/src/jit/x64/Trampoline-x64.cpp
@@ -35,17 +35,17 @@ JitRuntime::generateEnterJIT(JSContext* 
     masm.assertStackAlignment(ABIStackAlignment, -int32_t(sizeof(uintptr_t)) /* return address */);
 
     const Register reg_code  = IntArgReg0;
     const Register reg_argc  = IntArgReg1;
     const Register reg_argv  = IntArgReg2;
     MOZ_ASSERT(OsrFrameReg == IntArgReg3);
 
 #if defined(_WIN64)
-    const Operand token  = Operand(rbp, 16 + ShadowStackSpace);
+    const Address token  = Address(rbp, 16 + ShadowStackSpace);
     const Operand scopeChain = Operand(rbp, 24 + ShadowStackSpace);
     const Operand numStackValuesAddr = Operand(rbp, 32 + ShadowStackSpace);
     const Operand result = Operand(rbp, 40 + ShadowStackSpace);
 #else
     const Register token = IntArgReg4;
     const Register scopeChain = IntArgReg5;
     const Operand numStackValuesAddr = Operand(rbp, 16 + ShadowStackSpace);
     const Operand result = Operand(rbp, 24 + ShadowStackSpace);
--- a/js/src/jit/x86-shared/MacroAssembler-x86-shared-inl.h
+++ b/js/src/jit/x86-shared/MacroAssembler-x86-shared-inl.h
@@ -289,16 +289,42 @@ MacroAssembler::branchPtr(Condition cond
 }
 
 void
 MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmWord rhs, Label* label)
 {
     branchPtrImpl(cond, lhs, rhs, label);
 }
 
+template <class L>
+void
+MacroAssembler::branchTest32(Condition cond, Register lhs, Register rhs, L label)
+{
+    MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
+    test32(lhs, rhs);
+    j(cond, label);
+}
+
+template <class L>
+void
+MacroAssembler::branchTest32(Condition cond, Register lhs, Imm32 rhs, L label)
+{
+    MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
+    test32(lhs, rhs);
+    j(cond, label);
+}
+
+void
+MacroAssembler::branchTest32(Condition cond, const Address& lhs, Imm32 rhs, Label* label)
+{
+    MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
+    test32(Operand(lhs), rhs);
+    j(cond, label);
+}
+
 void
 MacroAssembler::branchTestPtr(Condition cond, Register lhs, Register rhs, Label* label)
 {
     testPtr(lhs, rhs);
     j(cond, label);
 }
 
 void
@@ -313,12 +339,25 @@ MacroAssembler::branchTestPtr(Condition 
 {
     testPtr(Operand(lhs), rhs);
     j(cond, label);
 }
 
 //}}} check_macroassembler_style
 // ===============================================================
 
+void
+MacroAssemblerX86Shared::clampIntToUint8(Register reg)
+{
+    Label inRange;
+    asMasm().branchTest32(Assembler::Zero, reg, Imm32(0xffffff00), &inRange);
+    {
+        sarl(Imm32(31), reg);
+        notl(reg);
+        andl(Imm32(255), reg);
+    }
+    bind(&inRange);
+}
+
 } // namespace jit
 } // namespace js
 
 #endif /* jit_x86_shared_MacroAssembler_x86_shared_inl_h */
--- a/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
+++ b/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
@@ -107,17 +107,17 @@ MacroAssemblerX86Shared::branchNegativeZ
         // If reg is non-zero, jump to nonZero.
         branchDouble(DoubleNotEqual, reg, scratchDouble, &nonZero);
     }
     // Input register is either zero or negative zero. Retrieve sign of input.
     vmovmskpd(reg, scratch);
 
     // If reg is 1 or 3, input is negative zero.
     // If reg is 0 or 2, input is a normal zero.
-    branchTest32(NonZero, scratch, Imm32(1), label);
+    asMasm().branchTest32(NonZero, scratch, Imm32(1), label);
 
     bind(&nonZero);
 #elif defined(JS_CODEGEN_X64)
     vmovq(reg, scratch);
     cmpq(Imm32(1), scratch);
     j(Overflow, label);
 #endif
 }
--- a/js/src/jit/x86-shared/MacroAssembler-x86-shared.h
+++ b/js/src/jit/x86-shared/MacroAssembler-x86-shared.h
@@ -567,38 +567,16 @@ class MacroAssemblerX86Shared : public A
     void branch16(Condition cond, Register lhs, Register rhs, Label* label) {
         cmpw(rhs, lhs);
         j(cond, label);
     }
     void branchTest16(Condition cond, Register lhs, Register rhs, Label* label) {
         testw(rhs, lhs);
         j(cond, label);
     }
-    template <class L>
-    void branchTest32(Condition cond, Register lhs, Register rhs, L label) {
-        MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
-        test32(lhs, rhs);
-        j(cond, label);
-    }
-    template <class L>
-    void branchTest32(Condition cond, Register lhs, Imm32 imm, L label) {
-        MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
-        test32(lhs, imm);
-        j(cond, label);
-    }
-    void branchTest32(Condition cond, const Address& address, Imm32 imm, Label* label) {
-        MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
-        test32(Operand(address), imm);
-        j(cond, label);
-    }
-    void branchTest32(Condition cond, const Operand& lhs, Imm32 imm, Label* label) {
-        MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
-        test32(lhs, imm);
-        j(cond, label);
-    }
 
     void jump(Label* label) {
         jmp(label);
     }
     void jump(JitCode* code) {
         jmp(code);
     }
     void jump(RepatchLabel* label) {
@@ -1278,26 +1256,17 @@ class MacroAssemblerX86Shared : public A
         ScratchFloat32Scope scratch(asMasm());
         vcvttss2si(src, dest);
         convertInt32ToFloat32(dest, scratch);
         vucomiss(scratch, src);
         j(Assembler::Parity, fail);
         j(Assembler::NotEqual, fail);
     }
 
-    void clampIntToUint8(Register reg) {
-        Label inRange;
-        branchTest32(Assembler::Zero, reg, Imm32(0xffffff00), &inRange);
-        {
-            sarl(Imm32(31), reg);
-            notl(reg);
-            andl(Imm32(255), reg);
-        }
-        bind(&inRange);
-    }
+    inline void clampIntToUint8(Register reg);
 
     bool maybeInlineDouble(double d, FloatRegister dest) {
         uint64_t u = mozilla::BitwiseCast<uint64_t>(d);
 
         // Loading zero with xor is specially optimized in hardware.
         if (u == 0) {
             zeroDouble(dest);
             return true;
--- a/js/src/jit/x86/MacroAssembler-x86-inl.h
+++ b/js/src/jit/x86/MacroAssembler-x86-inl.h
@@ -300,16 +300,23 @@ MacroAssembler::branchPtr(Condition cond
 
 void
 MacroAssembler::branchPrivatePtr(Condition cond, const Address& lhs, Register rhs, Label* label)
 {
     branchPtr(cond, lhs, rhs, label);
 }
 
 void
+MacroAssembler::branchTest32(Condition cond, const AbsoluteAddress& lhs, Imm32 rhs, Label* label)
+{
+    test32(Operand(lhs), rhs);
+    j(cond, label);
+}
+
+void
 MacroAssembler::branchTest64(Condition cond, Register64 lhs, Register64 rhs, Register temp,
                              Label* label)
 {
     if (cond == Assembler::Zero) {
         MOZ_ASSERT(lhs.low == rhs.low);
         MOZ_ASSERT(lhs.high == rhs.high);
         movl(lhs.low, temp);
         orl(lhs.high, temp);
--- a/js/src/jit/x86/MacroAssembler-x86.h
+++ b/js/src/jit/x86/MacroAssembler-x86.h
@@ -45,17 +45,16 @@ class MacroAssemblerX86 : public MacroAs
     }
     Operand tagOf(const BaseIndex& address) {
         return Operand(address.base, address.index, address.scale, address.offset + 4);
     }
 
     void setupABICall(uint32_t args);
 
   public:
-    using MacroAssemblerX86Shared::branchTest32;
     using MacroAssemblerX86Shared::load32;
     using MacroAssemblerX86Shared::store32;
     using MacroAssemblerX86Shared::call;
 
     MacroAssemblerX86()
     {
     }
 
@@ -546,21 +545,16 @@ class MacroAssemblerX86 : public MacroAs
         cmpPtr(lhs, rhs);
         emitSet(cond, dest);
     }
 
     /////////////////////////////////////////////////////////////////
     // Common interface.
     /////////////////////////////////////////////////////////////////
 
-    void branchTest32(Condition cond, AbsoluteAddress address, Imm32 imm, Label* label) {
-        test32(Operand(address), imm);
-        j(cond, label);
-    }
-
     template <typename T, typename S>
     void branchPtr(Condition cond, T lhs, S ptr, RepatchLabel* label) {
         cmpPtr(Operand(lhs), ptr);
         j(cond, label);
     }
 
     template <typename T, typename S>
     inline void branchPtrImpl(Condition cond, const T& lhs, const S& rhs, Label* label);