Bug 1317033 - Baldr: hoist mprotect out of MacroAssembler::patchCall/FarJump (r=sunfish)

MozReview-Commit-ID: Nejpro1fxc
This commit is contained in:
Luke Wagner 2016-11-13 13:21:49 -06:00
parent 19ae114a83
commit 392e723d67
7 changed files with 50 additions and 18 deletions

View File

@ -78,8 +78,7 @@ class PageProtectingVector final
}
void protect() {
MOZ_ASSERT(!regionUnprotected);
if (protectionEnabled && unprotectedBytes >= intptr_t(pageSize)) {
if (!regionUnprotected && protectionEnabled && unprotectedBytes >= intptr_t(pageSize)) {
size_t toProtect = size_t(unprotectedBytes) & ~pageMask;
uintptr_t addr = uintptr_t(vector.begin()) + offsetToPage + protectedBytes;
gc::MakePagesReadOnly(reinterpret_cast<void*>(addr), toProtect);
@ -89,9 +88,8 @@ class PageProtectingVector final
}
void unprotect() {
MOZ_ASSERT(!regionUnprotected);
MOZ_ASSERT_IF(!protectionEnabled, !protectedBytes);
if (protectedBytes) {
if (!regionUnprotected && protectedBytes) {
uintptr_t addr = uintptr_t(vector.begin()) + offsetToPage;
gc::UnprotectPages(reinterpret_cast<void*>(addr), protectedBytes);
unprotectedBytes += protectedBytes;

View File

@ -1536,6 +1536,10 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
// Instrumentation for entering and leaving the profiler.
void profilerEnterFrame(Register framePtr, Register scratch);
void profilerExitFrame();
struct AutoPrepareForPatching {
explicit AutoPrepareForPatching(MacroAssemblerARMCompat&) {}
};
};
typedef MacroAssemblerARMCompat MacroAssemblerSpecific;

View File

@ -2316,6 +2316,10 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
return nextOffset().getOffset();
}
struct AutoPrepareForPatching {
explicit AutoPrepareForPatching(MacroAssemblerCompat&) {}
};
protected:
bool buildOOLFakeExitFrame(void* fakeReturnAddr) {
uint32_t descriptor = MakeFrameDescriptor(framePushed(), JitFrame_IonJS,

View File

@ -249,6 +249,11 @@ class MacroAssemblerMIPSShared : public Assembler
void atomicExchange(int nbytes, bool signExtend, const BaseIndex& address, Register value,
Register valueTemp, Register offsetTemp, Register maskTemp,
Register output);
public:
struct AutoPrepareForPatching {
explicit AutoPrepareForPatching(MacroAssemblerMIPSShared&) {}
};
};
} // namespace jit

View File

@ -1057,17 +1057,24 @@ class AssemblerX86Shared : public AssemblerShared
CodeOffset callWithPatch() {
return CodeOffset(masm.call().offset());
}
struct AutoPrepareForPatching : X86Encoding::AutoUnprotectAssemblerBufferRegion {
explicit AutoPrepareForPatching(AssemblerX86Shared& masm)
: X86Encoding::AutoUnprotectAssemblerBufferRegion(masm.masm, 0, masm.size())
{}
};
void patchCall(uint32_t callerOffset, uint32_t calleeOffset) {
// The caller uses AutoUnprotectBuffer.
unsigned char* code = masm.data();
X86Encoding::AutoUnprotectAssemblerBufferRegion unprotect(masm, callerOffset - 4, 4);
X86Encoding::SetRel32(code + callerOffset, code + calleeOffset);
}
CodeOffset farJumpWithPatch() {
return CodeOffset(masm.jmp().offset());
}
void patchFarJump(CodeOffset farJump, uint32_t targetOffset) {
// The caller uses AutoUnprotectBuffer.
unsigned char* code = masm.data();
X86Encoding::AutoUnprotectAssemblerBufferRegion unprotect(masm, farJump.offset() - 4, 4);
X86Encoding::SetRel32(code + farJump.offset(), code + targetOffset);
}
static void repatchFarJump(uint8_t* code, uint32_t farJumpOffset, uint32_t targetOffset) {

View File

@ -250,6 +250,8 @@ typedef HashMap<uint32_t, uint32_t, DefaultHasher<uint32_t>, SystemAllocPolicy>
bool
ModuleGenerator::patchCallSites(TrapExitOffsetArray* maybeTrapExits)
{
MacroAssembler::AutoPrepareForPatching patching(masm_);
masm_.haltingAlign(CodeAlignment);
// Create far jumps for calls that have relative offsets that may otherwise
@ -342,6 +344,24 @@ ModuleGenerator::patchCallSites(TrapExitOffsetArray* maybeTrapExits)
return true;
}
bool
ModuleGenerator::patchFarJumps(const TrapExitOffsetArray& trapExits)
{
MacroAssembler::AutoPrepareForPatching patching(masm_);
for (CallThunk& callThunk : metadata_->callThunks) {
uint32_t funcIndex = callThunk.u.funcIndex;
callThunk.u.codeRangeIndex = funcToCodeRange_[funcIndex];
CodeOffset farJump(callThunk.offset);
masm_.patchFarJump(farJump, funcCodeRange(funcIndex).funcNonProfilingEntry());
}
for (const TrapFarJump& farJump : masm_.trapFarJumps())
masm_.patchFarJump(farJump.jump, trapExits[farJump.trap].begin);
return true;
}
bool
ModuleGenerator::finishTask(IonCompileTask* task)
{
@ -530,22 +550,15 @@ ModuleGenerator::finishCodegen()
linkData_.outOfBoundsOffset = outOfBoundsExit.begin;
linkData_.interruptOffset = interruptExit.begin;
// Now that all other code has been emitted, patch all remaining callsites.
// Now that all other code has been emitted, patch all remaining callsites
// then far jumps. Patching callsites can generate far jumps so there is an
// ordering dependency.
if (!patchCallSites(&trapExits))
return false;
// Now that all code has been generated, patch far jumps to destinations.
for (CallThunk& callThunk : metadata_->callThunks) {
uint32_t funcIndex = callThunk.u.funcIndex;
callThunk.u.codeRangeIndex = funcToCodeRange_[funcIndex];
CodeOffset farJump(callThunk.offset);
masm_.patchFarJump(farJump, funcCodeRange(funcIndex).funcNonProfilingEntry());
}
for (const TrapFarJump& farJump : masm_.trapFarJumps())
masm_.patchFarJump(farJump.jump, trapExits[farJump.trap].begin);
if (!patchFarJumps(trapExits))
return false;
// Code-generation is complete!

View File

@ -118,6 +118,7 @@ class MOZ_STACK_CLASS ModuleGenerator
bool funcIsCompiled(uint32_t funcIndex) const;
const CodeRange& funcCodeRange(uint32_t funcIndex) const;
MOZ_MUST_USE bool patchCallSites(TrapExitOffsetArray* maybeTrapExits = nullptr);
MOZ_MUST_USE bool patchFarJumps(const TrapExitOffsetArray& trapExits);
MOZ_MUST_USE bool finishTask(IonCompileTask* task);
MOZ_MUST_USE bool finishOutstandingTask();
MOZ_MUST_USE bool finishFuncExports();