diff options
Diffstat (limited to 'deps/v8/src/compiler/instruction-selector.cc')
-rw-r--r-- | deps/v8/src/compiler/instruction-selector.cc | 261 |
1 files changed, 206 insertions, 55 deletions
diff --git a/deps/v8/src/compiler/instruction-selector.cc b/deps/v8/src/compiler/instruction-selector.cc index 8f899f3c8c..ae96b9106f 100644 --- a/deps/v8/src/compiler/instruction-selector.cc +++ b/deps/v8/src/compiler/instruction-selector.cc @@ -127,7 +127,6 @@ void InstructionSelector::AddInstruction(Instruction* instr) { } } - Instruction* InstructionSelector::Emit(InstructionCode opcode, InstructionOperand output, size_t temp_count, @@ -414,13 +413,10 @@ void InstructionSelector::MarkAsRepresentation(MachineRepresentation rep, sequence()->MarkAsRepresentation(rep, GetVirtualRegister(node)); } - namespace { -enum class FrameStateInputKind { kAny, kStackSlot }; - -InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input, - FrameStateInputKind kind, +InstructionOperand OperandForDeopt(Isolate* isolate, OperandGenerator* g, + Node* input, FrameStateInputKind kind, MachineRepresentation rep) { if (rep == MachineRepresentation::kNone) { return g->TempImmediate(FrameStateDescriptor::kImpossibleValue); @@ -432,8 +428,30 @@ InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input, case IrOpcode::kNumberConstant: case IrOpcode::kFloat32Constant: case IrOpcode::kFloat64Constant: - case IrOpcode::kHeapConstant: return g->UseImmediate(input); + case IrOpcode::kHeapConstant: { + if (!CanBeTaggedPointer(rep)) { + // If we have inconsistent static and dynamic types, e.g. if we + // smi-check a string, we can get here with a heap object that + // says it is a smi. In that case, we return an invalid instruction + // operand, which will be interpreted as an optimized-out value. + + // TODO(jarin) Ideally, we should turn the current instruction + // into an abort (we should never execute it). + return InstructionOperand(); + } + + Handle<HeapObject> constant = OpParameter<Handle<HeapObject>>(input); + Heap::RootListIndex root_index; + if (isolate->heap()->IsRootHandle(constant, &root_index) && + root_index == Heap::kOptimizedOutRootIndex) { + // For an optimized-out object we return an invalid instruction + // operand, so that we take the fast path for optimized-out values. + return InstructionOperand(); + } + + return g->UseImmediate(input); + } case IrOpcode::kObjectState: case IrOpcode::kTypedObjectState: UNREACHABLE(); @@ -452,6 +470,7 @@ InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input, return InstructionOperand(); } +} // namespace class StateObjectDeduplicator { public: @@ -477,14 +496,16 @@ class StateObjectDeduplicator { ZoneVector<Node*> objects_; }; - // Returns the number of instruction operands added to inputs. -size_t AddOperandToStateValueDescriptor(StateValueDescriptor* descriptor, - InstructionOperandVector* inputs, - OperandGenerator* g, - StateObjectDeduplicator* deduplicator, - Node* input, MachineType type, - FrameStateInputKind kind, Zone* zone) { +size_t InstructionSelector::AddOperandToStateValueDescriptor( + StateValueList* values, InstructionOperandVector* inputs, + OperandGenerator* g, StateObjectDeduplicator* deduplicator, Node* input, + MachineType type, FrameStateInputKind kind, Zone* zone) { + if (input == nullptr) { + values->PushOptimizedOut(); + return 0; + } + switch (input->opcode()) { case IrOpcode::kObjectState: { UNREACHABLE(); @@ -495,41 +516,45 @@ size_t AddOperandToStateValueDescriptor(StateValueDescriptor* descriptor, if (id == StateObjectDeduplicator::kNotDuplicated) { size_t entries = 0; id = deduplicator->InsertObject(input); - descriptor->fields().push_back( - StateValueDescriptor::Recursive(zone, id)); - StateValueDescriptor* new_desc = &descriptor->fields().back(); + StateValueList* nested = values->PushRecursiveField(zone, id); int const input_count = input->op()->ValueInputCount(); ZoneVector<MachineType> const* types = MachineTypesOf(input->op()); for (int i = 0; i < input_count; ++i) { entries += AddOperandToStateValueDescriptor( - new_desc, inputs, g, deduplicator, input->InputAt(i), - types->at(i), kind, zone); + nested, inputs, g, deduplicator, input->InputAt(i), types->at(i), + kind, zone); } return entries; } else { // Crankshaft counts duplicate objects for the running id, so we have // to push the input again. deduplicator->InsertObject(input); - descriptor->fields().push_back( - StateValueDescriptor::Duplicate(zone, id)); + values->PushDuplicate(id); return 0; } } default: { - inputs->push_back(OperandForDeopt(g, input, kind, type.representation())); - descriptor->fields().push_back(StateValueDescriptor::Plain(zone, type)); - return 1; + InstructionOperand op = + OperandForDeopt(isolate(), g, input, kind, type.representation()); + if (op.kind() == InstructionOperand::INVALID) { + // Invalid operand means the value is impossible or optimized-out. + values->PushOptimizedOut(); + return 0; + } else { + inputs->push_back(op); + values->PushPlain(type); + return 1; + } } } } // Returns the number of instruction operands added to inputs. -size_t AddInputsToFrameStateDescriptor(FrameStateDescriptor* descriptor, - Node* state, OperandGenerator* g, - StateObjectDeduplicator* deduplicator, - InstructionOperandVector* inputs, - FrameStateInputKind kind, Zone* zone) { +size_t InstructionSelector::AddInputsToFrameStateDescriptor( + FrameStateDescriptor* descriptor, Node* state, OperandGenerator* g, + StateObjectDeduplicator* deduplicator, InstructionOperandVector* inputs, + FrameStateInputKind kind, Zone* zone) { DCHECK_EQ(IrOpcode::kFrameState, state->op()->opcode()); size_t entries = 0; @@ -553,8 +578,12 @@ size_t AddInputsToFrameStateDescriptor(FrameStateDescriptor* descriptor, DCHECK_EQ(descriptor->locals_count(), StateValuesAccess(locals).size()); DCHECK_EQ(descriptor->stack_count(), StateValuesAccess(stack).size()); - StateValueDescriptor* values_descriptor = - descriptor->GetStateValueDescriptor(); + StateValueList* values_descriptor = descriptor->GetStateValueDescriptors(); + + DCHECK_EQ(values_descriptor->size(), 0u); + values_descriptor->ReserveSize( + descriptor->GetSize(OutputFrameStateCombine::Ignore())); + entries += AddOperandToStateValueDescriptor( values_descriptor, inputs, g, deduplicator, function, MachineType::AnyTagged(), FrameStateInputKind::kStackSlot, zone); @@ -583,8 +612,6 @@ size_t AddInputsToFrameStateDescriptor(FrameStateDescriptor* descriptor, return entries; } -} // namespace - // An internal helper class for generating the operands to calls. // TODO(bmeurer): Get rid of the CallBuffer business and make @@ -796,17 +823,30 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, } } +bool InstructionSelector::IsSourcePositionUsed(Node* node) { + return (source_position_mode_ == kAllSourcePositions || + node->opcode() == IrOpcode::kCall || + node->opcode() == IrOpcode::kTrapIf || + node->opcode() == IrOpcode::kTrapUnless); +} + void InstructionSelector::VisitBlock(BasicBlock* block) { DCHECK(!current_block_); current_block_ = block; - int current_block_end = static_cast<int>(instructions_.size()); + auto current_num_instructions = [&] { + DCHECK_GE(kMaxInt, instructions_.size()); + return static_cast<int>(instructions_.size()); + }; + int current_block_end = current_num_instructions(); int effect_level = 0; for (Node* const node : *block) { if (node->opcode() == IrOpcode::kStore || node->opcode() == IrOpcode::kUnalignedStore || node->opcode() == IrOpcode::kCheckedStore || - node->opcode() == IrOpcode::kCall) { + node->opcode() == IrOpcode::kCall || + node->opcode() == IrOpcode::kProtectedLoad || + node->opcode() == IrOpcode::kProtectedStore) { ++effect_level; } SetEffectLevel(node, effect_level); @@ -818,10 +858,25 @@ void InstructionSelector::VisitBlock(BasicBlock* block) { SetEffectLevel(block->control_input(), effect_level); } + auto FinishEmittedInstructions = [&](Node* node, int instruction_start) { + if (instruction_selection_failed()) return false; + if (current_num_instructions() == instruction_start) return true; + std::reverse(instructions_.begin() + instruction_start, + instructions_.end()); + if (!node) return true; + SourcePosition source_position = source_positions_->GetSourcePosition(node); + if (source_position.IsKnown() && IsSourcePositionUsed(node)) { + sequence()->SetSourcePosition(instructions_[instruction_start], + source_position); + } + return true; + }; + // Generate code for the block control "top down", but schedule the code // "bottom up". VisitControl(block); - std::reverse(instructions_.begin() + current_block_end, instructions_.end()); + if (!FinishEmittedInstructions(block->control_input(), current_block_end)) + return; // Visit code in reverse control flow order, because architecture-specific // matching may cover more than one node at a time. @@ -830,19 +885,9 @@ void InstructionSelector::VisitBlock(BasicBlock* block) { if (!IsUsed(node) || IsDefined(node)) continue; // Generate code for this node "top down", but schedule the code "bottom // up". - size_t current_node_end = instructions_.size(); + int current_node_end = current_num_instructions(); VisitNode(node); - if (instruction_selection_failed()) return; - std::reverse(instructions_.begin() + current_node_end, instructions_.end()); - if (instructions_.size() == current_node_end) continue; - // Mark source position on first instruction emitted. - SourcePosition source_position = source_positions_->GetSourcePosition(node); - if (source_position.IsKnown() && - (source_position_mode_ == kAllSourcePositions || - node->opcode() == IrOpcode::kCall)) { - sequence()->SetSourcePosition(instructions_[current_node_end], - source_position); - } + if (!FinishEmittedInstructions(node, current_node_end)) return; } // We're done with the block. @@ -1013,6 +1058,12 @@ void InstructionSelector::VisitNode(Node* node) { return VisitDeoptimizeIf(node); case IrOpcode::kDeoptimizeUnless: return VisitDeoptimizeUnless(node); + case IrOpcode::kTrapIf: + return VisitTrapIf(node, static_cast<Runtime::FunctionId>( + OpParameter<int32_t>(node->op()))); + case IrOpcode::kTrapUnless: + return VisitTrapUnless(node, static_cast<Runtime::FunctionId>( + OpParameter<int32_t>(node->op()))); case IrOpcode::kFrameState: case IrOpcode::kStateValues: case IrOpcode::kObjectState: @@ -1033,6 +1084,8 @@ void InstructionSelector::VisitNode(Node* node) { } case IrOpcode::kStore: return VisitStore(node); + case IrOpcode::kProtectedStore: + return VisitProtectedStore(node); case IrOpcode::kWord32And: return MarkAsWord32(node), VisitWord32And(node); case IrOpcode::kWord32Or: @@ -1387,15 +1440,56 @@ void InstructionSelector::VisitNode(Node* node) { } case IrOpcode::kAtomicStore: return VisitAtomicStore(node); - case IrOpcode::kProtectedLoad: + case IrOpcode::kProtectedLoad: { + LoadRepresentation type = LoadRepresentationOf(node->op()); + MarkAsRepresentation(type.representation(), node); return VisitProtectedLoad(node); + } case IrOpcode::kUnsafePointerAdd: MarkAsRepresentation(MachineType::PointerRepresentation(), node); return VisitUnsafePointerAdd(node); + case IrOpcode::kCreateFloat32x4: + return MarkAsSimd128(node), VisitCreateFloat32x4(node); + case IrOpcode::kFloat32x4ExtractLane: + return MarkAsFloat32(node), VisitFloat32x4ExtractLane(node); + case IrOpcode::kFloat32x4ReplaceLane: + return MarkAsSimd128(node), VisitFloat32x4ReplaceLane(node); + case IrOpcode::kFloat32x4FromInt32x4: + return MarkAsSimd128(node), VisitFloat32x4FromInt32x4(node); + case IrOpcode::kFloat32x4FromUint32x4: + return MarkAsSimd128(node), VisitFloat32x4FromUint32x4(node); + case IrOpcode::kFloat32x4Abs: + return MarkAsSimd128(node), VisitFloat32x4Abs(node); + case IrOpcode::kFloat32x4Neg: + return MarkAsSimd128(node), VisitFloat32x4Neg(node); + case IrOpcode::kFloat32x4Add: + return MarkAsSimd128(node), VisitFloat32x4Add(node); + case IrOpcode::kFloat32x4Sub: + return MarkAsSimd128(node), VisitFloat32x4Sub(node); + case IrOpcode::kFloat32x4Equal: + return MarkAsSimd128(node), VisitFloat32x4Equal(node); + case IrOpcode::kFloat32x4NotEqual: + return MarkAsSimd128(node), VisitFloat32x4NotEqual(node); case IrOpcode::kCreateInt32x4: return MarkAsSimd128(node), VisitCreateInt32x4(node); case IrOpcode::kInt32x4ExtractLane: return MarkAsWord32(node), VisitInt32x4ExtractLane(node); + case IrOpcode::kInt32x4ReplaceLane: + return MarkAsSimd128(node), VisitInt32x4ReplaceLane(node); + case IrOpcode::kInt32x4FromFloat32x4: + return MarkAsSimd128(node), VisitInt32x4FromFloat32x4(node); + case IrOpcode::kUint32x4FromFloat32x4: + return MarkAsSimd128(node), VisitUint32x4FromFloat32x4(node); + case IrOpcode::kInt32x4Add: + return MarkAsSimd128(node), VisitInt32x4Add(node); + case IrOpcode::kInt32x4Sub: + return MarkAsSimd128(node), VisitInt32x4Sub(node); + case IrOpcode::kInt32x4Equal: + return MarkAsSimd128(node), VisitInt32x4Equal(node); + case IrOpcode::kInt32x4NotEqual: + return MarkAsSimd128(node), VisitInt32x4NotEqual(node); + case IrOpcode::kSimd32x4Select: + return MarkAsSimd128(node), VisitSimd32x4Select(node); default: V8_Fatal(__FILE__, __LINE__, "Unexpected operator #%d:%s @ node #%d", node->opcode(), node->op()->mnemonic(), node->id()); @@ -1538,7 +1632,7 @@ void InstructionSelector::EmitLookupSwitch(const SwitchInfo& sw, } void InstructionSelector::VisitStackSlot(Node* node) { - int size = 1 << ElementSizeLog2Of(StackSlotRepresentationOf(node->op())); + int size = StackSlotSizeOf(node->op()); int slot = frame_->AllocateSpillSlot(size); OperandGenerator g(this); @@ -1547,8 +1641,7 @@ void InstructionSelector::VisitStackSlot(Node* node) { } void InstructionSelector::VisitBitcastTaggedToWord(Node* node) { - OperandGenerator g(this); - Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(node->InputAt(0))); + EmitIdentity(node); } void InstructionSelector::VisitBitcastWordToTagged(Node* node) { @@ -1723,13 +1816,70 @@ void InstructionSelector::VisitWord32PairShr(Node* node) { UNIMPLEMENTED(); } void InstructionSelector::VisitWord32PairSar(Node* node) { UNIMPLEMENTED(); } #endif // V8_TARGET_ARCH_64_BIT -#if !V8_TARGET_ARCH_X64 +#if !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_ARM void InstructionSelector::VisitCreateInt32x4(Node* node) { UNIMPLEMENTED(); } void InstructionSelector::VisitInt32x4ExtractLane(Node* node) { UNIMPLEMENTED(); } -#endif // !V8_TARGET_ARCH_X64 + +void InstructionSelector::VisitInt32x4ReplaceLane(Node* node) { + UNIMPLEMENTED(); +} + +void InstructionSelector::VisitInt32x4Add(Node* node) { UNIMPLEMENTED(); } + +void InstructionSelector::VisitInt32x4Sub(Node* node) { UNIMPLEMENTED(); } + +#endif // !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_ARM + +#if !V8_TARGET_ARCH_ARM +void InstructionSelector::VisitCreateFloat32x4(Node* node) { UNIMPLEMENTED(); } + +void InstructionSelector::VisitFloat32x4ExtractLane(Node* node) { + UNIMPLEMENTED(); +} + +void InstructionSelector::VisitFloat32x4ReplaceLane(Node* node) { + UNIMPLEMENTED(); +} + +void InstructionSelector::VisitFloat32x4FromInt32x4(Node* node) { + UNIMPLEMENTED(); +} + +void InstructionSelector::VisitFloat32x4FromUint32x4(Node* node) { + UNIMPLEMENTED(); +} + +void InstructionSelector::VisitFloat32x4Abs(Node* node) { UNIMPLEMENTED(); } + +void InstructionSelector::VisitFloat32x4Neg(Node* node) { UNIMPLEMENTED(); } + +void InstructionSelector::VisitFloat32x4Add(Node* node) { UNIMPLEMENTED(); } + +void InstructionSelector::VisitFloat32x4Sub(Node* node) { UNIMPLEMENTED(); } + +void InstructionSelector::VisitFloat32x4Equal(Node* node) { UNIMPLEMENTED(); } + +void InstructionSelector::VisitFloat32x4NotEqual(Node* node) { + UNIMPLEMENTED(); +} + +void InstructionSelector::VisitInt32x4FromFloat32x4(Node* node) { + UNIMPLEMENTED(); +} + +void InstructionSelector::VisitUint32x4FromFloat32x4(Node* node) { + UNIMPLEMENTED(); +} + +void InstructionSelector::VisitInt32x4Equal(Node* node) { UNIMPLEMENTED(); } + +void InstructionSelector::VisitInt32x4NotEqual(Node* node) { UNIMPLEMENTED(); } + +void InstructionSelector::VisitSimd32x4Select(Node* node) { UNIMPLEMENTED(); } +#endif // !V8_TARGET_ARCH_ARM void InstructionSelector::VisitFinishRegion(Node* node) { EmitIdentity(node); } @@ -1970,7 +2120,8 @@ void InstructionSelector::VisitReturn(Node* ret) { DCHECK_GE(input_count, 1); auto value_locations = zone()->NewArray<InstructionOperand>(input_count); Node* pop_count = ret->InputAt(0); - value_locations[0] = pop_count->opcode() == IrOpcode::kInt32Constant + value_locations[0] = (pop_count->opcode() == IrOpcode::kInt32Constant || + pop_count->opcode() == IrOpcode::kInt64Constant) ? g.UseImmediate(pop_count) : g.UseRegister(pop_count); for (int i = 1; i < input_count; ++i) { |