diff options
Diffstat (limited to 'deps/v8/src/compiler/instruction-selector.cc')
-rw-r--r-- | deps/v8/src/compiler/instruction-selector.cc | 440 |
1 files changed, 274 insertions, 166 deletions
diff --git a/deps/v8/src/compiler/instruction-selector.cc b/deps/v8/src/compiler/instruction-selector.cc index 954a1fc272..6fce9ea470 100644 --- a/deps/v8/src/compiler/instruction-selector.cc +++ b/deps/v8/src/compiler/instruction-selector.cc @@ -25,10 +25,10 @@ InstructionSelector::InstructionSelector( InstructionSequence* sequence, Schedule* schedule, SourcePositionTable* source_positions, Frame* frame, EnableSwitchJumpTable enable_switch_jump_table, - EnableSpeculationPoison enable_speculation_poison, SourcePositionMode source_position_mode, Features features, EnableScheduling enable_scheduling, - EnableSerialization enable_serialization, LoadPoisoning load_poisoning) + EnableSerialization enable_serialization, + PoisoningMitigationLevel poisoning_enabled) : zone_(zone), linkage_(linkage), sequence_(sequence), @@ -38,6 +38,8 @@ InstructionSelector::InstructionSelector( schedule_(schedule), current_block_(nullptr), instructions_(zone), + continuation_inputs_(sequence->zone()), + continuation_outputs_(sequence->zone()), defined_(node_count, false, zone), used_(node_count, false, zone), effect_level_(node_count, 0, zone), @@ -48,11 +50,12 @@ InstructionSelector::InstructionSelector( enable_scheduling_(enable_scheduling), enable_serialization_(enable_serialization), enable_switch_jump_table_(enable_switch_jump_table), - enable_speculation_poison_(enable_speculation_poison), - load_poisoning_(load_poisoning), + poisoning_enabled_(poisoning_enabled), frame_(frame), instruction_selection_failed_(false) { instructions_.reserve(node_count); + continuation_inputs_.reserve(5); + continuation_outputs_.reserve(2); } bool InstructionSelector::SelectInstructions() { @@ -92,9 +95,13 @@ bool InstructionSelector::SelectInstructions() { size_t start = instruction_block->code_start(); DCHECK_LE(end, start); StartBlock(RpoNumber::FromInt(block->rpo_number())); - while (start-- > end) { - UpdateRenames(instructions_[start]); - AddInstruction(instructions_[start]); + if (end != start) { + while (start-- > end + 1) { + UpdateRenames(instructions_[start]); + AddInstruction(instructions_[start]); + } + UpdateRenames(instructions_[end]); + AddTerminator(instructions_[end]); } EndBlock(RpoNumber::FromInt(block->rpo_number())); } @@ -123,6 +130,14 @@ void InstructionSelector::EndBlock(RpoNumber rpo) { } } +void InstructionSelector::AddTerminator(Instruction* instr) { + if (UseInstructionScheduling()) { + DCHECK_NOT_NULL(scheduler_); + scheduler_->AddTerminator(instr); + } else { + sequence()->AddInstruction(instr); + } +} void InstructionSelector::AddInstruction(Instruction* instr) { if (UseInstructionScheduling()) { @@ -448,7 +463,7 @@ InstructionOperand OperandForDeopt(Isolate* isolate, OperandGenerator* g, return InstructionOperand(); } - Handle<HeapObject> constant = OpParameter<Handle<HeapObject>>(input); + Handle<HeapObject> constant = HeapConstantOf(input->op()); Heap::RootListIndex root_index; if (isolate->heap()->IsRootHandle(constant, &root_index) && root_index == Heap::kOptimizedOutRootIndex) { @@ -651,6 +666,105 @@ size_t InstructionSelector::AddInputsToFrameStateDescriptor( return entries; } +Instruction* InstructionSelector::EmitWithContinuation( + InstructionCode opcode, FlagsContinuation* cont) { + return EmitWithContinuation(opcode, 0, nullptr, 0, nullptr, cont); +} + +Instruction* InstructionSelector::EmitWithContinuation( + InstructionCode opcode, InstructionOperand a, FlagsContinuation* cont) { + return EmitWithContinuation(opcode, 0, nullptr, 1, &a, cont); +} + +Instruction* InstructionSelector::EmitWithContinuation( + InstructionCode opcode, InstructionOperand a, InstructionOperand b, + FlagsContinuation* cont) { + InstructionOperand inputs[] = {a, b}; + return EmitWithContinuation(opcode, 0, nullptr, arraysize(inputs), inputs, + cont); +} + +Instruction* InstructionSelector::EmitWithContinuation( + InstructionCode opcode, InstructionOperand a, InstructionOperand b, + InstructionOperand c, FlagsContinuation* cont) { + InstructionOperand inputs[] = {a, b, c}; + return EmitWithContinuation(opcode, 0, nullptr, arraysize(inputs), inputs, + cont); +} + +Instruction* InstructionSelector::EmitWithContinuation( + InstructionCode opcode, size_t output_count, InstructionOperand* outputs, + size_t input_count, InstructionOperand* inputs, FlagsContinuation* cont) { + OperandGenerator g(this); + + opcode = cont->Encode(opcode); + + continuation_inputs_.resize(0); + for (size_t i = 0; i < input_count; i++) { + continuation_inputs_.push_back(inputs[i]); + } + + continuation_outputs_.resize(0); + for (size_t i = 0; i < output_count; i++) { + continuation_outputs_.push_back(outputs[i]); + } + + if (cont->IsBranch()) { + continuation_inputs_.push_back(g.Label(cont->true_block())); + continuation_inputs_.push_back(g.Label(cont->false_block())); + } else if (cont->IsDeoptimize()) { + opcode |= MiscField::encode(static_cast<int>(input_count)); + AppendDeoptimizeArguments(&continuation_inputs_, cont->kind(), + cont->reason(), cont->feedback(), + cont->frame_state()); + } else if (cont->IsSet()) { + continuation_outputs_.push_back(g.DefineAsRegister(cont->result())); + } else if (cont->IsTrap()) { + continuation_inputs_.push_back(g.UseImmediate(cont->trap_id())); + } else { + DCHECK(cont->IsNone()); + } + + size_t const emit_inputs_size = continuation_inputs_.size(); + auto* emit_inputs = + emit_inputs_size ? &continuation_inputs_.front() : nullptr; + size_t const emit_outputs_size = continuation_outputs_.size(); + auto* emit_outputs = + emit_outputs_size ? &continuation_outputs_.front() : nullptr; + return Emit(opcode, emit_outputs_size, emit_outputs, emit_inputs_size, + emit_inputs, 0, nullptr); +} + +void InstructionSelector::AppendDeoptimizeArguments( + InstructionOperandVector* args, DeoptimizeKind kind, + DeoptimizeReason reason, VectorSlotPair const& feedback, + Node* frame_state) { + OperandGenerator g(this); + FrameStateDescriptor* const descriptor = GetFrameStateDescriptor(frame_state); + DCHECK_NE(DeoptimizeKind::kLazy, kind); + int const state_id = + sequence()->AddDeoptimizationEntry(descriptor, kind, reason, feedback); + args->push_back(g.TempImmediate(state_id)); + StateObjectDeduplicator deduplicator(instruction_zone()); + AddInputsToFrameStateDescriptor(descriptor, frame_state, &g, &deduplicator, + args, FrameStateInputKind::kAny, + instruction_zone()); +} + +Instruction* InstructionSelector::EmitDeoptimize( + InstructionCode opcode, size_t output_count, InstructionOperand* outputs, + size_t input_count, InstructionOperand* inputs, DeoptimizeKind kind, + DeoptimizeReason reason, VectorSlotPair const& feedback, + Node* frame_state) { + InstructionOperandVector args(instruction_zone()); + for (size_t i = 0; i < input_count; ++i) { + args.push_back(inputs[i]); + } + opcode |= MiscField::encode(static_cast<int>(input_count)); + AppendDeoptimizeArguments(&args, kind, reason, feedback, frame_state); + return Emit(opcode, output_count, outputs, args.size(), &args.front(), 0, + nullptr); +} // An internal helper class for generating the operands to calls. // TODO(bmeurer): Get rid of the CallBuffer business and make @@ -776,12 +890,8 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, ? g.UseImmediate(callee) : call_use_fixed_target_reg ? g.UseFixed(callee, kJavaScriptCallCodeStartRegister) -#ifdef V8_EMBEDDED_BUILTINS : is_tail_call ? g.UseUniqueRegister(callee) : g.UseRegister(callee)); -#else - : g.UseRegister(callee)); -#endif break; case CallDescriptor::kCallAddress: buffer->instruction_args.push_back( @@ -809,10 +919,17 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, } DCHECK_EQ(1u, buffer->instruction_args.size()); + // Argument 1 is used for poison-alias index (encoded in a word-sized + // immediate. This an index of the operand that aliases with poison register + // or -1 if there is no aliasing. + buffer->instruction_args.push_back(g.TempImmediate(-1)); + const size_t poison_alias_index = 1; + DCHECK_EQ(buffer->instruction_args.size() - 1, poison_alias_index); + // If the call needs a frame state, we insert the state information as // follows (n is the number of value inputs to the frame state): - // arg 1 : deoptimization id. - // arg 2 - arg (n + 1) : value inputs to the frame state. + // arg 2 : deoptimization id. + // arg 3 - arg (n + 2) : value inputs to the frame state. size_t frame_state_entries = 0; USE(frame_state_entries); // frame_state_entries is only used for debug. if (buffer->frame_state_descriptor != nullptr) { @@ -848,7 +965,7 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, &buffer->instruction_args, FrameStateInputKind::kStackSlot, instruction_zone()); - DCHECK_EQ(1 + frame_state_entries, buffer->instruction_args.size()); + DCHECK_EQ(2 + frame_state_entries, buffer->instruction_args.size()); } size_t input_count = static_cast<size_t>(buffer->input_count()); @@ -871,8 +988,9 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, location, stack_param_delta); } InstructionOperand op = g.UseLocation(*iter, location); - if (UnallocatedOperand::cast(op).HasFixedSlotPolicy() && !call_tail) { - int stack_index = -UnallocatedOperand::cast(op).fixed_slot_index() - 1; + UnallocatedOperand unallocated = UnallocatedOperand::cast(op); + if (unallocated.HasFixedSlotPolicy() && !call_tail) { + int stack_index = -unallocated.fixed_slot_index() - 1; if (static_cast<size_t>(stack_index) >= buffer->pushed_nodes.size()) { buffer->pushed_nodes.resize(stack_index + 1); } @@ -880,11 +998,23 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, buffer->pushed_nodes[stack_index] = param; pushed_count++; } else { + // If we do load poisoning and the linkage uses the poisoning register, + // then we request the input in memory location, and during code + // generation, we move the input to the register. + if (poisoning_enabled_ != PoisoningMitigationLevel::kOff && + unallocated.HasFixedRegisterPolicy()) { + int reg = unallocated.fixed_register_index(); + if (reg == kSpeculationPoisonRegister.code()) { + buffer->instruction_args[poison_alias_index] = g.TempImmediate( + static_cast<int32_t>(buffer->instruction_args.size())); + op = g.UseRegisterOrSlotOrConstant(*iter); + } + } buffer->instruction_args.push_back(op); } } DCHECK_EQ(input_count, buffer->instruction_args.size() + pushed_count - - frame_state_entries); + frame_state_entries - 1); if (V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK && call_tail && stack_param_delta != 0) { // For tail calls that change the size of their parameter list and keep @@ -1023,33 +1153,24 @@ void InstructionSelector::VisitControl(BasicBlock* block) { } case BasicBlock::kSwitch: { DCHECK_EQ(IrOpcode::kSwitch, input->opcode()); - SwitchInfo sw; - // Last successor must be Default. - sw.default_branch = block->successors().back(); - DCHECK_EQ(IrOpcode::kIfDefault, sw.default_branch->front()->opcode()); - // All other successors must be cases. - sw.case_count = block->SuccessorCount() - 1; - sw.case_branches = &block->successors().front(); - // Determine case values and their min/max. - sw.case_values = zone()->NewArray<int32_t>(sw.case_count); - sw.min_value = std::numeric_limits<int32_t>::max(); - sw.max_value = std::numeric_limits<int32_t>::min(); - for (size_t index = 0; index < sw.case_count; ++index) { - BasicBlock* branch = sw.case_branches[index]; - int32_t value = OpParameter<int32_t>(branch->front()->op()); - sw.case_values[index] = value; - if (sw.min_value > value) sw.min_value = value; - if (sw.max_value < value) sw.max_value = value; - } - if (sw.case_count != 0) { - DCHECK_LE(sw.min_value, sw.max_value); - // Note that {value_range} can be 0 if {min_value} is -2^31 and - // {max_value} is 2^31-1, so don't assume that it's non-zero below. - sw.value_range = 1u + bit_cast<uint32_t>(sw.max_value) - - bit_cast<uint32_t>(sw.min_value); - } else { - sw.value_range = 0; + // Last successor must be {IfDefault}. + BasicBlock* default_branch = block->successors().back(); + DCHECK_EQ(IrOpcode::kIfDefault, default_branch->front()->opcode()); + // All other successors must be {IfValue}s. + int32_t min_value = std::numeric_limits<int32_t>::max(); + int32_t max_value = std::numeric_limits<int32_t>::min(); + size_t case_count = block->SuccessorCount() - 1; + ZoneVector<CaseInfo> cases(case_count, zone()); + for (size_t i = 0; i < case_count; ++i) { + BasicBlock* branch = block->SuccessorAt(i); + const IfValueParameters& p = IfValueParametersOf(branch->front()->op()); + cases[i] = CaseInfo{p.value(), p.comparison_order(), branch}; + if (min_value > p.value()) min_value = p.value(); + if (max_value < p.value()) max_value = p.value(); } + // Ensure that comparison order of if-cascades is preserved. + std::stable_sort(cases.begin(), cases.end()); + SwitchInfo sw(cases, min_value, max_value, default_branch); return VisitSwitch(input, sw); } case BasicBlock::kReturn: { @@ -1138,7 +1259,7 @@ void InstructionSelector::VisitNode(Node* node) { case IrOpcode::kHeapConstant: return MarkAsReference(node), VisitConstant(node); case IrOpcode::kNumberConstant: { - double value = OpParameter<double>(node); + double value = OpParameter<double>(node->op()); if (!IsSmiDouble(value)) MarkAsReference(node); return VisitConstant(node); } @@ -1497,8 +1618,11 @@ void InstructionSelector::VisitNode(Node* node) { return MarkAsFloat64(node), VisitFloat64InsertLowWord32(node); case IrOpcode::kFloat64InsertHighWord32: return MarkAsFloat64(node), VisitFloat64InsertHighWord32(node); - case IrOpcode::kSpeculationPoison: - return VisitSpeculationPoison(node); + case IrOpcode::kPoisonOnSpeculationTagged: + return MarkAsReference(node), VisitPoisonOnSpeculationTagged(node); + case IrOpcode::kPoisonOnSpeculationWord: + return MarkAsRepresentation(MachineType::PointerRepresentation(), node), + VisitPoisonOnSpeculationWord(node); case IrOpcode::kStackSlot: return VisitStackSlot(node); case IrOpcode::kLoadStackPointer: @@ -1507,9 +1631,10 @@ void InstructionSelector::VisitNode(Node* node) { return VisitLoadFramePointer(node); case IrOpcode::kLoadParentFramePointer: return VisitLoadParentFramePointer(node); + case IrOpcode::kLoadRootsPointer: + return VisitLoadRootsPointer(node); case IrOpcode::kUnalignedLoad: { - UnalignedLoadRepresentation type = - UnalignedLoadRepresentationOf(node->op()); + LoadRepresentation type = LoadRepresentationOf(node->op()); MarkAsRepresentation(type.representation(), node); return VisitUnalignedLoad(node); } @@ -1544,21 +1669,35 @@ void InstructionSelector::VisitNode(Node* node) { MarkAsRepresentation(type.representation(), node); return VisitWord32AtomicLoad(node); } + case IrOpcode::kWord64AtomicLoad: { + LoadRepresentation type = LoadRepresentationOf(node->op()); + MarkAsRepresentation(type.representation(), node); + return VisitWord64AtomicLoad(node); + } case IrOpcode::kWord32AtomicStore: return VisitWord32AtomicStore(node); -#define ATOMIC_CASE(name) \ - case IrOpcode::kWord32Atomic##name: { \ + case IrOpcode::kWord64AtomicStore: + return VisitWord64AtomicStore(node); +#define ATOMIC_CASE(name, rep) \ + case IrOpcode::k##rep##Atomic##name: { \ MachineType type = AtomicOpRepresentationOf(node->op()); \ MarkAsRepresentation(type.representation(), node); \ - return VisitWord32Atomic##name(node); \ - } - ATOMIC_CASE(Exchange) - ATOMIC_CASE(CompareExchange) - ATOMIC_CASE(Add) - ATOMIC_CASE(Sub) - ATOMIC_CASE(And) - ATOMIC_CASE(Or) - ATOMIC_CASE(Xor) + return Visit##rep##Atomic##name(node); \ + } + ATOMIC_CASE(Add, Word32) + ATOMIC_CASE(Add, Word64) + ATOMIC_CASE(Sub, Word32) + ATOMIC_CASE(Sub, Word64) + ATOMIC_CASE(And, Word32) + ATOMIC_CASE(And, Word64) + ATOMIC_CASE(Or, Word32) + ATOMIC_CASE(Or, Word64) + ATOMIC_CASE(Xor, Word32) + ATOMIC_CASE(Xor, Word64) + ATOMIC_CASE(Exchange, Word32) + ATOMIC_CASE(Exchange, Word64) + ATOMIC_CASE(CompareExchange, Word32) + ATOMIC_CASE(CompareExchange, Word64) #undef ATOMIC_CASE case IrOpcode::kSpeculationFence: return VisitSpeculationFence(node); @@ -1819,12 +1958,20 @@ void InstructionSelector::VisitNode(Node* node) { } } -void InstructionSelector::VisitSpeculationPoison(Node* node) { - CHECK(enable_speculation_poison_ == kEnableSpeculationPoison); - OperandGenerator g(this); - Emit(kArchNop, g.DefineAsLocation(node, LinkageLocation::ForRegister( - kSpeculationPoisonRegister.code(), - MachineType::UintPtr()))); +void InstructionSelector::VisitPoisonOnSpeculationWord(Node* node) { + if (poisoning_enabled_ != PoisoningMitigationLevel::kOff) { + OperandGenerator g(this); + Node* input_node = NodeProperties::GetValueInput(node, 0); + InstructionOperand input = g.UseRegister(input_node); + InstructionOperand output = g.DefineSameAsFirst(node); + Emit(kArchPoisonOnSpeculationWord, output, input); + } else { + EmitIdentity(node); + } +} + +void InstructionSelector::VisitPoisonOnSpeculationTagged(Node* node) { + VisitPoisonOnSpeculationWord(node); } void InstructionSelector::VisitLoadStackPointer(Node* node) { @@ -1842,6 +1989,11 @@ void InstructionSelector::VisitLoadParentFramePointer(Node* node) { Emit(kArchParentFramePointer, g.DefineAsRegister(node)); } +void InstructionSelector::VisitLoadRootsPointer(Node* node) { + OperandGenerator g(this); + Emit(kArchRootsPointer, g.DefineAsRegister(node)); +} + void InstructionSelector::VisitFloat64Acos(Node* node) { VisitFloat64Ieee754Unop(node, kIeee754Float64Acos); } @@ -1929,18 +2081,18 @@ void InstructionSelector::VisitFloat64Tanh(Node* node) { void InstructionSelector::EmitTableSwitch(const SwitchInfo& sw, InstructionOperand& index_operand) { OperandGenerator g(this); - size_t input_count = 2 + sw.value_range; - DCHECK_LE(sw.value_range, std::numeric_limits<size_t>::max() - 2); + size_t input_count = 2 + sw.value_range(); + DCHECK_LE(sw.value_range(), std::numeric_limits<size_t>::max() - 2); auto* inputs = zone()->NewArray<InstructionOperand>(input_count); inputs[0] = index_operand; - InstructionOperand default_operand = g.Label(sw.default_branch); + InstructionOperand default_operand = g.Label(sw.default_branch()); std::fill(&inputs[1], &inputs[input_count], default_operand); - for (size_t index = 0; index < sw.case_count; ++index) { - size_t value = sw.case_values[index] - sw.min_value; - BasicBlock* branch = sw.case_branches[index]; + for (size_t index = 0; index < sw.case_count(); ++index) { + const CaseInfo& c = sw.GetCase(index); + size_t value = c.value - sw.min_value(); DCHECK_LE(0u, value); DCHECK_LT(value + 2, input_count); - inputs[value + 2] = g.Label(branch); + inputs[value + 2] = g.Label(c.branch); } Emit(kArchTableSwitch, 0, nullptr, input_count, inputs, 0, nullptr); } @@ -1949,16 +2101,15 @@ void InstructionSelector::EmitTableSwitch(const SwitchInfo& sw, void InstructionSelector::EmitLookupSwitch(const SwitchInfo& sw, InstructionOperand& value_operand) { OperandGenerator g(this); - size_t input_count = 2 + sw.case_count * 2; - DCHECK_LE(sw.case_count, (std::numeric_limits<size_t>::max() - 2) / 2); + size_t input_count = 2 + sw.case_count() * 2; + DCHECK_LE(sw.case_count(), (std::numeric_limits<size_t>::max() - 2) / 2); auto* inputs = zone()->NewArray<InstructionOperand>(input_count); inputs[0] = value_operand; - inputs[1] = g.Label(sw.default_branch); - for (size_t index = 0; index < sw.case_count; ++index) { - int32_t value = sw.case_values[index]; - BasicBlock* branch = sw.case_branches[index]; - inputs[index * 2 + 2 + 0] = g.TempImmediate(value); - inputs[index * 2 + 2 + 1] = g.Label(branch); + inputs[1] = g.Label(sw.default_branch()); + for (size_t index = 0; index < sw.case_count(); ++index) { + const CaseInfo& c = sw.GetCase(index); + inputs[index * 2 + 2 + 0] = g.TempImmediate(c.value); + inputs[index * 2 + 2 + 1] = g.Label(c.branch); } Emit(kArchLookupSwitch, 0, nullptr, input_count, inputs, 0, nullptr); } @@ -2155,7 +2306,7 @@ void InstructionSelector::VisitWord32PairSar(Node* node) { UNIMPLEMENTED(); } #endif // V8_TARGET_ARCH_64_BIT #if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_MIPS && \ - !V8_TARGET_ARCH_MIPS64 + !V8_TARGET_ARCH_MIPS64 && !V8_TARGET_ARCH_IA32 void InstructionSelector::VisitF32x4SConvertI32x4(Node* node) { UNIMPLEMENTED(); } @@ -2164,19 +2315,37 @@ void InstructionSelector::VisitF32x4UConvertI32x4(Node* node) { UNIMPLEMENTED(); } #endif // !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_MIPS - // && !V8_TARGET_ARCH_MIPS64 + // && !V8_TARGET_ARCH_MIPS64 && !V8_TARGET_ARCH_IA32 -#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_MIPS && \ - !V8_TARGET_ARCH_MIPS64 && !V8_TARGET_ARCH_X64 -void InstructionSelector::VisitF32x4RecipApprox(Node* node) { UNIMPLEMENTED(); } +#if !V8_TARGET_ARCH_X64 +void InstructionSelector::VisitWord64AtomicLoad(Node* node) { UNIMPLEMENTED(); } -void InstructionSelector::VisitF32x4RecipSqrtApprox(Node* node) { +void InstructionSelector::VisitWord64AtomicStore(Node* node) { UNIMPLEMENTED(); } +#endif // !V8_TARGET_ARCH_X64 + +#if !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_ARM64 +void InstructionSelector::VisitWord64AtomicAdd(Node* node) { UNIMPLEMENTED(); } + +void InstructionSelector::VisitWord64AtomicSub(Node* node) { UNIMPLEMENTED(); } + +void InstructionSelector::VisitWord64AtomicAnd(Node* node) { UNIMPLEMENTED(); } + +void InstructionSelector::VisitWord64AtomicOr(Node* node) { UNIMPLEMENTED(); } -void InstructionSelector::VisitF32x4AddHoriz(Node* node) { UNIMPLEMENTED(); } -#endif // !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_X64 - // && !V8_TARGET_ARCH_MIPS && !V8_TARGET_ARCH_MIPS64 +void InstructionSelector::VisitWord64AtomicXor(Node* node) { UNIMPLEMENTED(); } +#endif // !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_ARM64 + +#if !V8_TARGET_ARCH_X64 +void InstructionSelector::VisitWord64AtomicExchange(Node* node) { + UNIMPLEMENTED(); +} + +void InstructionSelector::VisitWord64AtomicCompareExchange(Node* node) { + UNIMPLEMENTED(); +} +#endif // !V8_TARGET_ARCH_X64 #if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_MIPS && \ !V8_TARGET_ARCH_MIPS64 @@ -2191,12 +2360,6 @@ void InstructionSelector::VisitI32x4UConvertF32x4(Node* node) { // && !V8_TARGET_ARCH_MIPS64 #if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_MIPS && \ - !V8_TARGET_ARCH_MIPS64 && !V8_TARGET_ARCH_X64 -void InstructionSelector::VisitI32x4AddHoriz(Node* node) { UNIMPLEMENTED(); } -#endif // !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_MIPS - // && !V8_TARGET_ARCH_MIPS64 && !V8_TARGET_ARCH_X64 - -#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_MIPS && \ !V8_TARGET_ARCH_MIPS64 void InstructionSelector::VisitI32x4SConvertI16x8Low(Node* node) { UNIMPLEMENTED(); @@ -2228,12 +2391,6 @@ void InstructionSelector::VisitI16x8SConvertI32x4(Node* node) { #endif // !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_MIPS // && !V8_TARGET_ARCH_MIPS64 -#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_X64 && \ - !V8_TARGET_ARCH_MIPS && !V8_TARGET_ARCH_MIPS64 -void InstructionSelector::VisitI16x8AddHoriz(Node* node) { UNIMPLEMENTED(); } -#endif // !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_X64 - // && !V8_TARGET_ARCH_MIPS && !V8_TARGET_ARCH_MIPS64 - #if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_MIPS && \ !V8_TARGET_ARCH_MIPS64 void InstructionSelector::VisitI16x8UConvertI32x4(Node* node) { @@ -2267,13 +2424,13 @@ void InstructionSelector::VisitI8x16ShrS(Node* node) { UNIMPLEMENTED(); } void InstructionSelector::VisitI8x16ShrU(Node* node) { UNIMPLEMENTED(); } void InstructionSelector::VisitI8x16Mul(Node* node) { UNIMPLEMENTED(); } + +void InstructionSelector::VisitS8x16Shuffle(Node* node) { UNIMPLEMENTED(); } #endif // !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_MIPS // && !V8_TARGET_ARCH_MIPS64 && !V8_TARGET_ARCH_IA32 #if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_MIPS && \ !V8_TARGET_ARCH_MIPS64 -void InstructionSelector::VisitS8x16Shuffle(Node* node) { UNIMPLEMENTED(); } - void InstructionSelector::VisitS1x4AnyTrue(Node* node) { UNIMPLEMENTED(); } void InstructionSelector::VisitS1x4AllTrue(Node* node) { UNIMPLEMENTED(); } @@ -2559,33 +2716,31 @@ void InstructionSelector::VisitReturn(Node* ret) { void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, BasicBlock* fbranch) { - LoadPoisoning poisoning = - IsSafetyCheckOf(branch->op()) == IsSafetyCheck::kSafetyCheck - ? load_poisoning_ - : LoadPoisoning::kDontPoison; + bool update_poison = + IsSafetyCheckOf(branch->op()) == IsSafetyCheck::kSafetyCheck && + poisoning_enabled_ == PoisoningMitigationLevel::kOn; FlagsContinuation cont = - FlagsContinuation::ForBranch(kNotEqual, tbranch, fbranch, poisoning); + FlagsContinuation::ForBranch(kNotEqual, tbranch, fbranch, update_poison); VisitWordCompareZero(branch, branch->InputAt(0), &cont); } void InstructionSelector::VisitDeoptimizeIf(Node* node) { DeoptimizeParameters p = DeoptimizeParametersOf(node->op()); - LoadPoisoning poisoning = p.is_safety_check() == IsSafetyCheck::kSafetyCheck - ? load_poisoning_ - : LoadPoisoning::kDontPoison; + bool update_poison = p.is_safety_check() == IsSafetyCheck::kSafetyCheck && + poisoning_enabled_ == PoisoningMitigationLevel::kOn; FlagsContinuation cont = FlagsContinuation::ForDeoptimize( kNotEqual, p.kind(), p.reason(), p.feedback(), node->InputAt(1), - poisoning); + update_poison); VisitWordCompareZero(node, node->InputAt(0), &cont); } void InstructionSelector::VisitDeoptimizeUnless(Node* node) { DeoptimizeParameters p = DeoptimizeParametersOf(node->op()); - LoadPoisoning poisoning = p.is_safety_check() == IsSafetyCheck::kSafetyCheck - ? load_poisoning_ - : LoadPoisoning::kDontPoison; + bool update_poison = p.is_safety_check() == IsSafetyCheck::kSafetyCheck && + poisoning_enabled_ == PoisoningMitigationLevel::kOn; FlagsContinuation cont = FlagsContinuation::ForDeoptimize( - kEqual, p.kind(), p.reason(), p.feedback(), node->InputAt(1), poisoning); + kEqual, p.kind(), p.reason(), p.feedback(), node->InputAt(1), + update_poison); VisitWordCompareZero(node, node->InputAt(0), &cont); } @@ -2602,53 +2757,6 @@ void InstructionSelector::VisitTrapUnless(Node* node, VisitWordCompareZero(node, node->InputAt(0), &cont); } -Instruction* InstructionSelector::EmitDeoptimize( - InstructionCode opcode, InstructionOperand output, InstructionOperand a, - DeoptimizeKind kind, DeoptimizeReason reason, - VectorSlotPair const& feedback, Node* frame_state) { - size_t output_count = output.IsInvalid() ? 0 : 1; - InstructionOperand inputs[] = {a}; - size_t input_count = arraysize(inputs); - return EmitDeoptimize(opcode, output_count, &output, input_count, inputs, - kind, reason, feedback, frame_state); -} - -Instruction* InstructionSelector::EmitDeoptimize( - InstructionCode opcode, InstructionOperand output, InstructionOperand a, - InstructionOperand b, DeoptimizeKind kind, DeoptimizeReason reason, - VectorSlotPair const& feedback, Node* frame_state) { - size_t output_count = output.IsInvalid() ? 0 : 1; - InstructionOperand inputs[] = {a, b}; - size_t input_count = arraysize(inputs); - return EmitDeoptimize(opcode, output_count, &output, input_count, inputs, - kind, reason, feedback, frame_state); -} - -Instruction* InstructionSelector::EmitDeoptimize( - InstructionCode opcode, size_t output_count, InstructionOperand* outputs, - size_t input_count, InstructionOperand* inputs, DeoptimizeKind kind, - DeoptimizeReason reason, VectorSlotPair const& feedback, - Node* frame_state) { - OperandGenerator g(this); - FrameStateDescriptor* const descriptor = GetFrameStateDescriptor(frame_state); - InstructionOperandVector args(instruction_zone()); - args.reserve(input_count + 1 + descriptor->GetTotalSize()); - for (size_t i = 0; i < input_count; ++i) { - args.push_back(inputs[i]); - } - opcode |= MiscField::encode(static_cast<int>(input_count)); - DCHECK_NE(DeoptimizeKind::kLazy, kind); - int const state_id = - sequence()->AddDeoptimizationEntry(descriptor, kind, reason, feedback); - args.push_back(g.TempImmediate(state_id)); - StateObjectDeduplicator deduplicator(instruction_zone()); - AddInputsToFrameStateDescriptor(descriptor, frame_state, &g, &deduplicator, - &args, FrameStateInputKind::kAny, - instruction_zone()); - return Emit(opcode, output_count, outputs, args.size(), &args.front(), 0, - nullptr); -} - void InstructionSelector::EmitIdentity(Node* node) { OperandGenerator g(this); MarkAsUsed(node->InputAt(0)); @@ -2717,7 +2825,7 @@ FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor( Node* state) { DCHECK_EQ(IrOpcode::kFrameState, state->opcode()); DCHECK_EQ(kFrameStateInputCount, state->InputCount()); - FrameStateInfo state_info = OpParameter<FrameStateInfo>(state); + FrameStateInfo state_info = FrameStateInfoOf(state->op()); int parameters = static_cast<int>( StateValuesAccess(state->InputAt(kFrameStateParametersInput)).size()); @@ -2776,7 +2884,7 @@ uint8_t InstructionSelector::CanonicalizeShuffle(Node* node) { static const int kMaxLaneIndex = 15; static const int kMaxShuffleIndex = 31; - const uint8_t* shuffle = OpParameter<uint8_t*>(node); + const uint8_t* shuffle = OpParameter<uint8_t*>(node->op()); uint8_t mask = kMaxShuffleIndex; // If shuffle is unary, set 'mask' to ignore the high bit of the indices. // Replace any unused source with the other. |