v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
common-operator.cc
Go to the documentation of this file.
1// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <optional>
8
9#include "src/base/hashing.h"
12#include "src/compiler/node.h"
16#include "src/zone/zone.h"
17
18namespace v8 {
19namespace internal {
20
21std::ostream& operator<<(std::ostream& os, BranchHint hint) {
22 switch (hint) {
24 return os << "None";
26 return os << "True";
28 return os << "False";
29 }
31}
32
33namespace compiler {
34
35std::ostream& operator<<(std::ostream& os, BranchSemantics semantics) {
36 switch (semantics) {
38 return os << "JS";
40 return os << "Machine";
42 return os << "Unspecified";
43 }
45}
46
47#if V8_ENABLE_WEBASSEMBLY
48std::ostream& operator<<(std::ostream& os, TrapId trap_id) {
49 switch (trap_id) {
50#define TRAP_CASE(Name) \
51 case TrapId::k##Name: \
52 return os << #Name;
54#undef TRAP_CASE
55 }
57}
58
59TrapId TrapIdOf(const Operator* const op) {
60 DCHECK(op->opcode() == IrOpcode::kTrapIf ||
61 op->opcode() == IrOpcode::kTrapUnless);
62 return OpParameter<TrapId>(op);
63}
64#endif // V8_ENABLE_WEBASSEMBLY
65
66bool operator==(const BranchParameters& lhs, const BranchParameters& rhs) {
67 return lhs.semantics() == rhs.semantics() && lhs.hint() == rhs.hint();
68}
69
70size_t hash_value(const BranchParameters& p) {
71 return base::hash_combine(p.semantics(), p.hint());
72}
73
74std::ostream& operator<<(std::ostream& os, const BranchParameters& p) {
75 return os << p.semantics() << ", " << p.hint();
76}
77
79 DCHECK_EQ(op->opcode(), IrOpcode::kBranch);
81}
82
84 switch (op->opcode()) {
85 case IrOpcode::kIfValue:
86 return IfValueParametersOf(op).hint();
87 case IrOpcode::kIfDefault:
88 return OpParameter<BranchHint>(op);
89 // TODO(nicohartmann@): Should remove all uses of BranchHintOf for branches
90 // and replace with BranchParametersOf.
91 case IrOpcode::kBranch:
92 return BranchParametersOf(op).hint();
93 default:
95 }
96}
97
98bool operator==(const AssertParameters& lhs, const AssertParameters& rhs) {
99 return lhs.semantics() == rhs.semantics() &&
100 strcmp(lhs.condition_string(), rhs.condition_string()) == 0 &&
101 strcmp(lhs.file(), rhs.file()) == 0 && lhs.line() == rhs.line();
102}
103
104size_t hash_value(const AssertParameters& p) {
105 return base::hash_combine(
106 p.semantics(),
109 p.condition_string() + std::strlen(p.condition_string())),
110 base::hash_range(p.file(), p.file() + std::strlen(p.file())), p.line());
111}
112
113std::ostream& operator<<(std::ostream& os, const AssertParameters& p) {
114 return os << p.semantics() << ", " << p.condition_string() << ", " << p.file()
115 << ", " << p.line();
116}
117
119 DCHECK_EQ(op->opcode(), IrOpcode::kAssert);
121}
122
123int ValueInputCountOfReturn(Operator const* const op) {
124 DCHECK_EQ(IrOpcode::kReturn, op->opcode());
125 // Return nodes have a hidden input at index 0 which we ignore in the value
126 // input count.
127 return op->ValueInputCount() - 1;
128}
129
131 return lhs.reason() == rhs.reason() && lhs.feedback() == rhs.feedback();
132}
133
135 return !(lhs == rhs);
136}
137
139 FeedbackSource::Hash feebdack_hash;
140 return base::hash_combine(p.reason(), feebdack_hash(p.feedback()));
141}
142
143std::ostream& operator<<(std::ostream& os, DeoptimizeParameters p) {
144 return os << p.reason() << ", " << p.feedback();
145}
146
148 DCHECK(op->opcode() == IrOpcode::kDeoptimize ||
149 op->opcode() == IrOpcode::kDeoptimizeIf ||
150 op->opcode() == IrOpcode::kDeoptimizeUnless);
152}
153
154bool operator==(SelectParameters const& lhs, SelectParameters const& rhs) {
155 return lhs.representation() == rhs.representation() &&
156 lhs.hint() == rhs.hint() && lhs.semantics() == rhs.semantics();
157}
158
159
160bool operator!=(SelectParameters const& lhs, SelectParameters const& rhs) {
161 return !(lhs == rhs);
162}
163
164
165size_t hash_value(SelectParameters const& p) {
166 return base::hash_combine(p.representation(), p.hint(), p.semantics());
167}
168
169
170std::ostream& operator<<(std::ostream& os, SelectParameters const& p) {
171 return os << p.representation() << ", " << p.hint() << ", " << p.semantics();
172}
173
174
176 DCHECK_EQ(IrOpcode::kSelect, op->opcode());
178}
179
180CallDescriptor const* CallDescriptorOf(const Operator* const op) {
181 DCHECK(op->opcode() == IrOpcode::kCall ||
182 op->opcode() == IrOpcode::kTailCall);
184}
185
186size_t ProjectionIndexOf(const Operator* const op) {
187 DCHECK_EQ(IrOpcode::kProjection, op->opcode());
188 return OpParameter<size_t>(op);
189}
190
191
193 DCHECK_EQ(IrOpcode::kPhi, op->opcode());
195}
196
198 DCHECK_EQ(IrOpcode::kLoopExitValue, op->opcode());
200}
201
202int ParameterIndexOf(const Operator* const op) {
203 DCHECK_EQ(IrOpcode::kParameter, op->opcode());
204 return OpParameter<ParameterInfo>(op).index();
205}
206
207
208const ParameterInfo& ParameterInfoOf(const Operator* const op) {
209 DCHECK_EQ(IrOpcode::kParameter, op->opcode());
211}
212
213
214bool operator==(ParameterInfo const& lhs, ParameterInfo const& rhs) {
215 return lhs.index() == rhs.index();
216}
217
218
219bool operator!=(ParameterInfo const& lhs, ParameterInfo const& rhs) {
220 return !(lhs == rhs);
221}
222
223
224size_t hash_value(ParameterInfo const& p) { return p.index(); }
225
226
227std::ostream& operator<<(std::ostream& os, ParameterInfo const& i) {
228 os << i.index();
229 if (i.debug_name()) os << ", debug name: " << i.debug_name();
230 return os;
231}
232
233std::ostream& operator<<(std::ostream& os, ObjectStateInfo const& i) {
234 return os << "id:" << i.object_id() << ", size:" << i.size();
235}
236
237size_t hash_value(ObjectStateInfo const& p) {
238 return base::hash_combine(p.object_id(), p.size());
239}
240
241std::ostream& operator<<(std::ostream& os, TypedObjectStateInfo const& i) {
242 return os << "id:" << i.object_id() << ", " << i.machine_types();
243}
244
247}
248
250 RelocatablePtrConstantInfo const& rhs) {
251 return lhs.rmode() == rhs.rmode() && lhs.value() == rhs.value() &&
252 lhs.type() == rhs.type();
253}
254
256 RelocatablePtrConstantInfo const& rhs) {
257 return !(lhs == rhs);
258}
259
261 return base::hash_combine(p.value(), int8_t{p.rmode()}, p.type());
262}
263
264std::ostream& operator<<(std::ostream& os,
266 return os << p.value() << ", " << static_cast<int>(p.rmode()) << ", "
267 << p.type();
268}
269
271 SparseInputMask::BitMaskType bit_mask, Node* parent)
272 : bit_mask_(bit_mask), parent_(parent), real_index_(0) {
273#if DEBUG
277 parent->InputCount());
278 }
279#endif
280}
281
283 DCHECK(!IsEnd());
284
285 if (IsReal()) {
286 ++real_index_;
287 }
288 bit_mask_ >>= 1;
289}
290
299
301 DCHECK(IsReal());
302 return parent_->InputAt(real_index_);
303}
304
309
311 return (bit_mask_ == kEndMarker) ||
313 real_index_ >= parent_->InputCount());
314}
315
321
326
327bool operator==(SparseInputMask const& lhs, SparseInputMask const& rhs) {
328 return lhs.mask() == rhs.mask();
329}
330
331bool operator!=(SparseInputMask const& lhs, SparseInputMask const& rhs) {
332 return !(lhs == rhs);
333}
334
335size_t hash_value(SparseInputMask const& p) {
336 return base::hash_value(p.mask());
337}
338
339std::ostream& operator<<(std::ostream& os, SparseInputMask const& p) {
340 if (p.IsDense()) {
341 return os << "dense";
342 } else {
345
346 os << "sparse:";
347
350 os << "^";
351 } else {
352 os << ".";
353 }
354 mask >>= 1;
355 }
356 return os;
357 }
358}
359
361 TypedStateValueInfo const& rhs) {
362 return lhs.machine_types() == rhs.machine_types() &&
364}
365
367 TypedStateValueInfo const& rhs) {
368 return !(lhs == rhs);
369}
370
374
375std::ostream& operator<<(std::ostream& os, TypedStateValueInfo const& p) {
376 return os << p.machine_types() << ", " << p.sparse_input_mask();
377}
378
379size_t hash_value(RegionObservability observability) {
380 return static_cast<size_t>(observability);
381}
382
383std::ostream& operator<<(std::ostream& os, RegionObservability observability) {
384 switch (observability) {
386 return os << "observable";
388 return os << "not-observable";
389 }
390 UNREACHABLE();
391}
392
394 DCHECK_EQ(IrOpcode::kBeginRegion, op->opcode());
396}
397
399 DCHECK_EQ(IrOpcode::kTypeGuard, op->opcode());
400 return OpParameter<Type>(op);
401}
402
403std::ostream& operator<<(std::ostream& os,
404 const ZoneVector<MachineType>* types) {
405 // Print all the MachineTypes, separated by commas.
406 bool first = true;
407 for (MachineType elem : *types) {
408 if (!first) {
409 os << ", ";
410 }
411 first = false;
412 os << elem;
413 }
414 return os;
415}
416
417int OsrValueIndexOf(Operator const* op) {
418 DCHECK_EQ(IrOpcode::kOsrValue, op->opcode());
419 return OpParameter<int>(op);
420}
421
423 DCHECK(op->opcode() == IrOpcode::kStateValues ||
424 op->opcode() == IrOpcode::kTypedStateValues);
425
426 if (op->opcode() == IrOpcode::kTypedStateValues) {
427 return OpParameter<TypedStateValueInfo>(op).sparse_input_mask();
428 }
430}
431
433 DCHECK(op->opcode() == IrOpcode::kTypedObjectState ||
434 op->opcode() == IrOpcode::kTypedStateValues);
435
436 if (op->opcode() == IrOpcode::kTypedStateValues) {
437 return OpParameter<TypedStateValueInfo>(op).machine_types();
438 }
439 return OpParameter<TypedObjectStateInfo>(op).machine_types();
440}
441
443 IfValueParameters const& r) {
444 return l.value() == r.value() &&
445 l.comparison_order() == r.comparison_order() && l.hint() == r.hint();
446}
447
449 return base::hash_combine(p.value(), p.comparison_order(), p.hint());
450}
451
452V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
453 IfValueParameters const& p) {
454 out << p.value() << " (order " << p.comparison_order() << ", hint "
455 << p.hint() << ")";
456 return out;
457}
458
460 DCHECK(op->opcode() == IrOpcode::kIfValue);
462}
463
466 return p1.semantics() == p2.semantics() &&
467 p1.override_output_type() == p2.override_output_type();
468}
469
475
476V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
477 const SLVerifierHintParameters& p) {
478 if (p.semantics()) {
479 p.semantics()->PrintTo(out);
480 } else {
481 out << "nullptr";
482 }
483 if (const auto& t = p.override_output_type()) {
484 out << ", ";
485 t->PrintTo(out);
486 } else {
487 out << ", nullopt";
488 }
489 return out;
490}
491
493 DCHECK_EQ(op->opcode(), IrOpcode::kSLVerifierHint);
495}
496
498 const ExitMachineGraphParameters& rhs) {
499 return lhs.output_representation() == rhs.output_representation() &&
500 lhs.output_type().Equals(rhs.output_type());
501}
502
506
508 std::ostream& os, const ExitMachineGraphParameters& p) {
509 return os << p.output_representation() << ", " << p.output_type();
510}
511
513 const Operator* op) {
514 DCHECK_EQ(op->opcode(), IrOpcode::kExitMachineGraph);
516}
517
518#define COMMON_CACHED_OP_LIST(V) \
519 V(Plug, Operator::kNoProperties, 0, 0, 0, 1, 0, 0) \
520 V(Dead, Operator::kFoldable, 0, 0, 0, 1, 1, 1) \
521 V(Unreachable, Operator::kFoldable, 0, 1, 1, 1, 1, 0) \
522 V(IfTrue, Operator::kKontrol, 0, 0, 1, 0, 0, 1) \
523 V(IfFalse, Operator::kKontrol, 0, 0, 1, 0, 0, 1) \
524 V(IfSuccess, Operator::kKontrol, 0, 0, 1, 0, 0, 1) \
525 V(IfException, Operator::kKontrol, 0, 1, 1, 1, 1, 1) \
526 V(Throw, Operator::kKontrol, 0, 1, 1, 0, 0, 1) \
527 V(Terminate, Operator::kKontrol, 0, 1, 1, 0, 0, 1) \
528 V(LoopExit, Operator::kKontrol, 0, 0, 2, 0, 0, 1) \
529 V(LoopExitEffect, Operator::kNoThrow, 0, 1, 1, 0, 1, 0) \
530 V(Checkpoint, Operator::kKontrol, 0, 1, 1, 0, 1, 0) \
531 V(FinishRegion, Operator::kKontrol, 1, 1, 0, 1, 1, 0) \
532 V(Retain, Operator::kKontrol, 1, 1, 0, 0, 1, 0)
533
534#define CACHED_LOOP_EXIT_VALUE_LIST(V) V(kTagged)
535
536#define CACHED_BRANCH_LIST(V) \
537 V(JS, None) \
538 V(JS, True) \
539 V(JS, False) \
540 V(Machine, None) \
541 V(Machine, True) \
542 V(Machine, False) \
543 V(Unspecified, None) \
544 V(Unspecified, True) \
545 V(Unspecified, False)
546
547#define CACHED_RETURN_LIST(V) \
548 V(1) \
549 V(2) \
550 V(3) \
551 V(4)
552
553#define CACHED_END_LIST(V) \
554 V(1) \
555 V(2) \
556 V(3) \
557 V(4) \
558 V(5) \
559 V(6) \
560 V(7) \
561 V(8)
562
563
564#define CACHED_EFFECT_PHI_LIST(V) \
565 V(1) \
566 V(2) \
567 V(3) \
568 V(4) \
569 V(5) \
570 V(6)
571
572#define CACHED_INDUCTION_VARIABLE_PHI_LIST(V) \
573 V(4) \
574 V(5) \
575 V(6) \
576 V(7)
577
578#define CACHED_LOOP_LIST(V) \
579 V(1) \
580 V(2)
581
582
583#define CACHED_MERGE_LIST(V) \
584 V(1) \
585 V(2) \
586 V(3) \
587 V(4) \
588 V(5) \
589 V(6) \
590 V(7) \
591 V(8)
592
593#define CACHED_DEOPTIMIZE_LIST(V) \
594 V(MinusZero) \
595 V(WrongMap) \
596 V(InsufficientTypeFeedbackForGenericKeyedAccess) \
597 V(InsufficientTypeFeedbackForGenericNamedAccess)
598
599#define CACHED_DEOPTIMIZE_IF_LIST(V) \
600 V(DivisionByZero) \
601 V(Hole) \
602 V(MinusZero) \
603 V(Overflow) \
604 V(Smi)
605
606#define CACHED_DEOPTIMIZE_UNLESS_LIST(V) \
607 V(LostPrecision) \
608 V(LostPrecisionOrNaN) \
609 V(NotAHeapNumber) \
610 V(NotANumberOrOddball) \
611 V(NotASmi) \
612 V(OutOfBounds) \
613 V(WrongInstanceType) \
614 V(WrongMap)
615
616#define CACHED_TRAP_IF_LIST(V) \
617 V(TrapDivUnrepresentable) \
618 V(TrapFloatUnrepresentable)
619
620// The reason for a trap.
621#define CACHED_TRAP_UNLESS_LIST(V) \
622 V(TrapUnreachable) \
623 V(TrapMemOutOfBounds) \
624 V(TrapDivByZero) \
625 V(TrapDivUnrepresentable) \
626 V(TrapRemByZero) \
627 V(TrapFloatUnrepresentable) \
628 V(TrapTableOutOfBounds) \
629 V(TrapFuncSigMismatch)
630
631#define CACHED_PARAMETER_LIST(V) \
632 V(0) \
633 V(1) \
634 V(2) \
635 V(3) \
636 V(4) \
637 V(5) \
638 V(6)
639
640
641#define CACHED_PHI_LIST(V) \
642 V(kTagged, 1) \
643 V(kTagged, 2) \
644 V(kTagged, 3) \
645 V(kTagged, 4) \
646 V(kTagged, 5) \
647 V(kTagged, 6) \
648 V(kBit, 2) \
649 V(kFloat64, 2) \
650 V(kWord32, 2)
651
652
653#define CACHED_PROJECTION_LIST(V) \
654 V(0) \
655 V(1)
656
657
658#define CACHED_STATE_VALUES_LIST(V) \
659 V(0) \
660 V(1) \
661 V(2) \
662 V(3) \
663 V(4) \
664 V(5) \
665 V(6) \
666 V(7) \
667 V(8) \
668 V(10) \
669 V(11) \
670 V(12) \
671 V(13) \
672 V(14)
673
674
676#define CACHED(Name, properties, value_input_count, effect_input_count, \
677 control_input_count, value_output_count, effect_output_count, \
678 control_output_count) \
679 struct Name##Operator final : public Operator { \
680 Name##Operator() \
681 : Operator(IrOpcode::k##Name, properties, #Name, value_input_count, \
682 effect_input_count, control_input_count, \
683 value_output_count, effect_output_count, \
684 control_output_count) {} \
685 }; \
686 Name##Operator k##Name##Operator;
688#undef CACHED
689
690 template <size_t kInputCount>
691 struct EndOperator final : public Operator {
693 : Operator( // --
694 IrOpcode::kEnd, Operator::kKontrol, // opcode
695 "End", // name
696 0, 0, kInputCount, 0, 0, 0) {} // counts
697 };
698#define CACHED_END(input_count) \
699 EndOperator<input_count> kEnd##input_count##Operator;
701#undef CACHED_END
702
703 template <size_t kValueInputCount>
704 struct ReturnOperator final : public Operator {
706 : Operator( // --
707 IrOpcode::kReturn, Operator::kNoThrow, // opcode
708 "Return", // name
709 kValueInputCount + 1, 1, 1, 0, 0, 1) {} // counts
710 };
711#define CACHED_RETURN(value_input_count) \
712 ReturnOperator<value_input_count> kReturn##value_input_count##Operator;
714#undef CACHED_RETURN
715
716 template <BranchSemantics semantics, BranchHint hint>
717 struct BranchOperator final : public Operator1<BranchParameters> {
720 IrOpcode::kBranch, Operator::kKontrol, // opcode
721 "Branch", // name
722 1, 0, 1, 0, 0, 2, // counts
723 {semantics, hint}) {} // parameter
724 };
725#define CACHED_BRANCH(Semantics, Hint) \
726 BranchOperator<BranchSemantics::k##Semantics, BranchHint::k##Hint> \
727 kBranch##Semantics##Hint##Operator;
729#undef CACHED_BRANCH
730
731 template <int kEffectInputCount>
732 struct EffectPhiOperator final : public Operator {
734 : Operator( // --
735 IrOpcode::kEffectPhi, Operator::kKontrol, // opcode
736 "EffectPhi", // name
737 0, kEffectInputCount, 1, 0, 1, 0) {} // counts
738 };
739#define CACHED_EFFECT_PHI(input_count) \
740 EffectPhiOperator<input_count> kEffectPhi##input_count##Operator;
742#undef CACHED_EFFECT_PHI
743
744 template <RegionObservability kRegionObservability>
745 struct BeginRegionOperator final : public Operator1<RegionObservability> {
748 IrOpcode::kBeginRegion, Operator::kKontrol, // opcode
749 "BeginRegion", // name
750 0, 1, 0, 0, 1, 0, // counts
751 kRegionObservability) {} // parameter
752 };
753 BeginRegionOperator<RegionObservability::kObservable>
757
758 template <size_t kInputCount>
759 struct LoopOperator final : public Operator {
761 : Operator( // --
762 IrOpcode::kLoop, Operator::kKontrol, // opcode
763 "Loop", // name
764 0, 0, kInputCount, 0, 0, 1) {} // counts
765 };
766#define CACHED_LOOP(input_count) \
767 LoopOperator<input_count> kLoop##input_count##Operator;
769#undef CACHED_LOOP
770
771 template <size_t kInputCount>
772 struct MergeOperator final : public Operator {
774 : Operator( // --
775 IrOpcode::kMerge, Operator::kKontrol, // opcode
776 "Merge", // name
777 0, 0, kInputCount, 0, 0, 1) {} // counts
778 };
779#define CACHED_MERGE(input_count) \
780 MergeOperator<input_count> kMerge##input_count##Operator;
782#undef CACHED_MERGE
783
784 template <MachineRepresentation kRep>
785 struct LoopExitValueOperator final : public Operator1<MachineRepresentation> {
787 : Operator1<MachineRepresentation>(IrOpcode::kLoopExitValue,
788 Operator::kPure, "LoopExitValue", 1,
789 0, 1, 1, 0, 0, kRep) {}
790 };
791#define CACHED_LOOP_EXIT_VALUE(rep) \
792 LoopExitValueOperator<MachineRepresentation::rep> \
793 kLoopExitValue##rep##Operator;
795#undef CACHED_LOOP_EXIT_VALUE
796
797 template <DeoptimizeReason kReason>
798 struct DeoptimizeOperator final : public Operator1<DeoptimizeParameters> {
801 IrOpcode::kDeoptimize, // opcode
802 Operator::kFoldable | Operator::kNoThrow, // properties
803 "Deoptimize", // name
804 1, 1, 1, 0, 0, 1, // counts
806 };
807#define CACHED_DEOPTIMIZE(Reason) \
808 DeoptimizeOperator<DeoptimizeReason::k##Reason> kDeoptimize##Reason##Operator;
810#undef CACHED_DEOPTIMIZE
811
812 template <DeoptimizeReason kReason>
813 struct DeoptimizeIfOperator final : public Operator1<DeoptimizeParameters> {
816 IrOpcode::kDeoptimizeIf, // opcode
817 Operator::kFoldable | Operator::kNoThrow, // properties
818 "DeoptimizeIf", // name
819 2, 1, 1, 0, 1, 1, // counts
821 };
822#define CACHED_DEOPTIMIZE_IF(Reason) \
823 DeoptimizeIfOperator<DeoptimizeReason::k##Reason> \
824 kDeoptimizeIf##Reason##Operator;
826#undef CACHED_DEOPTIMIZE_IF
827
828 template <DeoptimizeReason kReason>
830 : public Operator1<DeoptimizeParameters> {
833 IrOpcode::kDeoptimizeUnless, // opcode
834 Operator::kFoldable | Operator::kNoThrow, // properties
835 "DeoptimizeUnless", // name
836 2, 1, 1, 0, 1, 1, // counts
838 };
839#define CACHED_DEOPTIMIZE_UNLESS(Reason) \
840 DeoptimizeUnlessOperator<DeoptimizeReason::k##Reason> \
841 kDeoptimizeUnless##Reason##Operator;
843#undef CACHED_DEOPTIMIZE_UNLESS
844
845#if V8_ENABLE_WEBASSEMBLY
846 template <TrapId trap_id, bool has_frame_state>
847 struct TrapIfOperator final : public Operator1<TrapId> {
848 TrapIfOperator()
849 : Operator1<TrapId>( // --
850 IrOpcode::kTrapIf, // opcode
851 Operator::kFoldable | Operator::kNoThrow, // properties
852 "TrapIf", // name
853 1 + has_frame_state, 1, 1, 0, 1, 1, // counts
854 trap_id) {} // parameter
855 };
856#define CACHED_TRAP_IF(Trap) \
857 TrapIfOperator<TrapId::k##Trap, true> kTrapIf##Trap##OperatorWithFrameState;
858 CACHED_TRAP_IF_LIST(CACHED_TRAP_IF)
859#undef CACHED_TRAP_IF
860
861#define CACHED_TRAP_IF(Trap) \
862 TrapIfOperator<TrapId::k##Trap, false> \
863 kTrapIf##Trap##OperatorWithoutFrameState;
864 CACHED_TRAP_IF_LIST(CACHED_TRAP_IF)
865#undef CACHED_TRAP_IF
866
867 template <TrapId trap_id, bool has_frame_state>
868 struct TrapUnlessOperator final : public Operator1<TrapId> {
869 TrapUnlessOperator()
870 : Operator1<TrapId>( // --
871 IrOpcode::kTrapUnless, // opcode
872 Operator::kFoldable | Operator::kNoThrow, // properties
873 "TrapUnless", // name
874 1 + has_frame_state, 1, 1, 0, 1, 1, // counts
875 trap_id) {} // parameter
876 };
877#define CACHED_TRAP_UNLESS(Trap) \
878 TrapUnlessOperator<TrapId::k##Trap, true> \
879 kTrapUnless##Trap##OperatorWithFrameState;
880 CACHED_TRAP_UNLESS_LIST(CACHED_TRAP_UNLESS)
881#undef CACHED_TRAP_UNLESS
882
883#define CACHED_TRAP_UNLESS(Trap) \
884 TrapUnlessOperator<TrapId::k##Trap, false> \
885 kTrapUnless##Trap##OperatorWithoutFrameState;
886 CACHED_TRAP_UNLESS_LIST(CACHED_TRAP_UNLESS)
887#undef CACHED_TRAP_UNLESS
888
889#endif // V8_ENABLE_WEBASSEMBLY
890
891 template <MachineRepresentation kRep, int kInputCount>
892 struct PhiOperator final : public Operator1<MachineRepresentation> {
895 IrOpcode::kPhi, Operator::kPure, // opcode
896 "Phi", // name
897 kInputCount, 0, 1, 1, 0, 0, // counts
898 kRep) {} // parameter
899 };
900#define CACHED_PHI(rep, input_count) \
901 PhiOperator<MachineRepresentation::rep, input_count> \
902 kPhi##rep##input_count##Operator;
904#undef CACHED_PHI
905
906 template <int kInputCount>
909 : Operator( //--
910 IrOpcode::kInductionVariablePhi, Operator::kPure, // opcode
911 "InductionVariablePhi", // name
912 kInputCount, 0, 1, 1, 0, 0) {} // counts
913 };
914#define CACHED_INDUCTION_VARIABLE_PHI(input_count) \
915 InductionVariablePhiOperator<input_count> \
916 kInductionVariablePhi##input_count##Operator;
918#undef CACHED_INDUCTION_VARIABLE_PHI
919
920 template <int kIndex>
921 struct ParameterOperator final : public Operator1<ParameterInfo> {
923 : Operator1<ParameterInfo>( // --
924 IrOpcode::kParameter, Operator::kPure, // opcode
925 "Parameter", // name
926 1, 0, 0, 1, 0, 0, // counts,
927 ParameterInfo(kIndex, nullptr)) {} // parameter and name
928 };
929#define CACHED_PARAMETER(index) \
930 ParameterOperator<index> kParameter##index##Operator;
932#undef CACHED_PARAMETER
933
934 template <size_t kIndex>
935 struct ProjectionOperator final : public Operator1<size_t> {
937 : Operator1<size_t>( // --
938 IrOpcode::kProjection, // opcode
939 Operator::kPure, // flags
940 "Projection", // name
941 1, 0, 1, 1, 0, 0, // counts,
942 kIndex) {} // parameter
943 };
944#define CACHED_PROJECTION(index) \
945 ProjectionOperator<index> kProjection##index##Operator;
947#undef CACHED_PROJECTION
948
949 template <int kInputCount>
950 struct StateValuesOperator final : public Operator1<SparseInputMask> {
952 : Operator1<SparseInputMask>( // --
953 IrOpcode::kStateValues, // opcode
954 Operator::kPure, // flags
955 "StateValues", // name
956 kInputCount, 0, 0, 1, 0, 0, // counts
957 SparseInputMask::Dense()) {} // parameter
958 };
959#define CACHED_STATE_VALUES(input_count) \
960 StateValuesOperator<input_count> kStateValues##input_count##Operator;
962#undef CACHED_STATE_VALUES
963};
964
965namespace {
966DEFINE_LAZY_LEAKY_OBJECT_GETTER(CommonOperatorGlobalCache,
967 GetCommonOperatorGlobalCache)
968} // namespace
969
971 : cache_(*GetCommonOperatorGlobalCache()), zone_(zone) {}
972
973#define CACHED(Name, properties, value_input_count, effect_input_count, \
974 control_input_count, value_output_count, effect_output_count, \
975 control_output_count) \
976 const Operator* CommonOperatorBuilder::Name() { \
977 return &cache_.k##Name##Operator; \
978 }
980#undef CACHED
981
982
983const Operator* CommonOperatorBuilder::End(size_t control_input_count) {
984 switch (control_input_count) {
985#define CACHED_END(input_count) \
986 case input_count: \
987 return &cache_.kEnd##input_count##Operator;
989#undef CACHED_END
990 default:
991 break;
992 }
993 // Uncached.
994 return zone()->New<Operator>( //--
995 IrOpcode::kEnd, Operator::kKontrol, // opcode
996 "End", // name
997 0, 0, control_input_count, 0, 0, 0); // counts
998}
999
1000const Operator* CommonOperatorBuilder::Return(int value_input_count) {
1001 switch (value_input_count) {
1002#define CACHED_RETURN(input_count) \
1003 case input_count: \
1004 return &cache_.kReturn##input_count##Operator;
1006#undef CACHED_RETURN
1007 default:
1008 break;
1009 }
1010 // Uncached.
1011 return zone()->New<Operator>( //--
1012 IrOpcode::kReturn, Operator::kNoThrow, // opcode
1013 "Return", // name
1014 value_input_count + 1, 1, 1, 0, 0, 1); // counts
1015}
1016
1018 return zone()->New<Operator1<const char*>>(
1019 IrOpcode::kStaticAssert, Operator::kFoldable, "StaticAssert", 1, 1, 0, 0,
1020 1, 0, source);
1021}
1022
1024 const Operator* semantics,
1025 const std::optional<Type>& override_output_type) {
1027 IrOpcode::kSLVerifierHint, Operator::kNoProperties, "SLVerifierHint", 1,
1028 0, 0, 1, 0, 0, SLVerifierHintParameters(semantics, override_output_type));
1029}
1030
1032 BranchSemantics semantics) {
1033#define CACHED_BRANCH(Semantics, Hint) \
1034 if (semantics == BranchSemantics::k##Semantics && \
1035 hint == BranchHint::k##Hint) { \
1036 return &cache_.kBranch##Semantics##Hint##Operator; \
1037 }
1039#undef CACHED_BRANCH
1040 UNREACHABLE();
1041}
1042
1044 DeoptimizeReason reason, FeedbackSource const& feedback) {
1045#define CACHED_DEOPTIMIZE(Reason) \
1046 if (reason == DeoptimizeReason::k##Reason && !feedback.IsValid()) { \
1047 return &cache_.kDeoptimize##Reason##Operator; \
1048 }
1050#undef CACHED_DEOPTIMIZE
1051 // Uncached
1052 DeoptimizeParameters parameter(reason, feedback);
1053 return zone()->New<Operator1<DeoptimizeParameters>>( // --
1054 IrOpcode::kDeoptimize, // opcodes
1056 "Deoptimize", // name
1057 1, 1, 1, 0, 0, 1, // counts
1058 parameter); // parameter
1059}
1060
1062 DeoptimizeReason reason, FeedbackSource const& feedback) {
1063#define CACHED_DEOPTIMIZE_IF(Reason) \
1064 if (reason == DeoptimizeReason::k##Reason && !feedback.IsValid()) { \
1065 return &cache_.kDeoptimizeIf##Reason##Operator; \
1066 }
1068#undef CACHED_DEOPTIMIZE_IF
1069 // Uncached
1070 DeoptimizeParameters parameter(reason, feedback);
1071 return zone()->New<Operator1<DeoptimizeParameters>>( // --
1072 IrOpcode::kDeoptimizeIf, // opcode
1074 "DeoptimizeIf", // name
1075 2, 1, 1, 0, 1, 1, // counts
1076 parameter); // parameter
1077}
1078
1080 DeoptimizeReason reason, FeedbackSource const& feedback) {
1081#define CACHED_DEOPTIMIZE_UNLESS(Reason) \
1082 if (reason == DeoptimizeReason::k##Reason && !feedback.IsValid()) { \
1083 return &cache_.kDeoptimizeUnless##Reason##Operator; \
1084 }
1086#undef CACHED_DEOPTIMIZE_UNLESS
1087 // Uncached
1088 DeoptimizeParameters parameter(reason, feedback);
1089 return zone()->New<Operator1<DeoptimizeParameters>>( // --
1090 IrOpcode::kDeoptimizeUnless, // opcode
1092 "DeoptimizeUnless", // name
1093 2, 1, 1, 0, 1, 1, // counts
1094 parameter); // parameter
1095}
1096
1098 const char* condition_string,
1099 const char* file, int line) {
1100 AssertParameters parameter(semantics, condition_string, file, line);
1101 return zone()->New<Operator1<AssertParameters>>( // --
1102 IrOpcode::kAssert, // opcode
1104 "Assert", // name
1105 1, 1, 1, 0, 1, 0, // counts
1106 parameter); // parameter
1107}
1108
1109#if V8_ENABLE_WEBASSEMBLY
1110const Operator* CommonOperatorBuilder::TrapIf(TrapId trap_id,
1111 bool has_frame_state) {
1112 switch (trap_id) {
1113#define CACHED_TRAP_IF(Trap) \
1114 case TrapId::k##Trap: \
1115 return has_frame_state \
1116 ? static_cast<const Operator*>( \
1117 &cache_.kTrapIf##Trap##OperatorWithFrameState) \
1118 : &cache_.kTrapIf##Trap##OperatorWithoutFrameState;
1119 CACHED_TRAP_IF_LIST(CACHED_TRAP_IF)
1120#undef CACHED_TRAP_IF
1121 default:
1122 break;
1123 }
1124 // Uncached
1125 return zone()->New<Operator1<TrapId>>( // --
1126 IrOpcode::kTrapIf, // opcode
1128 "TrapIf", // name
1129 1 + has_frame_state, 1, 1, 0, 1, 1, // counts
1130 trap_id); // parameter
1131}
1132
1133const Operator* CommonOperatorBuilder::TrapUnless(TrapId trap_id,
1134 bool has_frame_state) {
1135 switch (trap_id) {
1136#define CACHED_TRAP_UNLESS(Trap) \
1137 case TrapId::k##Trap: \
1138 return has_frame_state \
1139 ? static_cast<const Operator*>( \
1140 &cache_.kTrapUnless##Trap##OperatorWithFrameState) \
1141 : &cache_.kTrapUnless##Trap##OperatorWithoutFrameState;
1142 CACHED_TRAP_UNLESS_LIST(CACHED_TRAP_UNLESS)
1143#undef CACHED_TRAP_UNLESS
1144 default:
1145 break;
1146 }
1147 // Uncached
1148 return zone()->New<Operator1<TrapId>>( // --
1149 IrOpcode::kTrapUnless, // opcode
1151 "TrapUnless", // name
1152 1 + has_frame_state, 1, 1, 0, 1, 1, // counts
1153 trap_id); // parameter
1154}
1155
1156#endif // V8_ENABLE_WEBASSEMBLY
1157
1158const Operator* CommonOperatorBuilder::Switch(size_t control_output_count) {
1159 return zone()->New<Operator>( // --
1160 IrOpcode::kSwitch, Operator::kKontrol, // opcode
1161 "Switch", // name
1162 1, 0, 1, 0, 0, control_output_count); // counts
1163}
1164
1166 int32_t comparison_order,
1167 BranchHint hint) {
1168 return zone()->New<Operator1<IfValueParameters>>( // --
1169 IrOpcode::kIfValue, Operator::kKontrol, // opcode
1170 "IfValue", // name
1171 0, 0, 1, 0, 0, 1, // counts
1172 IfValueParameters(index, comparison_order, hint)); // parameter
1173}
1174
1176 return zone()->New<Operator1<BranchHint>>( // --
1177 IrOpcode::kIfDefault, Operator::kKontrol, // opcode
1178 "IfDefault", // name
1179 0, 0, 1, 0, 0, 1, // counts
1180 hint); // parameter
1181}
1182
1183const Operator* CommonOperatorBuilder::Start(int value_output_count) {
1184 return zone()->New<Operator>( // --
1185 IrOpcode::kStart, Operator::kFoldable | Operator::kNoThrow, // opcode
1186 "Start", // name
1187 0, 0, 0, value_output_count, 1, 1); // counts
1188}
1189
1190
1191const Operator* CommonOperatorBuilder::Loop(int control_input_count) {
1192 switch (control_input_count) {
1193#define CACHED_LOOP(input_count) \
1194 case input_count: \
1195 return &cache_.kLoop##input_count##Operator;
1197#undef CACHED_LOOP
1198 default:
1199 break;
1200 }
1201 // Uncached.
1202 return zone()->New<Operator>( // --
1203 IrOpcode::kLoop, Operator::kKontrol, // opcode
1204 "Loop", // name
1205 0, 0, control_input_count, 0, 0, 1); // counts
1206}
1207
1208
1209const Operator* CommonOperatorBuilder::Merge(int control_input_count) {
1210 switch (control_input_count) {
1211#define CACHED_MERGE(input_count) \
1212 case input_count: \
1213 return &cache_.kMerge##input_count##Operator;
1215#undef CACHED_MERGE
1216 default:
1217 break;
1218 }
1219 // Uncached.
1220 return zone()->New<Operator>( // --
1221 IrOpcode::kMerge, Operator::kKontrol, // opcode
1222 "Merge", // name
1223 0, 0, control_input_count, 0, 0, 1); // counts
1224}
1225
1228 switch (rep) {
1229#define CACHED_LOOP_EXIT_VALUE(kRep) \
1230 case MachineRepresentation::kRep: \
1231 return &cache_.kLoopExitValue##kRep##Operator;
1232
1234#undef CACHED_LOOP_EXIT_VALUE
1235 default:
1236 // Uncached.
1237 return zone()->New<Operator1<MachineRepresentation>>( // --
1238 IrOpcode::kLoopExitValue, Operator::kPure, // opcode
1239 "LoopExitValue", // name
1240 1, 0, 1, 1, 0, 0, // counts
1241 rep); // parameter
1242 }
1243}
1244
1246 const char* debug_name) {
1247 if (!debug_name) {
1248 switch (index) {
1249#define CACHED_PARAMETER(index) \
1250 case index: \
1251 return &cache_.kParameter##index##Operator;
1253#undef CACHED_PARAMETER
1254 default:
1255 break;
1256 }
1257 }
1258 // Uncached.
1259 return zone()->New<Operator1<ParameterInfo>>( // --
1260 IrOpcode::kParameter, Operator::kPure, // opcode
1261 "Parameter", // name
1262 1, 0, 0, 1, 0, 0, // counts
1263 ParameterInfo(index, debug_name)); // parameter info
1264}
1265
1267 return zone()->New<Operator1<int>>( // --
1268 IrOpcode::kOsrValue, Operator::kNoProperties, // opcode
1269 "OsrValue", // name
1270 0, 0, 1, 1, 0, 0, // counts
1271 index); // parameter
1272}
1273
1275 return zone()->New<Operator1<int32_t>>( // --
1276 IrOpcode::kInt32Constant, Operator::kPure, // opcode
1277 "Int32Constant", // name
1278 0, 0, 0, 1, 0, 0, // counts
1279 value); // parameter
1280}
1281
1282
1284 return zone()->New<Operator1<int64_t>>( // --
1285 IrOpcode::kInt64Constant, Operator::kPure, // opcode
1286 "Int64Constant", // name
1287 0, 0, 0, 1, 0, 0, // counts
1288 value); // parameter
1289}
1290
1292 return zone()->New<Operator1<int32_t>>( // --
1293 IrOpcode::kTaggedIndexConstant, Operator::kPure, // opcode
1294 "TaggedIndexConstant", // name
1295 0, 0, 0, 1, 0, 0, // counts
1296 value); // parameter
1297}
1298
1300 return zone()->New<Operator1<float>>( // --
1301 IrOpcode::kFloat32Constant, Operator::kPure, // opcode
1302 "Float32Constant", // name
1303 0, 0, 0, 1, 0, 0, // counts
1304 value); // parameter
1305}
1306
1307
1309 return zone()->New<Operator1<double>>( // --
1310 IrOpcode::kFloat64Constant, Operator::kPure, // opcode
1311 "Float64Constant", // name
1312 0, 0, 0, 1, 0, 0, // counts
1313 value); // parameter
1314}
1315
1316
1318 const ExternalReference& value) {
1319 return zone()->New<Operator1<ExternalReference>>( // --
1320 IrOpcode::kExternalConstant, Operator::kPure, // opcode
1321 "ExternalConstant", // name
1322 0, 0, 0, 1, 0, 0, // counts
1323 value); // parameter
1324}
1325
1326
1328 return zone()->New<Operator1<double>>( // --
1329 IrOpcode::kNumberConstant, Operator::kPure, // opcode
1330 "NumberConstant", // name
1331 0, 0, 0, 1, 0, 0, // counts
1332 value); // parameter
1333}
1334
1336 return zone()->New<Operator1<intptr_t>>( // --
1337 IrOpcode::kPointerConstant, Operator::kPure, // opcode
1338 "PointerConstant", // name
1339 0, 0, 0, 1, 0, 0, // counts
1340 value); // parameter
1341}
1342
1344 const Handle<HeapObject>& value) {
1346 IrOpcode::kHeapConstant, Operator::kPure, // opcode
1347 "HeapConstant", // name
1348 0, 0, 0, 1, 0, 0, // counts
1349 value); // parameter
1350}
1351
1353 const Handle<HeapObject>& value) {
1355 IrOpcode::kCompressedHeapConstant, Operator::kPure, // opcode
1356 "CompressedHeapConstant", // name
1357 0, 0, 0, 1, 0, 0, // counts
1358 value); // parameter
1359}
1360
1362 const Handle<HeapObject>& value) {
1364 IrOpcode::kTrustedHeapConstant, Operator::kPure, // opcode
1365 "TrustedHeapConstant", // name
1366 0, 0, 0, 1, 0, 0, // counts
1367 value); // parameter
1368}
1369
1371 DCHECK(IrOpcode::kHeapConstant == op->opcode() ||
1372 IrOpcode::kCompressedHeapConstant == op->opcode() ||
1373 IrOpcode::kTrustedHeapConstant == op->opcode());
1375}
1376
1377const char* StaticAssertSourceOf(const Operator* op) {
1378 DCHECK_EQ(IrOpcode::kStaticAssert, op->opcode());
1379 return OpParameter<const char*>(op);
1380}
1381
1383 int32_t value, RelocInfo::Mode rmode) {
1385 IrOpcode::kRelocatableInt32Constant, Operator::kPure, // opcode
1386 "RelocatableInt32Constant", // name
1387 0, 0, 0, 1, 0, 0, // counts
1388 RelocatablePtrConstantInfo(value, rmode)); // parameter
1389}
1390
1392 int64_t value, RelocInfo::Mode rmode) {
1394 IrOpcode::kRelocatableInt64Constant, Operator::kPure, // opcode
1395 "RelocatableInt64Constant", // name
1396 0, 0, 0, 1, 0, 0, // counts
1397 RelocatablePtrConstantInfo(value, rmode)); // parameter
1398}
1399
1400const Operator* CommonOperatorBuilder::ObjectId(uint32_t object_id) {
1401 return zone()->New<Operator1<uint32_t>>( // --
1402 IrOpcode::kObjectId, Operator::kPure, // opcode
1403 "ObjectId", // name
1404 0, 0, 0, 1, 0, 0, // counts
1405 object_id); // parameter
1406}
1407
1409 BranchHint hint,
1410 BranchSemantics semantics) {
1411 return zone()->New<Operator1<SelectParameters>>( // --
1412 IrOpcode::kSelect, Operator::kPure, // opcode
1413 "Select", // name
1414 3, 0, 0, 1, 0, 0, // counts
1415 SelectParameters(rep, hint, semantics)); // parameter
1416}
1417
1419 int value_input_count) {
1420 DCHECK_LT(0, value_input_count); // Disallow empty phis.
1421#define CACHED_PHI(kRep, kValueInputCount) \
1422 if (MachineRepresentation::kRep == rep && \
1423 kValueInputCount == value_input_count) { \
1424 return &cache_.kPhi##kRep##kValueInputCount##Operator; \
1425 }
1427#undef CACHED_PHI
1428 // Uncached.
1429 return zone()->New<Operator1<MachineRepresentation>>( // --
1430 IrOpcode::kPhi, Operator::kPure, // opcode
1431 "Phi", // name
1432 value_input_count, 0, 1, 1, 0, 0, // counts
1433 rep); // parameter
1434}
1435
1437 return zone()->New<Operator1<Type>>( // --
1438 IrOpcode::kTypeGuard, Operator::kPure, // opcode
1439 "TypeGuard", // name
1440 1, 1, 1, 1, 1, 0, // counts
1441 type); // parameter
1442}
1443
1445 return zone()->New<Operator1<UseInfo>>(IrOpcode::kEnterMachineGraph,
1446 Operator::kPure, "EnterMachineGraph",
1447 1, 0, 0, 1, 0, 0, use_info);
1448}
1449
1451 MachineRepresentation output_representation, Type output_type) {
1453 IrOpcode::kExitMachineGraph, Operator::kPure, "ExitMachineGraph", 1, 0, 0,
1454 1, 0, 0, ExitMachineGraphParameters{output_representation, output_type});
1455}
1456
1457const Operator* CommonOperatorBuilder::EffectPhi(int effect_input_count) {
1458 DCHECK_LT(0, effect_input_count); // Disallow empty effect phis.
1459 switch (effect_input_count) {
1460#define CACHED_EFFECT_PHI(input_count) \
1461 case input_count: \
1462 return &cache_.kEffectPhi##input_count##Operator;
1464#undef CACHED_EFFECT_PHI
1465 default:
1466 break;
1467 }
1468 // Uncached.
1469 return zone()->New<Operator>( // --
1470 IrOpcode::kEffectPhi, Operator::kKontrol, // opcode
1471 "EffectPhi", // name
1472 0, effect_input_count, 1, 0, 1, 0); // counts
1473}
1474
1476 DCHECK_LE(4, input_count); // There must be always the entry, backedge,
1477 // increment and at least one bound.
1478 switch (input_count) {
1479#define CACHED_INDUCTION_VARIABLE_PHI(input_count) \
1480 case input_count: \
1481 return &cache_.kInductionVariablePhi##input_count##Operator;
1483#undef CACHED_INDUCTION_VARIABLE_PHI
1484 default:
1485 break;
1486 }
1487 // Uncached.
1488 return zone()->New<Operator>( // --
1489 IrOpcode::kInductionVariablePhi, Operator::kPure, // opcode
1490 "InductionVariablePhi", // name
1491 input_count, 0, 1, 1, 0, 0); // counts
1492}
1493
1495 RegionObservability region_observability) {
1496 switch (region_observability) {
1498 return &cache_.kBeginRegionObservableOperator;
1500 return &cache_.kBeginRegionNotObservableOperator;
1501 }
1502 UNREACHABLE();
1503}
1504
1506 SparseInputMask bitmask) {
1507 if (bitmask.IsDense()) {
1508 switch (arguments) {
1509#define CACHED_STATE_VALUES(arguments) \
1510 case arguments: \
1511 return &cache_.kStateValues##arguments##Operator;
1513#undef CACHED_STATE_VALUES
1514 default:
1515 break;
1516 }
1517 }
1518
1519#if DEBUG
1520 DCHECK(bitmask.IsDense() || bitmask.CountReal() == arguments);
1521#endif
1522
1523 // Uncached.
1524 return zone()->New<Operator1<SparseInputMask>>( // --
1525 IrOpcode::kStateValues, Operator::kPure, // opcode
1526 "StateValues", // name
1527 arguments, 0, 0, 1, 0, 0, // counts
1528 bitmask); // parameter
1529}
1530
1532 const ZoneVector<MachineType>* types, SparseInputMask bitmask) {
1533#if DEBUG
1534 DCHECK(bitmask.IsDense() ||
1535 bitmask.CountReal() == static_cast<int>(types->size()));
1536#endif
1537
1538 return zone()->New<Operator1<TypedStateValueInfo>>( // --
1539 IrOpcode::kTypedStateValues, Operator::kPure, // opcode
1540 "TypedStateValues", // name
1541 static_cast<int>(types->size()), 0, 0, 1, 0, 0, // counts
1542 TypedStateValueInfo(types, bitmask)); // parameters
1543}
1544
1546 ArgumentsStateType type) {
1547 return zone()->New<Operator1<ArgumentsStateType>>( // --
1548 IrOpcode::kArgumentsElementsState, Operator::kPure, // opcode
1549 "ArgumentsElementsState", // name
1550 0, 0, 0, 1, 0, 0, // counts
1551 type); // parameter
1552}
1553
1555 return zone()->New<Operator>( // --
1556 IrOpcode::kArgumentsLengthState, Operator::kPure, // opcode
1557 "ArgumentsLengthState", // name
1558 0, 0, 0, 1, 0, 0); // counts
1559}
1560
1562 DCHECK(op->opcode() == IrOpcode::kArgumentsElementsState);
1564}
1565
1567 int pointer_slots) {
1568 return zone()->New<Operator1<ObjectStateInfo>>( // --
1569 IrOpcode::kObjectState, Operator::kPure, // opcode
1570 "ObjectState", // name
1571 pointer_slots, 0, 0, 1, 0, 0, // counts
1572 ObjectStateInfo{object_id, pointer_slots}); // parameter
1573}
1574
1576 uint32_t object_id, const ZoneVector<MachineType>* types) {
1577 return zone()->New<Operator1<TypedObjectStateInfo>>( // --
1578 IrOpcode::kTypedObjectState, Operator::kPure, // opcode
1579 "TypedObjectState", // name
1580 static_cast<int>(types->size()), 0, 0, 1, 0, 0, // counts
1581 TypedObjectStateInfo(object_id, types)); // parameter
1582}
1583
1584uint32_t ObjectIdOf(Operator const* op) {
1585 switch (op->opcode()) {
1586 case IrOpcode::kObjectState:
1587 return OpParameter<ObjectStateInfo>(op).object_id();
1588 case IrOpcode::kTypedObjectState:
1589 return OpParameter<TypedObjectStateInfo>(op).object_id();
1590 case IrOpcode::kObjectId:
1591 return OpParameter<uint32_t>(op);
1592 default:
1593 UNREACHABLE();
1594 }
1595}
1596
1598 DCHECK_EQ(IrOpcode::kDeadValue, op->opcode());
1600}
1601
1603 BytecodeOffset bailout_id, OutputFrameStateCombine state_combine,
1604 const FrameStateFunctionInfo* function_info) {
1605 FrameStateInfo state_info(bailout_id, state_combine, function_info);
1606 return zone()->New<Operator1<FrameStateInfo>>( // --
1607 IrOpcode::kFrameState, Operator::kPure, // opcode
1608 "FrameState", // name
1609 5, 0, 0, 1, 0, 0, // counts
1610 state_info); // parameter
1611}
1612
1614 const CallDescriptor* call_descriptor) {
1615 class CallOperator final : public Operator1<const CallDescriptor*> {
1616 public:
1617 explicit CallOperator(const CallDescriptor* call_descriptor)
1619 IrOpcode::kCall, call_descriptor->properties(), "Call",
1620 call_descriptor->InputCount() +
1621 call_descriptor->FrameStateCount(),
1622 Operator::ZeroIfPure(call_descriptor->properties()),
1623 Operator::ZeroIfEliminatable(call_descriptor->properties()),
1624 call_descriptor->ReturnCount(),
1625 Operator::ZeroIfPure(call_descriptor->properties()),
1626 Operator::ZeroIfNoThrow(call_descriptor->properties()),
1627 call_descriptor) {}
1628
1629 void PrintParameter(std::ostream& os,
1630 PrintVerbosity verbose) const override {
1631 os << "[" << *parameter() << "]";
1632 }
1633 };
1634 return zone()->New<CallOperator>(call_descriptor);
1635}
1636
1638 const CallDescriptor* call_descriptor) {
1639 class TailCallOperator final : public Operator1<const CallDescriptor*> {
1640 public:
1641 explicit TailCallOperator(const CallDescriptor* call_descriptor)
1643 IrOpcode::kTailCall,
1644 call_descriptor->properties() | Operator::kNoThrow, "TailCall",
1645 call_descriptor->InputCount() +
1646 call_descriptor->FrameStateCount(),
1647 1, 1, 0, 0, 1, call_descriptor) {}
1648
1649 void PrintParameter(std::ostream& os,
1650 PrintVerbosity verbose) const override {
1651 os << "[" << *parameter() << "]";
1652 }
1653 };
1654 return zone()->New<TailCallOperator>(call_descriptor);
1655}
1656
1658 switch (index) {
1659#define CACHED_PROJECTION(index) \
1660 case index: \
1661 return &cache_.kProjection##index##Operator;
1663#undef CACHED_PROJECTION
1664 default:
1665 break;
1666 }
1667 // Uncached.
1668 return zone()->New<Operator1<size_t>>( // --
1669 IrOpcode::kProjection, // opcode
1670 Operator::kPure, // flags
1671 "Projection", // name
1672 1, 0, 1, 1, 0, 0, // counts
1673 index); // parameter
1674}
1675
1676
1678 int size) {
1679 if (op->opcode() == IrOpcode::kPhi) {
1680 return Phi(PhiRepresentationOf(op), size);
1681 } else if (op->opcode() == IrOpcode::kEffectPhi) {
1682 return EffectPhi(size);
1683 } else if (op->opcode() == IrOpcode::kMerge) {
1684 return Merge(size);
1685 } else if (op->opcode() == IrOpcode::kLoop) {
1686 return Loop(size);
1687 } else {
1688 UNREACHABLE();
1689 }
1690}
1691
1694 FrameStateType type, uint16_t parameter_count, uint16_t max_arguments,
1695 int local_count, IndirectHandle<SharedFunctionInfo> shared_info,
1696 IndirectHandle<BytecodeArray> bytecode_array) {
1698 max_arguments, local_count,
1699 shared_info, bytecode_array);
1700}
1701
1702#if V8_ENABLE_WEBASSEMBLY
1704CommonOperatorBuilder::CreateJSToWasmFrameStateFunctionInfo(
1705 FrameStateType type, uint16_t parameter_count, int local_count,
1706 Handle<SharedFunctionInfo> shared_info,
1707 const wasm::CanonicalSig* signature) {
1708 DCHECK_EQ(type, FrameStateType::kJSToWasmBuiltinContinuation);
1709 DCHECK_NOT_NULL(signature);
1710 return zone()->New<JSToWasmFrameStateFunctionInfo>(
1711 type, parameter_count, local_count, shared_info, signature);
1712}
1713#endif // V8_ENABLE_WEBASSEMBLY
1714
1716 // Use Chained only for operators that are not on the effect chain already.
1717 DCHECK_EQ(op->EffectInputCount(), 0);
1718 DCHECK_EQ(op->ControlInputCount(), 0);
1719 const char* mnemonic;
1720 switch (op->opcode()) {
1721 case IrOpcode::kChangeInt64ToBigInt:
1722 mnemonic = "Chained[ChangeInt64ToBigInt]";
1723 break;
1724 case IrOpcode::kChangeUint64ToBigInt:
1725 mnemonic = "Chained[ChangeUint64ToBigInt]";
1726 break;
1727 default:
1728 UNREACHABLE();
1729 }
1730 // TODO(nicohartmann@): Need to store operator properties once we have to
1731 // support Operator1 operators.
1732 Operator::Properties properties = op->properties();
1733 return zone()->New<Operator>(op->opcode(), properties, mnemonic,
1734 op->ValueInputCount(), 1, 1,
1735 op->ValueOutputCount(), 1, 0);
1736}
1737
1739 return zone()->New<Operator1<MachineRepresentation>>( // --
1740 IrOpcode::kDeadValue, Operator::kPure, // opcode
1741 "DeadValue", // name
1742 1, 0, 0, 1, 0, 0, // counts
1743 rep); // parameter
1744}
1745
1747 DCHECK_EQ(IrOpcode::kFrameState, op->opcode());
1748 return OpParameter<FrameStateInfo>(op);
1749}
1750
1751#undef COMMON_CACHED_OP_LIST
1752#undef CACHED_BRANCH_LIST
1753#undef CACHED_RETURN_LIST
1754#undef CACHED_END_LIST
1755#undef CACHED_EFFECT_PHI_LIST
1756#undef CACHED_INDUCTION_VARIABLE_PHI_LIST
1757#undef CACHED_LOOP_LIST
1758#undef CACHED_MERGE_LIST
1759#undef CACHED_DEOPTIMIZE_LIST
1760#undef CACHED_DEOPTIMIZE_IF_LIST
1761#undef CACHED_DEOPTIMIZE_UNLESS_LIST
1762#undef CACHED_TRAP_IF_LIST
1763#undef CACHED_TRAP_UNLESS_LIST
1764#undef CACHED_PARAMETER_LIST
1765#undef CACHED_PHI_LIST
1766#undef CACHED_PROJECTION_LIST
1767#undef CACHED_STATE_VALUES_LIST
1768
1769} // namespace compiler
1770} // namespace internal
1771} // namespace v8
int16_t parameter_count
Definition builtins.cc:67
T * New(Args &&... args)
Definition zone.h:114
Operator::Properties properties() const
Definition linkage.h:297
const Operator * InductionVariablePhi(int value_input_count)
const Operator * End(size_t control_input_count)
const Operator * Phi(MachineRepresentation representation, int value_input_count)
const Operator * RelocatableInt64Constant(int64_t value, RelocInfo::Mode rmode)
const Operator * Loop(int control_input_count)
const Operator * CompressedHeapConstant(const Handle< HeapObject > &)
const Operator * StateValues(int arguments, SparseInputMask bitmask)
const Operator * LoopExitValue(MachineRepresentation rep)
const Operator * StaticAssert(const char *source)
const Operator * EffectPhi(int effect_input_count)
const Operator * ResizeMergeOrPhi(const Operator *op, int size)
const Operator * ArgumentsElementsState(ArgumentsStateType type)
const Operator * Assert(BranchSemantics semantics, const char *condition_string, const char *file, int line)
const Operator * ExternalConstant(const ExternalReference &)
const Operator * IfDefault(BranchHint hint=BranchHint::kNone)
const Operator * ObjectState(uint32_t object_id, int pointer_slots)
const Operator * TailCall(const CallDescriptor *call_descriptor)
const Operator * TypedStateValues(const ZoneVector< MachineType > *types, SparseInputMask bitmask)
const Operator * RelocatableInt32Constant(int32_t value, RelocInfo::Mode rmode)
const Operator * EnterMachineGraph(UseInfo use_info)
const Operator * DeadValue(MachineRepresentation rep)
const Operator * Select(MachineRepresentation, BranchHint=BranchHint::kNone, BranchSemantics semantics=BranchSemantics::kUnspecified)
const Operator * TypedObjectState(uint32_t object_id, const ZoneVector< MachineType > *types)
const Operator * FrameState(BytecodeOffset bailout_id, OutputFrameStateCombine state_combine, const FrameStateFunctionInfo *function_info)
const Operator * Return(int value_input_count=1)
const Operator * Chained(const Operator *op)
const Operator * BeginRegion(RegionObservability)
const Operator * Merge(int control_input_count)
const Operator * TrustedHeapConstant(const Handle< HeapObject > &)
const Operator * Start(int value_output_count)
const Operator * IfValue(int32_t value, int32_t order=0, BranchHint hint=BranchHint::kNone)
const CommonOperatorGlobalCache & cache_
const Operator * DeoptimizeUnless(DeoptimizeReason reason, FeedbackSource const &feedback)
const Operator * Deoptimize(DeoptimizeReason reason, FeedbackSource const &feedback)
const Operator * ExitMachineGraph(MachineRepresentation output_representation, Type output_type)
const Operator * DeoptimizeIf(DeoptimizeReason reason, FeedbackSource const &feedback)
const Operator * Switch(size_t control_output_count)
const Operator * Branch(BranchHint=BranchHint::kNone, BranchSemantics semantics=BranchSemantics::kUnspecified)
const Operator * HeapConstant(const Handle< HeapObject > &)
const Operator * Call(const CallDescriptor *call_descriptor)
const Operator * TaggedIndexConstant(int32_t value)
const FrameStateFunctionInfo * CreateFrameStateFunctionInfo(FrameStateType type, uint16_t parameter_count, uint16_t max_arguments, int local_count, IndirectHandle< SharedFunctionInfo > shared_info, IndirectHandle< BytecodeArray > bytecode_array)
const Operator * SLVerifierHint(const Operator *semantics, const std::optional< Type > &override_output_type)
const Operator * Parameter(int index, const char *debug_name=nullptr)
const FeedbackSource & feedback() const
int InputCount() const
Definition node.h:59
Properties properties() const
Definition operator.h:98
constexpr Opcode opcode() const
Definition operator.h:75
const std::optional< Type > & override_output_type() const
MachineRepresentation representation() const
InputIterator IterateOverInputs(Node *node)
ZoneVector< MachineType > const * machine_types() const
Zone * zone_
#define CACHED_DEOPTIMIZE(Reason)
#define CACHED_DEOPTIMIZE_UNLESS(Reason)
#define CACHED_END_LIST(V)
#define CACHED_LOOP_EXIT_VALUE_LIST(V)
#define COMMON_CACHED_OP_LIST(V)
#define CACHED_EFFECT_PHI_LIST(V)
#define CACHED_RETURN_LIST(V)
#define CACHED_LOOP_EXIT_VALUE(rep)
#define CACHED_LOOP_LIST(V)
#define CACHED_STATE_VALUES_LIST(V)
#define CACHED_PARAMETER(index)
#define CACHED_PARAMETER_LIST(V)
#define CACHED_RETURN(value_input_count)
#define CACHED_BRANCH(Semantics, Hint)
#define CACHED_DEOPTIMIZE_IF(Reason)
#define CACHED_EFFECT_PHI(input_count)
#define CACHED_TRAP_IF_LIST(V)
#define CACHED_STATE_VALUES(input_count)
#define CACHED_PROJECTION(index)
#define CACHED_END(input_count)
#define CACHED_INDUCTION_VARIABLE_PHI_LIST(V)
#define CACHED_PROJECTION_LIST(V)
#define CACHED_BRANCH_LIST(V)
#define CACHED_DEOPTIMIZE_LIST(V)
#define CACHED(Name, properties, value_input_count, effect_input_count, control_input_count, value_output_count, effect_output_count, control_output_count)
#define CACHED_DEOPTIMIZE_IF_LIST(V)
#define CACHED_TRAP_UNLESS_LIST(V)
#define CACHED_INDUCTION_VARIABLE_PHI(input_count)
#define CACHED_PHI_LIST(V)
#define CACHED_MERGE(input_count)
#define CACHED_DEOPTIMIZE_UNLESS_LIST(V)
#define CACHED_LOOP(input_count)
#define CACHED_PHI(rep, input_count)
#define CACHED_MERGE_LIST(V)
#define FOREACH_WASM_TRAPREASON(V)
Definition globals.h:2650
uint32_t count
#define DEFINE_LAZY_LEAKY_OBJECT_GETTER(T, FunctionName,...)
InstructionOperand source
int r
Definition mul-fft.cc:298
constexpr unsigned CountTrailingZeros(T value)
Definition bits.h:144
constexpr unsigned CountPopulation(T value)
Definition bits.h:26
V8_INLINE size_t hash_value(unsigned int v)
Definition hashing.h:205
V8_INLINE size_t hash_combine(size_t seed, size_t hash)
Definition hashing.h:77
V8_INLINE size_t hash_range(Iterator first, Iterator last)
Definition hashing.h:308
uint32_t ObjectIdOf(Operator const *op)
const BranchParameters & BranchParametersOf(const Operator *const op)
IfValueParameters const & IfValueParametersOf(const Operator *op)
RegionObservability RegionObservabilityOf(Operator const *op)
ZoneVector< MachineType > const * MachineTypesOf(Operator const *op)
size_t ProjectionIndexOf(const Operator *const op)
int ValueInputCountOfReturn(Operator const *const op)
ArgumentsStateType ArgumentsStateTypeOf(Operator const *op)
BranchHint BranchHintOf(const Operator *const op)
Handle< HeapObject > HeapConstantOf(const Operator *op)
const AssertParameters & AssertParametersOf(const Operator *const op)
const char * StaticAssertSourceOf(const Operator *op)
CallDescriptor const * CallDescriptorOf(const Operator *const op)
int ParameterIndexOf(const Operator *const op)
const ParameterInfo & ParameterInfoOf(const Operator *const op)
const FrameStateInfo & FrameStateInfoOf(const Operator *op)
DeoptimizeParameters const & DeoptimizeParametersOf(Operator const *const op)
Type TypeGuardTypeOf(Operator const *op)
size_t hash_value(const BranchParameters &p)
SelectParameters const & SelectParametersOf(const Operator *const op)
const SLVerifierHintParameters & SLVerifierHintParametersOf(const Operator *op)
T const & OpParameter(const Operator *op)
Definition operator.h:214
bool operator!=(DeoptimizeParameters lhs, DeoptimizeParameters rhs)
bool operator==(const BranchParameters &lhs, const BranchParameters &rhs)
std::ostream & operator<<(std::ostream &os, AccessMode access_mode)
const ExitMachineGraphParameters & ExitMachineGraphParametersOf(const Operator *op)
MachineRepresentation LoopExitValueRepresentationOf(const Operator *const op)
SparseInputMask SparseInputMaskOf(Operator const *op)
MachineRepresentation PhiRepresentationOf(const Operator *const op)
MachineRepresentation DeadValueRepresentationOf(Operator const *op)
int OsrValueIndexOf(Operator const *op)
std::ostream & operator<<(std::ostream &os, AtomicMemoryOrder order)
return value
Definition map-inl.h:893
BytecodeSequenceNode * parent_
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define V8_EXPORT_PRIVATE
Definition macros.h:460
BeginRegionOperator< RegionObservability::kObservable > kBeginRegionObservableOperator
BeginRegionOperator< RegionObservability::kNotObservable > kBeginRegionNotObservableOperator
const ZoneVector< MachineType > * machine_types() const
wasm::ValueType type