Bug 1319388 - Add add32ToPtrWithPatch and patchAdd32ToPtr to MacroAssembler. r=jandem
authorLars T Hansen <lhansen@mozilla.com>
Thu, 29 Dec 2016 07:23:33 +0100
changeset 327533 e0e05d0bc34b19e5c034de40f1435cde9a803226
parent 327532 db38dbe32679ad449fecadf6e5f8501d6a0d7234
child 327534 0de5f500516b0d576fd77f342ac2570b536e8115
push id35517
push userkwierso@gmail.com
push dateThu, 29 Dec 2016 20:22:54 +0000
treeherderautoland@3f2f8d77ad27 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1319388
milestone53.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 1319388 - Add add32ToPtrWithPatch and patchAdd32ToPtr to MacroAssembler. r=jandem
js/src/jit/MacroAssembler.h
js/src/jit/arm/MacroAssembler-arm-inl.h
js/src/jit/arm/MacroAssembler-arm.cpp
js/src/jit/arm/MacroAssembler-arm.h
js/src/jit/arm64/MacroAssembler-arm64-inl.h
js/src/jit/mips32/MacroAssembler-mips32-inl.h
js/src/jit/mips64/MacroAssembler-mips64-inl.h
js/src/jit/x64/Assembler-x64.h
js/src/jit/x64/BaseAssembler-x64.h
js/src/jit/x64/MacroAssembler-x64-inl.h
js/src/jit/x86-shared/Assembler-x86-shared.h
js/src/jit/x86/MacroAssembler-x86-inl.h
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -774,16 +774,23 @@ class MacroAssembler : public MacroAssem
 
     inline void add64(Register64 src, Register64 dest) PER_ARCH;
     inline void add64(Imm32 imm, Register64 dest) PER_ARCH;
     inline void add64(Imm64 imm, Register64 dest) PER_ARCH;
     inline void add64(const Operand& src, Register64 dest) DEFINED_ON(x64, mips64);
 
     inline void addFloat32(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
 
+    // Compute dest=src+imm where `src` and `dest` are pointer registers; `src`
+    // may be SP, and `src` may equal `dest`.  `dest` should not normally be SP,
+    // as stack probes are required for large negative immediates.  The offset
+    // returned from add32ToPtrWithPatch() must be passed to patchAdd32ToPtr().
+    inline CodeOffset add32ToPtrWithPatch(Register src, Register dest) PER_ARCH;
+    inline void patchAdd32ToPtr(CodeOffset offset, Imm32 imm) PER_ARCH;
+
     inline void addDouble(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
     inline void addConstantDouble(double d, FloatRegister dest) DEFINED_ON(x86);
 
     inline void sub32(const Address& src, Register dest) PER_SHARED_ARCH;
     inline void sub32(Register src, Register dest) PER_SHARED_ARCH;
     inline void sub32(Imm32 imm, Register dest) PER_SHARED_ARCH;
 
     inline void subPtr(Register src, Register dest) PER_ARCH;
--- a/js/src/jit/arm/MacroAssembler-arm-inl.h
+++ b/js/src/jit/arm/MacroAssembler-arm-inl.h
@@ -304,16 +304,34 @@ MacroAssembler::add64(Imm32 imm, Registe
 void
 MacroAssembler::add64(Imm64 imm, Register64 dest)
 {
     ScratchRegisterScope scratch(*this);
     ma_add(imm.low(), dest.low, scratch, SetCC);
     ma_adc(imm.hi(), dest.high, scratch, LeaveCC);
 }
 
+CodeOffset
+MacroAssembler::add32ToPtrWithPatch(Register src, Register dest)
+{
+    ScratchRegisterScope scratch(*this);
+    CodeOffset offs = CodeOffset(currentOffset());
+    ma_movPatchable(Imm32(0), scratch, Always);
+    ma_add(src, scratch, dest);
+    return offs;
+}
+
+void
+MacroAssembler::patchAdd32ToPtr(CodeOffset offset, Imm32 imm)
+{
+    ScratchRegisterScope scratch(*this);
+    ma_mov_patch(imm, scratch, Always,
+                 HasMOVWT() ? L_MOVWT : L_LDR, offsetToInstruction(offset));
+}
+
 void
 MacroAssembler::addDouble(FloatRegister src, FloatRegister dest)
 {
     ma_vadd(dest, src, dest);
 }
 
 void
 MacroAssembler::addFloat32(FloatRegister src, FloatRegister dest)
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -370,16 +370,22 @@ MacroAssemblerARM::ma_mov_patch(Imm32 im
 
 /* static */ void
 MacroAssemblerARM::ma_mov_patch(ImmPtr imm, Register dest, Assembler::Condition c,
                                 RelocStyle rs, Instruction* i)
 {
     ma_mov_patch(Imm32(int32_t(imm.value)), dest, c, rs, i);
 }
 
+Instruction*
+MacroAssemblerARM::offsetToInstruction(CodeOffset offs)
+{
+    return editSrc(BufferOffset(offs.offset()));
+}
+
 void
 MacroAssemblerARM::ma_mov(Register src, Register dest, SBit s, Assembler::Condition c)
 {
     if (s == SetCC || dest != src)
         as_mov(dest, O2Reg(src), s, c);
 }
 
 void
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -125,16 +125,18 @@ class MacroAssemblerARM : public Assembl
     void ma_movPatchable(Imm32 imm, Register dest, Assembler::Condition c);
     void ma_movPatchable(ImmPtr imm, Register dest, Assembler::Condition c);
 
     static void ma_mov_patch(Imm32 imm, Register dest, Assembler::Condition c,
                              RelocStyle rs, Instruction* i);
     static void ma_mov_patch(ImmPtr imm, Register dest, Assembler::Condition c,
                              RelocStyle rs, Instruction* i);
 
+    Instruction* offsetToInstruction(CodeOffset offs);
+
     // ALU based ops
     // mov
     void ma_mov(Register src, Register dest, SBit s = LeaveCC, Condition c = Always);
 
     void ma_mov(Imm32 imm, Register dest, Condition c = Always);
     void ma_mov(ImmWord imm, Register dest, Condition c = Always);
 
     void ma_mov(ImmGCPtr ptr, Register dest);
--- a/js/src/jit/arm64/MacroAssembler-arm64-inl.h
+++ b/js/src/jit/arm64/MacroAssembler-arm64-inl.h
@@ -307,16 +307,28 @@ MacroAssembler::add64(Imm32 imm, Registe
 }
 
 void
 MacroAssembler::add64(Imm64 imm, Register64 dest)
 {
     Add(ARMRegister(dest.reg, 64), ARMRegister(dest.reg, 64), Operand(imm.value));
 }
 
+CodeOffset
+MacroAssembler::add32ToPtrWithPatch(Register src, Register dest)
+{
+    MOZ_CRASH("NYI - add32ToPtrWithPatch");
+}
+
+void
+MacroAssembler::patchAdd32ToPtr(CodeOffset offset, Imm32 imm)
+{
+    MOZ_CRASH("NYI - patchAdd32ToPtr");
+}
+
 void
 MacroAssembler::addDouble(FloatRegister src, FloatRegister dest)
 {
     fadd(ARMFPRegister(dest, 64), ARMFPRegister(dest, 64), ARMFPRegister(src, 64));
 }
 
 void
 MacroAssembler::addFloat32(FloatRegister src, FloatRegister dest)
--- a/js/src/jit/mips32/MacroAssembler-mips32-inl.h
+++ b/js/src/jit/mips32/MacroAssembler-mips32-inl.h
@@ -158,16 +158,28 @@ MacroAssembler::add64(Imm32 imm, Registe
 
 void
 MacroAssembler::add64(Imm64 imm, Register64 dest)
 {
     add64(imm.low(), dest);
     ma_addu(dest.high, dest.high, imm.hi());
 }
 
+CodeOffset
+MacroAssembler::add32ToPtrWithPatch(Register src, Register dest)
+{
+    MOZ_CRASH("NYI - add32ToPtrWithPatch");
+}
+
+void
+MacroAssembler::patchAdd32ToPtr(CodeOffset offset, Imm32 imm)
+{
+    MOZ_CRASH("NYI - patchAdd32ToPtr");
+}
+
 void
 MacroAssembler::subPtr(Register src, Register dest)
 {
     as_subu(dest, dest, src);
 }
 
 void
 MacroAssembler::subPtr(Imm32 imm, Register dest)
--- a/js/src/jit/mips64/MacroAssembler-mips64-inl.h
+++ b/js/src/jit/mips64/MacroAssembler-mips64-inl.h
@@ -195,16 +195,28 @@ MacroAssembler::add64(Imm32 imm, Registe
 void
 MacroAssembler::add64(Imm64 imm, Register64 dest)
 {
     MOZ_ASSERT(dest.reg != ScratchRegister);
     mov(ImmWord(imm.value), ScratchRegister);
     ma_daddu(dest.reg, ScratchRegister);
 }
 
+CodeOffset
+MacroAssembler::add32ToPtrWithPatch(Register src, Register dest)
+{
+    MOZ_CRASH("NYI - add32ToPtrWithPatch");
+}
+
+void
+MacroAssembler::patchAdd32ToPtr(CodeOffset offset, Imm32 imm)
+{
+    MOZ_CRASH("NYI - patchAdd32ToPtr");
+}
+
 void
 MacroAssembler::subPtr(Register src, Register dest)
 {
     as_dsubu(dest, dest, src);
 }
 
 void
 MacroAssembler::subPtr(Imm32 imm, Register dest)
--- a/js/src/jit/x64/Assembler-x64.h
+++ b/js/src/jit/x64/Assembler-x64.h
@@ -355,16 +355,21 @@ class Assembler : public AssemblerX86Sha
     CodeOffset movWithPatch(ImmWord word, Register dest) {
         masm.movq_i64r(word.value, dest.encoding());
         return CodeOffset(masm.currentOffset());
     }
     CodeOffset movWithPatch(ImmPtr imm, Register dest) {
         return movWithPatch(ImmWord(uintptr_t(imm.value)), dest);
     }
 
+    // This is for patching during code generation, not after.
+    void patchAddq(CodeOffset offset, int32_t n) {
+        X86Encoding::SetInt32(masm.data() + offset.offset(), n);
+    }
+
     // Load an ImmWord value into a register. Note that this instruction will
     // attempt to optimize its immediate field size. When a full 64-bit
     // immediate is needed for a relocation, use movWithPatch.
     void movq(ImmWord word, Register dest) {
         // Load a 64-bit immediate into a register. If the value falls into
         // certain ranges, we can use specialized instructions which have
         // smaller encodings.
         if (word.value <= UINT32_MAX) {
@@ -549,16 +554,20 @@ class Assembler : public AssemblerX86Sha
           default:
             MOZ_CRASH("unexpected operand kind");
         }
     }
 
     void addq(Imm32 imm, Register dest) {
         masm.addq_ir(imm.value, dest.encoding());
     }
+    CodeOffset addqWithPatch(Imm32 imm, Register dest) {
+        masm.addq_i32r(imm.value, dest.encoding());
+        return CodeOffset(masm.currentOffset());
+    }
     void addq(Imm32 imm, const Operand& dest) {
         switch (dest.kind()) {
           case Operand::REG:
             masm.addq_ir(imm.value, dest.reg());
             break;
           case Operand::MEM_REG_DISP:
             masm.addq_im(imm.value, dest.disp(), dest.base());
             break;
--- a/js/src/jit/x64/BaseAssembler-x64.h
+++ b/js/src/jit/x64/BaseAssembler-x64.h
@@ -48,16 +48,27 @@ class BaseAssemblerX64 : public BaseAsse
             if (dst == rax)
                 m_formatter.oneByteOp64(OP_ADD_EAXIv);
             else
                 m_formatter.oneByteOp64(OP_GROUP1_EvIz, dst, GROUP1_OP_ADD);
             m_formatter.immediate32(imm);
         }
     }
 
+    void addq_i32r(int32_t imm, RegisterID dst)
+    {
+        // 32-bit immediate always, for patching.
+        spew("addq       $0x%04x, %s", imm, GPReg64Name(dst));
+        if (dst == rax)
+            m_formatter.oneByteOp64(OP_ADD_EAXIv);
+        else
+            m_formatter.oneByteOp64(OP_GROUP1_EvIz, dst, GROUP1_OP_ADD);
+        m_formatter.immediate32(imm);
+    }
+
     void addq_im(int32_t imm, int32_t offset, RegisterID base)
     {
         spew("addq       $%d, " MEM_ob, imm, ADDR_ob(offset, base));
         if (CAN_SIGN_EXTEND_8_32(imm)) {
             m_formatter.oneByteOp64(OP_GROUP1_EvIb, offset, base, GROUP1_OP_ADD);
             m_formatter.immediate8s(imm);
         } else {
             m_formatter.oneByteOp64(OP_GROUP1_EvIz, offset, base, GROUP1_OP_ADD);
--- a/js/src/jit/x64/MacroAssembler-x64-inl.h
+++ b/js/src/jit/x64/MacroAssembler-x64-inl.h
@@ -202,16 +202,31 @@ MacroAssembler::add64(Imm32 imm, Registe
 }
 
 void
 MacroAssembler::add64(Imm64 imm, Register64 dest)
 {
     addPtr(ImmWord(imm.value), dest.reg);
 }
 
+CodeOffset
+MacroAssembler::add32ToPtrWithPatch(Register src, Register dest)
+{
+    if (src != dest)
+        movePtr(src, dest);
+    addqWithPatch(Imm32(0), dest);
+    return CodeOffset(currentOffset());
+}
+
+void
+MacroAssembler::patchAdd32ToPtr(CodeOffset offset, Imm32 imm)
+{
+    patchAddq(offset, imm.value);
+}
+
 void
 MacroAssembler::subPtr(Register src, Register dest)
 {
     subq(src, dest);
 }
 
 void
 MacroAssembler::subPtr(Register src, const Address& dest)
--- a/js/src/jit/x86-shared/Assembler-x86-shared.h
+++ b/js/src/jit/x86-shared/Assembler-x86-shared.h
@@ -1070,16 +1070,21 @@ class AssemblerX86Shared : public Assemb
     void patchFarJump(CodeOffset farJump, uint32_t targetOffset) {
         unsigned char* code = masm.data();
         X86Encoding::SetRel32(code + farJump.offset(), code + targetOffset);
     }
     static void repatchFarJump(uint8_t* code, uint32_t farJumpOffset, uint32_t targetOffset) {
         X86Encoding::SetRel32(code + farJumpOffset, code + targetOffset);
     }
 
+    // This is for patching during code generation, not after.
+    void patchAddl(CodeOffset offset, int32_t n) {
+        X86Encoding::SetInt32(masm.data() + offset.offset(), n);
+    }
+
     CodeOffset twoByteNop() {
         return CodeOffset(masm.twoByteNop().offset());
     }
     static void patchTwoByteNopToJump(uint8_t* jump, uint8_t* target) {
         X86Encoding::BaseAssembler::patchTwoByteNopToJump(jump, target);
     }
     static void patchJumpToTwoByteNop(uint8_t* jump) {
         X86Encoding::BaseAssembler::patchJumpToTwoByteNop(jump);
--- a/js/src/jit/x86/MacroAssembler-x86-inl.h
+++ b/js/src/jit/x86/MacroAssembler-x86-inl.h
@@ -186,16 +186,31 @@ MacroAssembler::addConstantDouble(double
 {
     Double* dbl = getDouble(wasm::RawF64(d));
     if (!dbl)
         return;
     masm.vaddsd_mr(nullptr, dest.encoding(), dest.encoding());
     propagateOOM(dbl->uses.append(CodeOffset(masm.size())));
 }
 
+CodeOffset
+MacroAssembler::add32ToPtrWithPatch(Register src, Register dest)
+{
+    if (src != dest)
+        movePtr(src, dest);
+    addlWithPatch(Imm32(0), dest);
+    return CodeOffset(currentOffset());
+}
+
+void
+MacroAssembler::patchAdd32ToPtr(CodeOffset offset, Imm32 imm)
+{
+    patchAddl(offset, imm.value);
+}
+
 void
 MacroAssembler::subPtr(Register src, Register dest)
 {
     subl(src, dest);
 }
 
 void
 MacroAssembler::subPtr(Register src, const Address& dest)