Bug 1534840 part 2 - Prevent ARM64 from generating constant pools within jump tables. r=sstangl

Depends on D26521

Differential Revision: https://phabricator.services.mozilla.com/D26522

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Nicolas B. Pierron 2019-04-16 13:56:50 +00:00
parent 092c959227
commit 5b00acfbdf
7 changed files with 37 additions and 32 deletions

View File

@ -12055,10 +12055,6 @@ void CodeGenerator::visitOutOfLineSwitch(
OutOfLineSwitch<tableType>* jumpTable) {
jumpTable->setOutOfLine();
auto& labels = jumpTable->labels();
#if defined(JS_CODEGEN_ARM64)
AutoForbidPools afp(
&masm, (labels.length() + 1) * (sizeof(void*) / vixl::kInstructionSize));
#endif
if (tableType == SwitchTableType::OutOfLine) {
#if defined(JS_CODEGEN_ARM)
@ -12066,7 +12062,15 @@ void CodeGenerator::visitOutOfLineSwitch(
#elif defined(JS_CODEGEN_NONE)
MOZ_CRASH();
#else
# if defined(JS_CODEGEN_ARM64)
AutoForbidPoolsAndNops afp(
&masm,
(labels.length() + 1) * (sizeof(void*) / vixl::kInstructionSize));
# endif
masm.haltingAlign(sizeof(void*));
// Bind the address of the jump table and reserve the space for code
// pointers to jump in the newly generated code.
masm.bind(jumpTable->start());

View File

@ -380,6 +380,7 @@ class Assembler : public vixl::Assembler {
public:
void writeCodePointer(CodeLabel* label) {
armbuffer_.assertNoPoolAndNoNops();
uintptr_t x = uintptr_t(-1);
BufferOffset off = EmitData(&x, sizeof(uintptr_t));
label->patchAt()->bind(off.getOffset());
@ -523,19 +524,9 @@ inline Imm32 Imm64::secondHalf() const { return hi(); }
void PatchJump(CodeLocationJump& jump_, CodeLocationLabel label);
// Forbids pool generation during a specified interval. Not nestable.
class AutoForbidPools {
Assembler* asm_;
public:
AutoForbidPools(Assembler* asm_, size_t maxInst) : asm_(asm_) {
asm_->enterNoPool(maxInst);
}
~AutoForbidPools() { asm_->leaveNoPool(); }
};
// Forbids nop filling for testing purposes. Not nestable.
class AutoForbidNops {
protected:
Assembler* asm_;
public:
@ -543,6 +534,15 @@ class AutoForbidNops {
~AutoForbidNops() { asm_->leaveNoNops(); }
};
// Forbids pool generation during a specified interval. Not nestable.
class AutoForbidPoolsAndNops : public AutoForbidNops {
public:
AutoForbidPoolsAndNops(Assembler* asm_, size_t maxInst) : AutoForbidNops(asm_) {
asm_->enterNoPool(maxInst);
}
~AutoForbidPoolsAndNops() { asm_->leaveNoPool(); }
};
} // namespace jit
} // namespace js

View File

@ -811,7 +811,8 @@ class js::jit::OutOfLineTableSwitch
void CodeGeneratorARM64::visitOutOfLineTableSwitch(OutOfLineTableSwitch* ool) {
MTableSwitch* mir = ool->mir();
AutoForbidPools afp(
// Prevent nop and pools sequences to appear in the jump table.
AutoForbidPoolsAndNops afp(
&masm, (mir->numCases() + 1) * (sizeof(void*) / vixl::kInstructionSize));
masm.haltingAlign(sizeof(void*));
masm.bind(ool->jumpLabel());

View File

@ -276,7 +276,7 @@ void MacroAssembler::add64(Imm64 imm, Register64 dest) {
CodeOffset MacroAssembler::sub32FromStackPtrWithPatch(Register dest) {
vixl::UseScratchRegisterScope temps(this);
const ARMRegister scratch = temps.AcquireX();
AutoForbidPools afp(this, /* max number of instructions in scope = */ 3);
AutoForbidPoolsAndNops afp(this, /* max number of instructions in scope = */ 3);
CodeOffset offs = CodeOffset(currentOffset());
movz(scratch, 0, 0);
movk(scratch, 0, 16);

View File

@ -309,12 +309,12 @@ void MacroAssemblerCompat::wasmLoadImpl(const wasm::MemoryAccessDesc& access,
asMasm().memoryBarrierBefore(access.sync());
// Reg+Reg addressing is directly encodable in one Load instruction, hence
// the AutoForbidPools will ensure that the access metadata is emitted at
// the AutoForbidPoolsAndNops will ensure that the access metadata is emitted at
// the address of the Load.
MemOperand srcAddr(memoryBase, ptr);
{
AutoForbidPools afp(this, /* max number of instructions in scope = */ 1);
AutoForbidPoolsAndNops afp(this, /* max number of instructions in scope = */ 1);
append(access, asMasm().currentOffset());
switch (access.type()) {
case Scalar::Int8:
@ -377,12 +377,12 @@ void MacroAssemblerCompat::wasmStoreImpl(const wasm::MemoryAccessDesc& access,
asMasm().memoryBarrierBefore(access.sync());
// Reg+Reg addressing is directly encodable in one Store instruction, hence
// the AutoForbidPools will ensure that the access metadata is emitted at
// the AutoForbidPoolsAndNops will ensure that the access metadata is emitted at
// the address of the Store.
MemOperand dstAddr(memoryBase, ptr);
{
AutoForbidPools afp(this, /* max number of instructions in scope = */ 1);
AutoForbidPoolsAndNops afp(this, /* max number of instructions in scope = */ 1);
append(access, asMasm().currentOffset());
switch (access.type()) {
case Scalar::Int8:
@ -683,7 +683,7 @@ CodeOffset MacroAssembler::farJumpWithPatch() {
const ARMRegister scratch = temps.AcquireX();
const ARMRegister scratch2 = temps.AcquireX();
AutoForbidPools afp(this, /* max number of instructions in scope = */ 7);
AutoForbidPoolsAndNops afp(this, /* max number of instructions in scope = */ 7);
mozilla::DebugOnly<uint32_t> before = currentOffset();
@ -720,7 +720,7 @@ void MacroAssembler::patchFarJump(CodeOffset farJump, uint32_t targetOffset) {
}
CodeOffset MacroAssembler::nopPatchableToCall(const wasm::CallSiteDesc& desc) {
AutoForbidPools afp(this, /* max number of instructions in scope = */ 1);
AutoForbidPoolsAndNops afp(this, /* max number of instructions in scope = */ 1);
CodeOffset offset(currentOffset());
Nop();
append(desc, CodeOffset(currentOffset()));
@ -1075,7 +1075,7 @@ void MacroAssembler::comment(const char* msg) { Assembler::comment(msg); }
// wasm support
CodeOffset MacroAssembler::wasmTrapInstruction() {
AutoForbidPools afp(this, /* max number of instructions in scope = */ 1);
AutoForbidPoolsAndNops afp(this, /* max number of instructions in scope = */ 1);
CodeOffset offs(currentOffset());
Unreachable();
return offs;
@ -1515,14 +1515,14 @@ static void LoadExclusive(MacroAssembler& masm,
bool signExtend = Scalar::isSignedIntType(srcType);
// With this address form, a single native ldxr* will be emitted, and the
// AutoForbidPools ensures that the metadata is emitted at the address of
// AutoForbidPoolsAndNops ensures that the metadata is emitted at the address of
// the ldxr*.
MOZ_ASSERT(ptr.IsImmediateOffset() && ptr.offset() == 0);
switch (Scalar::byteSize(srcType)) {
case 1: {
{
AutoForbidPools afp(&masm,
AutoForbidPoolsAndNops afp(&masm,
/* max number of instructions in scope = */ 1);
if (access) {
masm.append(*access, masm.currentOffset());
@ -1536,7 +1536,7 @@ static void LoadExclusive(MacroAssembler& masm,
}
case 2: {
{
AutoForbidPools afp(&masm,
AutoForbidPoolsAndNops afp(&masm,
/* max number of instructions in scope = */ 1);
if (access) {
masm.append(*access, masm.currentOffset());
@ -1550,7 +1550,7 @@ static void LoadExclusive(MacroAssembler& masm,
}
case 4: {
{
AutoForbidPools afp(&masm,
AutoForbidPoolsAndNops afp(&masm,
/* max number of instructions in scope = */ 1);
if (access) {
masm.append(*access, masm.currentOffset());
@ -1564,7 +1564,7 @@ static void LoadExclusive(MacroAssembler& masm,
}
case 8: {
{
AutoForbidPools afp(&masm,
AutoForbidPoolsAndNops afp(&masm,
/* max number of instructions in scope = */ 1);
if (access) {
masm.append(*access, masm.currentOffset());

View File

@ -4728,7 +4728,7 @@ class BaseCompiler final : public BaseCompilerInterface {
masm.branchToComputedAddress(BaseIndex(scratch, switchValue, ScalePointer));
#elif defined(JS_CODEGEN_ARM64)
AutoForbidPools afp(&masm, /* number of instructions in scope = */ 4);
AutoForbidPoolsAndNops afp(&masm, /* number of instructions in scope = */ 4);
ScratchI32 scratch(*this);

View File

@ -439,7 +439,7 @@ static void GenerateCallablePrologue(MacroAssembler& masm, uint32_t* entry) {
// We do not use the PseudoStackPointer.
MOZ_ASSERT(masm.GetStackPointer64().code() == sp.code());
AutoForbidPools afp(&masm, /* number of instructions in scope = */ 5);
AutoForbidPoolsAndNops afp(&masm, /* number of instructions in scope = */ 5);
*entry = masm.currentOffset();
@ -510,7 +510,7 @@ static void GenerateCallableEpilogue(MacroAssembler& masm, unsigned framePushed,
// We do not use the PseudoStackPointer.
MOZ_ASSERT(masm.GetStackPointer64().code() == sp.code());
AutoForbidPools afp(&masm, /* number of instructions in scope = */ 5);
AutoForbidPoolsAndNops afp(&masm, /* number of instructions in scope = */ 5);
masm.Ldr(ARMRegister(FramePointer, 64),
MemOperand(sp, offsetof(Frame, callerFP)));