mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
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:
parent
092c959227
commit
5b00acfbdf
@ -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());
|
||||
|
@ -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
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)));
|
||||
|
Loading…
Reference in New Issue
Block a user