diff options
Diffstat (limited to 'deps/v8/src/compiler/code-generator.cc')
-rw-r--r-- | deps/v8/src/compiler/code-generator.cc | 228 |
1 files changed, 173 insertions, 55 deletions
diff --git a/deps/v8/src/compiler/code-generator.cc b/deps/v8/src/compiler/code-generator.cc index 0fb38e5933..71b0394eab 100644 --- a/deps/v8/src/compiler/code-generator.cc +++ b/deps/v8/src/compiler/code-generator.cc @@ -42,7 +42,8 @@ CodeGenerator::CodeGenerator( InstructionSequence* code, CompilationInfo* info, Isolate* isolate, base::Optional<OsrHelper> osr_helper, int start_source_position, JumpOptimizationInfo* jump_opt, - std::vector<trap_handler::ProtectedInstructionData>* protected_instructions) + std::vector<trap_handler::ProtectedInstructionData>* protected_instructions, + LoadPoisoning load_poisoning) : zone_(codegen_zone), isolate_(isolate), frame_access_state_(nullptr), @@ -63,6 +64,7 @@ CodeGenerator::CodeGenerator( deoptimization_literals_(zone()), inlined_function_count_(0), translations_(zone()), + handler_table_offset_(0), last_lazy_deopt_pc_(0), caller_registers_saved_(false), jump_tables_(nullptr), @@ -72,7 +74,8 @@ CodeGenerator::CodeGenerator( optimized_out_literal_id_(-1), source_position_table_builder_(info->SourcePositionRecordingMode()), protected_instructions_(protected_instructions), - result_(kSuccess) { + result_(kSuccess), + load_poisoning_(load_poisoning) { for (int i = 0; i < code->InstructionBlockCount(); ++i) { new (&labels_[i]) Label; } @@ -148,16 +151,36 @@ void CodeGenerator::AssembleCode() { ProfileEntryHookStub::MaybeCallEntryHookDelayed(tasm(), zone()); } - // TODO(jupvfranco): This should be the first thing in the code, - // or otherwise MaybeCallEntryHookDelayed may happen twice (for - // optimized and deoptimized code). - // We want to bailout only from JS functions, which are the only ones + // Check that {kJavaScriptCallCodeStartRegister} has been set correctly. + if (FLAG_debug_code & (info->code_kind() == Code::OPTIMIZED_FUNCTION || + info->code_kind() == Code::BYTECODE_HANDLER)) { + tasm()->RecordComment("-- Prologue: check code start register --"); + AssembleCodeStartRegisterCheck(); + } + + // TODO(jupvfranco): This should be the first thing in the code, otherwise + // MaybeCallEntryHookDelayed may happen twice (for optimized and deoptimized + // code). We want to bailout only from JS functions, which are the only ones // that are optimized. if (info->IsOptimizing()) { DCHECK(linkage()->GetIncomingDescriptor()->IsJSFunctionCall()); + tasm()->RecordComment("-- Prologue: check for deoptimization --"); BailoutIfDeoptimized(); } + // Initialize {kSpeculationPoisonRegister} either by comparing the expected + // with the actual call target, or by unconditionally using {-1} initially. + // Masking register arguments with it only makes sense in the first case. + if (info->is_generating_speculation_poison_on_entry()) { + tasm()->RecordComment("-- Prologue: generate speculation poison --"); + GenerateSpeculationPoison(); + if (info->is_poisoning_register_arguments()) { + AssembleRegisterArgumentPoisoning(); + } + } else { + InitializePoisonForLoadsIfNeeded(); + } + // Define deoptimization literals for all inlined functions. DCHECK_EQ(0u, deoptimization_literals_.size()); for (CompilationInfo::InlinedFunctionHolder& inlined : @@ -218,6 +241,9 @@ void CodeGenerator::AssembleCode() { frame_access_state()->MarkHasFrame(block->needs_frame()); tasm()->bind(GetLabel(current_block_)); + + TryInsertBranchPoisoning(block); + if (block->must_construct_frame()) { AssembleConstructFrame(); // We need to setup the root register after we assemble the prologue, to @@ -287,26 +313,54 @@ void CodeGenerator::AssembleCode() { unwinding_info_writer_.Finish(tasm()->pc_offset()); safepoints()->Emit(tasm(), frame()->GetTotalFrameSlotCount()); - result_ = kSuccess; -} -Handle<ByteArray> CodeGenerator::GetSourcePositionTable() { - return source_position_table_builder_.ToSourcePositionTable(isolate()); -} - -MaybeHandle<HandlerTable> CodeGenerator::GetHandlerTable() const { + // Emit the exception handler table. if (!handlers_.empty()) { - Handle<HandlerTable> table = - Handle<HandlerTable>::cast(isolate()->factory()->NewFixedArray( - HandlerTable::LengthForReturn(static_cast<int>(handlers_.size())), - TENURED)); + handler_table_offset_ = HandlerTable::EmitReturnTableStart( + tasm(), static_cast<int>(handlers_.size())); for (size_t i = 0; i < handlers_.size(); ++i) { - table->SetReturnOffset(static_cast<int>(i), handlers_[i].pc_offset); - table->SetReturnHandler(static_cast<int>(i), handlers_[i].handler->pos()); + HandlerTable::EmitReturnEntry(tasm(), handlers_[i].pc_offset, + handlers_[i].handler->pos()); + } + } + + result_ = kSuccess; +} + +void CodeGenerator::TryInsertBranchPoisoning(const InstructionBlock* block) { + // See if our predecessor was a basic block terminated by a branch_and_poison + // instruction. If yes, then perform the masking based on the flags. + if (block->PredecessorCount() != 1) return; + RpoNumber pred_rpo = (block->predecessors())[0]; + const InstructionBlock* pred = code()->InstructionBlockAt(pred_rpo); + if (pred->code_start() == pred->code_end()) return; + Instruction* instr = code()->InstructionAt(pred->code_end() - 1); + FlagsMode mode = FlagsModeField::decode(instr->opcode()); + switch (mode) { + case kFlags_branch_and_poison: { + BranchInfo branch; + RpoNumber target = ComputeBranchInfo(&branch, instr); + if (!target.IsValid()) { + // Non-trivial branch, add the masking code. + FlagsCondition condition = branch.condition; + if (branch.false_label == GetLabel(block->rpo_number())) { + condition = NegateFlagsCondition(condition); + } + AssembleBranchPoisoning(condition, instr); + } + break; } - return table; + case kFlags_deoptimize_and_poison: { + UNREACHABLE(); + break; + } + default: + break; } - return {}; +} + +Handle<ByteArray> CodeGenerator::GetSourcePositionTable() { + return source_position_table_builder_.ToSourcePositionTable(isolate()); } Handle<Code> CodeGenerator::FinalizeCode() { @@ -315,18 +369,6 @@ Handle<Code> CodeGenerator::FinalizeCode() { return Handle<Code>(); } - // Allocate exception handler table. - Handle<HandlerTable> table = HandlerTable::Empty(isolate()); - if (!handlers_.empty()) { - table = Handle<HandlerTable>::cast(isolate()->factory()->NewFixedArray( - HandlerTable::LengthForReturn(static_cast<int>(handlers_.size())), - TENURED)); - for (size_t i = 0; i < handlers_.size(); ++i) { - table->SetReturnOffset(static_cast<int>(i), handlers_[i].pc_offset); - table->SetReturnHandler(static_cast<int>(i), handlers_[i].handler->pos()); - } - } - // Allocate the source position table. Handle<ByteArray> source_positions = source_position_table_builder_.ToSourcePositionTable(isolate()); @@ -343,8 +385,9 @@ Handle<Code> CodeGenerator::FinalizeCode() { Handle<Code> result = isolate()->factory()->NewCode( desc, info()->code_kind(), Handle<Object>(), info()->builtin_index(), - table, source_positions, deopt_data, kMovable, info()->stub_key(), true, - frame()->GetTotalFrameSlotCount(), safepoints()->GetCodeOffset()); + source_positions, deopt_data, kMovable, info()->stub_key(), true, + frame()->GetTotalFrameSlotCount(), safepoints()->GetCodeOffset(), + handler_table_offset_); isolate()->counters()->total_compiled_code_size()->Increment( result->instruction_size()); @@ -488,6 +531,77 @@ void CodeGenerator::GetPushCompatibleMoves(Instruction* instr, pushes->resize(push_count); } +CodeGenerator::MoveType::Type CodeGenerator::MoveType::InferMove( + InstructionOperand* source, InstructionOperand* destination) { + if (source->IsConstant()) { + if (destination->IsAnyRegister()) { + return MoveType::kConstantToRegister; + } else { + DCHECK(destination->IsAnyStackSlot()); + return MoveType::kConstantToStack; + } + } + DCHECK(LocationOperand::cast(source)->IsCompatible( + LocationOperand::cast(destination))); + if (source->IsAnyRegister()) { + if (destination->IsAnyRegister()) { + return MoveType::kRegisterToRegister; + } else { + DCHECK(destination->IsAnyStackSlot()); + return MoveType::kRegisterToStack; + } + } else { + DCHECK(source->IsAnyStackSlot()); + if (destination->IsAnyRegister()) { + return MoveType::kStackToRegister; + } else { + DCHECK(destination->IsAnyStackSlot()); + return MoveType::kStackToStack; + } + } +} + +CodeGenerator::MoveType::Type CodeGenerator::MoveType::InferSwap( + InstructionOperand* source, InstructionOperand* destination) { + DCHECK(LocationOperand::cast(source)->IsCompatible( + LocationOperand::cast(destination))); + if (source->IsAnyRegister()) { + if (destination->IsAnyRegister()) { + return MoveType::kRegisterToRegister; + } else { + DCHECK(destination->IsAnyStackSlot()); + return MoveType::kRegisterToStack; + } + } else { + DCHECK(source->IsAnyStackSlot()); + DCHECK(destination->IsAnyStackSlot()); + return MoveType::kStackToStack; + } +} + +RpoNumber CodeGenerator::ComputeBranchInfo(BranchInfo* branch, + Instruction* instr) { + // Assemble a branch after this instruction. + InstructionOperandConverter i(this, instr); + RpoNumber true_rpo = i.InputRpo(instr->InputCount() - 2); + RpoNumber false_rpo = i.InputRpo(instr->InputCount() - 1); + + if (true_rpo == false_rpo) { + return true_rpo; + } + FlagsCondition condition = FlagsConditionField::decode(instr->opcode()); + if (IsNextInAssemblyOrder(true_rpo)) { + // true block is next, can fall through if condition negated. + std::swap(true_rpo, false_rpo); + condition = NegateFlagsCondition(condition); + } + branch->condition = condition; + branch->true_label = GetLabel(true_rpo); + branch->false_label = GetLabel(false_rpo); + branch->fallthru = IsNextInAssemblyOrder(false_rpo); + return RpoNumber::Invalid(); +} + CodeGenerator::CodeGenResult CodeGenerator::AssembleInstruction( Instruction* instr, const InstructionBlock* block) { int first_unused_stack_slot; @@ -513,34 +627,23 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleInstruction( FlagsCondition condition = FlagsConditionField::decode(instr->opcode()); switch (mode) { - case kFlags_branch: { - // Assemble a branch after this instruction. - InstructionOperandConverter i(this, instr); - RpoNumber true_rpo = i.InputRpo(instr->InputCount() - 2); - RpoNumber false_rpo = i.InputRpo(instr->InputCount() - 1); - - if (true_rpo == false_rpo) { + case kFlags_branch: + case kFlags_branch_and_poison: { + BranchInfo branch; + RpoNumber target = ComputeBranchInfo(&branch, instr); + if (target.IsValid()) { // redundant branch. - if (!IsNextInAssemblyOrder(true_rpo)) { - AssembleArchJump(true_rpo); + if (!IsNextInAssemblyOrder(target)) { + AssembleArchJump(target); } return kSuccess; } - if (IsNextInAssemblyOrder(true_rpo)) { - // true block is next, can fall through if condition negated. - std::swap(true_rpo, false_rpo); - condition = NegateFlagsCondition(condition); - } - BranchInfo branch; - branch.condition = condition; - branch.true_label = GetLabel(true_rpo); - branch.false_label = GetLabel(false_rpo); - branch.fallthru = IsNextInAssemblyOrder(false_rpo); // Assemble architecture-specific branch. AssembleArchBranch(instr, &branch); break; } - case kFlags_deoptimize: { + case kFlags_deoptimize: + case kFlags_deoptimize_and_poison: { // Assemble a conditional eager deoptimization after this instruction. InstructionOperandConverter i(this, instr); size_t frame_state_offset = MiscField::decode(instr->opcode()); @@ -555,6 +658,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleInstruction( // Assemble architecture-specific branch. AssembleArchDeoptBranch(instr, &branch); tasm()->bind(&continue_label); + if (mode == kFlags_deoptimize_and_poison) { + AssembleBranchPoisoning(NegateFlagsCondition(branch.condition), instr); + } break; } case kFlags_set: { @@ -570,6 +676,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleInstruction( break; } } + + // TODO(jarin) We should thread the flag through rather than set it. + if (instr->IsCall()) { + InitializePoisonForLoadsIfNeeded(); + } + return kSuccess; } @@ -1078,6 +1190,12 @@ DeoptimizationExit* CodeGenerator::AddDeoptimizationExit( return exit; } +void CodeGenerator::InitializePoisonForLoadsIfNeeded() { + if (load_poisoning_ == LoadPoisoning::kDoPoison) { + tasm()->ResetSpeculationPoisonRegister(); + } +} + OutOfLineCode::OutOfLineCode(CodeGenerator* gen) : frame_(gen->frame()), tasm_(gen->tasm()), next_(gen->ools_) { gen->ools_ = this; |