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