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