diff options
Diffstat (limited to 'deps/v8/src/compiler/common-operator.cc')
-rw-r--r-- | deps/v8/src/compiler/common-operator.cc | 301 |
1 files changed, 280 insertions, 21 deletions
diff --git a/deps/v8/src/compiler/common-operator.cc b/deps/v8/src/compiler/common-operator.cc index 9ce6f71a0f..2cd63314cf 100644 --- a/deps/v8/src/compiler/common-operator.cc +++ b/deps/v8/src/compiler/common-operator.cc @@ -7,9 +7,11 @@ #include "src/assembler.h" #include "src/base/lazy-instance.h" #include "src/compiler/linkage.h" +#include "src/compiler/node.h" #include "src/compiler/opcodes.h" #include "src/compiler/operator.h" #include "src/handles-inl.h" +#include "src/objects-inl.h" #include "src/zone/zone.h" namespace v8 { @@ -41,6 +43,13 @@ DeoptimizeReason DeoptimizeReasonOf(Operator const* const op) { return OpParameter<DeoptimizeReason>(op); } +int ValueInputCountOfReturn(Operator const* const op) { + DCHECK(op->opcode() == IrOpcode::kReturn); + // Return nodes have a hidden input at index 0 which we ignore in the value + // input count. + return op->ValueInputCount() - 1; +} + size_t hash_value(DeoptimizeKind kind) { return static_cast<size_t>(kind); } std::ostream& operator<<(std::ostream& os, DeoptimizeKind kind) { @@ -171,6 +180,106 @@ std::ostream& operator<<(std::ostream& os, return os << p.value() << "|" << p.rmode() << "|" << p.type(); } +SparseInputMask::InputIterator::InputIterator( + SparseInputMask::BitMaskType bit_mask, Node* parent) + : bit_mask_(bit_mask), parent_(parent), real_index_(0) { +#if DEBUG + if (bit_mask_ != SparseInputMask::kDenseBitMask) { + DCHECK_EQ(base::bits::CountPopulation(bit_mask_) - + base::bits::CountPopulation(kEndMarker), + parent->InputCount()); + } +#endif +} + +void SparseInputMask::InputIterator::Advance() { + DCHECK(!IsEnd()); + + if (IsReal()) { + ++real_index_; + } + bit_mask_ >>= 1; +} + +Node* SparseInputMask::InputIterator::GetReal() const { + DCHECK(IsReal()); + return parent_->InputAt(real_index_); +} + +bool SparseInputMask::InputIterator::IsReal() const { + return bit_mask_ == SparseInputMask::kDenseBitMask || + (bit_mask_ & kEntryMask); +} + +bool SparseInputMask::InputIterator::IsEnd() const { + return (bit_mask_ == kEndMarker) || + (bit_mask_ == SparseInputMask::kDenseBitMask && + real_index_ >= parent_->InputCount()); +} + +int SparseInputMask::CountReal() const { + DCHECK(!IsDense()); + return base::bits::CountPopulation(bit_mask_) - + base::bits::CountPopulation(kEndMarker); +} + +SparseInputMask::InputIterator SparseInputMask::IterateOverInputs(Node* node) { + DCHECK(IsDense() || CountReal() == node->InputCount()); + return InputIterator(bit_mask_, node); +} + +bool operator==(SparseInputMask const& lhs, SparseInputMask const& rhs) { + return lhs.mask() == rhs.mask(); +} + +bool operator!=(SparseInputMask const& lhs, SparseInputMask const& rhs) { + return !(lhs == rhs); +} + +size_t hash_value(SparseInputMask const& p) { + return base::hash_value(p.mask()); +} + +std::ostream& operator<<(std::ostream& os, SparseInputMask const& p) { + if (p.IsDense()) { + return os << "dense"; + } else { + SparseInputMask::BitMaskType mask = p.mask(); + DCHECK_NE(mask, SparseInputMask::kDenseBitMask); + + os << "sparse:"; + + while (mask != SparseInputMask::kEndMarker) { + if (mask & SparseInputMask::kEntryMask) { + os << "^"; + } else { + os << "."; + } + mask >>= 1; + } + return os; + } +} + +bool operator==(TypedStateValueInfo const& lhs, + TypedStateValueInfo const& rhs) { + return lhs.machine_types() == rhs.machine_types() && + lhs.sparse_input_mask() == rhs.sparse_input_mask(); +} + +bool operator!=(TypedStateValueInfo const& lhs, + TypedStateValueInfo const& rhs) { + return !(lhs == rhs); +} + +size_t hash_value(TypedStateValueInfo const& p) { + return base::hash_combine(p.machine_types(), p.sparse_input_mask()); +} + +std::ostream& operator<<(std::ostream& os, TypedStateValueInfo const& p) { + return os << p.machine_types() << "|" << p.sparse_input_mask(); +} + size_t hash_value(RegionObservability observability) { return static_cast<size_t>(observability); } @@ -235,9 +344,23 @@ OsrGuardType OsrGuardTypeOf(Operator const* op) { return OpParameter<OsrGuardType>(op); } +SparseInputMask SparseInputMaskOf(Operator const* op) { + DCHECK(op->opcode() == IrOpcode::kStateValues || + op->opcode() == IrOpcode::kTypedStateValues); + + if (op->opcode() == IrOpcode::kTypedStateValues) { + return OpParameter<TypedStateValueInfo>(op).sparse_input_mask(); + } + return OpParameter<SparseInputMask>(op); +} + ZoneVector<MachineType> const* MachineTypesOf(Operator const* op) { DCHECK(op->opcode() == IrOpcode::kTypedObjectState || op->opcode() == IrOpcode::kTypedStateValues); + + if (op->opcode() == IrOpcode::kTypedStateValues) { + return OpParameter<TypedStateValueInfo>(op).machine_types(); + } return OpParameter<const ZoneVector<MachineType>*>(op); } @@ -330,6 +453,21 @@ ZoneVector<MachineType> const* MachineTypesOf(Operator const* op) { V(WrongInstanceType) \ V(WrongMap) +#define CACHED_TRAP_IF_LIST(V) \ + V(TrapDivUnrepresentable) \ + V(TrapFloatUnrepresentable) + +// The reason for a trap. +#define CACHED_TRAP_UNLESS_LIST(V) \ + V(TrapUnreachable) \ + V(TrapMemOutOfBounds) \ + V(TrapDivByZero) \ + V(TrapDivUnrepresentable) \ + V(TrapRemByZero) \ + V(TrapFloatUnrepresentable) \ + V(TrapFuncInvalid) \ + V(TrapFuncSigMismatch) + #define CACHED_PARAMETER_LIST(V) \ V(0) \ V(1) \ @@ -529,6 +667,38 @@ struct CommonOperatorGlobalCache final { CACHED_DEOPTIMIZE_UNLESS_LIST(CACHED_DEOPTIMIZE_UNLESS) #undef CACHED_DEOPTIMIZE_UNLESS + template <int32_t trap_id> + struct TrapIfOperator final : public Operator1<int32_t> { + TrapIfOperator() + : Operator1<int32_t>( // -- + IrOpcode::kTrapIf, // opcode + Operator::kFoldable | Operator::kNoThrow, // properties + "TrapIf", // name + 1, 1, 1, 0, 0, 1, // counts + trap_id) {} // parameter + }; +#define CACHED_TRAP_IF(Trap) \ + TrapIfOperator<static_cast<int32_t>(Runtime::kThrowWasm##Trap)> \ + kTrapIf##Trap##Operator; + CACHED_TRAP_IF_LIST(CACHED_TRAP_IF) +#undef CACHED_TRAP_IF + + template <int32_t trap_id> + struct TrapUnlessOperator final : public Operator1<int32_t> { + TrapUnlessOperator() + : Operator1<int32_t>( // -- + IrOpcode::kTrapUnless, // opcode + Operator::kFoldable | Operator::kNoThrow, // properties + "TrapUnless", // name + 1, 1, 1, 0, 0, 1, // counts + trap_id) {} // parameter + }; +#define CACHED_TRAP_UNLESS(Trap) \ + TrapUnlessOperator<static_cast<int32_t>(Runtime::kThrowWasm##Trap)> \ + kTrapUnless##Trap##Operator; + CACHED_TRAP_UNLESS_LIST(CACHED_TRAP_UNLESS) +#undef CACHED_TRAP_UNLESS + template <MachineRepresentation kRep, int kInputCount> struct PhiOperator final : public Operator1<MachineRepresentation> { PhiOperator() @@ -588,13 +758,14 @@ struct CommonOperatorGlobalCache final { #undef CACHED_PROJECTION template <int kInputCount> - struct StateValuesOperator final : public Operator { + struct StateValuesOperator final : public Operator1<SparseInputMask> { StateValuesOperator() - : Operator( // -- - IrOpcode::kStateValues, // opcode - Operator::kPure, // flags - "StateValues", // name - kInputCount, 0, 0, 1, 0, 0) {} // counts + : Operator1<SparseInputMask>( // -- + IrOpcode::kStateValues, // opcode + Operator::kPure, // flags + "StateValues", // name + kInputCount, 0, 0, 1, 0, 0, // counts + SparseInputMask::Dense()) {} // parameter }; #define CACHED_STATE_VALUES(input_count) \ StateValuesOperator<input_count> kStateValues##input_count##Operator; @@ -727,6 +898,43 @@ const Operator* CommonOperatorBuilder::DeoptimizeUnless( reason); // parameter } +const Operator* CommonOperatorBuilder::TrapIf(int32_t trap_id) { + switch (trap_id) { +#define CACHED_TRAP_IF(Trap) \ + case Runtime::kThrowWasm##Trap: \ + return &cache_.kTrapIf##Trap##Operator; + CACHED_TRAP_IF_LIST(CACHED_TRAP_IF) +#undef CACHED_TRAP_IF + default: + break; + } + // Uncached + return new (zone()) Operator1<int>( // -- + IrOpcode::kTrapIf, // opcode + Operator::kFoldable | Operator::kNoThrow, // properties + "TrapIf", // name + 1, 1, 1, 0, 0, 1, // counts + trap_id); // parameter +} + +const Operator* CommonOperatorBuilder::TrapUnless(int32_t trap_id) { + switch (trap_id) { +#define CACHED_TRAP_UNLESS(Trap) \ + case Runtime::kThrowWasm##Trap: \ + return &cache_.kTrapUnless##Trap##Operator; + CACHED_TRAP_UNLESS_LIST(CACHED_TRAP_UNLESS) +#undef CACHED_TRAP_UNLESS + default: + break; + } + // Uncached + return new (zone()) Operator1<int>( // -- + IrOpcode::kTrapUnless, // opcode + Operator::kFoldable | Operator::kNoThrow, // properties + "TrapUnless", // name + 1, 1, 1, 0, 0, 1, // counts + trap_id); // parameter +} const Operator* CommonOperatorBuilder::Switch(size_t control_output_count) { return new (zone()) Operator( // -- @@ -1000,30 +1208,44 @@ const Operator* CommonOperatorBuilder::BeginRegion( return nullptr; } -const Operator* CommonOperatorBuilder::StateValues(int arguments) { - switch (arguments) { +const Operator* CommonOperatorBuilder::StateValues(int arguments, + SparseInputMask bitmask) { + if (bitmask.IsDense()) { + switch (arguments) { #define CACHED_STATE_VALUES(arguments) \ case arguments: \ return &cache_.kStateValues##arguments##Operator; - CACHED_STATE_VALUES_LIST(CACHED_STATE_VALUES) + CACHED_STATE_VALUES_LIST(CACHED_STATE_VALUES) #undef CACHED_STATE_VALUES - default: - break; + default: + break; + } } + +#if DEBUG + DCHECK(bitmask.IsDense() || bitmask.CountReal() == arguments); +#endif + // Uncached. - return new (zone()) Operator( // -- - IrOpcode::kStateValues, Operator::kPure, // opcode - "StateValues", // name - arguments, 0, 0, 1, 0, 0); // counts + return new (zone()) Operator1<SparseInputMask>( // -- + IrOpcode::kStateValues, Operator::kPure, // opcode + "StateValues", // name + arguments, 0, 0, 1, 0, 0, // counts + bitmask); // parameter } const Operator* CommonOperatorBuilder::TypedStateValues( - const ZoneVector<MachineType>* types) { - return new (zone()) Operator1<const ZoneVector<MachineType>*>( // -- - IrOpcode::kTypedStateValues, Operator::kPure, // opcode - "TypedStateValues", // name - static_cast<int>(types->size()), 0, 0, 1, 0, 0, // counts - types); // parameter + const ZoneVector<MachineType>* types, SparseInputMask bitmask) { +#if DEBUG + DCHECK(bitmask.IsDense() || + bitmask.CountReal() == static_cast<int>(types->size())); +#endif + + return new (zone()) Operator1<TypedStateValueInfo>( // -- + IrOpcode::kTypedStateValues, Operator::kPure, // opcode + "TypedStateValues", // name + static_cast<int>(types->size()), 0, 0, 1, 0, 0, // counts + TypedStateValueInfo(types, bitmask)); // parameters } const Operator* CommonOperatorBuilder::ObjectState(int pointer_slots) { @@ -1131,6 +1353,43 @@ const Operator* CommonOperatorBuilder::ResizeMergeOrPhi(const Operator* op, } } +const Operator* CommonOperatorBuilder::Int32x4ExtractLane(int32_t lane_number) { + DCHECK(0 <= lane_number && lane_number < 4); + return new (zone()) Operator1<int32_t>( // -- + IrOpcode::kInt32x4ExtractLane, Operator::kPure, // opcode + "Int32x4ExtractLane", // name + 1, 0, 0, 1, 0, 0, // counts + lane_number); // parameter +} + +const Operator* CommonOperatorBuilder::Int32x4ReplaceLane(int32_t lane_number) { + DCHECK(0 <= lane_number && lane_number < 4); + return new (zone()) Operator1<int32_t>( // -- + IrOpcode::kInt32x4ReplaceLane, Operator::kPure, // opcode + "Int32x4ReplaceLane", // name + 2, 0, 0, 1, 0, 0, // counts + lane_number); // parameter +} + +const Operator* CommonOperatorBuilder::Float32x4ExtractLane( + int32_t lane_number) { + DCHECK(0 <= lane_number && lane_number < 4); + return new (zone()) Operator1<int32_t>( // -- + IrOpcode::kFloat32x4ExtractLane, Operator::kPure, // opcode + "Float32x4ExtractLane", // name + 1, 0, 0, 1, 0, 0, // counts + lane_number); // parameter +} + +const Operator* CommonOperatorBuilder::Float32x4ReplaceLane( + int32_t lane_number) { + DCHECK(0 <= lane_number && lane_number < 4); + return new (zone()) Operator1<int32_t>( // -- + IrOpcode::kFloat32x4ReplaceLane, Operator::kPure, // opcode + "Float32x4ReplaceLane", // name + 2, 0, 0, 1, 0, 0, // counts + lane_number); // parameter +} const FrameStateFunctionInfo* CommonOperatorBuilder::CreateFrameStateFunctionInfo( |