зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1271010 - Baldr: refactor nop-jump patching code (r=bbouvier)
MozReview-Commit-ID: 92hS8F1U9vO --HG-- extra : rebase_source : b48ddbbd799a24ecd13fabfb4ec316e64ac2cfa7
This commit is contained in:
Родитель
79a52254e6
Коммит
cee42a48aa
|
@ -334,18 +334,7 @@ wasm::GenerateFunctionEpilogue(MacroAssembler& masm, unsigned framePushed, FuncO
|
|||
// the nop since we need the location of the actual nop to patch it.
|
||||
AutoForbidPools afp(&masm, 1);
|
||||
#endif
|
||||
|
||||
// The exact form of this instruction must be kept consistent with the
|
||||
// patching in Module::setProfilingEnabled.
|
||||
offsets->profilingJump = masm.currentOffset();
|
||||
#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
|
||||
masm.twoByteNop();
|
||||
#elif defined(JS_CODEGEN_ARM)
|
||||
masm.nop();
|
||||
#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
|
||||
masm.nop();
|
||||
masm.nop();
|
||||
#endif
|
||||
offsets->profilingJump = masm.nopPatchableToNearJump().offset();
|
||||
}
|
||||
|
||||
// Normal epilogue:
|
||||
|
@ -769,47 +758,11 @@ wasm::EnableProfilingEpilogue(const Module& module, const CodeRange& codeRange,
|
|||
if (!codeRange.isFunction())
|
||||
return;
|
||||
|
||||
uint8_t* jump = module.code() + codeRange.funcProfilingJump();
|
||||
uint8_t* profilingJump = module.code() + codeRange.funcProfilingJump();
|
||||
uint8_t* profilingEpilogue = module.code() + codeRange.funcProfilingEpilogue();
|
||||
|
||||
#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
|
||||
// An unconditional jump with a 1 byte offset immediate has the opcode
|
||||
// 0x90. The offset is relative to the address of the instruction after
|
||||
// the jump. 0x66 0x90 is the canonical two-byte nop.
|
||||
ptrdiff_t jumpImmediate = profilingEpilogue - jump - 2;
|
||||
MOZ_ASSERT(jumpImmediate > 0 && jumpImmediate <= 127);
|
||||
if (enabled) {
|
||||
MOZ_ASSERT(jump[0] == 0x66);
|
||||
MOZ_ASSERT(jump[1] == 0x90);
|
||||
jump[0] = 0xeb;
|
||||
jump[1] = jumpImmediate;
|
||||
} else {
|
||||
MOZ_ASSERT(jump[0] == 0xeb);
|
||||
MOZ_ASSERT(jump[1] == jumpImmediate);
|
||||
jump[0] = 0x66;
|
||||
jump[1] = 0x90;
|
||||
}
|
||||
#elif defined(JS_CODEGEN_ARM)
|
||||
if (enabled) {
|
||||
MOZ_ASSERT(reinterpret_cast<Instruction*>(jump)->is<InstNOP>());
|
||||
new (jump) InstBImm(BOffImm(profilingEpilogue - jump), Assembler::Always);
|
||||
} else {
|
||||
MOZ_ASSERT(reinterpret_cast<Instruction*>(jump)->is<InstBImm>());
|
||||
new (jump) InstNOP();
|
||||
}
|
||||
#elif defined(JS_CODEGEN_ARM64)
|
||||
(void)jump;
|
||||
(void)profilingEpilogue;
|
||||
MOZ_CRASH();
|
||||
#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
|
||||
InstImm* instr = (InstImm*)jump;
|
||||
if (enabled)
|
||||
instr->setBOffImm16(BOffImm16(profilingEpilogue - jump));
|
||||
MacroAssembler::patchNopToNearJump(profilingJump, profilingEpilogue);
|
||||
else
|
||||
instr->makeNop();
|
||||
#elif defined(JS_CODEGEN_NONE)
|
||||
MOZ_CRASH();
|
||||
#else
|
||||
# error "Missing architecture"
|
||||
#endif
|
||||
MacroAssembler::patchNearJumpToNop(profilingJump);
|
||||
}
|
||||
|
|
|
@ -493,6 +493,12 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
void patchThunk(uint32_t thunkOffset, uint32_t targetOffset) PER_SHARED_ARCH;
|
||||
static void repatchThunk(uint8_t* code, uint32_t thunkOffset, uint32_t targetOffset) PER_SHARED_ARCH;
|
||||
|
||||
// Emit a nop that can be patched to and from a nop and a jump with an int8
|
||||
// relative displacement.
|
||||
CodeOffset nopPatchableToNearJump() PER_SHARED_ARCH;
|
||||
static void patchNopToNearJump(uint8_t* jump, uint8_t* target) PER_SHARED_ARCH;
|
||||
static void patchNearJumpToNop(uint8_t* jump) PER_SHARED_ARCH;
|
||||
|
||||
// Push the return address and make a call. On platforms where this function
|
||||
// is not defined, push the link register (pushReturnAddress) at the entry
|
||||
// point of the callee.
|
||||
|
|
|
@ -4834,6 +4834,28 @@ MacroAssembler::repatchThunk(uint8_t* code, uint32_t u32Offset, uint32_t targetO
|
|||
*u32 = (targetOffset - addOffset) - 8;
|
||||
}
|
||||
|
||||
CodeOffset
|
||||
MacroAssembler::nopPatchableToNearJump()
|
||||
{
|
||||
CodeOffset offset(currentOffset());
|
||||
ma_nop();
|
||||
return offset;
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::patchNopToNearJump(uint8_t* jump, uint8_t* target)
|
||||
{
|
||||
MOZ_ASSERT(reinterpret_cast<Instruction*>(jump)->is<InstNOP>());
|
||||
new (jump) InstBImm(BOffImm(target - jump), Assembler::Always);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::patchNearJumpToNop(uint8_t* jump)
|
||||
{
|
||||
MOZ_ASSERT(reinterpret_cast<Instruction*>(jump)->is<InstBImm>());
|
||||
new (jump) InstNOP();
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::pushReturnAddress()
|
||||
{
|
||||
|
|
|
@ -557,6 +557,24 @@ MacroAssembler::repatchThunk(uint8_t* code, uint32_t thunkOffset, uint32_t targe
|
|||
MOZ_CRASH("NYI");
|
||||
}
|
||||
|
||||
CodeOffset
|
||||
MacroAssembler::nopPatchableToNearJump()
|
||||
{
|
||||
MOZ_CRASH("NYI");
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::patchNopToNearJump(uint8_t* jump, uint8_t* target)
|
||||
{
|
||||
MOZ_CRASH("NYI");
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::patchNearJumpToNop(uint8_t* jump)
|
||||
{
|
||||
MOZ_CRASH("NYI");
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::pushReturnAddress()
|
||||
{
|
||||
|
|
|
@ -1235,6 +1235,27 @@ MacroAssembler::repatchThunk(uint8_t* code, uint32_t u32Offset, uint32_t targetO
|
|||
*u32 = targetOffset - u32Offset;
|
||||
}
|
||||
|
||||
CodeOffset
|
||||
MacroAssembler::nopPatchableToNearJump()
|
||||
{
|
||||
CodeOffset offset(currentOffset());
|
||||
masm.nop();
|
||||
masm.nop();
|
||||
return offset;
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::patchNopToNearJump(uint8_t* jump, uint8_t* target)
|
||||
{
|
||||
((InstImm*)jump)->setBOffImm16(BOffImm16(target - jump));
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::patchNearJumpToNop(uint8_t* jump)
|
||||
{
|
||||
((InstImm*)jump)->makeNop();
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::call(wasm::SymbolicAddress target)
|
||||
{
|
||||
|
|
|
@ -911,7 +911,6 @@ class AssemblerX86Shared : public AssemblerShared
|
|||
|
||||
public:
|
||||
void nop() { masm.nop(); }
|
||||
void twoByteNop() { masm.twoByteNop(); }
|
||||
void j(Condition cond, Label* label) { jSrc(cond, label); }
|
||||
void jmp(Label* label) { jmpSrc(label); }
|
||||
void j(Condition cond, RepatchLabel* label) { jSrc(cond, label); }
|
||||
|
@ -1070,6 +1069,16 @@ class AssemblerX86Shared : public AssemblerShared
|
|||
X86Encoding::SetRel32(code + thunkOffset, code + targetOffset);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void breakpoint() {
|
||||
masm.int3();
|
||||
}
|
||||
|
|
|
@ -75,11 +75,34 @@ public:
|
|||
m_formatter.oneByteOp(OP_NOP);
|
||||
}
|
||||
|
||||
void twoByteNop()
|
||||
MOZ_MUST_USE JmpSrc
|
||||
twoByteNop()
|
||||
{
|
||||
spew("nop (2 byte)");
|
||||
JmpSrc r(m_formatter.size());
|
||||
m_formatter.prefix(PRE_OPERAND_SIZE);
|
||||
m_formatter.oneByteOp(OP_NOP);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void patchTwoByteNopToJump(uint8_t* jump, uint8_t* target)
|
||||
{
|
||||
// Note: the offset is relative to the address of the instruction after
|
||||
// the jump which is two bytes.
|
||||
ptrdiff_t rel8 = target - jump - 2;
|
||||
MOZ_RELEASE_ASSERT(rel8 >= INT8_MIN && rel8 <= INT8_MAX);
|
||||
MOZ_RELEASE_ASSERT(jump[0] == PRE_OPERAND_SIZE);
|
||||
MOZ_RELEASE_ASSERT(jump[1] == OP_NOP);
|
||||
jump[0] = OP_JMP_rel8;
|
||||
jump[1] = rel8;
|
||||
}
|
||||
|
||||
static void patchJumpToTwoByteNop(uint8_t* jump)
|
||||
{
|
||||
// See twoByteNop.
|
||||
MOZ_RELEASE_ASSERT(jump[0] == OP_JMP_rel8);
|
||||
jump[0] = PRE_OPERAND_SIZE;
|
||||
jump[1] = OP_NOP;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -570,6 +570,24 @@ MacroAssembler::repatchThunk(uint8_t* code, uint32_t thunkOffset, uint32_t targe
|
|||
Assembler::repatchThunk(code, thunkOffset, targetOffset);
|
||||
}
|
||||
|
||||
CodeOffset
|
||||
MacroAssembler::nopPatchableToNearJump()
|
||||
{
|
||||
return Assembler::twoByteNop();
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::patchNopToNearJump(uint8_t* jump, uint8_t* target)
|
||||
{
|
||||
Assembler::patchTwoByteNopToJump(jump, target);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::patchNearJumpToNop(uint8_t* jump)
|
||||
{
|
||||
Assembler::patchJumpToTwoByteNop(jump);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::callAndPushReturnAddress(Register reg)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче