[turbofan] Masking/poisoning in codegen (optimized code, arm)
This introduces masking of loads with speculation bit during code generation. At the moment, this is done only under the --branch-load-poisoning flag, and this CL enlarges the set of supported platforms from {x64} to {x64, arm}. Overview of changes: - new register configuration configuration with one register reserved for the speculation poison/mask (kSpeculationPoisonRegister). - in codegen, we introduce an update to the poison register at the starts of all successors of branches (and deopts) that are marked as safety branches (deopts). - in memory optimizer, we lower all field and element loads to PoisonedLoads. - poisoned loads are then masked in codegen with the poison register. * only integer loads are masked at the moment. Bug: chromium:798964 Change-Id: I37f5531fd18a96038ea8b059641e3dfc852c2d34 Reviewed-on: https://chromium-review.googlesource.com/913354 Commit-Queue: Michael Stanton <mvstanton@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#51374}
This commit is contained in:
parent
e56eac022f
commit
2579951648
@ -385,6 +385,11 @@ void CEntryStub::Generate(MacroAssembler* masm) {
|
||||
__ cmp(cp, Operand(0));
|
||||
__ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
|
||||
|
||||
// Reset the masking register.
|
||||
if (FLAG_branch_load_poisoning) {
|
||||
__ ResetSpeculationPoisonRegister();
|
||||
}
|
||||
|
||||
// Compute the handler entry address and jump to it.
|
||||
ConstantPoolUnavailableScope constant_pool_unavailable(masm);
|
||||
__ mov(r1, Operand(pending_handler_entrypoint_address));
|
||||
|
@ -2312,7 +2312,9 @@ void TurboAssembler::ComputeCodeStartAddress(Register dst) {
|
||||
sub(dst, pc, Operand(pc_offset() + TurboAssembler::kPcLoadDelta));
|
||||
}
|
||||
|
||||
void TurboAssembler::ResetSpeculationPoisonRegister() { UNREACHABLE(); }
|
||||
void TurboAssembler::ResetSpeculationPoisonRegister() {
|
||||
mov(kSpeculationPoisonRegister, Operand(-1));
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -20,7 +20,7 @@ constexpr Register kReturnRegister2 = r2;
|
||||
constexpr Register kJSFunctionRegister = r1;
|
||||
constexpr Register kContextRegister = r7;
|
||||
constexpr Register kAllocateSizeRegister = r1;
|
||||
constexpr Register kSpeculationPoisonRegister = r4;
|
||||
constexpr Register kSpeculationPoisonRegister = r9;
|
||||
constexpr Register kInterpreterAccumulatorRegister = r0;
|
||||
constexpr Register kInterpreterBytecodeOffsetRegister = r5;
|
||||
constexpr Register kInterpreterBytecodeArrayRegister = r6;
|
||||
|
@ -323,6 +323,17 @@ Condition FlagsConditionToCondition(FlagsCondition condition) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void EmitWordLoadPoisoningIfNeeded(CodeGenerator* codegen,
|
||||
InstructionCode opcode, Instruction* instr,
|
||||
ArmOperandConverter& i) {
|
||||
const MemoryAccessMode access_mode =
|
||||
static_cast<MemoryAccessMode>(MiscField::decode(opcode));
|
||||
if (access_mode == kMemoryAccessPoisoned) {
|
||||
Register value = i.OutputRegister();
|
||||
codegen->tasm()->and_(value, value, Operand(kSpeculationPoisonRegister));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#define ASSEMBLE_ATOMIC_LOAD_INTEGER(asm_instr) \
|
||||
@ -1505,10 +1516,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
case kArmLdrb:
|
||||
__ ldrb(i.OutputRegister(), i.InputOffset());
|
||||
DCHECK_EQ(LeaveCC, i.OutputSBit());
|
||||
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
|
||||
break;
|
||||
case kArmLdrsb:
|
||||
__ ldrsb(i.OutputRegister(), i.InputOffset());
|
||||
DCHECK_EQ(LeaveCC, i.OutputSBit());
|
||||
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
|
||||
break;
|
||||
case kArmStrb:
|
||||
__ strb(i.InputRegister(0), i.InputOffset(1));
|
||||
@ -1516,9 +1529,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
break;
|
||||
case kArmLdrh:
|
||||
__ ldrh(i.OutputRegister(), i.InputOffset());
|
||||
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
|
||||
break;
|
||||
case kArmLdrsh:
|
||||
__ ldrsh(i.OutputRegister(), i.InputOffset());
|
||||
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
|
||||
break;
|
||||
case kArmStrh:
|
||||
__ strh(i.InputRegister(0), i.InputOffset(1));
|
||||
@ -1526,6 +1541,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
break;
|
||||
case kArmLdr:
|
||||
__ ldr(i.OutputRegister(), i.InputOffset());
|
||||
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
|
||||
break;
|
||||
case kArmStr:
|
||||
__ str(i.InputRegister(0), i.InputOffset(1));
|
||||
@ -2702,7 +2718,15 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
|
||||
|
||||
void CodeGenerator::AssembleBranchPoisoning(FlagsCondition condition,
|
||||
Instruction* instr) {
|
||||
UNREACHABLE();
|
||||
// TODO(jarin) Handle float comparisons (kUnordered[Not]Equal).
|
||||
if (condition == kUnorderedEqual || condition == kUnorderedNotEqual) {
|
||||
return;
|
||||
}
|
||||
|
||||
condition = NegateFlagsCondition(condition);
|
||||
__ eor(kSpeculationPoisonRegister, kSpeculationPoisonRegister,
|
||||
Operand(kSpeculationPoisonRegister), SBit::LeaveCC,
|
||||
FlagsConditionToCondition(condition));
|
||||
}
|
||||
|
||||
void CodeGenerator::AssembleArchDeoptBranch(Instruction* instr,
|
||||
@ -2879,6 +2903,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
|
||||
osr_pc_offset_ = __ pc_offset();
|
||||
shrink_slots -= osr_helper()->UnoptimizedFrameSlots();
|
||||
InitializePoisonForLoadsIfNeeded();
|
||||
}
|
||||
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
|
@ -2666,7 +2666,7 @@ InstructionSelector::AlignmentRequirements() {
|
||||
}
|
||||
|
||||
// static
|
||||
bool InstructionSelector::SupportsSpeculationPoisoning() { return false; }
|
||||
bool InstructionSelector::SupportsSpeculationPoisoning() { return true; }
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
|
Loading…
Reference in New Issue
Block a user