Commit 46a3c772 authored by Mike Stanton's avatar Mike Stanton Committed by Commit Bot

[turbofan] Masking/poisoning in codegen (optimized code, mips & mips64)

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, arm, arm64} to {x64, arm, arm64, mips, mips64}.

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: I211395b8305ed0ad9288d6da48fa159fa970c827
Reviewed-on: https://chromium-review.googlesource.com/951382Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarIvica Bogosavljevic <ivica.bogosavljevic@mips.com>
Commit-Queue: Ivica Bogosavljevic <ivica.bogosavljevic@mips.com>
Cr-Commit-Position: refs/heads/master@{#52042}
parent 58b0dea8
...@@ -349,6 +349,17 @@ FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate, ...@@ -349,6 +349,17 @@ FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate,
UNREACHABLE(); UNREACHABLE();
} }
void EmitWordLoadPoisoningIfNeeded(CodeGenerator* codegen,
InstructionCode opcode, Instruction* instr,
MipsOperandConverter& i) {
const MemoryAccessMode access_mode =
static_cast<MemoryAccessMode>(MiscField::decode(opcode));
if (access_mode == kMemoryAccessPoisoned) {
Register value = i.OutputRegister();
codegen->tasm()->And(value, value, kSpeculationPoisonRegister);
}
}
} // namespace } // namespace
#define ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(mode) \ #define ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(mode) \
...@@ -1502,24 +1513,30 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -1502,24 +1513,30 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
break; break;
case kMipsLbu: case kMipsLbu:
__ lbu(i.OutputRegister(), i.MemoryOperand()); __ lbu(i.OutputRegister(), i.MemoryOperand());
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break; break;
case kMipsLb: case kMipsLb:
__ lb(i.OutputRegister(), i.MemoryOperand()); __ lb(i.OutputRegister(), i.MemoryOperand());
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break; break;
case kMipsSb: case kMipsSb:
__ sb(i.InputOrZeroRegister(2), i.MemoryOperand()); __ sb(i.InputOrZeroRegister(2), i.MemoryOperand());
break; break;
case kMipsLhu: case kMipsLhu:
__ lhu(i.OutputRegister(), i.MemoryOperand()); __ lhu(i.OutputRegister(), i.MemoryOperand());
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break; break;
case kMipsUlhu: case kMipsUlhu:
__ Ulhu(i.OutputRegister(), i.MemoryOperand()); __ Ulhu(i.OutputRegister(), i.MemoryOperand());
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break; break;
case kMipsLh: case kMipsLh:
__ lh(i.OutputRegister(), i.MemoryOperand()); __ lh(i.OutputRegister(), i.MemoryOperand());
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break; break;
case kMipsUlh: case kMipsUlh:
__ Ulh(i.OutputRegister(), i.MemoryOperand()); __ Ulh(i.OutputRegister(), i.MemoryOperand());
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break; break;
case kMipsSh: case kMipsSh:
__ sh(i.InputOrZeroRegister(2), i.MemoryOperand()); __ sh(i.InputOrZeroRegister(2), i.MemoryOperand());
...@@ -1529,9 +1546,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -1529,9 +1546,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
break; break;
case kMipsLw: case kMipsLw:
__ lw(i.OutputRegister(), i.MemoryOperand()); __ lw(i.OutputRegister(), i.MemoryOperand());
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break; break;
case kMipsUlw: case kMipsUlw:
__ Ulw(i.OutputRegister(), i.MemoryOperand()); __ Ulw(i.OutputRegister(), i.MemoryOperand());
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break; break;
case kMipsSw: case kMipsSw:
__ sw(i.InputOrZeroRegister(2), i.MemoryOperand()); __ sw(i.InputOrZeroRegister(2), i.MemoryOperand());
...@@ -2934,7 +2953,15 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { ...@@ -2934,7 +2953,15 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
void CodeGenerator::AssembleBranchPoisoning(FlagsCondition condition, void CodeGenerator::AssembleBranchPoisoning(FlagsCondition condition,
Instruction* instr) { Instruction* instr) {
UNREACHABLE(); // TODO(jarin) Handle float comparisons (kUnordered[Not]Equal).
if (condition == kUnorderedEqual || condition == kUnorderedNotEqual) {
return;
}
Label end;
AssembleBranchToLabels(this, tasm(), instr, condition, &end, nullptr, true);
__ li(kSpeculationPoisonRegister, 0);
__ bind(&end);
} }
void CodeGenerator::AssembleArchDeoptBranch(Instruction* instr, void CodeGenerator::AssembleArchDeoptBranch(Instruction* instr,
...@@ -3261,6 +3288,7 @@ void CodeGenerator::AssembleConstructFrame() { ...@@ -3261,6 +3288,7 @@ void CodeGenerator::AssembleConstructFrame() {
if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --"); if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
osr_pc_offset_ = __ pc_offset(); osr_pc_offset_ = __ pc_offset();
shrink_slots -= osr_helper()->UnoptimizedFrameSlots(); shrink_slots -= osr_helper()->UnoptimizedFrameSlots();
InitializePoisonForLoadsIfNeeded();
} }
const RegList saves = call_descriptor->CalleeSavedRegisters(); const RegList saves = call_descriptor->CalleeSavedRegisters();
......
...@@ -2234,7 +2234,7 @@ InstructionSelector::AlignmentRequirements() { ...@@ -2234,7 +2234,7 @@ InstructionSelector::AlignmentRequirements() {
} }
// static // static
bool InstructionSelector::SupportsSpeculationPoisoning() { return false; } bool InstructionSelector::SupportsSpeculationPoisoning() { return true; }
#undef SIMD_BINOP_LIST #undef SIMD_BINOP_LIST
#undef SIMD_SHIFT_OP_LIST #undef SIMD_SHIFT_OP_LIST
......
...@@ -362,6 +362,17 @@ FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate, ...@@ -362,6 +362,17 @@ FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate,
UNREACHABLE(); UNREACHABLE();
} }
void EmitWordLoadPoisoningIfNeeded(CodeGenerator* codegen,
InstructionCode opcode, Instruction* instr,
MipsOperandConverter& i) {
const MemoryAccessMode access_mode =
static_cast<MemoryAccessMode>(MiscField::decode(opcode));
if (access_mode == kMemoryAccessPoisoned) {
Register value = i.OutputRegister();
codegen->tasm()->And(value, value, kSpeculationPoisonRegister);
}
}
} // namespace } // namespace
#define ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(mode) \ #define ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(mode) \
...@@ -1706,24 +1717,30 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -1706,24 +1717,30 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
break; break;
case kMips64Lbu: case kMips64Lbu:
__ Lbu(i.OutputRegister(), i.MemoryOperand()); __ Lbu(i.OutputRegister(), i.MemoryOperand());
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break; break;
case kMips64Lb: case kMips64Lb:
__ Lb(i.OutputRegister(), i.MemoryOperand()); __ Lb(i.OutputRegister(), i.MemoryOperand());
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break; break;
case kMips64Sb: case kMips64Sb:
__ Sb(i.InputOrZeroRegister(2), i.MemoryOperand()); __ Sb(i.InputOrZeroRegister(2), i.MemoryOperand());
break; break;
case kMips64Lhu: case kMips64Lhu:
__ Lhu(i.OutputRegister(), i.MemoryOperand()); __ Lhu(i.OutputRegister(), i.MemoryOperand());
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break; break;
case kMips64Ulhu: case kMips64Ulhu:
__ Ulhu(i.OutputRegister(), i.MemoryOperand()); __ Ulhu(i.OutputRegister(), i.MemoryOperand());
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break; break;
case kMips64Lh: case kMips64Lh:
__ Lh(i.OutputRegister(), i.MemoryOperand()); __ Lh(i.OutputRegister(), i.MemoryOperand());
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break; break;
case kMips64Ulh: case kMips64Ulh:
__ Ulh(i.OutputRegister(), i.MemoryOperand()); __ Ulh(i.OutputRegister(), i.MemoryOperand());
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break; break;
case kMips64Sh: case kMips64Sh:
__ Sh(i.InputOrZeroRegister(2), i.MemoryOperand()); __ Sh(i.InputOrZeroRegister(2), i.MemoryOperand());
...@@ -1733,21 +1750,27 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -1733,21 +1750,27 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
break; break;
case kMips64Lw: case kMips64Lw:
__ Lw(i.OutputRegister(), i.MemoryOperand()); __ Lw(i.OutputRegister(), i.MemoryOperand());
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break; break;
case kMips64Ulw: case kMips64Ulw:
__ Ulw(i.OutputRegister(), i.MemoryOperand()); __ Ulw(i.OutputRegister(), i.MemoryOperand());
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break; break;
case kMips64Lwu: case kMips64Lwu:
__ Lwu(i.OutputRegister(), i.MemoryOperand()); __ Lwu(i.OutputRegister(), i.MemoryOperand());
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break; break;
case kMips64Ulwu: case kMips64Ulwu:
__ Ulwu(i.OutputRegister(), i.MemoryOperand()); __ Ulwu(i.OutputRegister(), i.MemoryOperand());
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break; break;
case kMips64Ld: case kMips64Ld:
__ Ld(i.OutputRegister(), i.MemoryOperand()); __ Ld(i.OutputRegister(), i.MemoryOperand());
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break; break;
case kMips64Uld: case kMips64Uld:
__ Uld(i.OutputRegister(), i.MemoryOperand()); __ Uld(i.OutputRegister(), i.MemoryOperand());
EmitWordLoadPoisoningIfNeeded(this, opcode, instr, i);
break; break;
case kMips64Sw: case kMips64Sw:
__ Sw(i.InputOrZeroRegister(2), i.MemoryOperand()); __ Sw(i.InputOrZeroRegister(2), i.MemoryOperand());
...@@ -3154,7 +3177,15 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { ...@@ -3154,7 +3177,15 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
void CodeGenerator::AssembleBranchPoisoning(FlagsCondition condition, void CodeGenerator::AssembleBranchPoisoning(FlagsCondition condition,
Instruction* instr) { Instruction* instr) {
UNREACHABLE(); // TODO(jarin) Handle float comparisons (kUnordered[Not]Equal).
if (condition == kUnorderedEqual || condition == kUnorderedNotEqual) {
return;
}
Label end;
AssembleBranchToLabels(this, tasm(), instr, condition, &end, nullptr, true);
__ li(kSpeculationPoisonRegister, 0);
__ bind(&end);
} }
void CodeGenerator::AssembleArchDeoptBranch(Instruction* instr, void CodeGenerator::AssembleArchDeoptBranch(Instruction* instr,
...@@ -3487,6 +3518,7 @@ void CodeGenerator::AssembleConstructFrame() { ...@@ -3487,6 +3518,7 @@ void CodeGenerator::AssembleConstructFrame() {
if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --"); if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
osr_pc_offset_ = __ pc_offset(); osr_pc_offset_ = __ pc_offset();
shrink_slots -= osr_helper()->UnoptimizedFrameSlots(); shrink_slots -= osr_helper()->UnoptimizedFrameSlots();
InitializePoisonForLoadsIfNeeded();
} }
const RegList saves = call_descriptor->CalleeSavedRegisters(); const RegList saves = call_descriptor->CalleeSavedRegisters();
......
...@@ -2916,7 +2916,7 @@ InstructionSelector::AlignmentRequirements() { ...@@ -2916,7 +2916,7 @@ InstructionSelector::AlignmentRequirements() {
} }
// static // static
bool InstructionSelector::SupportsSpeculationPoisoning() { return false; } bool InstructionSelector::SupportsSpeculationPoisoning() { return true; }
#undef SIMD_BINOP_LIST #undef SIMD_BINOP_LIST
#undef SIMD_SHIFT_OP_LIST #undef SIMD_SHIFT_OP_LIST
......
...@@ -466,6 +466,12 @@ void CEntryStub::Generate(MacroAssembler* masm) { ...@@ -466,6 +466,12 @@ void CEntryStub::Generate(MacroAssembler* masm) {
__ sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); __ sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ bind(&zero); __ bind(&zero);
// Reset the masking register. This is done independent of the underlying
// feature flag {FLAG_branch_load_poisoning} to make the snapshot work with
// both configurations. It is safe to always do this, because the underlying
// register is caller-saved and can be arbitrarily clobbered.
__ ResetSpeculationPoisonRegister();
// Compute the handler entry address and jump to it. // Compute the handler entry address and jump to it.
__ li(t9, Operand(pending_handler_entrypoint_address)); __ li(t9, Operand(pending_handler_entrypoint_address));
__ lw(t9, MemOperand(t9)); __ lw(t9, MemOperand(t9));
......
...@@ -5248,7 +5248,9 @@ void TurboAssembler::ComputeCodeStartAddress(Register dst) { ...@@ -5248,7 +5248,9 @@ void TurboAssembler::ComputeCodeStartAddress(Register dst) {
pop(ra); // Restore ra pop(ra); // Restore ra
} }
void TurboAssembler::ResetSpeculationPoisonRegister() { UNREACHABLE(); } void TurboAssembler::ResetSpeculationPoisonRegister() {
li(kSpeculationPoisonRegister, -1);
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -465,6 +465,12 @@ void CEntryStub::Generate(MacroAssembler* masm) { ...@@ -465,6 +465,12 @@ void CEntryStub::Generate(MacroAssembler* masm) {
__ Sd(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); __ Sd(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ bind(&zero); __ bind(&zero);
// Reset the masking register. This is done independent of the underlying
// feature flag {FLAG_branch_load_poisoning} to make the snapshot work with
// both configurations. It is safe to always do this, because the underlying
// register is caller-saved and can be arbitrarily clobbered.
__ ResetSpeculationPoisonRegister();
// Compute the handler entry address and jump to it. // Compute the handler entry address and jump to it.
__ li(t9, Operand(pending_handler_entrypoint_address)); __ li(t9, Operand(pending_handler_entrypoint_address));
__ Ld(t9, MemOperand(t9)); __ Ld(t9, MemOperand(t9));
......
...@@ -5583,7 +5583,9 @@ void TurboAssembler::ComputeCodeStartAddress(Register dst) { ...@@ -5583,7 +5583,9 @@ void TurboAssembler::ComputeCodeStartAddress(Register dst) {
pop(ra); // Restore ra pop(ra); // Restore ra
} }
void TurboAssembler::ResetSpeculationPoisonRegister() { UNREACHABLE(); } void TurboAssembler::ResetSpeculationPoisonRegister() {
li(kSpeculationPoisonRegister, -1);
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment