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