[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:
Tobias Tebbi 2018-02-15 14:27:12 +01:00 committed by Commit Bot
parent e56eac022f
commit 2579951648
5 changed files with 36 additions and 4 deletions

View File

@ -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));

View File

@ -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

View File

@ -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;

View File

@ -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();

View File

@ -2666,7 +2666,7 @@ InstructionSelector::AlignmentRequirements() {
}
// static
bool InstructionSelector::SupportsSpeculationPoisoning() { return false; }
bool InstructionSelector::SupportsSpeculationPoisoning() { return true; }
} // namespace compiler
} // namespace internal