summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/code-generator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/code-generator.cc')
-rw-r--r--deps/v8/src/compiler/code-generator.cc228
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;