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
5#include "src/compiler/common-operator.h"
6
7#include "src/base/lazy-instance.h"
8#include "src/compiler/linkage.h"
9#include "src/compiler/node.h"
10#include "src/compiler/opcodes.h"
11#include "src/compiler/operator.h"
12#include "src/handles/handles-inl.h"
13#include "src/zone/zone.h"
14
15namespace v8 {
16namespace internal {
17namespace compiler {
18
19std::ostream& operator<<(std::ostream& os, BranchHint hint) {
20  switch (hint) {
21    case BranchHint::kNone:
22      return os << "None";
23    case BranchHint::kTrue:
24      return os << "True";
25    case BranchHint::kFalse:
26      return os << "False";
27  }
28  UNREACHABLE();
29}
30
31std::ostream& operator<<(std::ostream& os, TrapId trap_id) {
32  switch (trap_id) {
33#define TRAP_CASE(Name) \
34  case TrapId::k##Name: \
35    return os << #Name;
36    FOREACH_WASM_TRAPREASON(TRAP_CASE)
37#undef TRAP_CASE
38    case TrapId::kInvalid:
39      return os << "Invalid";
40  }
41  UNREACHABLE();
42}
43
44TrapId TrapIdOf(const Operator* const op) {
45  DCHECK(op->opcode() == IrOpcode::kTrapIf ||
46         op->opcode() == IrOpcode::kTrapUnless);
47  return OpParameter<TrapId>(op);
48}
49
50BranchHint BranchHintOf(const Operator* const op) {
51  switch (op->opcode()) {
52    case IrOpcode::kIfValue:
53      return IfValueParametersOf(op).hint();
54    case IrOpcode::kIfDefault:
55    case IrOpcode::kBranch:
56      return OpParameter<BranchHint>(op);
57    default:
58      UNREACHABLE();
59  }
60}
61
62int ValueInputCountOfReturn(Operator const* const op) {
63  DCHECK_EQ(IrOpcode::kReturn, op->opcode());
64  // Return nodes have a hidden input at index 0 which we ignore in the value
65  // input count.
66  return op->ValueInputCount() - 1;
67}
68
69bool operator==(DeoptimizeParameters lhs, DeoptimizeParameters rhs) {
70  return lhs.reason() == rhs.reason() && lhs.feedback() == rhs.feedback();
71}
72
73bool operator!=(DeoptimizeParameters lhs, DeoptimizeParameters rhs) {
74  return !(lhs == rhs);
75}
76
77size_t hash_value(DeoptimizeParameters p) {
78  FeedbackSource::Hash feebdack_hash;
79  return base::hash_combine(p.reason(), feebdack_hash(p.feedback()));
80}
81
82std::ostream& operator<<(std::ostream& os, DeoptimizeParameters p) {
83  return os << p.reason() << ", " << p.feedback();
84}
85
86DeoptimizeParameters const& DeoptimizeParametersOf(Operator const* const op) {
87  DCHECK(op->opcode() == IrOpcode::kDeoptimize ||
88         op->opcode() == IrOpcode::kDeoptimizeIf ||
89         op->opcode() == IrOpcode::kDeoptimizeUnless);
90  return OpParameter<DeoptimizeParameters>(op);
91}
92
93const Operator* CommonOperatorBuilder::DelayedStringConstant(
94    const StringConstantBase* str) {
95  return zone()->New<Operator1<const StringConstantBase*>>(
96      IrOpcode::kDelayedStringConstant, Operator::kPure,
97      "DelayedStringConstant", 0, 0, 0, 1, 0, 0, str);
98}
99
100bool operator==(SelectParameters const& lhs, SelectParameters const& rhs) {
101  return lhs.representation() == rhs.representation() &&
102         lhs.hint() == rhs.hint();
103}
104
105
106bool operator!=(SelectParameters const& lhs, SelectParameters const& rhs) {
107  return !(lhs == rhs);
108}
109
110
111size_t hash_value(SelectParameters const& p) {
112  return base::hash_combine(p.representation(), p.hint());
113}
114
115
116std::ostream& operator<<(std::ostream& os, SelectParameters const& p) {
117  return os << p.representation() << ", " << p.hint();
118}
119
120
121SelectParameters const& SelectParametersOf(const Operator* const op) {
122  DCHECK_EQ(IrOpcode::kSelect, op->opcode());
123  return OpParameter<SelectParameters>(op);
124}
125
126CallDescriptor const* CallDescriptorOf(const Operator* const op) {
127  DCHECK(op->opcode() == IrOpcode::kCall ||
128         op->opcode() == IrOpcode::kTailCall);
129  return OpParameter<CallDescriptor const*>(op);
130}
131
132size_t ProjectionIndexOf(const Operator* const op) {
133  DCHECK_EQ(IrOpcode::kProjection, op->opcode());
134  return OpParameter<size_t>(op);
135}
136
137
138MachineRepresentation PhiRepresentationOf(const Operator* const op) {
139  DCHECK_EQ(IrOpcode::kPhi, op->opcode());
140  return OpParameter<MachineRepresentation>(op);
141}
142
143MachineRepresentation LoopExitValueRepresentationOf(const Operator* const op) {
144  DCHECK_EQ(IrOpcode::kLoopExitValue, op->opcode());
145  return OpParameter<MachineRepresentation>(op);
146}
147
148int ParameterIndexOf(const Operator* const op) {
149  DCHECK_EQ(IrOpcode::kParameter, op->opcode());
150  return OpParameter<ParameterInfo>(op).index();
151}
152
153
154const ParameterInfo& ParameterInfoOf(const Operator* const op) {
155  DCHECK_EQ(IrOpcode::kParameter, op->opcode());
156  return OpParameter<ParameterInfo>(op);
157}
158
159
160bool operator==(ParameterInfo const& lhs, ParameterInfo const& rhs) {
161  return lhs.index() == rhs.index();
162}
163
164
165bool operator!=(ParameterInfo const& lhs, ParameterInfo const& rhs) {
166  return !(lhs == rhs);
167}
168
169
170size_t hash_value(ParameterInfo const& p) { return p.index(); }
171
172
173std::ostream& operator<<(std::ostream& os, ParameterInfo const& i) {
174  os << i.index();
175  if (i.debug_name()) os << ", debug name: " << i.debug_name();
176  return os;
177}
178
179std::ostream& operator<<(std::ostream& os, ObjectStateInfo const& i) {
180  return os << "id:" << i.object_id() << ", size:" << i.size();
181}
182
183size_t hash_value(ObjectStateInfo const& p) {
184  return base::hash_combine(p.object_id(), p.size());
185}
186
187std::ostream& operator<<(std::ostream& os, TypedObjectStateInfo const& i) {
188  return os << "id:" << i.object_id() << ", " << i.machine_types();
189}
190
191size_t hash_value(TypedObjectStateInfo const& p) {
192  return base::hash_combine(p.object_id(), p.machine_types());
193}
194
195bool operator==(RelocatablePtrConstantInfo const& lhs,
196                RelocatablePtrConstantInfo const& rhs) {
197  return lhs.rmode() == rhs.rmode() && lhs.value() == rhs.value() &&
198         lhs.type() == rhs.type();
199}
200
201bool operator!=(RelocatablePtrConstantInfo const& lhs,
202                RelocatablePtrConstantInfo const& rhs) {
203  return !(lhs == rhs);
204}
205
206size_t hash_value(RelocatablePtrConstantInfo const& p) {
207  return base::hash_combine(p.value(), int8_t{p.rmode()}, p.type());
208}
209
210std::ostream& operator<<(std::ostream& os,
211                         RelocatablePtrConstantInfo const& p) {
212  return os << p.value() << ", " << static_cast<int>(p.rmode()) << ", "
213            << p.type();
214}
215
216SparseInputMask::InputIterator::InputIterator(
217    SparseInputMask::BitMaskType bit_mask, Node* parent)
218    : bit_mask_(bit_mask), parent_(parent), real_index_(0) {
219#if DEBUG
220  if (bit_mask_ != SparseInputMask::kDenseBitMask) {
221    DCHECK_EQ(base::bits::CountPopulation(bit_mask_) -
222                  base::bits::CountPopulation(kEndMarker),
223              parent->InputCount());
224  }
225#endif
226}
227
228void SparseInputMask::InputIterator::Advance() {
229  DCHECK(!IsEnd());
230
231  if (IsReal()) {
232    ++real_index_;
233  }
234  bit_mask_ >>= 1;
235}
236
237size_t SparseInputMask::InputIterator::AdvanceToNextRealOrEnd() {
238  DCHECK_NE(bit_mask_, SparseInputMask::kDenseBitMask);
239
240  size_t count = base::bits::CountTrailingZeros(bit_mask_);
241  bit_mask_ >>= count;
242  DCHECK(IsReal() || IsEnd());
243  return count;
244}
245
246Node* SparseInputMask::InputIterator::GetReal() const {
247  DCHECK(IsReal());
248  return parent_->InputAt(real_index_);
249}
250
251bool SparseInputMask::InputIterator::IsReal() const {
252  return bit_mask_ == SparseInputMask::kDenseBitMask ||
253         (bit_mask_ & kEntryMask);
254}
255
256bool SparseInputMask::InputIterator::IsEnd() const {
257  return (bit_mask_ == kEndMarker) ||
258         (bit_mask_ == SparseInputMask::kDenseBitMask &&
259          real_index_ >= parent_->InputCount());
260}
261
262int SparseInputMask::CountReal() const {
263  DCHECK(!IsDense());
264  return base::bits::CountPopulation(bit_mask_) -
265         base::bits::CountPopulation(kEndMarker);
266}
267
268SparseInputMask::InputIterator SparseInputMask::IterateOverInputs(Node* node) {
269  DCHECK(IsDense() || CountReal() == node->InputCount());
270  return InputIterator(bit_mask_, node);
271}
272
273bool operator==(SparseInputMask const& lhs, SparseInputMask const& rhs) {
274  return lhs.mask() == rhs.mask();
275}
276
277bool operator!=(SparseInputMask const& lhs, SparseInputMask const& rhs) {
278  return !(lhs == rhs);
279}
280
281size_t hash_value(SparseInputMask const& p) {
282  return base::hash_value(p.mask());
283}
284
285std::ostream& operator<<(std::ostream& os, SparseInputMask const& p) {
286  if (p.IsDense()) {
287    return os << "dense";
288  } else {
289    SparseInputMask::BitMaskType mask = p.mask();
290    DCHECK_NE(mask, SparseInputMask::kDenseBitMask);
291
292    os << "sparse:";
293
294    while (mask != SparseInputMask::kEndMarker) {
295      if (mask & SparseInputMask::kEntryMask) {
296        os << "^";
297      } else {
298        os << ".";
299      }
300      mask >>= 1;
301    }
302    return os;
303  }
304}
305
306bool operator==(TypedStateValueInfo const& lhs,
307                TypedStateValueInfo const& rhs) {
308  return lhs.machine_types() == rhs.machine_types() &&
309         lhs.sparse_input_mask() == rhs.sparse_input_mask();
310}
311
312bool operator!=(TypedStateValueInfo const& lhs,
313                TypedStateValueInfo const& rhs) {
314  return !(lhs == rhs);
315}
316
317size_t hash_value(TypedStateValueInfo const& p) {
318  return base::hash_combine(p.machine_types(), p.sparse_input_mask());
319}
320
321std::ostream& operator<<(std::ostream& os, TypedStateValueInfo const& p) {
322  return os << p.machine_types() << ", " << p.sparse_input_mask();
323}
324
325size_t hash_value(RegionObservability observability) {
326  return static_cast<size_t>(observability);
327}
328
329std::ostream& operator<<(std::ostream& os, RegionObservability observability) {
330  switch (observability) {
331    case RegionObservability::kObservable:
332      return os << "observable";
333    case RegionObservability::kNotObservable:
334      return os << "not-observable";
335  }
336  UNREACHABLE();
337}
338
339RegionObservability RegionObservabilityOf(Operator const* op) {
340  DCHECK_EQ(IrOpcode::kBeginRegion, op->opcode());
341  return OpParameter<RegionObservability>(op);
342}
343
344Type TypeGuardTypeOf(Operator const* op) {
345  DCHECK_EQ(IrOpcode::kTypeGuard, op->opcode());
346  return OpParameter<Type>(op);
347}
348
349std::ostream& operator<<(std::ostream& os,
350                         const ZoneVector<MachineType>* types) {
351  // Print all the MachineTypes, separated by commas.
352  bool first = true;
353  for (MachineType elem : *types) {
354    if (!first) {
355      os << ", ";
356    }
357    first = false;
358    os << elem;
359  }
360  return os;
361}
362
363int OsrValueIndexOf(Operator const* op) {
364  DCHECK_EQ(IrOpcode::kOsrValue, op->opcode());
365  return OpParameter<int>(op);
366}
367
368SparseInputMask SparseInputMaskOf(Operator const* op) {
369  DCHECK(op->opcode() == IrOpcode::kStateValues ||
370         op->opcode() == IrOpcode::kTypedStateValues);
371
372  if (op->opcode() == IrOpcode::kTypedStateValues) {
373    return OpParameter<TypedStateValueInfo>(op).sparse_input_mask();
374  }
375  return OpParameter<SparseInputMask>(op);
376}
377
378ZoneVector<MachineType> const* MachineTypesOf(Operator const* op) {
379  DCHECK(op->opcode() == IrOpcode::kTypedObjectState ||
380         op->opcode() == IrOpcode::kTypedStateValues);
381
382  if (op->opcode() == IrOpcode::kTypedStateValues) {
383    return OpParameter<TypedStateValueInfo>(op).machine_types();
384  }
385  return OpParameter<TypedObjectStateInfo>(op).machine_types();
386}
387
388V8_EXPORT_PRIVATE bool operator==(IfValueParameters const& l,
389                                  IfValueParameters const& r) {
390  return l.value() == r.value() &&
391         l.comparison_order() == r.comparison_order() && l.hint() == r.hint();
392}
393
394size_t hash_value(IfValueParameters const& p) {
395  return base::hash_combine(p.value(), p.comparison_order(), p.hint());
396}
397
398V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
399                                           IfValueParameters const& p) {
400  out << p.value() << " (order " << p.comparison_order() << ", hint "
401      << p.hint() << ")";
402  return out;
403}
404
405IfValueParameters const& IfValueParametersOf(const Operator* op) {
406  DCHECK(op->opcode() == IrOpcode::kIfValue);
407  return OpParameter<IfValueParameters>(op);
408}
409
410V8_EXPORT_PRIVATE bool operator==(const SLVerifierHintParameters& p1,
411                                  const SLVerifierHintParameters& p2) {
412  return p1.semantics() == p2.semantics() &&
413         p1.override_output_type() == p2.override_output_type();
414}
415
416size_t hash_value(const SLVerifierHintParameters& p) {
417  return base::hash_combine(
418      p.semantics(),
419      p.override_output_type() ? hash_value(*p.override_output_type()) : 0);
420}
421
422V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
423                                           const SLVerifierHintParameters& p) {
424  if (p.semantics()) {
425    p.semantics()->PrintTo(out);
426  } else {
427    out << "nullptr";
428  }
429  out << ", ";
430  if (const auto& t = p.override_output_type()) {
431    t->PrintTo(out);
432  } else {
433    out << ", nullopt";
434  }
435  return out;
436}
437
438const SLVerifierHintParameters& SLVerifierHintParametersOf(const Operator* op) {
439  DCHECK_EQ(op->opcode(), IrOpcode::kSLVerifierHint);
440  return OpParameter<SLVerifierHintParameters>(op);
441}
442
443#define COMMON_CACHED_OP_LIST(V)                          \
444  V(Plug, Operator::kNoProperties, 0, 0, 0, 1, 0, 0)      \
445  V(Dead, Operator::kFoldable, 0, 0, 0, 1, 1, 1)          \
446  V(Unreachable, Operator::kFoldable, 0, 1, 1, 1, 1, 0)   \
447  V(IfTrue, Operator::kKontrol, 0, 0, 1, 0, 0, 1)         \
448  V(IfFalse, Operator::kKontrol, 0, 0, 1, 0, 0, 1)        \
449  V(IfSuccess, Operator::kKontrol, 0, 0, 1, 0, 0, 1)      \
450  V(IfException, Operator::kKontrol, 0, 1, 1, 1, 1, 1)    \
451  V(Throw, Operator::kKontrol, 0, 1, 1, 0, 0, 1)          \
452  V(Terminate, Operator::kKontrol, 0, 1, 1, 0, 0, 1)      \
453  V(LoopExit, Operator::kKontrol, 0, 0, 2, 0, 0, 1)       \
454  V(LoopExitEffect, Operator::kNoThrow, 0, 1, 1, 0, 1, 0) \
455  V(Checkpoint, Operator::kKontrol, 0, 1, 1, 0, 1, 0)     \
456  V(FinishRegion, Operator::kKontrol, 1, 1, 0, 1, 1, 0)   \
457  V(Retain, Operator::kKontrol, 1, 1, 0, 0, 1, 0)
458
459#define CACHED_LOOP_EXIT_VALUE_LIST(V) V(kTagged)
460
461#define CACHED_BRANCH_LIST(V) \
462  V(None)                     \
463  V(True)                     \
464  V(False)
465
466#define CACHED_RETURN_LIST(V) \
467  V(1)                        \
468  V(2)                        \
469  V(3)                        \
470  V(4)
471
472#define CACHED_END_LIST(V) \
473  V(1)                     \
474  V(2)                     \
475  V(3)                     \
476  V(4)                     \
477  V(5)                     \
478  V(6)                     \
479  V(7)                     \
480  V(8)
481
482
483#define CACHED_EFFECT_PHI_LIST(V) \
484  V(1)                            \
485  V(2)                            \
486  V(3)                            \
487  V(4)                            \
488  V(5)                            \
489  V(6)
490
491#define CACHED_INDUCTION_VARIABLE_PHI_LIST(V) \
492  V(4)                                        \
493  V(5)                                        \
494  V(6)                                        \
495  V(7)
496
497#define CACHED_LOOP_LIST(V) \
498  V(1)                      \
499  V(2)
500
501
502#define CACHED_MERGE_LIST(V) \
503  V(1)                       \
504  V(2)                       \
505  V(3)                       \
506  V(4)                       \
507  V(5)                       \
508  V(6)                       \
509  V(7)                       \
510  V(8)
511
512#define CACHED_DEOPTIMIZE_LIST(V)                  \
513  V(MinusZero)                                     \
514  V(WrongMap)                                      \
515  V(InsufficientTypeFeedbackForGenericKeyedAccess) \
516  V(InsufficientTypeFeedbackForGenericNamedAccess)
517
518#define CACHED_DEOPTIMIZE_IF_LIST(V) \
519  V(DivisionByZero)                  \
520  V(Hole)                            \
521  V(MinusZero)                       \
522  V(Overflow)                        \
523  V(Smi)
524
525#define CACHED_DEOPTIMIZE_UNLESS_LIST(V) \
526  V(LostPrecision)                       \
527  V(LostPrecisionOrNaN)                  \
528  V(NotAHeapNumber)                      \
529  V(NotANumberOrOddball)                 \
530  V(NotASmi)                             \
531  V(OutOfBounds)                         \
532  V(WrongInstanceType)                   \
533  V(WrongMap)
534
535#define CACHED_TRAP_IF_LIST(V) \
536  V(TrapDivUnrepresentable)    \
537  V(TrapFloatUnrepresentable)
538
539// The reason for a trap.
540#define CACHED_TRAP_UNLESS_LIST(V) \
541  V(TrapUnreachable)               \
542  V(TrapMemOutOfBounds)            \
543  V(TrapDivByZero)                 \
544  V(TrapDivUnrepresentable)        \
545  V(TrapRemByZero)                 \
546  V(TrapFloatUnrepresentable)      \
547  V(TrapTableOutOfBounds)          \
548  V(TrapFuncSigMismatch)
549
550#define CACHED_PARAMETER_LIST(V) \
551  V(0)                           \
552  V(1)                           \
553  V(2)                           \
554  V(3)                           \
555  V(4)                           \
556  V(5)                           \
557  V(6)
558
559
560#define CACHED_PHI_LIST(V) \
561  V(kTagged, 1)            \
562  V(kTagged, 2)            \
563  V(kTagged, 3)            \
564  V(kTagged, 4)            \
565  V(kTagged, 5)            \
566  V(kTagged, 6)            \
567  V(kBit, 2)               \
568  V(kFloat64, 2)           \
569  V(kWord32, 2)
570
571
572#define CACHED_PROJECTION_LIST(V) \
573  V(0)                            \
574  V(1)
575
576
577#define CACHED_STATE_VALUES_LIST(V) \
578  V(0)                              \
579  V(1)                              \
580  V(2)                              \
581  V(3)                              \
582  V(4)                              \
583  V(5)                              \
584  V(6)                              \
585  V(7)                              \
586  V(8)                              \
587  V(10)                             \
588  V(11)                             \
589  V(12)                             \
590  V(13)                             \
591  V(14)
592
593
594struct CommonOperatorGlobalCache final {
595#define CACHED(Name, properties, value_input_count, effect_input_count,      \
596               control_input_count, value_output_count, effect_output_count, \
597               control_output_count)                                         \
598  struct Name##Operator final : public Operator {                            \
599    Name##Operator()                                                         \
600        : Operator(IrOpcode::k##Name, properties, #Name, value_input_count,  \
601                   effect_input_count, control_input_count,                  \
602                   value_output_count, effect_output_count,                  \
603                   control_output_count) {}                                  \
604  };                                                                         \
605  Name##Operator k##Name##Operator;
606  COMMON_CACHED_OP_LIST(CACHED)
607#undef CACHED
608
609  template <size_t kInputCount>
610  struct EndOperator final : public Operator {
611    EndOperator()
612        : Operator(                                // --
613              IrOpcode::kEnd, Operator::kKontrol,  // opcode
614              "End",                               // name
615              0, 0, kInputCount, 0, 0, 0) {}       // counts
616  };
617#define CACHED_END(input_count) \
618  EndOperator<input_count> kEnd##input_count##Operator;
619  CACHED_END_LIST(CACHED_END)
620#undef CACHED_END
621
622  template <size_t kValueInputCount>
623  struct ReturnOperator final : public Operator {
624    ReturnOperator()
625        : Operator(                                    // --
626              IrOpcode::kReturn, Operator::kNoThrow,   // opcode
627              "Return",                                // name
628              kValueInputCount + 1, 1, 1, 0, 0, 1) {}  // counts
629  };
630#define CACHED_RETURN(value_input_count) \
631  ReturnOperator<value_input_count> kReturn##value_input_count##Operator;
632  CACHED_RETURN_LIST(CACHED_RETURN)
633#undef CACHED_RETURN
634
635  template <BranchHint hint>
636  struct BranchOperator final : public Operator1<BranchHint> {
637    BranchOperator()
638        : Operator1<BranchHint>(                      // --
639              IrOpcode::kBranch, Operator::kKontrol,  // opcode
640              "Branch",                               // name
641              1, 0, 1, 0, 0, 2,                       // counts
642              hint) {}                                // parameter
643  };
644#define CACHED_BRANCH(Hint) \
645  BranchOperator<BranchHint::k##Hint> kBranch##Hint##Operator;
646  CACHED_BRANCH_LIST(CACHED_BRANCH)
647#undef CACHED_BRANCH
648
649  template <int kEffectInputCount>
650  struct EffectPhiOperator final : public Operator {
651    EffectPhiOperator()
652        : Operator(                                      // --
653              IrOpcode::kEffectPhi, Operator::kKontrol,  // opcode
654              "EffectPhi",                               // name
655              0, kEffectInputCount, 1, 0, 1, 0) {}       // counts
656  };
657#define CACHED_EFFECT_PHI(input_count) \
658  EffectPhiOperator<input_count> kEffectPhi##input_count##Operator;
659  CACHED_EFFECT_PHI_LIST(CACHED_EFFECT_PHI)
660#undef CACHED_EFFECT_PHI
661
662  template <RegionObservability kRegionObservability>
663  struct BeginRegionOperator final : public Operator1<RegionObservability> {
664    BeginRegionOperator()
665        : Operator1<RegionObservability>(                  // --
666              IrOpcode::kBeginRegion, Operator::kKontrol,  // opcode
667              "BeginRegion",                               // name
668              0, 1, 0, 0, 1, 0,                            // counts
669              kRegionObservability) {}                     // parameter
670  };
671  BeginRegionOperator<RegionObservability::kObservable>
672      kBeginRegionObservableOperator;
673  BeginRegionOperator<RegionObservability::kNotObservable>
674      kBeginRegionNotObservableOperator;
675
676  template <size_t kInputCount>
677  struct LoopOperator final : public Operator {
678    LoopOperator()
679        : Operator(                                 // --
680              IrOpcode::kLoop, Operator::kKontrol,  // opcode
681              "Loop",                               // name
682              0, 0, kInputCount, 0, 0, 1) {}        // counts
683  };
684#define CACHED_LOOP(input_count) \
685  LoopOperator<input_count> kLoop##input_count##Operator;
686  CACHED_LOOP_LIST(CACHED_LOOP)
687#undef CACHED_LOOP
688
689  template <size_t kInputCount>
690  struct MergeOperator final : public Operator {
691    MergeOperator()
692        : Operator(                                  // --
693              IrOpcode::kMerge, Operator::kKontrol,  // opcode
694              "Merge",                               // name
695              0, 0, kInputCount, 0, 0, 1) {}         // counts
696  };
697#define CACHED_MERGE(input_count) \
698  MergeOperator<input_count> kMerge##input_count##Operator;
699  CACHED_MERGE_LIST(CACHED_MERGE)
700#undef CACHED_MERGE
701
702  template <MachineRepresentation kRep>
703  struct LoopExitValueOperator final : public Operator1<MachineRepresentation> {
704    LoopExitValueOperator()
705        : Operator1<MachineRepresentation>(IrOpcode::kLoopExitValue,
706                                           Operator::kPure, "LoopExitValue", 1,
707                                           0, 1, 1, 0, 0, kRep) {}
708  };
709#define CACHED_LOOP_EXIT_VALUE(rep)                 \
710  LoopExitValueOperator<MachineRepresentation::rep> \
711      kLoopExitValue##rep##Operator;
712  CACHED_LOOP_EXIT_VALUE_LIST(CACHED_LOOP_EXIT_VALUE)
713#undef CACHED_LOOP_EXIT_VALUE
714
715  template <DeoptimizeReason kReason>
716  struct DeoptimizeOperator final : public Operator1<DeoptimizeParameters> {
717    DeoptimizeOperator()
718        : Operator1<DeoptimizeParameters>(               // --
719              IrOpcode::kDeoptimize,                     // opcode
720              Operator::kFoldable | Operator::kNoThrow,  // properties
721              "Deoptimize",                              // name
722              1, 1, 1, 0, 0, 1,                          // counts
723              DeoptimizeParameters(kReason, FeedbackSource())) {}
724  };
725#define CACHED_DEOPTIMIZE(Reason) \
726  DeoptimizeOperator<DeoptimizeReason::k##Reason> kDeoptimize##Reason##Operator;
727  CACHED_DEOPTIMIZE_LIST(CACHED_DEOPTIMIZE)
728#undef CACHED_DEOPTIMIZE
729
730  template <DeoptimizeReason kReason>
731  struct DeoptimizeIfOperator final : public Operator1<DeoptimizeParameters> {
732    DeoptimizeIfOperator()
733        : Operator1<DeoptimizeParameters>(               // --
734              IrOpcode::kDeoptimizeIf,                   // opcode
735              Operator::kFoldable | Operator::kNoThrow,  // properties
736              "DeoptimizeIf",                            // name
737              2, 1, 1, 0, 1, 1,                          // counts
738              DeoptimizeParameters(kReason, FeedbackSource())) {}
739  };
740#define CACHED_DEOPTIMIZE_IF(Reason)                \
741  DeoptimizeIfOperator<DeoptimizeReason::k##Reason> \
742      kDeoptimizeIf##Reason##Operator;
743  CACHED_DEOPTIMIZE_IF_LIST(CACHED_DEOPTIMIZE_IF)
744#undef CACHED_DEOPTIMIZE_IF
745
746  template <DeoptimizeReason kReason>
747  struct DeoptimizeUnlessOperator final
748      : public Operator1<DeoptimizeParameters> {
749    DeoptimizeUnlessOperator()
750        : Operator1<DeoptimizeParameters>(               // --
751              IrOpcode::kDeoptimizeUnless,               // opcode
752              Operator::kFoldable | Operator::kNoThrow,  // properties
753              "DeoptimizeUnless",                        // name
754              2, 1, 1, 0, 1, 1,                          // counts
755              DeoptimizeParameters(kReason, FeedbackSource())) {}
756  };
757#define CACHED_DEOPTIMIZE_UNLESS(Reason)                \
758  DeoptimizeUnlessOperator<DeoptimizeReason::k##Reason> \
759      kDeoptimizeUnless##Reason##Operator;
760  CACHED_DEOPTIMIZE_UNLESS_LIST(CACHED_DEOPTIMIZE_UNLESS)
761#undef CACHED_DEOPTIMIZE_UNLESS
762
763  template <TrapId trap_id>
764  struct TrapIfOperator final : public Operator1<TrapId> {
765    TrapIfOperator()
766        : Operator1<TrapId>(                             // --
767              IrOpcode::kTrapIf,                         // opcode
768              Operator::kFoldable | Operator::kNoThrow,  // properties
769              "TrapIf",                                  // name
770              1, 1, 1, 0, 0, 1,                          // counts
771              trap_id) {}                                // parameter
772  };
773#define CACHED_TRAP_IF(Trap) \
774  TrapIfOperator<TrapId::k##Trap> kTrapIf##Trap##Operator;
775  CACHED_TRAP_IF_LIST(CACHED_TRAP_IF)
776#undef CACHED_TRAP_IF
777
778  template <TrapId trap_id>
779  struct TrapUnlessOperator final : public Operator1<TrapId> {
780    TrapUnlessOperator()
781        : Operator1<TrapId>(                             // --
782              IrOpcode::kTrapUnless,                     // opcode
783              Operator::kFoldable | Operator::kNoThrow,  // properties
784              "TrapUnless",                              // name
785              1, 1, 1, 0, 0, 1,                          // counts
786              trap_id) {}                                // parameter
787  };
788#define CACHED_TRAP_UNLESS(Trap) \
789  TrapUnlessOperator<TrapId::k##Trap> kTrapUnless##Trap##Operator;
790  CACHED_TRAP_UNLESS_LIST(CACHED_TRAP_UNLESS)
791#undef CACHED_TRAP_UNLESS
792
793  template <MachineRepresentation kRep, int kInputCount>
794  struct PhiOperator final : public Operator1<MachineRepresentation> {
795    PhiOperator()
796        : Operator1<MachineRepresentation>(     //--
797              IrOpcode::kPhi, Operator::kPure,  // opcode
798              "Phi",                            // name
799              kInputCount, 0, 1, 1, 0, 0,       // counts
800              kRep) {}                          // parameter
801  };
802#define CACHED_PHI(rep, input_count)                   \
803  PhiOperator<MachineRepresentation::rep, input_count> \
804      kPhi##rep##input_count##Operator;
805  CACHED_PHI_LIST(CACHED_PHI)
806#undef CACHED_PHI
807
808  template <int kInputCount>
809  struct InductionVariablePhiOperator final : public Operator {
810    InductionVariablePhiOperator()
811        : Operator(                                              //--
812              IrOpcode::kInductionVariablePhi, Operator::kPure,  // opcode
813              "InductionVariablePhi",                            // name
814              kInputCount, 0, 1, 1, 0, 0) {}                     // counts
815  };
816#define CACHED_INDUCTION_VARIABLE_PHI(input_count) \
817  InductionVariablePhiOperator<input_count>        \
818      kInductionVariablePhi##input_count##Operator;
819  CACHED_INDUCTION_VARIABLE_PHI_LIST(CACHED_INDUCTION_VARIABLE_PHI)
820#undef CACHED_INDUCTION_VARIABLE_PHI
821
822  template <int kIndex>
823  struct ParameterOperator final : public Operator1<ParameterInfo> {
824    ParameterOperator()
825        : Operator1<ParameterInfo>(                   // --
826              IrOpcode::kParameter, Operator::kPure,  // opcode
827              "Parameter",                            // name
828              1, 0, 0, 1, 0, 0,                       // counts,
829              ParameterInfo(kIndex, nullptr)) {}      // parameter and name
830  };
831#define CACHED_PARAMETER(index) \
832  ParameterOperator<index> kParameter##index##Operator;
833  CACHED_PARAMETER_LIST(CACHED_PARAMETER)
834#undef CACHED_PARAMETER
835
836  template <size_t kIndex>
837  struct ProjectionOperator final : public Operator1<size_t> {
838    ProjectionOperator()
839        : Operator1<size_t>(          // --
840              IrOpcode::kProjection,  // opcode
841              Operator::kPure,        // flags
842              "Projection",           // name
843              1, 0, 1, 1, 0, 0,       // counts,
844              kIndex) {}              // parameter
845  };
846#define CACHED_PROJECTION(index) \
847  ProjectionOperator<index> kProjection##index##Operator;
848  CACHED_PROJECTION_LIST(CACHED_PROJECTION)
849#undef CACHED_PROJECTION
850
851  template <int kInputCount>
852  struct StateValuesOperator final : public Operator1<SparseInputMask> {
853    StateValuesOperator()
854        : Operator1<SparseInputMask>(       // --
855              IrOpcode::kStateValues,       // opcode
856              Operator::kPure,              // flags
857              "StateValues",                // name
858              kInputCount, 0, 0, 1, 0, 0,   // counts
859              SparseInputMask::Dense()) {}  // parameter
860  };
861#define CACHED_STATE_VALUES(input_count) \
862  StateValuesOperator<input_count> kStateValues##input_count##Operator;
863  CACHED_STATE_VALUES_LIST(CACHED_STATE_VALUES)
864#undef CACHED_STATE_VALUES
865};
866
867namespace {
868DEFINE_LAZY_LEAKY_OBJECT_GETTER(CommonOperatorGlobalCache,
869                                GetCommonOperatorGlobalCache)
870}  // namespace
871
872CommonOperatorBuilder::CommonOperatorBuilder(Zone* zone)
873    : cache_(*GetCommonOperatorGlobalCache()), zone_(zone) {}
874
875#define CACHED(Name, properties, value_input_count, effect_input_count,      \
876               control_input_count, value_output_count, effect_output_count, \
877               control_output_count)                                         \
878  const Operator* CommonOperatorBuilder::Name() {                            \
879    return &cache_.k##Name##Operator;                                        \
880  }
881COMMON_CACHED_OP_LIST(CACHED)
882#undef CACHED
883
884
885const Operator* CommonOperatorBuilder::End(size_t control_input_count) {
886  switch (control_input_count) {
887#define CACHED_END(input_count) \
888  case input_count:             \
889    return &cache_.kEnd##input_count##Operator;
890    CACHED_END_LIST(CACHED_END)
891#undef CACHED_END
892    default:
893      break;
894  }
895  // Uncached.
896  return zone()->New<Operator>(             //--
897      IrOpcode::kEnd, Operator::kKontrol,   // opcode
898      "End",                                // name
899      0, 0, control_input_count, 0, 0, 0);  // counts
900}
901
902const Operator* CommonOperatorBuilder::Return(int value_input_count) {
903  switch (value_input_count) {
904#define CACHED_RETURN(input_count) \
905  case input_count:                \
906    return &cache_.kReturn##input_count##Operator;
907    CACHED_RETURN_LIST(CACHED_RETURN)
908#undef CACHED_RETURN
909    default:
910      break;
911  }
912  // Uncached.
913  return zone()->New<Operator>(               //--
914      IrOpcode::kReturn, Operator::kNoThrow,  // opcode
915      "Return",                               // name
916      value_input_count + 1, 1, 1, 0, 0, 1);  // counts
917}
918
919const Operator* CommonOperatorBuilder::StaticAssert(const char* source) {
920  return zone()->New<Operator1<const char*>>(
921      IrOpcode::kStaticAssert, Operator::kFoldable, "StaticAssert", 1, 1, 0, 0,
922      1, 0, source);
923}
924
925const Operator* CommonOperatorBuilder::SLVerifierHint(
926    const Operator* semantics,
927    const base::Optional<Type>& override_output_type) {
928  return zone()->New<Operator1<SLVerifierHintParameters>>(
929      IrOpcode::kSLVerifierHint, Operator::kNoProperties, "SLVerifierHint", 1,
930      0, 0, 1, 0, 0, SLVerifierHintParameters(semantics, override_output_type));
931}
932
933const Operator* CommonOperatorBuilder::Branch(BranchHint hint) {
934#define CACHED_BRANCH(Hint)                 \
935  if (hint == BranchHint::k##Hint) {        \
936    return &cache_.kBranch##Hint##Operator; \
937  }
938  CACHED_BRANCH_LIST(CACHED_BRANCH)
939#undef CACHED_BRANCH
940  UNREACHABLE();
941}
942
943const Operator* CommonOperatorBuilder::Deoptimize(
944    DeoptimizeReason reason, FeedbackSource const& feedback) {
945#define CACHED_DEOPTIMIZE(Reason)                                     \
946  if (reason == DeoptimizeReason::k##Reason && !feedback.IsValid()) { \
947    return &cache_.kDeoptimize##Reason##Operator;                     \
948  }
949  CACHED_DEOPTIMIZE_LIST(CACHED_DEOPTIMIZE)
950#undef CACHED_DEOPTIMIZE
951  // Uncached
952  DeoptimizeParameters parameter(reason, feedback);
953  return zone()->New<Operator1<DeoptimizeParameters>>(  // --
954      IrOpcode::kDeoptimize,                            // opcodes
955      Operator::kFoldable | Operator::kNoThrow,         // properties
956      "Deoptimize",                                     // name
957      1, 1, 1, 0, 0, 1,                                 // counts
958      parameter);                                       // parameter
959}
960
961const Operator* CommonOperatorBuilder::DeoptimizeIf(
962    DeoptimizeReason reason, FeedbackSource const& feedback) {
963#define CACHED_DEOPTIMIZE_IF(Reason)                                  \
964  if (reason == DeoptimizeReason::k##Reason && !feedback.IsValid()) { \
965    return &cache_.kDeoptimizeIf##Reason##Operator;                   \
966  }
967  CACHED_DEOPTIMIZE_IF_LIST(CACHED_DEOPTIMIZE_IF)
968#undef CACHED_DEOPTIMIZE_IF
969  // Uncached
970  DeoptimizeParameters parameter(reason, feedback);
971  return zone()->New<Operator1<DeoptimizeParameters>>(  // --
972      IrOpcode::kDeoptimizeIf,                          // opcode
973      Operator::kFoldable | Operator::kNoThrow,         // properties
974      "DeoptimizeIf",                                   // name
975      2, 1, 1, 0, 1, 1,                                 // counts
976      parameter);                                       // parameter
977}
978
979const Operator* CommonOperatorBuilder::DeoptimizeUnless(
980    DeoptimizeReason reason, FeedbackSource const& feedback) {
981#define CACHED_DEOPTIMIZE_UNLESS(Reason)                              \
982  if (reason == DeoptimizeReason::k##Reason && !feedback.IsValid()) { \
983    return &cache_.kDeoptimizeUnless##Reason##Operator;               \
984  }
985  CACHED_DEOPTIMIZE_UNLESS_LIST(CACHED_DEOPTIMIZE_UNLESS)
986#undef CACHED_DEOPTIMIZE_UNLESS
987  // Uncached
988  DeoptimizeParameters parameter(reason, feedback);
989  return zone()->New<Operator1<DeoptimizeParameters>>(  // --
990      IrOpcode::kDeoptimizeUnless,                      // opcode
991      Operator::kFoldable | Operator::kNoThrow,         // properties
992      "DeoptimizeUnless",                               // name
993      2, 1, 1, 0, 1, 1,                                 // counts
994      parameter);                                       // parameter
995}
996
997const Operator* CommonOperatorBuilder::TrapIf(TrapId trap_id) {
998  switch (trap_id) {
999#define CACHED_TRAP_IF(Trap) \
1000  case TrapId::k##Trap:      \
1001    return &cache_.kTrapIf##Trap##Operator;
1002    CACHED_TRAP_IF_LIST(CACHED_TRAP_IF)
1003#undef CACHED_TRAP_IF
1004    default:
1005      break;
1006  }
1007  // Uncached
1008  return zone()->New<Operator1<TrapId>>(         // --
1009      IrOpcode::kTrapIf,                         // opcode
1010      Operator::kFoldable | Operator::kNoThrow,  // properties
1011      "TrapIf",                                  // name
1012      1, 1, 1, 0, 0, 1,                          // counts
1013      trap_id);                                  // parameter
1014}
1015
1016const Operator* CommonOperatorBuilder::TrapUnless(TrapId trap_id) {
1017  switch (trap_id) {
1018#define CACHED_TRAP_UNLESS(Trap) \
1019  case TrapId::k##Trap:          \
1020    return &cache_.kTrapUnless##Trap##Operator;
1021    CACHED_TRAP_UNLESS_LIST(CACHED_TRAP_UNLESS)
1022#undef CACHED_TRAP_UNLESS
1023    default:
1024      break;
1025  }
1026  // Uncached
1027  return zone()->New<Operator1<TrapId>>(         // --
1028      IrOpcode::kTrapUnless,                     // opcode
1029      Operator::kFoldable | Operator::kNoThrow,  // properties
1030      "TrapUnless",                              // name
1031      1, 1, 1, 0, 0, 1,                          // counts
1032      trap_id);                                  // parameter
1033}
1034
1035const Operator* CommonOperatorBuilder::Switch(size_t control_output_count) {
1036  return zone()->New<Operator>(               // --
1037      IrOpcode::kSwitch, Operator::kKontrol,  // opcode
1038      "Switch",                               // name
1039      1, 0, 1, 0, 0, control_output_count);   // counts
1040}
1041
1042const Operator* CommonOperatorBuilder::IfValue(int32_t index,
1043                                               int32_t comparison_order,
1044                                               BranchHint hint) {
1045  return zone()->New<Operator1<IfValueParameters>>(       // --
1046      IrOpcode::kIfValue, Operator::kKontrol,             // opcode
1047      "IfValue",                                          // name
1048      0, 0, 1, 0, 0, 1,                                   // counts
1049      IfValueParameters(index, comparison_order, hint));  // parameter
1050}
1051
1052const Operator* CommonOperatorBuilder::IfDefault(BranchHint hint) {
1053  return zone()->New<Operator1<BranchHint>>(     // --
1054      IrOpcode::kIfDefault, Operator::kKontrol,  // opcode
1055      "IfDefault",                               // name
1056      0, 0, 1, 0, 0, 1,                          // counts
1057      hint);                                     // parameter
1058}
1059
1060const Operator* CommonOperatorBuilder::Start(int value_output_count) {
1061  return zone()->New<Operator>(                                    // --
1062      IrOpcode::kStart, Operator::kFoldable | Operator::kNoThrow,  // opcode
1063      "Start",                                                     // name
1064      0, 0, 0, value_output_count, 1, 1);                          // counts
1065}
1066
1067
1068const Operator* CommonOperatorBuilder::Loop(int control_input_count) {
1069  switch (control_input_count) {
1070#define CACHED_LOOP(input_count) \
1071  case input_count:              \
1072    return &cache_.kLoop##input_count##Operator;
1073    CACHED_LOOP_LIST(CACHED_LOOP)
1074#undef CACHED_LOOP
1075    default:
1076      break;
1077  }
1078  // Uncached.
1079  return zone()->New<Operator>(             // --
1080      IrOpcode::kLoop, Operator::kKontrol,  // opcode
1081      "Loop",                               // name
1082      0, 0, control_input_count, 0, 0, 1);  // counts
1083}
1084
1085
1086const Operator* CommonOperatorBuilder::Merge(int control_input_count) {
1087  switch (control_input_count) {
1088#define CACHED_MERGE(input_count) \
1089  case input_count:               \
1090    return &cache_.kMerge##input_count##Operator;
1091    CACHED_MERGE_LIST(CACHED_MERGE)
1092#undef CACHED_MERGE
1093    default:
1094      break;
1095  }
1096  // Uncached.
1097  return zone()->New<Operator>(              // --
1098      IrOpcode::kMerge, Operator::kKontrol,  // opcode
1099      "Merge",                               // name
1100      0, 0, control_input_count, 0, 0, 1);   // counts
1101}
1102
1103const Operator* CommonOperatorBuilder::LoopExitValue(
1104    MachineRepresentation rep) {
1105  switch (rep) {
1106#define CACHED_LOOP_EXIT_VALUE(kRep) \
1107  case MachineRepresentation::kRep:  \
1108    return &cache_.kLoopExitValue##kRep##Operator;
1109
1110    CACHED_LOOP_EXIT_VALUE_LIST(CACHED_LOOP_EXIT_VALUE)
1111#undef CACHED_LOOP_EXIT_VALUE
1112    default:
1113      // Uncached.
1114      return zone()->New<Operator1<MachineRepresentation>>(  // --
1115          IrOpcode::kLoopExitValue, Operator::kPure,         // opcode
1116          "LoopExitValue",                                   // name
1117          1, 0, 1, 1, 0, 0,                                  // counts
1118          rep);                                              // parameter
1119  }
1120}
1121
1122const Operator* CommonOperatorBuilder::Parameter(int index,
1123                                                 const char* debug_name) {
1124  if (!debug_name) {
1125    switch (index) {
1126#define CACHED_PARAMETER(index) \
1127  case index:                   \
1128    return &cache_.kParameter##index##Operator;
1129      CACHED_PARAMETER_LIST(CACHED_PARAMETER)
1130#undef CACHED_PARAMETER
1131      default:
1132        break;
1133    }
1134  }
1135  // Uncached.
1136  return zone()->New<Operator1<ParameterInfo>>(  // --
1137      IrOpcode::kParameter, Operator::kPure,     // opcode
1138      "Parameter",                               // name
1139      1, 0, 0, 1, 0, 0,                          // counts
1140      ParameterInfo(index, debug_name));         // parameter info
1141}
1142
1143const Operator* CommonOperatorBuilder::OsrValue(int index) {
1144  return zone()->New<Operator1<int>>(                // --
1145      IrOpcode::kOsrValue, Operator::kNoProperties,  // opcode
1146      "OsrValue",                                    // name
1147      0, 0, 1, 1, 0, 0,                              // counts
1148      index);                                        // parameter
1149}
1150
1151const Operator* CommonOperatorBuilder::Int32Constant(int32_t value) {
1152  return zone()->New<Operator1<int32_t>>(         // --
1153      IrOpcode::kInt32Constant, Operator::kPure,  // opcode
1154      "Int32Constant",                            // name
1155      0, 0, 0, 1, 0, 0,                           // counts
1156      value);                                     // parameter
1157}
1158
1159
1160const Operator* CommonOperatorBuilder::Int64Constant(int64_t value) {
1161  return zone()->New<Operator1<int64_t>>(         // --
1162      IrOpcode::kInt64Constant, Operator::kPure,  // opcode
1163      "Int64Constant",                            // name
1164      0, 0, 0, 1, 0, 0,                           // counts
1165      value);                                     // parameter
1166}
1167
1168const Operator* CommonOperatorBuilder::TaggedIndexConstant(int32_t value) {
1169  return zone()->New<Operator1<int32_t>>(               // --
1170      IrOpcode::kTaggedIndexConstant, Operator::kPure,  // opcode
1171      "TaggedIndexConstant",                            // name
1172      0, 0, 0, 1, 0, 0,                                 // counts
1173      value);                                           // parameter
1174}
1175
1176const Operator* CommonOperatorBuilder::Float32Constant(volatile float value) {
1177  return zone()->New<Operator1<float>>(             // --
1178      IrOpcode::kFloat32Constant, Operator::kPure,  // opcode
1179      "Float32Constant",                            // name
1180      0, 0, 0, 1, 0, 0,                             // counts
1181      value);                                       // parameter
1182}
1183
1184
1185const Operator* CommonOperatorBuilder::Float64Constant(volatile double value) {
1186  return zone()->New<Operator1<double>>(            // --
1187      IrOpcode::kFloat64Constant, Operator::kPure,  // opcode
1188      "Float64Constant",                            // name
1189      0, 0, 0, 1, 0, 0,                             // counts
1190      value);                                       // parameter
1191}
1192
1193
1194const Operator* CommonOperatorBuilder::ExternalConstant(
1195    const ExternalReference& value) {
1196  return zone()->New<Operator1<ExternalReference>>(  // --
1197      IrOpcode::kExternalConstant, Operator::kPure,  // opcode
1198      "ExternalConstant",                            // name
1199      0, 0, 0, 1, 0, 0,                              // counts
1200      value);                                        // parameter
1201}
1202
1203
1204const Operator* CommonOperatorBuilder::NumberConstant(volatile double value) {
1205  return zone()->New<Operator1<double>>(           // --
1206      IrOpcode::kNumberConstant, Operator::kPure,  // opcode
1207      "NumberConstant",                            // name
1208      0, 0, 0, 1, 0, 0,                            // counts
1209      value);                                      // parameter
1210}
1211
1212const Operator* CommonOperatorBuilder::PointerConstant(intptr_t value) {
1213  return zone()->New<Operator1<intptr_t>>(          // --
1214      IrOpcode::kPointerConstant, Operator::kPure,  // opcode
1215      "PointerConstant",                            // name
1216      0, 0, 0, 1, 0, 0,                             // counts
1217      value);                                       // parameter
1218}
1219
1220const Operator* CommonOperatorBuilder::HeapConstant(
1221    const Handle<HeapObject>& value) {
1222  return zone()->New<Operator1<Handle<HeapObject>>>(  // --
1223      IrOpcode::kHeapConstant, Operator::kPure,       // opcode
1224      "HeapConstant",                                 // name
1225      0, 0, 0, 1, 0, 0,                               // counts
1226      value);                                         // parameter
1227}
1228
1229const Operator* CommonOperatorBuilder::CompressedHeapConstant(
1230    const Handle<HeapObject>& value) {
1231  return zone()->New<Operator1<Handle<HeapObject>>>(       // --
1232      IrOpcode::kCompressedHeapConstant, Operator::kPure,  // opcode
1233      "CompressedHeapConstant",                            // name
1234      0, 0, 0, 1, 0, 0,                                    // counts
1235      value);                                              // parameter
1236}
1237
1238Handle<HeapObject> HeapConstantOf(const Operator* op) {
1239  DCHECK(IrOpcode::kHeapConstant == op->opcode() ||
1240         IrOpcode::kCompressedHeapConstant == op->opcode());
1241  return OpParameter<Handle<HeapObject>>(op);
1242}
1243
1244const StringConstantBase* StringConstantBaseOf(const Operator* op) {
1245  DCHECK_EQ(IrOpcode::kDelayedStringConstant, op->opcode());
1246  return OpParameter<const StringConstantBase*>(op);
1247}
1248
1249const char* StaticAssertSourceOf(const Operator* op) {
1250  DCHECK_EQ(IrOpcode::kStaticAssert, op->opcode());
1251  return OpParameter<const char*>(op);
1252}
1253
1254const Operator* CommonOperatorBuilder::RelocatableInt32Constant(
1255    int32_t value, RelocInfo::Mode rmode) {
1256  return zone()->New<Operator1<RelocatablePtrConstantInfo>>(  // --
1257      IrOpcode::kRelocatableInt32Constant, Operator::kPure,   // opcode
1258      "RelocatableInt32Constant",                             // name
1259      0, 0, 0, 1, 0, 0,                                       // counts
1260      RelocatablePtrConstantInfo(value, rmode));              // parameter
1261}
1262
1263const Operator* CommonOperatorBuilder::RelocatableInt64Constant(
1264    int64_t value, RelocInfo::Mode rmode) {
1265  return zone()->New<Operator1<RelocatablePtrConstantInfo>>(  // --
1266      IrOpcode::kRelocatableInt64Constant, Operator::kPure,   // opcode
1267      "RelocatableInt64Constant",                             // name
1268      0, 0, 0, 1, 0, 0,                                       // counts
1269      RelocatablePtrConstantInfo(value, rmode));              // parameter
1270}
1271
1272const Operator* CommonOperatorBuilder::ObjectId(uint32_t object_id) {
1273  return zone()->New<Operator1<uint32_t>>(   // --
1274      IrOpcode::kObjectId, Operator::kPure,  // opcode
1275      "ObjectId",                            // name
1276      0, 0, 0, 1, 0, 0,                      // counts
1277      object_id);                            // parameter
1278}
1279
1280const Operator* CommonOperatorBuilder::Select(MachineRepresentation rep,
1281                                              BranchHint hint) {
1282  return zone()->New<Operator1<SelectParameters>>(  // --
1283      IrOpcode::kSelect, Operator::kPure,           // opcode
1284      "Select",                                     // name
1285      3, 0, 0, 1, 0, 0,                             // counts
1286      SelectParameters(rep, hint));                 // parameter
1287}
1288
1289
1290const Operator* CommonOperatorBuilder::Phi(MachineRepresentation rep,
1291                                           int value_input_count) {
1292  DCHECK_LT(0, value_input_count);  // Disallow empty phis.
1293#define CACHED_PHI(kRep, kValueInputCount)                 \
1294  if (MachineRepresentation::kRep == rep &&                \
1295      kValueInputCount == value_input_count) {             \
1296    return &cache_.kPhi##kRep##kValueInputCount##Operator; \
1297  }
1298  CACHED_PHI_LIST(CACHED_PHI)
1299#undef CACHED_PHI
1300  // Uncached.
1301  return zone()->New<Operator1<MachineRepresentation>>(  // --
1302      IrOpcode::kPhi, Operator::kPure,                   // opcode
1303      "Phi",                                             // name
1304      value_input_count, 0, 1, 1, 0, 0,                  // counts
1305      rep);                                              // parameter
1306}
1307
1308const Operator* CommonOperatorBuilder::TypeGuard(Type type) {
1309  return zone()->New<Operator1<Type>>(        // --
1310      IrOpcode::kTypeGuard, Operator::kPure,  // opcode
1311      "TypeGuard",                            // name
1312      1, 1, 1, 1, 1, 0,                       // counts
1313      type);                                  // parameter
1314}
1315
1316const Operator* CommonOperatorBuilder::FoldConstant() {
1317  return zone()->New<Operator>(                  // --
1318      IrOpcode::kFoldConstant, Operator::kPure,  // opcode
1319      "FoldConstant",                            // name
1320      2, 0, 0, 1, 0, 0);                         // counts
1321}
1322
1323const Operator* CommonOperatorBuilder::EffectPhi(int effect_input_count) {
1324  DCHECK_LT(0, effect_input_count);  // Disallow empty effect phis.
1325  switch (effect_input_count) {
1326#define CACHED_EFFECT_PHI(input_count) \
1327  case input_count:                    \
1328    return &cache_.kEffectPhi##input_count##Operator;
1329    CACHED_EFFECT_PHI_LIST(CACHED_EFFECT_PHI)
1330#undef CACHED_EFFECT_PHI
1331    default:
1332      break;
1333  }
1334  // Uncached.
1335  return zone()->New<Operator>(                  // --
1336      IrOpcode::kEffectPhi, Operator::kKontrol,  // opcode
1337      "EffectPhi",                               // name
1338      0, effect_input_count, 1, 0, 1, 0);        // counts
1339}
1340
1341const Operator* CommonOperatorBuilder::InductionVariablePhi(int input_count) {
1342  DCHECK_LE(4, input_count);  // There must be always the entry, backedge,
1343                              // increment and at least one bound.
1344  switch (input_count) {
1345#define CACHED_INDUCTION_VARIABLE_PHI(input_count) \
1346  case input_count:                                \
1347    return &cache_.kInductionVariablePhi##input_count##Operator;
1348    CACHED_INDUCTION_VARIABLE_PHI_LIST(CACHED_INDUCTION_VARIABLE_PHI)
1349#undef CACHED_INDUCTION_VARIABLE_PHI
1350    default:
1351      break;
1352  }
1353  // Uncached.
1354  return zone()->New<Operator>(                          // --
1355      IrOpcode::kInductionVariablePhi, Operator::kPure,  // opcode
1356      "InductionVariablePhi",                            // name
1357      input_count, 0, 1, 1, 0, 0);                       // counts
1358}
1359
1360const Operator* CommonOperatorBuilder::BeginRegion(
1361    RegionObservability region_observability) {
1362  switch (region_observability) {
1363    case RegionObservability::kObservable:
1364      return &cache_.kBeginRegionObservableOperator;
1365    case RegionObservability::kNotObservable:
1366      return &cache_.kBeginRegionNotObservableOperator;
1367  }
1368  UNREACHABLE();
1369}
1370
1371const Operator* CommonOperatorBuilder::StateValues(int arguments,
1372                                                   SparseInputMask bitmask) {
1373  if (bitmask.IsDense()) {
1374    switch (arguments) {
1375#define CACHED_STATE_VALUES(arguments) \
1376  case arguments:                      \
1377    return &cache_.kStateValues##arguments##Operator;
1378      CACHED_STATE_VALUES_LIST(CACHED_STATE_VALUES)
1379#undef CACHED_STATE_VALUES
1380      default:
1381        break;
1382    }
1383  }
1384
1385#if DEBUG
1386  DCHECK(bitmask.IsDense() || bitmask.CountReal() == arguments);
1387#endif
1388
1389  // Uncached.
1390  return zone()->New<Operator1<SparseInputMask>>(  // --
1391      IrOpcode::kStateValues, Operator::kPure,     // opcode
1392      "StateValues",                               // name
1393      arguments, 0, 0, 1, 0, 0,                    // counts
1394      bitmask);                                    // parameter
1395}
1396
1397const Operator* CommonOperatorBuilder::TypedStateValues(
1398    const ZoneVector<MachineType>* types, SparseInputMask bitmask) {
1399#if DEBUG
1400  DCHECK(bitmask.IsDense() ||
1401         bitmask.CountReal() == static_cast<int>(types->size()));
1402#endif
1403
1404  return zone()->New<Operator1<TypedStateValueInfo>>(  // --
1405      IrOpcode::kTypedStateValues, Operator::kPure,    // opcode
1406      "TypedStateValues",                              // name
1407      static_cast<int>(types->size()), 0, 0, 1, 0, 0,  // counts
1408      TypedStateValueInfo(types, bitmask));            // parameters
1409}
1410
1411const Operator* CommonOperatorBuilder::ArgumentsElementsState(
1412    ArgumentsStateType type) {
1413  return zone()->New<Operator1<ArgumentsStateType>>(       // --
1414      IrOpcode::kArgumentsElementsState, Operator::kPure,  // opcode
1415      "ArgumentsElementsState",                            // name
1416      0, 0, 0, 1, 0, 0,                                    // counts
1417      type);                                               // parameter
1418}
1419
1420const Operator* CommonOperatorBuilder::ArgumentsLengthState() {
1421  return zone()->New<Operator>(                          // --
1422      IrOpcode::kArgumentsLengthState, Operator::kPure,  // opcode
1423      "ArgumentsLengthState",                            // name
1424      0, 0, 0, 1, 0, 0);                                 // counts
1425}
1426
1427ArgumentsStateType ArgumentsStateTypeOf(Operator const* op) {
1428  DCHECK(op->opcode() == IrOpcode::kArgumentsElementsState);
1429  return OpParameter<ArgumentsStateType>(op);
1430}
1431
1432const Operator* CommonOperatorBuilder::ObjectState(uint32_t object_id,
1433                                                   int pointer_slots) {
1434  return zone()->New<Operator1<ObjectStateInfo>>(  // --
1435      IrOpcode::kObjectState, Operator::kPure,     // opcode
1436      "ObjectState",                               // name
1437      pointer_slots, 0, 0, 1, 0, 0,                // counts
1438      ObjectStateInfo{object_id, pointer_slots});  // parameter
1439}
1440
1441const Operator* CommonOperatorBuilder::TypedObjectState(
1442    uint32_t object_id, const ZoneVector<MachineType>* types) {
1443  return zone()->New<Operator1<TypedObjectStateInfo>>(  // --
1444      IrOpcode::kTypedObjectState, Operator::kPure,     // opcode
1445      "TypedObjectState",                               // name
1446      static_cast<int>(types->size()), 0, 0, 1, 0, 0,   // counts
1447      TypedObjectStateInfo(object_id, types));          // parameter
1448}
1449
1450uint32_t ObjectIdOf(Operator const* op) {
1451  switch (op->opcode()) {
1452    case IrOpcode::kObjectState:
1453      return OpParameter<ObjectStateInfo>(op).object_id();
1454    case IrOpcode::kTypedObjectState:
1455      return OpParameter<TypedObjectStateInfo>(op).object_id();
1456    case IrOpcode::kObjectId:
1457      return OpParameter<uint32_t>(op);
1458    default:
1459      UNREACHABLE();
1460  }
1461}
1462
1463MachineRepresentation DeadValueRepresentationOf(Operator const* op) {
1464  DCHECK_EQ(IrOpcode::kDeadValue, op->opcode());
1465  return OpParameter<MachineRepresentation>(op);
1466}
1467
1468const Operator* CommonOperatorBuilder::FrameState(
1469    BytecodeOffset bailout_id, OutputFrameStateCombine state_combine,
1470    const FrameStateFunctionInfo* function_info) {
1471  FrameStateInfo state_info(bailout_id, state_combine, function_info);
1472  return zone()->New<Operator1<FrameStateInfo>>(  // --
1473      IrOpcode::kFrameState, Operator::kPure,     // opcode
1474      "FrameState",                               // name
1475      5, 0, 0, 1, 0, 0,                           // counts
1476      state_info);                                // parameter
1477}
1478
1479const Operator* CommonOperatorBuilder::Call(
1480    const CallDescriptor* call_descriptor) {
1481  class CallOperator final : public Operator1<const CallDescriptor*> {
1482   public:
1483    explicit CallOperator(const CallDescriptor* call_descriptor)
1484        : Operator1<const CallDescriptor*>(
1485              IrOpcode::kCall, call_descriptor->properties(), "Call",
1486              call_descriptor->InputCount() +
1487                  call_descriptor->FrameStateCount(),
1488              Operator::ZeroIfPure(call_descriptor->properties()),
1489              Operator::ZeroIfEliminatable(call_descriptor->properties()),
1490              call_descriptor->ReturnCount(),
1491              Operator::ZeroIfPure(call_descriptor->properties()),
1492              Operator::ZeroIfNoThrow(call_descriptor->properties()),
1493              call_descriptor) {}
1494
1495    void PrintParameter(std::ostream& os,
1496                        PrintVerbosity verbose) const override {
1497      os << "[" << *parameter() << "]";
1498    }
1499  };
1500  return zone()->New<CallOperator>(call_descriptor);
1501}
1502
1503const Operator* CommonOperatorBuilder::TailCall(
1504    const CallDescriptor* call_descriptor) {
1505  class TailCallOperator final : public Operator1<const CallDescriptor*> {
1506   public:
1507    explicit TailCallOperator(const CallDescriptor* call_descriptor)
1508        : Operator1<const CallDescriptor*>(
1509              IrOpcode::kTailCall,
1510              call_descriptor->properties() | Operator::kNoThrow, "TailCall",
1511              call_descriptor->InputCount() +
1512                  call_descriptor->FrameStateCount(),
1513              1, 1, 0, 0, 1, call_descriptor) {}
1514
1515    void PrintParameter(std::ostream& os,
1516                        PrintVerbosity verbose) const override {
1517      os << "[" << *parameter() << "]";
1518    }
1519  };
1520  return zone()->New<TailCallOperator>(call_descriptor);
1521}
1522
1523const Operator* CommonOperatorBuilder::Projection(size_t index) {
1524  switch (index) {
1525#define CACHED_PROJECTION(index) \
1526  case index:                    \
1527    return &cache_.kProjection##index##Operator;
1528    CACHED_PROJECTION_LIST(CACHED_PROJECTION)
1529#undef CACHED_PROJECTION
1530    default:
1531      break;
1532  }
1533  // Uncached.
1534  return zone()->New<Operator1<size_t>>(  // --
1535      IrOpcode::kProjection,              // opcode
1536      Operator::kPure,                    // flags
1537      "Projection",                       // name
1538      1, 0, 1, 1, 0, 0,                   // counts
1539      index);                             // parameter
1540}
1541
1542
1543const Operator* CommonOperatorBuilder::ResizeMergeOrPhi(const Operator* op,
1544                                                        int size) {
1545  if (op->opcode() == IrOpcode::kPhi) {
1546    return Phi(PhiRepresentationOf(op), size);
1547  } else if (op->opcode() == IrOpcode::kEffectPhi) {
1548    return EffectPhi(size);
1549  } else if (op->opcode() == IrOpcode::kMerge) {
1550    return Merge(size);
1551  } else if (op->opcode() == IrOpcode::kLoop) {
1552    return Loop(size);
1553  } else {
1554    UNREACHABLE();
1555  }
1556}
1557
1558const FrameStateFunctionInfo*
1559CommonOperatorBuilder::CreateFrameStateFunctionInfo(
1560    FrameStateType type, int parameter_count, int local_count,
1561    Handle<SharedFunctionInfo> shared_info) {
1562  return zone()->New<FrameStateFunctionInfo>(type, parameter_count, local_count,
1563                                             shared_info);
1564}
1565
1566#if V8_ENABLE_WEBASSEMBLY
1567const FrameStateFunctionInfo*
1568CommonOperatorBuilder::CreateJSToWasmFrameStateFunctionInfo(
1569    FrameStateType type, int parameter_count, int local_count,
1570    Handle<SharedFunctionInfo> shared_info,
1571    const wasm::FunctionSig* signature) {
1572  DCHECK_EQ(type, FrameStateType::kJSToWasmBuiltinContinuation);
1573  DCHECK_NOT_NULL(signature);
1574  return zone()->New<JSToWasmFrameStateFunctionInfo>(
1575      type, parameter_count, local_count, shared_info, signature);
1576}
1577#endif  // V8_ENABLE_WEBASSEMBLY
1578
1579const Operator* CommonOperatorBuilder::DeadValue(MachineRepresentation rep) {
1580  return zone()->New<Operator1<MachineRepresentation>>(  // --
1581      IrOpcode::kDeadValue, Operator::kPure,             // opcode
1582      "DeadValue",                                       // name
1583      1, 0, 0, 1, 0, 0,                                  // counts
1584      rep);                                              // parameter
1585}
1586
1587const FrameStateInfo& FrameStateInfoOf(const Operator* op) {
1588  DCHECK_EQ(IrOpcode::kFrameState, op->opcode());
1589  return OpParameter<FrameStateInfo>(op);
1590}
1591
1592#undef COMMON_CACHED_OP_LIST
1593#undef CACHED_BRANCH_LIST
1594#undef CACHED_RETURN_LIST
1595#undef CACHED_END_LIST
1596#undef CACHED_EFFECT_PHI_LIST
1597#undef CACHED_INDUCTION_VARIABLE_PHI_LIST
1598#undef CACHED_LOOP_LIST
1599#undef CACHED_MERGE_LIST
1600#undef CACHED_DEOPTIMIZE_LIST
1601#undef CACHED_DEOPTIMIZE_IF_LIST
1602#undef CACHED_DEOPTIMIZE_UNLESS_LIST
1603#undef CACHED_TRAP_IF_LIST
1604#undef CACHED_TRAP_UNLESS_LIST
1605#undef CACHED_PARAMETER_LIST
1606#undef CACHED_PHI_LIST
1607#undef CACHED_PROJECTION_LIST
1608#undef CACHED_STATE_VALUES_LIST
1609
1610}  // namespace compiler
1611}  // namespace internal
1612}  // namespace v8
1613