зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1415931 - [MIPS] Make long jumps visible to Wasm module code linking and caching. r=bbouvier
--HG-- extra : rebase_source : 30f424703d9420a149db98a21befb805bde33806
This commit is contained in:
Родитель
00ee6fdea3
Коммит
f17743cf65
|
@ -877,7 +877,6 @@ class AssemblerMIPSShared : public AssemblerShared
|
|||
};
|
||||
|
||||
js::Vector<RelativePatch, 8, SystemAllocPolicy> jumps_;
|
||||
js::Vector<uint32_t, 8, SystemAllocPolicy> longJumps_;
|
||||
|
||||
CompactBufferWriter jumpRelocations_;
|
||||
CompactBufferWriter dataRelocations_;
|
||||
|
@ -1280,18 +1279,13 @@ class AssemblerMIPSShared : public AssemblerShared
|
|||
writeRelocation(src);
|
||||
}
|
||||
|
||||
void addLongJump(BufferOffset src) {
|
||||
enoughMemory_ &= longJumps_.append(src.getOffset());
|
||||
void addLongJump(BufferOffset src, BufferOffset dst) {
|
||||
CodeOffset patchAt(src.getOffset());
|
||||
CodeOffset target(dst.getOffset());
|
||||
addCodeLabel(CodeLabel(patchAt, target));
|
||||
}
|
||||
|
||||
public:
|
||||
size_t numLongJumps() const {
|
||||
return longJumps_.length();
|
||||
}
|
||||
uint32_t longJump(size_t i) {
|
||||
return longJumps_[i];
|
||||
}
|
||||
|
||||
void flushBuffer() {
|
||||
}
|
||||
|
||||
|
|
|
@ -163,14 +163,6 @@ Assembler::executableCopy(uint8_t* buffer, bool flushICache)
|
|||
MOZ_ASSERT(isFinished);
|
||||
m_buffer.executableCopy(buffer);
|
||||
|
||||
// Patch all long jumps during code copy.
|
||||
for (size_t i = 0; i < longJumps_.length(); i++) {
|
||||
Instruction* inst1 = (Instruction*) ((uint32_t)buffer + longJumps_[i]);
|
||||
|
||||
uint32_t value = Assembler::ExtractLuiOriValue(inst1, inst1->next());
|
||||
AssemblerMIPSShared::UpdateLuiOriValue(inst1, inst1->next(), (uint32_t)buffer + value);
|
||||
}
|
||||
|
||||
if (flushICache)
|
||||
AutoFlushICache::setRange(uintptr_t(buffer), m_buffer.size());
|
||||
}
|
||||
|
@ -329,8 +321,9 @@ Assembler::bind(InstImm* inst, uintptr_t branch, uintptr_t target)
|
|||
// Generate the long jump for calls because return address has to be the
|
||||
// address after the reserved block.
|
||||
if (inst[0].encode() == inst_bgezal.encode()) {
|
||||
addLongJump(BufferOffset(branch));
|
||||
Assembler::WriteLuiOriInstructions(inst, &inst[1], ScratchRegister, target);
|
||||
addLongJump(BufferOffset(branch), BufferOffset(target));
|
||||
Assembler::WriteLuiOriInstructions(inst, &inst[1], ScratchRegister,
|
||||
LabelBase::INVALID_OFFSET);
|
||||
inst[2] = InstReg(op_special, ScratchRegister, zero, ra, ff_jalr).encode();
|
||||
// There is 1 nop after this.
|
||||
return;
|
||||
|
@ -353,16 +346,18 @@ Assembler::bind(InstImm* inst, uintptr_t branch, uintptr_t target)
|
|||
|
||||
if (inst[0].encode() == inst_beq.encode()) {
|
||||
// Handle long unconditional jump.
|
||||
addLongJump(BufferOffset(branch));
|
||||
Assembler::WriteLuiOriInstructions(inst, &inst[1], ScratchRegister, target);
|
||||
addLongJump(BufferOffset(branch), BufferOffset(target));
|
||||
Assembler::WriteLuiOriInstructions(inst, &inst[1], ScratchRegister,
|
||||
LabelBase::INVALID_OFFSET);
|
||||
inst[2] = InstReg(op_special, ScratchRegister, zero, zero, ff_jr).encode();
|
||||
// There is 1 nop after this.
|
||||
} else {
|
||||
// Handle long conditional jump.
|
||||
inst[0] = invertBranch(inst[0], BOffImm16(5 * sizeof(void*)));
|
||||
// No need for a "nop" here because we can clobber scratch.
|
||||
addLongJump(BufferOffset(branch + sizeof(void*)));
|
||||
Assembler::WriteLuiOriInstructions(&inst[1], &inst[2], ScratchRegister, target);
|
||||
addLongJump(BufferOffset(branch + sizeof(void*)), BufferOffset(target));
|
||||
Assembler::WriteLuiOriInstructions(&inst[1], &inst[2], ScratchRegister,
|
||||
LabelBase::INVALID_OFFSET);
|
||||
inst[3] = InstReg(op_special, ScratchRegister, zero, zero, ff_jr).encode();
|
||||
// There is 1 nop after this.
|
||||
}
|
||||
|
@ -386,7 +381,7 @@ Assembler::bind(RepatchLabel* label)
|
|||
// For unconditional long branches generated by ma_liPatchable,
|
||||
// such as under:
|
||||
// jumpWithpatch
|
||||
AssemblerMIPSShared::UpdateLuiOriValue(inst, inst->next(), dest.getOffset());
|
||||
addLongJump(BufferOffset(label->offset()), dest);
|
||||
} else if (inst[1].extractOpcode() == (uint32_t(op_lui) >> OpcodeShift) ||
|
||||
BOffImm16::IsInRange(offset))
|
||||
{
|
||||
|
@ -407,8 +402,9 @@ Assembler::bind(RepatchLabel* label)
|
|||
MOZ_ASSERT(inst[1].encode() == NopInst);
|
||||
MOZ_ASSERT(inst[2].encode() == NopInst);
|
||||
MOZ_ASSERT(inst[3].encode() == NopInst);
|
||||
addLongJump(BufferOffset(label->offset()));
|
||||
Assembler::WriteLuiOriInstructions(inst, &inst[1], ScratchRegister, dest.getOffset());
|
||||
addLongJump(BufferOffset(label->offset()), dest);
|
||||
Assembler::WriteLuiOriInstructions(inst, &inst[1], ScratchRegister,
|
||||
LabelBase::INVALID_OFFSET);
|
||||
inst[2] = InstReg(op_special, ScratchRegister, zero, zero, ff_jr).encode();
|
||||
} else {
|
||||
// Handle open long conditional jumps created by
|
||||
|
@ -421,8 +417,9 @@ Assembler::bind(RepatchLabel* label)
|
|||
MOZ_ASSERT(inst[2].encode() == NopInst);
|
||||
MOZ_ASSERT(inst[3].encode() == NopInst);
|
||||
MOZ_ASSERT(inst[4].encode() == NopInst);
|
||||
addLongJump(BufferOffset(label->offset() + sizeof(void*)));
|
||||
Assembler::WriteLuiOriInstructions(&inst[1], &inst[2], ScratchRegister, dest.getOffset());
|
||||
addLongJump(BufferOffset(label->offset() + sizeof(void*)), dest);
|
||||
Assembler::WriteLuiOriInstructions(&inst[1], &inst[2], ScratchRegister,
|
||||
LabelBase::INVALID_OFFSET);
|
||||
inst[3] = InstReg(op_special, ScratchRegister, zero, zero, ff_jr).encode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -510,8 +510,8 @@ MacroAssemblerMIPS::ma_bal(Label* label, DelaySlotFill delaySlotFill)
|
|||
if (label->bound()) {
|
||||
// Generate the long jump for calls because return address has to be
|
||||
// the address after the reserved block.
|
||||
addLongJump(nextOffset());
|
||||
ma_liPatchable(ScratchRegister, Imm32(label->offset()));
|
||||
addLongJump(nextOffset(), BufferOffset(label->offset()));
|
||||
ma_liPatchable(ScratchRegister, Imm32(LabelBase::INVALID_OFFSET));
|
||||
as_jalr(ScratchRegister);
|
||||
if (delaySlotFill == FillDelaySlot)
|
||||
as_nop();
|
||||
|
@ -561,8 +561,8 @@ MacroAssemblerMIPS::branchWithCode(InstImm code, Label* label, JumpKind jumpKind
|
|||
|
||||
if (code.encode() == inst_beq.encode()) {
|
||||
// Handle long jump
|
||||
addLongJump(nextOffset());
|
||||
ma_liPatchable(ScratchRegister, Imm32(label->offset()));
|
||||
addLongJump(nextOffset(), BufferOffset(label->offset()));
|
||||
ma_liPatchable(ScratchRegister, Imm32(LabelBase::INVALID_OFFSET));
|
||||
as_jr(ScratchRegister);
|
||||
as_nop();
|
||||
return;
|
||||
|
@ -577,8 +577,8 @@ MacroAssemblerMIPS::branchWithCode(InstImm code, Label* label, JumpKind jumpKind
|
|||
writeInst(code_r.encode());
|
||||
|
||||
// No need for a "nop" here because we can clobber scratch.
|
||||
addLongJump(nextOffset());
|
||||
ma_liPatchable(ScratchRegister, Imm32(label->offset()));
|
||||
addLongJump(nextOffset(), BufferOffset(label->offset()));
|
||||
ma_liPatchable(ScratchRegister, Imm32(LabelBase::INVALID_OFFSET));
|
||||
as_jr(ScratchRegister);
|
||||
as_nop();
|
||||
return;
|
||||
|
@ -1549,26 +1549,20 @@ MacroAssemblerMIPSCompat::backedgeJump(RepatchLabel* label, Label* documentation
|
|||
{
|
||||
// Only one branch per label.
|
||||
MOZ_ASSERT(!label->used());
|
||||
uint32_t dest = label->bound() ? label->offset() : LabelBase::INVALID_OFFSET;
|
||||
|
||||
BufferOffset bo = nextOffset();
|
||||
label->use(bo.getOffset());
|
||||
|
||||
// Backedges are short jumps when bound, but can become long when patched.
|
||||
m_buffer.ensureSpace(8 * sizeof(uint32_t));
|
||||
if (label->bound()) {
|
||||
int32_t offset = label->offset() - bo.getOffset();
|
||||
MOZ_ASSERT(BOffImm16::IsInRange(offset));
|
||||
as_b(BOffImm16(offset));
|
||||
} else {
|
||||
// Jump to "label1" by default to jump to the loop header.
|
||||
as_b(BOffImm16(2 * sizeof(uint32_t)));
|
||||
}
|
||||
// Jump to "label1" by default to jump to the loop header.
|
||||
as_b(BOffImm16(2 * sizeof(uint32_t)));
|
||||
// No need for nop here. We can safely put next instruction in delay slot.
|
||||
ma_liPatchable(ScratchRegister, Imm32(dest));
|
||||
ma_liPatchable(ScratchRegister, Imm32(LabelBase::INVALID_OFFSET));
|
||||
MOZ_ASSERT(nextOffset().getOffset() - bo.getOffset() == 3 * sizeof(uint32_t));
|
||||
as_jr(ScratchRegister);
|
||||
// No need for nop here. We can safely put next instruction in delay slot.
|
||||
ma_liPatchable(ScratchRegister, Imm32(dest));
|
||||
ma_liPatchable(ScratchRegister, Imm32(LabelBase::INVALID_OFFSET));
|
||||
as_jr(ScratchRegister);
|
||||
as_nop();
|
||||
MOZ_ASSERT(nextOffset().getOffset() - bo.getOffset() == 8 * sizeof(uint32_t));
|
||||
|
@ -1580,12 +1574,10 @@ MacroAssemblerMIPSCompat::jumpWithPatch(RepatchLabel* label, Label* documentatio
|
|||
{
|
||||
// Only one branch per label.
|
||||
MOZ_ASSERT(!label->used());
|
||||
uint32_t dest = label->bound() ? label->offset() : LabelBase::INVALID_OFFSET;
|
||||
|
||||
BufferOffset bo = nextOffset();
|
||||
label->use(bo.getOffset());
|
||||
addLongJump(bo);
|
||||
ma_liPatchable(ScratchRegister, Imm32(dest));
|
||||
ma_liPatchable(ScratchRegister, Imm32(LabelBase::INVALID_OFFSET));
|
||||
as_jr(ScratchRegister);
|
||||
as_nop();
|
||||
return CodeOffsetJump(bo.getOffset());
|
||||
|
|
|
@ -131,14 +131,6 @@ Assembler::executableCopy(uint8_t* buffer, bool flushICache)
|
|||
MOZ_ASSERT(isFinished);
|
||||
m_buffer.executableCopy(buffer);
|
||||
|
||||
// Patch all long jumps during code copy.
|
||||
for (size_t i = 0; i < longJumps_.length(); i++) {
|
||||
Instruction* inst = (Instruction*) ((uintptr_t)buffer + longJumps_[i]);
|
||||
|
||||
uint64_t value = Assembler::ExtractLoad64Value(inst);
|
||||
Assembler::UpdateLoad64Value(inst, (uint64_t)buffer + value);
|
||||
}
|
||||
|
||||
if (flushICache)
|
||||
AutoFlushICache::setRange(uintptr_t(buffer), m_buffer.size());
|
||||
}
|
||||
|
@ -262,8 +254,8 @@ Assembler::bind(InstImm* inst, uintptr_t branch, uintptr_t target)
|
|||
// Generate the long jump for calls because return address has to be the
|
||||
// address after the reserved block.
|
||||
if (inst[0].encode() == inst_bgezal.encode()) {
|
||||
addLongJump(BufferOffset(branch));
|
||||
Assembler::WriteLoad64Instructions(inst, ScratchRegister, target);
|
||||
addLongJump(BufferOffset(branch), BufferOffset(target));
|
||||
Assembler::WriteLoad64Instructions(inst, ScratchRegister, LabelBase::INVALID_OFFSET);
|
||||
inst[4] = InstReg(op_special, ScratchRegister, zero, ra, ff_jalr).encode();
|
||||
// There is 1 nop after this.
|
||||
return;
|
||||
|
@ -287,16 +279,16 @@ Assembler::bind(InstImm* inst, uintptr_t branch, uintptr_t target)
|
|||
|
||||
if (inst[0].encode() == inst_beq.encode()) {
|
||||
// Handle long unconditional jump.
|
||||
addLongJump(BufferOffset(branch));
|
||||
Assembler::WriteLoad64Instructions(inst, ScratchRegister, target);
|
||||
addLongJump(BufferOffset(branch), BufferOffset(target));
|
||||
Assembler::WriteLoad64Instructions(inst, ScratchRegister, LabelBase::INVALID_OFFSET);
|
||||
inst[4] = InstReg(op_special, ScratchRegister, zero, zero, ff_jr).encode();
|
||||
// There is 1 nop after this.
|
||||
} else {
|
||||
// Handle long conditional jump.
|
||||
inst[0] = invertBranch(inst[0], BOffImm16(7 * sizeof(uint32_t)));
|
||||
// No need for a "nop" here because we can clobber scratch.
|
||||
addLongJump(BufferOffset(branch + sizeof(uint32_t)));
|
||||
Assembler::WriteLoad64Instructions(&inst[1], ScratchRegister, target);
|
||||
addLongJump(BufferOffset(branch + sizeof(uint32_t)), BufferOffset(target));
|
||||
Assembler::WriteLoad64Instructions(&inst[1], ScratchRegister, LabelBase::INVALID_OFFSET);
|
||||
inst[5] = InstReg(op_special, ScratchRegister, zero, zero, ff_jr).encode();
|
||||
// There is 1 nop after this.
|
||||
}
|
||||
|
@ -320,7 +312,7 @@ Assembler::bind(RepatchLabel* label)
|
|||
// For unconditional long branches generated by ma_liPatchable,
|
||||
// such as under:
|
||||
// jumpWithpatch
|
||||
Assembler::UpdateLoad64Value(inst, dest.getOffset());
|
||||
addLongJump(BufferOffset(label->offset()), dest);
|
||||
} else if (inst[1].extractOpcode() == (uint32_t(op_lui) >> OpcodeShift) ||
|
||||
BOffImm16::IsInRange(offset))
|
||||
{
|
||||
|
@ -343,8 +335,8 @@ Assembler::bind(RepatchLabel* label)
|
|||
MOZ_ASSERT(inst[3].encode() == NopInst);
|
||||
MOZ_ASSERT(inst[4].encode() == NopInst);
|
||||
MOZ_ASSERT(inst[5].encode() == NopInst);
|
||||
addLongJump(BufferOffset(label->offset()));
|
||||
Assembler::WriteLoad64Instructions(inst, ScratchRegister, dest.getOffset());
|
||||
addLongJump(BufferOffset(label->offset()), dest);
|
||||
Assembler::WriteLoad64Instructions(inst, ScratchRegister, LabelBase::INVALID_OFFSET);
|
||||
inst[4] = InstReg(op_special, ScratchRegister, zero, zero, ff_jr).encode();
|
||||
} else {
|
||||
// Handle open long conditional jumps created by
|
||||
|
@ -359,8 +351,8 @@ Assembler::bind(RepatchLabel* label)
|
|||
MOZ_ASSERT(inst[4].encode() == NopInst);
|
||||
MOZ_ASSERT(inst[5].encode() == NopInst);
|
||||
MOZ_ASSERT(inst[6].encode() == NopInst);
|
||||
addLongJump(BufferOffset(label->offset() + sizeof(uint32_t)));
|
||||
Assembler::WriteLoad64Instructions(&inst[1], ScratchRegister, dest.getOffset());
|
||||
addLongJump(BufferOffset(label->offset() + sizeof(uint32_t)), dest);
|
||||
Assembler::WriteLoad64Instructions(&inst[1], ScratchRegister, LabelBase::INVALID_OFFSET);
|
||||
inst[5] = InstReg(op_special, ScratchRegister, zero, zero, ff_jr).encode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -763,8 +763,8 @@ MacroAssemblerMIPS64::ma_bal(Label* label, DelaySlotFill delaySlotFill)
|
|||
if (label->bound()) {
|
||||
// Generate the long jump for calls because return address has to be
|
||||
// the address after the reserved block.
|
||||
addLongJump(nextOffset());
|
||||
ma_liPatchable(ScratchRegister, ImmWord(label->offset()));
|
||||
addLongJump(nextOffset(), BufferOffset(label->offset()));
|
||||
ma_liPatchable(ScratchRegister, ImmWord(LabelBase::INVALID_OFFSET));
|
||||
as_jalr(ScratchRegister);
|
||||
if (delaySlotFill == FillDelaySlot)
|
||||
as_nop();
|
||||
|
@ -819,8 +819,8 @@ MacroAssemblerMIPS64::branchWithCode(InstImm code, Label* label, JumpKind jumpKi
|
|||
|
||||
if (code.encode() == inst_beq.encode()) {
|
||||
// Handle long jump
|
||||
addLongJump(nextOffset());
|
||||
ma_liPatchable(ScratchRegister, ImmWord(label->offset()));
|
||||
addLongJump(nextOffset(), BufferOffset(label->offset()));
|
||||
ma_liPatchable(ScratchRegister, ImmWord(LabelBase::INVALID_OFFSET));
|
||||
as_jr(ScratchRegister);
|
||||
as_nop();
|
||||
return;
|
||||
|
@ -835,8 +835,8 @@ MacroAssemblerMIPS64::branchWithCode(InstImm code, Label* label, JumpKind jumpKi
|
|||
#endif
|
||||
writeInst(code_r.encode());
|
||||
// No need for a "nop" here because we can clobber scratch.
|
||||
addLongJump(nextOffset());
|
||||
ma_liPatchable(ScratchRegister, ImmWord(label->offset()));
|
||||
addLongJump(nextOffset(), BufferOffset(label->offset()));
|
||||
ma_liPatchable(ScratchRegister, ImmWord(LabelBase::INVALID_OFFSET));
|
||||
as_jr(ScratchRegister);
|
||||
as_nop();
|
||||
return;
|
||||
|
@ -1795,26 +1795,20 @@ MacroAssemblerMIPS64Compat::backedgeJump(RepatchLabel* label, Label* documentati
|
|||
{
|
||||
// Only one branch per label.
|
||||
MOZ_ASSERT(!label->used());
|
||||
uint32_t dest = label->bound() ? label->offset() : LabelBase::INVALID_OFFSET;
|
||||
|
||||
BufferOffset bo = nextOffset();
|
||||
label->use(bo.getOffset());
|
||||
|
||||
// Backedges are short jumps when bound, but can become long when patched.
|
||||
m_buffer.ensureSpace(16 * sizeof(uint32_t));
|
||||
if (label->bound()) {
|
||||
int32_t offset = label->offset() - bo.getOffset();
|
||||
MOZ_ASSERT(BOffImm16::IsInRange(offset));
|
||||
as_b(BOffImm16(offset));
|
||||
} else {
|
||||
// Jump to "label1" by default to jump to the loop header.
|
||||
as_b(BOffImm16(2 * sizeof(uint32_t)));
|
||||
}
|
||||
// Jump to "label1" by default to jump to the loop header.
|
||||
as_b(BOffImm16(2 * sizeof(uint32_t)));
|
||||
// No need for nop here. We can safely put next instruction in delay slot.
|
||||
ma_liPatchable(ScratchRegister, ImmWord(dest));
|
||||
ma_liPatchable(ScratchRegister, ImmWord(LabelBase::INVALID_OFFSET));
|
||||
MOZ_ASSERT(nextOffset().getOffset() - bo.getOffset() == 5 * sizeof(uint32_t));
|
||||
as_jr(ScratchRegister);
|
||||
// No need for nop here. We can safely put next instruction in delay slot.
|
||||
ma_liPatchable(ScratchRegister, ImmWord(dest));
|
||||
ma_liPatchable(ScratchRegister, ImmWord(LabelBase::INVALID_OFFSET));
|
||||
as_jr(ScratchRegister);
|
||||
as_nop();
|
||||
MOZ_ASSERT(nextOffset().getOffset() - bo.getOffset() == 12 * sizeof(uint32_t));
|
||||
|
@ -1826,12 +1820,10 @@ MacroAssemblerMIPS64Compat::jumpWithPatch(RepatchLabel* label, Label* documentat
|
|||
{
|
||||
// Only one branch per label.
|
||||
MOZ_ASSERT(!label->used());
|
||||
uint32_t dest = label->bound() ? label->offset() : LabelBase::INVALID_OFFSET;
|
||||
|
||||
BufferOffset bo = nextOffset();
|
||||
label->use(bo.getOffset());
|
||||
addLongJump(bo);
|
||||
ma_liPatchable(ScratchRegister, ImmWord(dest));
|
||||
ma_liPatchable(ScratchRegister, ImmWord(LabelBase::INVALID_OFFSET));
|
||||
as_jr(ScratchRegister);
|
||||
as_nop();
|
||||
return CodeOffsetJump(bo.getOffset());
|
||||
|
|
Загрузка…
Ссылка в новой задаче