Bug 1517553 - ARM64 JIT: Change JSVAL_TAG comparisons to require only 2 instructions and 1 register. r=sstangl
authorNicolas B. Pierron <nicolas.b.pierron@nbp.name>
Mon, 07 Jan 2019 16:58:02 +0100
changeset 510270 9429979e423ce7358a453d717175771aef609ee8
parent 510201 89ca00a3e30767aaf57562ac8c2e2b3994123de3
child 510271 3951a4f90911165844975c095dfccb960526ecc0
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssstangl
bugs1517553
milestone66.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 1517553 - ARM64 JIT: Change JSVAL_TAG comparisons to require only 2 instructions and 1 register. r=sstangl
js/src/jit/arm64/CodeGenerator-arm64.cpp
js/src/jit/arm64/MacroAssembler-arm64.h
--- a/js/src/jit/arm64/CodeGenerator-arm64.cpp
+++ b/js/src/jit/arm64/CodeGenerator-arm64.cpp
@@ -1188,17 +1188,18 @@ void CodeGenerator::visitUnbox(LUnbox* u
   } else {
 #ifdef DEBUG
     JSValueTag tag = MIRTypeToTag(mir->type());
     Label ok;
 
     ValueOperand input = ToValue(unbox, LUnbox::Input);
     ScratchTagScope scratch(masm, input);
     masm.splitTagForTest(input, scratch);
-    masm.branch32(Assembler::Condition::Equal, scratch, Imm32(tag), &ok);
+    masm.cmpTag(scratch, ImmTag(tag));
+    masm.B(&ok, Assembler::Condition::Equal);
     masm.assumeUnreachable("Infallible unbox type mismatch");
     masm.bind(&ok);
 #endif
   }
 
   ValueOperand input = ToValue(unbox, LUnbox::Input);
   Register result = ToRegister(unbox->output());
   switch (mir->type()) {
--- a/js/src/jit/arm64/MacroAssembler-arm64.h
+++ b/js/src/jit/arm64/MacroAssembler-arm64.h
@@ -389,28 +389,28 @@ class MacroAssemblerCompat : public vixl
     BufferOffset off = immPool64(ARMRegister(dest, 64), uint64_t(imm.value));
     return CodeOffset(off.getOffset());
   }
 
   void boxValue(JSValueType type, Register src, Register dest) {
     Orr(ARMRegister(dest, 64), ARMRegister(src, 64),
         Operand(ImmShiftedTag(type).value));
   }
-  void splitTag(Register src, Register dest) {
-    ubfx(ARMRegister(dest, 64), ARMRegister(src, 64), JSVAL_TAG_SHIFT,
+  void splitSignExtTag(Register src, Register dest) {
+    sbfx(ARMRegister(dest, 64), ARMRegister(src, 64), JSVAL_TAG_SHIFT,
          (64 - JSVAL_TAG_SHIFT));
   }
   MOZ_MUST_USE Register extractTag(const Address& address, Register scratch) {
     loadPtr(address, scratch);
-    splitTag(scratch, scratch);
+    splitSignExtTag(scratch, scratch);
     return scratch;
   }
   MOZ_MUST_USE Register extractTag(const ValueOperand& value,
                                    Register scratch) {
-    splitTag(value.valueReg(), scratch);
+    splitSignExtTag(value.valueReg(), scratch);
     return scratch;
   }
   MOZ_MUST_USE Register extractObject(const Address& address,
                                       Register scratch) {
     loadPtr(address, scratch);
     unboxObject(scratch, scratch);
     return scratch;
   }
@@ -995,16 +995,20 @@ class MacroAssemblerCompat : public vixl
   }
   void cmp32(Register lhs, const vixl::Operand& rhs) {
     vixl::UseScratchRegisterScope temps(this);
     const ARMRegister scratch32 = temps.AcquireW();
     Mov(scratch32, rhs);
     Cmp(scratch32, Operand(ARMRegister(lhs, 32)));
   }
 
+  void cmn32(Register lhs, Imm32 rhs) {
+    Cmn(ARMRegister(lhs, 32), Operand(rhs.value));
+  }
+
   void cmpPtr(Register lhs, Imm32 rhs) {
     Cmp(ARMRegister(lhs, 64), Operand(rhs.value));
   }
   void cmpPtr(Register lhs, ImmWord rhs) {
     Cmp(ARMRegister(lhs, 64), Operand(rhs.value));
   }
   void cmpPtr(Register lhs, ImmPtr rhs) {
     Cmp(ARMRegister(lhs, 64), Operand(uint64_t(rhs.value)));
@@ -1125,26 +1129,26 @@ class MacroAssemblerCompat : public vixl
 
   void moveFloat32(FloatRegister src, FloatRegister dest) {
     fmov(ARMFPRegister(dest, 32), ARMFPRegister(src, 32));
   }
   void moveFloatAsDouble(Register src, FloatRegister dest) {
     MOZ_CRASH("moveFloatAsDouble");
   }
 
-  void splitTag(const ValueOperand& operand, Register dest) {
-    splitTag(operand.valueReg(), dest);
+  void splitSignExtTag(const ValueOperand& operand, Register dest) {
+    splitSignExtTag(operand.valueReg(), dest);
   }
-  void splitTag(const Address& operand, Register dest) {
+  void splitSignExtTag(const Address& operand, Register dest) {
     loadPtr(operand, dest);
-    splitTag(dest, dest);
+    splitSignExtTag(dest, dest);
   }
-  void splitTag(const BaseIndex& operand, Register dest) {
+  void splitSignExtTag(const BaseIndex& operand, Register dest) {
     loadPtr(operand, dest);
-    splitTag(dest, dest);
+    splitSignExtTag(dest, dest);
   }
 
   // Extracts the tag of a value and places it in tag
   inline void splitTagForTest(const ValueOperand& value, ScratchTagScope& tag);
   void cmpTag(const ValueOperand& operand, ImmTag tag) { MOZ_CRASH("cmpTag"); }
 
   void load32(const Address& address, Register dest) {
     Ldr(ARMRegister(dest, 32), toMemOperand(address));
@@ -1407,350 +1411,359 @@ class MacroAssemblerCompat : public vixl
 
   void loadConstantDouble(double d, FloatRegister dest) {
     Fmov(ARMFPRegister(dest, 64), d);
   }
   void loadConstantFloat32(float f, FloatRegister dest) {
     Fmov(ARMFPRegister(dest, 32), f);
   }
 
+  void cmpTag(Register tag, ImmTag ref) {
+    // As opposed to other architecture, splitTag is replaced by splitSignExtTag
+    // which extract the tag with a sign extension. The reason being that cmp32
+    // with a tag value would be too large to fit as a 12 bits immediate value,
+    // and would require the VIXL macro assembler to add an extra instruction
+    // and require extra scratch register to load the Tag value.
+    //
+    // Instead, we compare with the negative value of the sign extended tag with
+    // the CMN instruction. The sign extended tag is expected to be a negative
+    // value. Therefore the negative of the sign extended tag is expected to be
+    // near 0 and fit on 12 bits.
+    //
+    // Ignoring the sign extension, the logic is the following:
+    //
+    //   CMP32(Reg, Tag) = Reg - Tag
+    //                   = Reg + (-Tag)
+    //                   = CMN32(Reg, -Tag)
+    //
+    // Note: testGCThing, testPrimitive and testNumber which are checking for
+    // inequalities should use unsigned comparisons (as done by default) in
+    // order to keep the same relation order after the sign extension, i.e.
+    // using Above or Below which are based on the carry flag.
+    uint32_t hiShift = JSVAL_TAG_SHIFT - 32;
+    int32_t seTag = int32_t(ref.value);
+    seTag = (seTag << hiShift) >> hiShift;
+    MOZ_ASSERT(seTag < 0);
+    int32_t negTag = -seTag;
+    // Check thest negTag is encoded on a 12 bits immediate value.
+    MOZ_ASSERT((negTag & ~0xFFF) == 0);
+    cmn32(tag, Imm32(negTag));
+  }
+
   // Register-based tests.
   Condition testUndefined(Condition cond, Register tag) {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
-    cmp32(tag, ImmTag(JSVAL_TAG_UNDEFINED));
+    cmpTag(tag, ImmTag(JSVAL_TAG_UNDEFINED));
     return cond;
   }
   Condition testInt32(Condition cond, Register tag) {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
-    cmp32(tag, ImmTag(JSVAL_TAG_INT32));
+    cmpTag(tag, ImmTag(JSVAL_TAG_INT32));
     return cond;
   }
   Condition testBoolean(Condition cond, Register tag) {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
-    cmp32(tag, ImmTag(JSVAL_TAG_BOOLEAN));
+    cmpTag(tag, ImmTag(JSVAL_TAG_BOOLEAN));
     return cond;
   }
   Condition testNull(Condition cond, Register tag) {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
-    cmp32(tag, ImmTag(JSVAL_TAG_NULL));
+    cmpTag(tag, ImmTag(JSVAL_TAG_NULL));
     return cond;
   }
   Condition testString(Condition cond, Register tag) {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
-    cmp32(tag, ImmTag(JSVAL_TAG_STRING));
+    cmpTag(tag, ImmTag(JSVAL_TAG_STRING));
     return cond;
   }
   Condition testSymbol(Condition cond, Register tag) {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
-    cmp32(tag, ImmTag(JSVAL_TAG_SYMBOL));
+    cmpTag(tag, ImmTag(JSVAL_TAG_SYMBOL));
     return cond;
   }
   Condition testObject(Condition cond, Register tag) {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
-    cmp32(tag, ImmTag(JSVAL_TAG_OBJECT));
+    cmpTag(tag, ImmTag(JSVAL_TAG_OBJECT));
     return cond;
   }
   Condition testDouble(Condition cond, Register tag) {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
-    cmp32(tag, Imm32(JSVAL_TAG_MAX_DOUBLE));
+    cmpTag(tag, ImmTag(JSVAL_TAG_MAX_DOUBLE));
+    // Requires unsigned comparison due to cmpTag internals.
     return (cond == Equal) ? BelowOrEqual : Above;
   }
   Condition testNumber(Condition cond, Register tag) {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
-    cmp32(tag, Imm32(JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET));
+    cmpTag(tag, ImmTag(JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET));
+    // Requires unsigned comparison due to cmpTag internals.
     return (cond == Equal) ? BelowOrEqual : Above;
   }
   Condition testGCThing(Condition cond, Register tag) {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
-    cmp32(tag, Imm32(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
+    cmpTag(tag, ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
+    // Requires unsigned comparison due to cmpTag internals.
     return (cond == Equal) ? AboveOrEqual : Below;
   }
   Condition testMagic(Condition cond, Register tag) {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
-    cmp32(tag, ImmTag(JSVAL_TAG_MAGIC));
+    cmpTag(tag, ImmTag(JSVAL_TAG_MAGIC));
     return cond;
   }
   Condition testPrimitive(Condition cond, Register tag) {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
-    cmp32(tag, Imm32(JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET));
+    cmpTag(tag, ImmTag(JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET));
+    // Requires unsigned comparison due to cmpTag internals.
     return (cond == Equal) ? Below : AboveOrEqual;
   }
   Condition testError(Condition cond, Register tag) {
     return testMagic(cond, tag);
   }
 
   // ValueOperand-based tests.
   Condition testInt32(Condition cond, const ValueOperand& value) {
     // The incoming ValueOperand may use scratch registers.
     vixl::UseScratchRegisterScope temps(this);
-
-    if (value.valueReg() == ScratchReg2) {
-      MOZ_ASSERT(temps.IsAvailable(ScratchReg64));
-      MOZ_ASSERT(!temps.IsAvailable(ScratchReg2_64));
-      temps.Exclude(ScratchReg64);
-
-      if (cond != Equal && cond != NotEqual) {
-        MOZ_CRASH("NYI: non-equality comparisons");
-      }
-
-      // In the event that the tag is not encodable in a single cmp / teq
-      // instruction, perform the xor that teq would use, this will leave the
-      // tag bits being zero, or non-zero, which can be tested with either and
-      // or shift.
-      unsigned int n, imm_r, imm_s;
-      uint64_t immediate = uint64_t(ImmTag(JSVAL_TAG_INT32).value)
-                           << JSVAL_TAG_SHIFT;
-      if (IsImmLogical(immediate, 64, &n, &imm_s, &imm_r)) {
-        Eor(ScratchReg64, ScratchReg2_64, Operand(immediate));
-      } else {
-        Mov(ScratchReg64, immediate);
-        Eor(ScratchReg64, ScratchReg2_64, ScratchReg64);
-      }
-      Tst(ScratchReg64, Operand((unsigned long long)(-1ll) << JSVAL_TAG_SHIFT));
-      return cond;
-    }
-
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(scratch != value.valueReg());
 
-    splitTag(value, scratch);
+    splitSignExtTag(value, scratch);
     return testInt32(cond, scratch);
   }
   Condition testBoolean(Condition cond, const ValueOperand& value) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(value.valueReg() != scratch);
-    splitTag(value, scratch);
+    splitSignExtTag(value, scratch);
     return testBoolean(cond, scratch);
   }
   Condition testDouble(Condition cond, const ValueOperand& value) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(value.valueReg() != scratch);
-    splitTag(value, scratch);
+    splitSignExtTag(value, scratch);
     return testDouble(cond, scratch);
   }
   Condition testNull(Condition cond, const ValueOperand& value) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(value.valueReg() != scratch);
-    splitTag(value, scratch);
+    splitSignExtTag(value, scratch);
     return testNull(cond, scratch);
   }
   Condition testUndefined(Condition cond, const ValueOperand& value) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(value.valueReg() != scratch);
-    splitTag(value, scratch);
+    splitSignExtTag(value, scratch);
     return testUndefined(cond, scratch);
   }
   Condition testString(Condition cond, const ValueOperand& value) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(value.valueReg() != scratch);
-    splitTag(value, scratch);
+    splitSignExtTag(value, scratch);
     return testString(cond, scratch);
   }
   Condition testSymbol(Condition cond, const ValueOperand& value) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(value.valueReg() != scratch);
-    splitTag(value, scratch);
+    splitSignExtTag(value, scratch);
     return testSymbol(cond, scratch);
   }
   Condition testObject(Condition cond, const ValueOperand& value) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(value.valueReg() != scratch);
-    splitTag(value, scratch);
+    splitSignExtTag(value, scratch);
     return testObject(cond, scratch);
   }
   Condition testNumber(Condition cond, const ValueOperand& value) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(value.valueReg() != scratch);
-    splitTag(value, scratch);
+    splitSignExtTag(value, scratch);
     return testNumber(cond, scratch);
   }
   Condition testPrimitive(Condition cond, const ValueOperand& value) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(value.valueReg() != scratch);
-    splitTag(value, scratch);
+    splitSignExtTag(value, scratch);
     return testPrimitive(cond, scratch);
   }
   Condition testMagic(Condition cond, const ValueOperand& value) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(value.valueReg() != scratch);
-    splitTag(value, scratch);
+    splitSignExtTag(value, scratch);
     return testMagic(cond, scratch);
   }
   Condition testError(Condition cond, const ValueOperand& value) {
     return testMagic(cond, value);
   }
 
   // Address-based tests.
   Condition testGCThing(Condition cond, const Address& address) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(address.base != scratch);
-    splitTag(address, scratch);
+    splitSignExtTag(address, scratch);
     return testGCThing(cond, scratch);
   }
   Condition testMagic(Condition cond, const Address& address) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(address.base != scratch);
-    splitTag(address, scratch);
+    splitSignExtTag(address, scratch);
     return testMagic(cond, scratch);
   }
   Condition testInt32(Condition cond, const Address& address) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(address.base != scratch);
-    splitTag(address, scratch);
+    splitSignExtTag(address, scratch);
     return testInt32(cond, scratch);
   }
   Condition testDouble(Condition cond, const Address& address) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(address.base != scratch);
-    splitTag(address, scratch);
+    splitSignExtTag(address, scratch);
     return testDouble(cond, scratch);
   }
   Condition testBoolean(Condition cond, const Address& address) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(address.base != scratch);
-    splitTag(address, scratch);
+    splitSignExtTag(address, scratch);
     return testBoolean(cond, scratch);
   }
   Condition testNull(Condition cond, const Address& address) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(address.base != scratch);
-    splitTag(address, scratch);
+    splitSignExtTag(address, scratch);
     return testNull(cond, scratch);
   }
   Condition testUndefined(Condition cond, const Address& address) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(address.base != scratch);
-    splitTag(address, scratch);
+    splitSignExtTag(address, scratch);
     return testUndefined(cond, scratch);
   }
   Condition testString(Condition cond, const Address& address) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(address.base != scratch);
-    splitTag(address, scratch);
+    splitSignExtTag(address, scratch);
     return testString(cond, scratch);
   }
   Condition testSymbol(Condition cond, const Address& address) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(address.base != scratch);
-    splitTag(address, scratch);
+    splitSignExtTag(address, scratch);
     return testSymbol(cond, scratch);
   }
   Condition testObject(Condition cond, const Address& address) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(address.base != scratch);
-    splitTag(address, scratch);
+    splitSignExtTag(address, scratch);
     return testObject(cond, scratch);
   }
   Condition testNumber(Condition cond, const Address& address) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(address.base != scratch);
-    splitTag(address, scratch);
+    splitSignExtTag(address, scratch);
     return testNumber(cond, scratch);
   }
 
   // BaseIndex-based tests.
   Condition testUndefined(Condition cond, const BaseIndex& src) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(src.base != scratch);
     MOZ_ASSERT(src.index != scratch);
-    splitTag(src, scratch);
+    splitSignExtTag(src, scratch);
     return testUndefined(cond, scratch);
   }
   Condition testNull(Condition cond, const BaseIndex& src) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(src.base != scratch);
     MOZ_ASSERT(src.index != scratch);
-    splitTag(src, scratch);
+    splitSignExtTag(src, scratch);
     return testNull(cond, scratch);
   }
   Condition testBoolean(Condition cond, const BaseIndex& src) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(src.base != scratch);
     MOZ_ASSERT(src.index != scratch);
-    splitTag(src, scratch);
+    splitSignExtTag(src, scratch);
     return testBoolean(cond, scratch);
   }
   Condition testString(Condition cond, const BaseIndex& src) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(src.base != scratch);
     MOZ_ASSERT(src.index != scratch);
-    splitTag(src, scratch);
+    splitSignExtTag(src, scratch);
     return testString(cond, scratch);
   }
   Condition testSymbol(Condition cond, const BaseIndex& src) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(src.base != scratch);
     MOZ_ASSERT(src.index != scratch);
-    splitTag(src, scratch);
+    splitSignExtTag(src, scratch);
     return testSymbol(cond, scratch);
   }
   Condition testInt32(Condition cond, const BaseIndex& src) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(src.base != scratch);
     MOZ_ASSERT(src.index != scratch);
-    splitTag(src, scratch);
+    splitSignExtTag(src, scratch);
     return testInt32(cond, scratch);
   }
   Condition testObject(Condition cond, const BaseIndex& src) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(src.base != scratch);
     MOZ_ASSERT(src.index != scratch);
-    splitTag(src, scratch);
+    splitSignExtTag(src, scratch);
     return testObject(cond, scratch);
   }
   Condition testDouble(Condition cond, const BaseIndex& src) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(src.base != scratch);
     MOZ_ASSERT(src.index != scratch);
-    splitTag(src, scratch);
+    splitSignExtTag(src, scratch);
     return testDouble(cond, scratch);
   }
   Condition testMagic(Condition cond, const BaseIndex& src) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(src.base != scratch);
     MOZ_ASSERT(src.index != scratch);
-    splitTag(src, scratch);
+    splitSignExtTag(src, scratch);
     return testMagic(cond, scratch);
   }
   Condition testGCThing(Condition cond, const BaseIndex& src) {
     vixl::UseScratchRegisterScope temps(this);
     const Register scratch = temps.AcquireX().asUnsized();
     MOZ_ASSERT(src.base != scratch);
     MOZ_ASSERT(src.index != scratch);
-    splitTag(src, scratch);
+    splitSignExtTag(src, scratch);
     return testGCThing(cond, scratch);
   }
 
   Condition testInt32Truthy(bool truthy, const ValueOperand& operand) {
     ARMRegister payload32(operand.valueReg(), 32);
     Tst(payload32, payload32);
     return truthy ? NonZero : Zero;
   }
@@ -2063,17 +2076,17 @@ class ScratchTagScopeRelease {
   explicit ScratchTagScopeRelease(ScratchTagScope* ts) : ts_(ts) {
     ts_->release();
   }
   ~ScratchTagScopeRelease() { ts_->reacquire(); }
 };
 
 inline void MacroAssemblerCompat::splitTagForTest(const ValueOperand& value,
                                                   ScratchTagScope& tag) {
-  splitTag(value, tag);
+  splitSignExtTag(value, tag);
 }
 
 typedef MacroAssemblerCompat MacroAssemblerSpecific;
 
 }  // namespace jit
 }  // namespace js
 
 #endif  // jit_arm64_MacroAssembler_arm64_h