5 #ifndef V8_COMPILER_BACKEND_INSTRUCTION_H_ 6 #define V8_COMPILER_BACKEND_INSTRUCTION_H_ 13 #include "src/base/compiler-specific.h" 14 #include "src/compiler/backend/instruction-codes.h" 15 #include "src/compiler/common-operator.h" 16 #include "src/compiler/frame.h" 17 #include "src/compiler/opcodes.h" 18 #include "src/double.h" 19 #include "src/globals.h" 20 #include "src/macro-assembler.h" 21 #include "src/source-position.h" 22 #include "src/zone/zone-allocator.h" 27 class RegisterConfiguration;
32 class SourcePositionTable;
36 static const int kInvalidVirtualRegister = -1;
46 FIRST_LOCATION_OPERAND_KIND = EXPLICIT
52 Kind kind()
const {
return KindField::decode(value_); }
54 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \ 55 bool Is##name() const { return kind() == type; } 56 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID)
59 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED)
64 INSTRUCTION_OPERAND_PREDICATE(
Constant, CONSTANT)
68 INSTRUCTION_OPERAND_PREDICATE(
Immediate, IMMEDIATE)
73 INSTRUCTION_OPERAND_PREDICATE(Explicit, EXPLICIT)
76 INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED)
77 #undef INSTRUCTION_OPERAND_PREDICATE 79 inline bool IsAnyLocationOperand()
const;
80 inline bool IsLocationOperand()
const;
81 inline bool IsFPLocationOperand()
const;
82 inline bool IsAnyRegister()
const;
83 inline bool IsRegister()
const;
84 inline bool IsFPRegister()
const;
85 inline bool IsFloatRegister()
const;
86 inline bool IsDoubleRegister()
const;
87 inline bool IsSimd128Register()
const;
88 inline bool IsAnyStackSlot()
const;
89 inline bool IsStackSlot()
const;
90 inline bool IsFPStackSlot()
const;
91 inline bool IsFloatStackSlot()
const;
92 inline bool IsDoubleStackSlot()
const;
93 inline bool IsSimd128StackSlot()
const;
95 template <
typename SubKindOperand>
96 static SubKindOperand* New(
Zone* zone,
const SubKindOperand& op) {
97 void* buffer = zone->New(
sizeof(op));
98 return new (buffer) SubKindOperand(op);
107 return this->value_ == that.value_;
111 return this->value_ < that.value_;
115 return this->GetCanonicalizedValue() == that.GetCanonicalizedValue();
119 return this->GetCanonicalizedValue() < that.GetCanonicalizedValue();
130 inline uint64_t GetCanonicalizedValue()
const;
141 #define INSTRUCTION_OPERAND_CASTS(OperandType, OperandKind) \ 143 static OperandType* cast(InstructionOperand* op) { \ 144 DCHECK_EQ(OperandKind, op->kind()); \ 145 return static_cast<OperandType*>(op); \ 148 static const OperandType* cast(const InstructionOperand* op) { \ 149 DCHECK_EQ(OperandKind, op->kind()); \ 150 return static_cast<const OperandType*>(op); \ 153 static OperandType cast(const InstructionOperand& op) { \ 154 DCHECK_EQ(OperandKind, op.kind()); \ 155 return *static_cast<const OperandType*>(&op); \ 160 enum BasicPolicy { FIXED_SLOT, EXTENDED_POLICY };
162 enum ExtendedPolicy {
165 REGISTER_OR_SLOT_OR_CONSTANT,
188 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
189 value_ |= ExtendedPolicyField::encode(policy);
190 value_ |= LifetimeField::encode(USED_AT_END);
195 DCHECK(policy == FIXED_SLOT);
196 value_ |= BasicPolicyField::encode(policy);
197 value_ |=
static_cast<int64_t>(index) << FixedSlotIndexField::kShift;
198 DCHECK(this->fixed_slot_index() == index);
203 DCHECK(policy == FIXED_REGISTER || policy == FIXED_FP_REGISTER);
204 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
205 value_ |= ExtendedPolicyField::encode(policy);
206 value_ |= LifetimeField::encode(USED_AT_END);
207 value_ |= FixedRegisterField::encode(index);
211 int virtual_register)
213 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
214 value_ |= ExtendedPolicyField::encode(policy);
215 value_ |= LifetimeField::encode(lifetime);
220 value_ |= HasSecondaryStorageField::encode(
true);
221 value_ |= SecondaryStorageField::encode(slot_id);
225 DCHECK_NE(kInvalidVirtualRegister, virtual_register);
226 value_ = VirtualRegisterField::update(
227 other.value_, static_cast<uint32_t>(virtual_register));
231 bool HasRegisterOrSlotPolicy()
const {
232 return basic_policy() == EXTENDED_POLICY &&
233 extended_policy() == REGISTER_OR_SLOT;
235 bool HasRegisterOrSlotOrConstantPolicy()
const {
236 return basic_policy() == EXTENDED_POLICY &&
237 extended_policy() == REGISTER_OR_SLOT_OR_CONSTANT;
239 bool HasFixedPolicy()
const {
240 return basic_policy() == FIXED_SLOT ||
241 extended_policy() == FIXED_REGISTER ||
242 extended_policy() == FIXED_FP_REGISTER;
244 bool HasRegisterPolicy()
const {
245 return basic_policy() == EXTENDED_POLICY &&
246 extended_policy() == MUST_HAVE_REGISTER;
248 bool HasSlotPolicy()
const {
249 return basic_policy() == EXTENDED_POLICY &&
250 extended_policy() == MUST_HAVE_SLOT;
252 bool HasSameAsInputPolicy()
const {
253 return basic_policy() == EXTENDED_POLICY &&
254 extended_policy() == SAME_AS_FIRST_INPUT;
256 bool HasFixedSlotPolicy()
const {
return basic_policy() == FIXED_SLOT; }
257 bool HasFixedRegisterPolicy()
const {
258 return basic_policy() == EXTENDED_POLICY &&
259 extended_policy() == FIXED_REGISTER;
261 bool HasFixedFPRegisterPolicy()
const {
262 return basic_policy() == EXTENDED_POLICY &&
263 extended_policy() == FIXED_FP_REGISTER;
265 bool HasSecondaryStorage()
const {
266 return basic_policy() == EXTENDED_POLICY &&
267 extended_policy() == FIXED_REGISTER &&
268 HasSecondaryStorageField::decode(value_);
270 int GetSecondaryStorage()
const {
271 DCHECK(HasSecondaryStorage());
272 return SecondaryStorageField::decode(value_);
276 BasicPolicy basic_policy()
const {
return BasicPolicyField::decode(value_); }
279 ExtendedPolicy extended_policy()
const {
280 DCHECK(basic_policy() == EXTENDED_POLICY);
281 return ExtendedPolicyField::decode(value_);
285 int fixed_slot_index()
const {
286 DCHECK(HasFixedSlotPolicy());
287 return static_cast<int>(
static_cast<int64_t>(value_) >>
288 FixedSlotIndexField::kShift);
292 int fixed_register_index()
const {
293 DCHECK(HasFixedRegisterPolicy() || HasFixedFPRegisterPolicy());
294 return FixedRegisterField::decode(value_);
298 int32_t virtual_register()
const {
299 return static_cast<int32_t
>(VirtualRegisterField::decode(value_));
303 bool IsUsedAtStart()
const {
304 DCHECK(basic_policy() == EXTENDED_POLICY);
305 return LifetimeField::decode(value_) == USED_AT_START;
330 STATIC_ASSERT(KindField::kSize == 3);
351 VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
360 VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
363 int32_t virtual_register()
const {
364 return static_cast<int32_t
>(VirtualRegisterField::decode(value_));
368 return InstructionOperand::New(zone,
ConstantOperand(virtual_register));
373 STATIC_ASSERT(KindField::kSize == 3);
379 enum ImmediateType { INLINE, INDEXED };
383 value_ |= TypeField::encode(
type);
384 value_ |=
static_cast<int64_t>(value) << ValueField::kShift;
387 ImmediateType
type()
const {
return TypeField::decode(value_); }
389 int32_t inline_value()
const {
390 DCHECK_EQ(INLINE,
type());
391 return static_cast<int64_t>(value_) >> ValueField::kShift;
394 int32_t indexed_value()
const {
395 DCHECK_EQ(INDEXED,
type());
396 return static_cast<int64_t>(value_) >> ValueField::kShift;
405 STATIC_ASSERT(KindField::kSize == 3);
412 enum LocationKind { REGISTER, STACK_SLOT };
415 LocationOperand::LocationKind location_kind,
416 MachineRepresentation rep,
int index)
418 DCHECK_IMPLIES(location_kind == REGISTER, index >= 0);
419 DCHECK(IsSupportedRepresentation(rep));
420 value_ |= LocationKindField::encode(location_kind);
421 value_ |= RepresentationField::encode(rep);
422 value_ |=
static_cast<int64_t>(index) << IndexField::kShift;
426 DCHECK(IsStackSlot() || IsFPStackSlot());
427 return static_cast<int64_t>(value_) >> IndexField::kShift;
430 int register_code()
const {
431 DCHECK(IsRegister() || IsFPRegister());
432 return static_cast<int64_t>(value_) >> IndexField::kShift;
436 DCHECK(IsRegister());
437 return Register::from_code(register_code());
441 DCHECK(IsFloatRegister());
442 return FloatRegister::from_code(register_code());
449 DCHECK(IsFPRegister());
450 return DoubleRegister::from_code(register_code());
454 DCHECK(IsSimd128Register());
455 return Simd128Register::from_code(register_code());
458 LocationKind location_kind()
const {
459 return LocationKindField::decode(value_);
462 MachineRepresentation representation()
const {
463 return RepresentationField::decode(value_);
466 static bool IsSupportedRepresentation(MachineRepresentation rep) {
468 case MachineRepresentation::kWord32:
469 case MachineRepresentation::kWord64:
470 case MachineRepresentation::kFloat32:
471 case MachineRepresentation::kFloat64:
472 case MachineRepresentation::kSimd128:
473 case MachineRepresentation::kTaggedSigned:
474 case MachineRepresentation::kTaggedPointer:
475 case MachineRepresentation::kTagged:
477 case MachineRepresentation::kBit:
478 case MachineRepresentation::kWord8:
479 case MachineRepresentation::kWord16:
480 case MachineRepresentation::kNone:
490 DCHECK(op->IsAnyLocationOperand());
495 DCHECK(op->IsAnyLocationOperand());
500 DCHECK(op.IsAnyLocationOperand());
504 STATIC_ASSERT(KindField::kSize == 3);
511 :
public NON_EXPORTED_BASE(LocationOperand) {
513 ExplicitOperand(LocationKind kind, MachineRepresentation rep,
int index);
516 MachineRepresentation rep,
int index) {
517 return InstructionOperand::New(zone,
ExplicitOperand(kind, rep, index));
529 MachineRepresentation rep,
int index) {
536 #undef INSTRUCTION_OPERAND_CASTS 538 bool InstructionOperand::IsAnyLocationOperand()
const {
539 return this->kind() >= FIRST_LOCATION_OPERAND_KIND;
542 bool InstructionOperand::IsLocationOperand()
const {
543 return IsAnyLocationOperand() &&
544 !IsFloatingPoint(LocationOperand::cast(
this)->representation());
547 bool InstructionOperand::IsFPLocationOperand()
const {
548 return IsAnyLocationOperand() &&
549 IsFloatingPoint(LocationOperand::cast(
this)->representation());
552 bool InstructionOperand::IsAnyRegister()
const {
553 return IsAnyLocationOperand() &&
554 LocationOperand::cast(
this)->location_kind() ==
555 LocationOperand::REGISTER;
558 bool InstructionOperand::IsRegister()
const {
559 return IsAnyRegister() &&
560 !IsFloatingPoint(LocationOperand::cast(
this)->representation());
563 bool InstructionOperand::IsFPRegister()
const {
564 return IsAnyRegister() &&
565 IsFloatingPoint(LocationOperand::cast(
this)->representation());
568 bool InstructionOperand::IsFloatRegister()
const {
569 return IsAnyRegister() && LocationOperand::cast(
this)->representation() ==
570 MachineRepresentation::kFloat32;
573 bool InstructionOperand::IsDoubleRegister()
const {
574 return IsAnyRegister() && LocationOperand::cast(
this)->representation() ==
575 MachineRepresentation::kFloat64;
578 bool InstructionOperand::IsSimd128Register()
const {
579 return IsAnyRegister() && LocationOperand::cast(
this)->representation() ==
580 MachineRepresentation::kSimd128;
583 bool InstructionOperand::IsAnyStackSlot()
const {
584 return IsAnyLocationOperand() &&
585 LocationOperand::cast(
this)->location_kind() ==
586 LocationOperand::STACK_SLOT;
589 bool InstructionOperand::IsStackSlot()
const {
590 return IsAnyStackSlot() &&
591 !IsFloatingPoint(LocationOperand::cast(
this)->representation());
594 bool InstructionOperand::IsFPStackSlot()
const {
595 return IsAnyStackSlot() &&
596 IsFloatingPoint(LocationOperand::cast(
this)->representation());
599 bool InstructionOperand::IsFloatStackSlot()
const {
600 return IsAnyLocationOperand() &&
601 LocationOperand::cast(
this)->location_kind() ==
602 LocationOperand::STACK_SLOT &&
603 LocationOperand::cast(
this)->representation() ==
604 MachineRepresentation::kFloat32;
607 bool InstructionOperand::IsDoubleStackSlot()
const {
608 return IsAnyLocationOperand() &&
609 LocationOperand::cast(
this)->location_kind() ==
610 LocationOperand::STACK_SLOT &&
611 LocationOperand::cast(
this)->representation() ==
612 MachineRepresentation::kFloat64;
615 bool InstructionOperand::IsSimd128StackSlot()
const {
616 return IsAnyLocationOperand() &&
617 LocationOperand::cast(
this)->location_kind() ==
618 LocationOperand::STACK_SLOT &&
619 LocationOperand::cast(
this)->representation() ==
620 MachineRepresentation::kSimd128;
623 uint64_t InstructionOperand::GetCanonicalizedValue()
const {
624 if (IsAnyLocationOperand()) {
625 MachineRepresentation canonical = MachineRepresentation::kNone;
626 if (IsFPRegister()) {
627 if (kSimpleFPAliasing) {
629 canonical = MachineRepresentation::kFloat64;
633 canonical = LocationOperand::cast(
this)->representation();
636 return InstructionOperand::KindField::update(
637 LocationOperand::RepresentationField::update(this->value_, canonical),
638 LocationOperand::EXPLICIT);
647 return a.CompareCanonicalized(b);
652 :
public NON_EXPORTED_BASE(ZoneObject) {
656 : source_(source), destination_(destination) {
657 DCHECK(!source.IsInvalid() && !destination.IsInvalid());
667 destination_ = operand;
672 bool IsPending()
const {
673 return destination_.IsInvalid() && !source_.IsInvalid();
679 bool IsRedundant()
const {
680 DCHECK_IMPLIES(!destination_.IsInvalid(), !destination_.IsConstant());
681 return IsEliminated() || source_.EqualsCanonicalized(destination_);
686 bool IsEliminated()
const {
687 DCHECK_IMPLIES(source_.IsInvalid(), destination_.IsInvalid());
688 return source_.IsInvalid();
701 std::ostream& operator<<(std::ostream&,
const MoveOperands&);
704 :
public NON_EXPORTED_BASE(ZoneVector<MoveOperands*>),
705 public NON_EXPORTED_BASE(ZoneObject) {
713 Zone* zone = get_allocator().zone();
714 return AddMove(from, to, zone);
719 Zone* operand_allocation_zone) {
725 bool IsRedundant()
const;
737 std::ostream& operator<<(std::ostream&,
const ParallelMove&);
742 : reference_operands_(8, zone), instruction_position_(-1) {}
745 return reference_operands_;
747 int instruction_position()
const {
return instruction_position_; }
749 void set_instruction_position(
int pos) {
750 DCHECK_EQ(-1, instruction_position_);
751 instruction_position_ = pos;
757 friend std::ostream& operator<<(std::ostream&,
const ReferenceMap&);
760 int instruction_position_;
763 std::ostream& operator<<(std::ostream&,
const ReferenceMap&);
769 size_t OutputCount()
const {
return OutputCountField::decode(bit_field_); }
771 DCHECK(
i < OutputCount());
772 return &operands_[
i];
775 DCHECK(
i < OutputCount());
776 return &operands_[
i];
779 bool HasOutput()
const {
return OutputCount() > 0; }
783 size_t InputCount()
const {
return InputCountField::decode(bit_field_); }
785 DCHECK(
i < InputCount());
786 return &operands_[OutputCount() +
i];
789 DCHECK(
i < InputCount());
790 return &operands_[OutputCount() +
i];
793 size_t TempCount()
const {
return TempCountField::decode(bit_field_); }
795 DCHECK(
i < TempCount());
796 return &operands_[OutputCount() + InputCount() +
i];
799 DCHECK(
i < TempCount());
800 return &operands_[OutputCount() + InputCount() +
i];
803 InstructionCode opcode()
const {
return opcode_; }
804 ArchOpcode arch_opcode()
const {
return ArchOpcodeField::decode(opcode()); }
805 AddressingMode addressing_mode()
const {
806 return AddressingModeField::decode(opcode());
808 FlagsMode flags_mode()
const {
return FlagsModeField::decode(opcode()); }
809 FlagsCondition flags_condition()
const {
810 return FlagsConditionField::decode(opcode());
814 return New(zone, opcode, 0,
nullptr, 0,
nullptr, 0,
nullptr);
821 DCHECK_LE(0, opcode);
822 DCHECK(output_count == 0 || outputs !=
nullptr);
823 DCHECK(input_count == 0 || inputs !=
nullptr);
824 DCHECK(temp_count == 0 || temps !=
nullptr);
826 CHECK(InputCountField::is_valid(input_count));
828 size_t total_extra_ops = output_count + input_count + temp_count;
829 if (total_extra_ops != 0) total_extra_ops--;
830 int size =
static_cast<int>(
834 opcode, output_count, outputs, input_count, inputs, temp_count, temps);
838 bit_field_ = IsCallField::update(bit_field_,
true);
841 bool IsCall()
const {
return IsCallField::decode(bit_field_); }
842 bool NeedsReferenceMap()
const {
return IsCall(); }
843 bool HasReferenceMap()
const {
return reference_map_ !=
nullptr; }
845 bool ClobbersRegisters()
const {
return IsCall(); }
846 bool ClobbersTemps()
const {
return IsCall(); }
847 bool ClobbersDoubleRegisters()
const {
return IsCall(); }
848 ReferenceMap* reference_map()
const {
return reference_map_; }
851 DCHECK(NeedsReferenceMap());
852 DCHECK(!reference_map_);
853 reference_map_ = map;
856 void OverwriteWithNop() {
857 opcode_ = ArchOpcodeField::encode(kArchNop);
859 reference_map_ =
nullptr;
862 bool IsNop()
const {
return arch_opcode() == kArchNop; }
864 bool IsDeoptimizeCall()
const {
865 return arch_opcode() == ArchOpcode::kArchDeoptimize ||
866 FlagsModeField::decode(opcode()) == kFlags_deoptimize ||
867 FlagsModeField::decode(opcode()) == kFlags_deoptimize_and_poison;
870 bool IsTrap()
const {
871 return FlagsModeField::decode(opcode()) == kFlags_trap;
874 bool IsJump()
const {
return arch_opcode() == ArchOpcode::kArchJmp; }
875 bool IsRet()
const {
return arch_opcode() == ArchOpcode::kArchRet; }
876 bool IsTailCall()
const {
877 return arch_opcode() == ArchOpcode::kArchTailCallCodeObject ||
878 arch_opcode() == ArchOpcode::kArchTailCallCodeObjectFromJSFunction ||
879 arch_opcode() == ArchOpcode::kArchTailCallAddress ||
880 arch_opcode() == ArchOpcode::kArchTailCallWasm;
882 bool IsThrow()
const {
883 return arch_opcode() == ArchOpcode::kArchThrowTerminator;
889 FIRST_GAP_POSITION = START,
890 LAST_GAP_POSITION = END
894 if (parallel_moves_[pos] ==
nullptr) {
897 return parallel_moves_[pos];
901 return parallel_moves_[pos];
904 const ParallelMove* GetParallelMove(GapPosition pos)
const {
905 return parallel_moves_[pos];
908 bool AreMovesRedundant()
const;
910 ParallelMove*
const* parallel_moves()
const {
return ¶llel_moves_[0]; }
911 ParallelMove** parallel_moves() {
return ¶llel_moves_[0]; }
918 DCHECK_NOT_NULL(block);
929 static const size_t kMaxOutputCount = OutputCountField::kMax;
930 static const size_t kMaxInputCount = InputCountField::kMax;
931 static const size_t kMaxTempCount = TempCountField::kMax;
936 Instruction(InstructionCode opcode,
size_t output_count,
943 InstructionCode opcode_;
953 std::ostream& operator<<(std::ostream&,
const Instruction&);
957 static const int kInvalidRpoNumber = -1;
962 size_t ToSize()
const {
964 return static_cast<size_t>(index_);
966 bool IsValid()
const {
return index_ >= 0; }
970 bool IsNext(
const RpoNumber other)
const {
972 return other.index_ == this->index_ + 1;
976 bool operator==(
RpoNumber other)
const {
return index_ == other.index_; }
977 bool operator!=(
RpoNumber other)
const {
return index_ != other.index_; }
978 bool operator>(
RpoNumber other)
const {
return index_ > other.index_; }
979 bool operator<(
RpoNumber other)
const {
return index_ < other.index_; }
980 bool operator<=(
RpoNumber other)
const {
return index_ <= other.index_; }
981 bool operator>=(
RpoNumber other)
const {
return index_ >= other.index_; }
984 explicit RpoNumber(int32_t index) : index_(index) {}
988 std::ostream& operator<<(std::ostream&,
const RpoNumber&);
1000 kDelayedStringConstant
1005 explicit Constant(
float v) : type_(kFloat32), value_(bit_cast<int32_t>(v)) {}
1006 explicit Constant(
double v) : type_(kFloat64), value_(bit_cast<int64_t>(v)) {}
1008 : type_(kExternalReference), value_(bit_cast<intptr_t>(ref.address())) {}
1010 : type_(kHeapObject), value_(bit_cast<intptr_t>(obj)) {}
1013 : type_(kDelayedStringConstant), value_(bit_cast<intptr_t>(str)) {}
1016 Type
type()
const {
return type_; }
1018 RelocInfo::Mode rmode()
const {
return rmode_; }
1020 int32_t ToInt32()
const {
1021 DCHECK(
type() == kInt32 ||
type() == kInt64);
1022 const int32_t value =
static_cast<int32_t
>(value_);
1023 DCHECK_EQ(value_, static_cast<int64_t>(value));
1028 if (
type() == kInt32)
return ToInt32();
1029 DCHECK_EQ(kInt64,
type());
1033 float ToFloat32()
const {
1037 DCHECK_EQ(kFloat32,
type());
1038 return bit_cast<
float>(
static_cast<int32_t
>(value_));
1042 DCHECK_EQ(kFloat32,
type());
1043 return bit_cast<
uint32_t>(
static_cast<int32_t
>(value_));
1046 Double ToFloat64()
const {
1047 DCHECK_EQ(kFloat64,
type());
1048 return Double(bit_cast<uint64_t>(value_));
1052 DCHECK_EQ(kExternalReference,
type());
1053 return ExternalReference::FromRawAddress(static_cast<Address>(value_));
1057 DCHECK_EQ(kRpoNumber,
type());
1058 return RpoNumber::FromInt(static_cast<int>(value_));
1067 RelocInfo::Mode rmode_ = RelocInfo::NONE;
1071 std::ostream& operator<<(std::ostream&,
const Constant&);
1076 enum class StateValueKind : uint8_t {
1088 : kind_(StateValueKind::kPlain), type_(MachineType::AnyTagged()) {}
1092 MachineType::AnyTagged());
1093 descr.args_type_ =
type;
1098 MachineType::AnyTagged());
1099 descr.args_type_ =
type;
1107 MachineType::AnyTagged());
1111 MachineType::AnyTagged());
1117 MachineType::AnyTagged());
1122 bool IsArgumentsElements()
const {
1123 return kind_ == StateValueKind::kArgumentsElements;
1125 bool IsArgumentsLength()
const {
1126 return kind_ == StateValueKind::kArgumentsLength;
1128 bool IsPlain()
const {
return kind_ == StateValueKind::kPlain; }
1129 bool IsOptimizedOut()
const {
return kind_ == StateValueKind::kOptimizedOut; }
1130 bool IsNested()
const {
return kind_ == StateValueKind::kNested; }
1131 bool IsDuplicate()
const {
return kind_ == StateValueKind::kDuplicate; }
1134 DCHECK(kind_ == StateValueKind::kDuplicate ||
1135 kind_ == StateValueKind::kNested);
1138 ArgumentsStateType arguments_type()
const {
1139 DCHECK(kind_ == StateValueKind::kArgumentsElements ||
1140 kind_ == StateValueKind::kArgumentsLength);
1146 : kind_(kind), type_(
type) {}
1148 StateValueKind kind_;
1152 ArgumentsStateType args_type_;
1160 size_t size() {
return fields_.size(); }
1167 : desc(desc), nested(nested) {}
1173 bool operator!=(
const iterator& other)
const {
1174 return field_iterator != other.field_iterator;
1176 bool operator==(
const iterator& other)
const {
1177 return field_iterator == other.field_iterator;
1180 if (field_iterator->IsNested()) {
1188 StateValueList* nested = desc->IsNested() ? *nested_iterator :
nullptr;
1189 return Value(desc, nested);
1197 : field_iterator(it), nested_iterator(nested) {}
1203 void ReserveSize(
size_t size) { fields_.reserve(size); }
1206 fields_.push_back(StateValueDescriptor::Recursive(
id));
1209 nested_.push_back(nested);
1212 void PushArgumentsElements(ArgumentsStateType
type) {
1213 fields_.push_back(StateValueDescriptor::ArgumentsElements(
type));
1215 void PushArgumentsLength(ArgumentsStateType
type) {
1216 fields_.push_back(StateValueDescriptor::ArgumentsLength(
type));
1218 void PushDuplicate(
size_t id) {
1219 fields_.push_back(StateValueDescriptor::Duplicate(
id));
1221 void PushPlain(MachineType type) {
1222 fields_.push_back(StateValueDescriptor::Plain(type));
1224 void PushOptimizedOut() {
1225 fields_.push_back(StateValueDescriptor::OptimizedOut());
1228 iterator begin() {
return iterator(fields_.begin(), nested_.begin()); }
1229 iterator end() {
return iterator(fields_.end(), nested_.end()); }
1232 ZoneVector<StateValueDescriptor> fields_;
1233 ZoneVector<StateValueList*> nested_;
1240 size_t parameters_count,
size_t locals_count,
1245 FrameStateType
type()
const {
return type_; }
1246 BailoutId bailout_id()
const {
return bailout_id_; }
1248 size_t parameters_count()
const {
return parameters_count_; }
1249 size_t locals_count()
const {
return locals_count_; }
1250 size_t stack_count()
const {
return stack_count_; }
1253 bool HasContext()
const {
1254 return FrameStateFunctionInfo::IsJSFunctionType(type_) ||
1255 type_ == FrameStateType::kBuiltinContinuation ||
1256 type_ == FrameStateType::kConstructStub;
1259 size_t GetSize()
const;
1260 size_t GetTotalSize()
const;
1261 size_t GetFrameCount()
const;
1262 size_t GetJSFrameCount()
const;
1266 static const int kImpossibleValue = 0xdead;
1269 FrameStateType type_;
1272 size_t parameters_count_;
1273 size_t locals_count_;
1274 size_t stack_count_;
1287 : descriptor_(descriptor),
1290 feedback_(feedback) {}
1293 DeoptimizeKind kind()
const {
return kind_; }
1294 DeoptimizeReason reason()
const {
return reason_; }
1299 DeoptimizeKind kind_ = DeoptimizeKind::kEager;
1300 DeoptimizeReason reason_ = DeoptimizeReason::kUnknown;
1307 :
public NON_EXPORTED_BASE(ZoneObject) {
1313 void SetInput(
size_t offset,
int virtual_register);
1314 void RenameInput(
size_t offset,
int virtual_register);
1316 int virtual_register()
const {
return virtual_register_; }
1317 const IntVector& operands()
const {
return operands_; }
1325 const int virtual_register_;
1332 :
public NON_EXPORTED_BASE(ZoneObject) {
1335 RpoNumber loop_end,
bool deferred,
bool handler);
1338 int first_instruction_index()
const {
1339 DCHECK_LE(0, code_start_);
1340 DCHECK_LT(0, code_end_);
1341 DCHECK_GE(code_end_, code_start_);
1344 int last_instruction_index()
const {
1345 DCHECK_LE(0, code_start_);
1346 DCHECK_LT(0, code_end_);
1347 DCHECK_GE(code_end_, code_start_);
1348 return code_end_ - 1;
1351 int32_t code_start()
const {
return code_start_; }
1352 void set_code_start(int32_t start) { code_start_ = start; }
1354 int32_t code_end()
const {
return code_end_; }
1355 void set_code_end(int32_t end) { code_end_ = end; }
1357 bool IsDeferred()
const {
return deferred_; }
1358 bool IsHandler()
const {
return handler_; }
1360 RpoNumber ao_number()
const {
return ao_number_; }
1361 RpoNumber rpo_number()
const {
return rpo_number_; }
1362 RpoNumber loop_header()
const {
return loop_header_; }
1364 DCHECK(IsLoopHeader());
1367 inline bool IsLoopHeader()
const {
return loop_end_.IsValid(); }
1368 inline bool ShouldAlign()
const {
return alignment_; }
1372 const Predecessors& predecessors()
const {
return predecessors_; }
1373 size_t PredecessorCount()
const {
return predecessors_.size(); }
1374 size_t PredecessorIndexOf(
RpoNumber rpo_number)
const;
1377 Successors& successors() {
return successors_; }
1378 const Successors& successors()
const {
return successors_; }
1379 size_t SuccessorCount()
const {
return successors_.size(); }
1386 void set_ao_number(
RpoNumber ao_number) { ao_number_ = ao_number; }
1388 void set_alignment(
bool val) { alignment_ = val; }
1390 bool needs_frame()
const {
return needs_frame_; }
1391 void mark_needs_frame() { needs_frame_ =
true; }
1393 bool must_construct_frame()
const {
return must_construct_frame_; }
1394 void mark_must_construct_frame() { must_construct_frame_ =
true; }
1396 bool must_deconstruct_frame()
const {
return must_deconstruct_frame_; }
1397 void mark_must_deconstruct_frame() { must_deconstruct_frame_ =
true; }
1407 int32_t code_start_;
1408 int32_t code_end_ = -1;
1409 const bool deferred_ = -1;
1410 const bool handler_;
1411 bool alignment_ =
false;
1412 bool needs_frame_ =
false;
1413 bool must_construct_frame_ =
false;
1414 bool must_deconstruct_frame_ =
false;
1427 typedef std::map<int, Constant, std::less<int>,
1438 :
public NON_EXPORTED_BASE(ZoneObject) {
1445 int NextVirtualRegister();
1446 int VirtualRegisterCount()
const {
return next_virtual_register_; }
1449 return *instruction_blocks_;
1454 int InstructionBlockCount()
const {
1455 return static_cast<int>(instruction_blocks_->size());
1459 return instruction_blocks_->at(rpo_number.ToSize());
1463 return instruction_blocks_->at(block->loop_end().ToSize() - 1)
1464 ->last_instruction_index();
1468 return instruction_blocks_->at(rpo_number.ToSize());
1473 static MachineRepresentation DefaultRepresentation() {
1474 return MachineType::PointerRepresentation();
1476 MachineRepresentation GetRepresentation(
int virtual_register)
const;
1477 void MarkAsRepresentation(MachineRepresentation rep,
int virtual_register);
1479 bool IsReference(
int virtual_register)
const {
1480 return CanBeTaggedPointer(GetRepresentation(virtual_register));
1482 bool IsFP(
int virtual_register)
const {
1483 return IsFloatingPoint(GetRepresentation(virtual_register));
1485 int representation_mask()
const {
return representation_mask_; }
1486 bool HasFPVirtualRegisters()
const {
1487 constexpr
int kFPRepMask =
1488 RepresentationBit(MachineRepresentation::kFloat32) |
1489 RepresentationBit(MachineRepresentation::kFloat64) |
1490 RepresentationBit(MachineRepresentation::kSimd128);
1491 return (representation_mask() & kFPRepMask) != 0;
1496 typedef InstructionDeque::const_iterator const_iterator;
1497 const_iterator begin()
const {
return instructions_.begin(); }
1498 const_iterator end()
const {
return instructions_.end(); }
1500 int LastInstructionIndex()
const {
1501 return static_cast<int>(instructions().size()) - 1;
1505 DCHECK_LE(0, index);
1506 DCHECK_GT(instructions_.size(), index);
1507 return instructions_[index];
1510 Isolate* isolate()
const {
return isolate_; }
1512 Zone* zone()
const {
return zone_; }
1519 int AddConstant(
int virtual_register,
Constant constant) {
1521 DCHECK_NE(Constant::kRpoNumber, constant.type());
1522 DCHECK(virtual_register >= 0 && virtual_register < next_virtual_register_);
1523 DCHECK(constants_.find(virtual_register) == constants_.end());
1524 constants_.insert(std::make_pair(virtual_register, constant));
1525 return virtual_register;
1527 Constant GetConstant(
int virtual_register)
const {
1528 ConstantMap::const_iterator it = constants_.find(virtual_register);
1529 DCHECK(it != constants_.end());
1530 DCHECK_EQ(virtual_register, it->first);
1535 Immediates& immediates() {
return immediates_; }
1538 if (constant.type() == Constant::kInt32 &&
1539 RelocInfo::IsNone(constant.rmode())) {
1542 int index =
static_cast<int>(immediates_.size());
1543 immediates_.push_back(constant);
1548 switch (op->type()) {
1549 case ImmediateOperand::INLINE:
1550 return Constant(op->inline_value());
1551 case ImmediateOperand::INDEXED: {
1552 int index = op->indexed_value();
1553 DCHECK_LE(0, index);
1554 DCHECK_GT(immediates_.size(), index);
1555 return immediates_[index];
1562 DeoptimizeKind kind, DeoptimizeReason reason,
1565 int GetDeoptimizationEntryCount()
const {
1566 return static_cast<int>(deoptimization_entries_.size());
1575 bool ContainsCall()
const {
1577 if (instr->IsCall())
return true;
1585 void PrintBlock(
int block_id)
const;
1587 void ValidateEdgeSplitForm()
const;
1588 void ValidateDeferredBlockExitPaths()
const;
1589 void ValidateDeferredBlockEntryPaths()
const;
1590 void ValidateSSA()
const;
1592 static void SetRegisterConfigurationForTesting(
1594 static void ClearRegisterConfigurationForTesting();
1596 void RecomputeAssemblyOrderForTesting();
1599 friend V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
1608 void ComputeAssemblyOrder();
1615 ConstantMap constants_;
1618 int next_virtual_register_;
1621 int representation_mask_;
1630 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
1637 #endif // V8_COMPILER_BACKEND_INSTRUCTION_H_