Home | History | Annotate | Download | only in compiler
      1 // Copyright 2012 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/simplified-operator.h"
      6 
      7 #include "src/base/lazy-instance.h"
      8 #include "src/compiler/opcodes.h"
      9 #include "src/compiler/operator.h"
     10 #include "src/compiler/types.h"
     11 #include "src/handles-inl.h"
     12 #include "src/objects-inl.h"
     13 #include "src/objects/map.h"
     14 #include "src/objects/name.h"
     15 
     16 namespace v8 {
     17 namespace internal {
     18 namespace compiler {
     19 
     20 size_t hash_value(BaseTaggedness base_taggedness) {
     21   return static_cast<uint8_t>(base_taggedness);
     22 }
     23 
     24 std::ostream& operator<<(std::ostream& os, BaseTaggedness base_taggedness) {
     25   switch (base_taggedness) {
     26     case kUntaggedBase:
     27       return os << "untagged base";
     28     case kTaggedBase:
     29       return os << "tagged base";
     30   }
     31   UNREACHABLE();
     32 }
     33 
     34 bool operator==(FieldAccess const& lhs, FieldAccess const& rhs) {
     35   // On purpose we don't include the write barrier kind here, as this method is
     36   // really only relevant for eliminating loads and they don't care about the
     37   // write barrier mode.
     38   return lhs.base_is_tagged == rhs.base_is_tagged && lhs.offset == rhs.offset &&
     39          lhs.map.address() == rhs.map.address() &&
     40          lhs.machine_type == rhs.machine_type;
     41 }
     42 
     43 size_t hash_value(FieldAccess const& access) {
     44   // On purpose we don't include the write barrier kind here, as this method is
     45   // really only relevant for eliminating loads and they don't care about the
     46   // write barrier mode.
     47   return base::hash_combine(access.base_is_tagged, access.offset,
     48                             access.machine_type);
     49 }
     50 
     51 size_t hash_value(LoadSensitivity load_sensitivity) {
     52   return static_cast<size_t>(load_sensitivity);
     53 }
     54 
     55 std::ostream& operator<<(std::ostream& os, LoadSensitivity load_sensitivity) {
     56   switch (load_sensitivity) {
     57     case LoadSensitivity::kCritical:
     58       return os << "Critical";
     59     case LoadSensitivity::kSafe:
     60       return os << "Safe";
     61     case LoadSensitivity::kUnsafe:
     62       return os << "Unsafe";
     63   }
     64   UNREACHABLE();
     65 }
     66 
     67 std::ostream& operator<<(std::ostream& os, FieldAccess const& access) {
     68   os << "[" << access.base_is_tagged << ", " << access.offset << ", ";
     69 #ifdef OBJECT_PRINT
     70   Handle<Name> name;
     71   if (access.name.ToHandle(&name)) {
     72     name->NamePrint(os);
     73     os << ", ";
     74   }
     75   Handle<Map> map;
     76   if (access.map.ToHandle(&map)) {
     77     os << Brief(*map) << ", ";
     78   }
     79 #endif
     80   os << access.type << ", " << access.machine_type << ", "
     81      << access.write_barrier_kind;
     82   if (FLAG_untrusted_code_mitigations || FLAG_branch_load_poisoning) {
     83     os << ", " << access.load_sensitivity;
     84   }
     85   os << "]";
     86   return os;
     87 }
     88 
     89 template <>
     90 void Operator1<FieldAccess>::PrintParameter(std::ostream& os,
     91                                             PrintVerbosity verbose) const {
     92   if (verbose == PrintVerbosity::kVerbose) {
     93     os << parameter();
     94   } else {
     95     os << "[+" << parameter().offset << "]";
     96   }
     97 }
     98 
     99 bool operator==(ElementAccess const& lhs, ElementAccess const& rhs) {
    100   // On purpose we don't include the write barrier kind here, as this method is
    101   // really only relevant for eliminating loads and they don't care about the
    102   // write barrier mode.
    103   return lhs.base_is_tagged == rhs.base_is_tagged &&
    104          lhs.header_size == rhs.header_size &&
    105          lhs.machine_type == rhs.machine_type;
    106 }
    107 
    108 size_t hash_value(ElementAccess const& access) {
    109   // On purpose we don't include the write barrier kind here, as this method is
    110   // really only relevant for eliminating loads and they don't care about the
    111   // write barrier mode.
    112   return base::hash_combine(access.base_is_tagged, access.header_size,
    113                             access.machine_type);
    114 }
    115 
    116 
    117 std::ostream& operator<<(std::ostream& os, ElementAccess const& access) {
    118   os << access.base_is_tagged << ", " << access.header_size << ", "
    119      << access.type << ", " << access.machine_type << ", "
    120      << access.write_barrier_kind;
    121   if (FLAG_untrusted_code_mitigations || FLAG_branch_load_poisoning) {
    122     os << ", " << access.load_sensitivity;
    123   }
    124   return os;
    125 }
    126 
    127 const FieldAccess& FieldAccessOf(const Operator* op) {
    128   DCHECK_NOT_NULL(op);
    129   DCHECK(op->opcode() == IrOpcode::kLoadField ||
    130          op->opcode() == IrOpcode::kStoreField);
    131   return OpParameter<FieldAccess>(op);
    132 }
    133 
    134 
    135 const ElementAccess& ElementAccessOf(const Operator* op) {
    136   DCHECK_NOT_NULL(op);
    137   DCHECK(op->opcode() == IrOpcode::kLoadElement ||
    138          op->opcode() == IrOpcode::kStoreElement);
    139   return OpParameter<ElementAccess>(op);
    140 }
    141 
    142 ExternalArrayType ExternalArrayTypeOf(const Operator* op) {
    143   DCHECK(op->opcode() == IrOpcode::kLoadTypedElement ||
    144          op->opcode() == IrOpcode::kLoadDataViewElement ||
    145          op->opcode() == IrOpcode::kStoreTypedElement ||
    146          op->opcode() == IrOpcode::kStoreDataViewElement);
    147   return OpParameter<ExternalArrayType>(op);
    148 }
    149 
    150 ConvertReceiverMode ConvertReceiverModeOf(Operator const* op) {
    151   DCHECK_EQ(IrOpcode::kConvertReceiver, op->opcode());
    152   return OpParameter<ConvertReceiverMode>(op);
    153 }
    154 
    155 size_t hash_value(CheckFloat64HoleMode mode) {
    156   return static_cast<size_t>(mode);
    157 }
    158 
    159 std::ostream& operator<<(std::ostream& os, CheckFloat64HoleMode mode) {
    160   switch (mode) {
    161     case CheckFloat64HoleMode::kAllowReturnHole:
    162       return os << "allow-return-hole";
    163     case CheckFloat64HoleMode::kNeverReturnHole:
    164       return os << "never-return-hole";
    165   }
    166   UNREACHABLE();
    167 }
    168 
    169 CheckFloat64HoleParameters const& CheckFloat64HoleParametersOf(
    170     Operator const* op) {
    171   DCHECK_EQ(IrOpcode::kCheckFloat64Hole, op->opcode());
    172   return OpParameter<CheckFloat64HoleParameters>(op);
    173 }
    174 
    175 std::ostream& operator<<(std::ostream& os,
    176                          CheckFloat64HoleParameters const& params) {
    177   os << params.mode();
    178   if (params.feedback().IsValid()) os << "; " << params.feedback();
    179   return os;
    180 }
    181 
    182 size_t hash_value(const CheckFloat64HoleParameters& params) {
    183   return base::hash_combine(params.mode(), params.feedback());
    184 }
    185 
    186 bool operator==(CheckFloat64HoleParameters const& lhs,
    187                 CheckFloat64HoleParameters const& rhs) {
    188   return lhs.mode() == rhs.mode() && lhs.feedback() == rhs.feedback();
    189 }
    190 
    191 bool operator!=(CheckFloat64HoleParameters const& lhs,
    192                 CheckFloat64HoleParameters const& rhs) {
    193   return !(lhs == rhs);
    194 }
    195 
    196 CheckForMinusZeroMode CheckMinusZeroModeOf(const Operator* op) {
    197   DCHECK(op->opcode() == IrOpcode::kChangeFloat64ToTagged ||
    198          op->opcode() == IrOpcode::kCheckedInt32Mul);
    199   return OpParameter<CheckForMinusZeroMode>(op);
    200 }
    201 
    202 size_t hash_value(CheckForMinusZeroMode mode) {
    203   return static_cast<size_t>(mode);
    204 }
    205 
    206 std::ostream& operator<<(std::ostream& os, CheckForMinusZeroMode mode) {
    207   switch (mode) {
    208     case CheckForMinusZeroMode::kCheckForMinusZero:
    209       return os << "check-for-minus-zero";
    210     case CheckForMinusZeroMode::kDontCheckForMinusZero:
    211       return os << "dont-check-for-minus-zero";
    212   }
    213   UNREACHABLE();
    214 }
    215 
    216 std::ostream& operator<<(std::ostream& os, CheckMapsFlags flags) {
    217   bool empty = true;
    218   if (flags & CheckMapsFlag::kTryMigrateInstance) {
    219     os << "TryMigrateInstance";
    220     empty = false;
    221   }
    222   if (empty) os << "None";
    223   return os;
    224 }
    225 
    226 MapsParameterInfo::MapsParameterInfo(ZoneHandleSet<Map> const& maps)
    227     : maps_(maps), instance_type_(Nothing<InstanceType>()) {
    228   DCHECK_LT(0, maps.size());
    229   instance_type_ = Just(maps.at(0)->instance_type());
    230   for (size_t i = 1; i < maps.size(); ++i) {
    231     if (instance_type_.FromJust() != maps.at(i)->instance_type()) {
    232       instance_type_ = Nothing<InstanceType>();
    233       break;
    234     }
    235   }
    236 }
    237 
    238 std::ostream& operator<<(std::ostream& os, MapsParameterInfo const& p) {
    239   ZoneHandleSet<Map> const& maps = p.maps();
    240   InstanceType instance_type;
    241   if (p.instance_type().To(&instance_type)) {
    242     os << ", " << instance_type;
    243   }
    244   for (size_t i = 0; i < maps.size(); ++i) {
    245     os << ", " << Brief(*maps[i]);
    246   }
    247   return os;
    248 }
    249 
    250 bool operator==(MapsParameterInfo const& lhs, MapsParameterInfo const& rhs) {
    251   return lhs.maps() == rhs.maps();
    252 }
    253 
    254 bool operator!=(MapsParameterInfo const& lhs, MapsParameterInfo const& rhs) {
    255   return !(lhs == rhs);
    256 }
    257 
    258 size_t hash_value(MapsParameterInfo const& p) { return hash_value(p.maps()); }
    259 
    260 bool operator==(CheckMapsParameters const& lhs,
    261                 CheckMapsParameters const& rhs) {
    262   return lhs.flags() == rhs.flags() && lhs.maps() == rhs.maps() &&
    263          lhs.feedback() == rhs.feedback();
    264 }
    265 
    266 size_t hash_value(CheckMapsParameters const& p) {
    267   return base::hash_combine(p.flags(), p.maps(), p.feedback());
    268 }
    269 
    270 std::ostream& operator<<(std::ostream& os, CheckMapsParameters const& p) {
    271   os << p.flags() << p.maps_info();
    272   if (p.feedback().IsValid()) {
    273     os << "; " << p.feedback();
    274   }
    275   return os;
    276 }
    277 
    278 CheckMapsParameters const& CheckMapsParametersOf(Operator const* op) {
    279   DCHECK_EQ(IrOpcode::kCheckMaps, op->opcode());
    280   return OpParameter<CheckMapsParameters>(op);
    281 }
    282 
    283 MapsParameterInfo const& CompareMapsParametersOf(Operator const* op) {
    284   DCHECK_EQ(IrOpcode::kCompareMaps, op->opcode());
    285   return OpParameter<MapsParameterInfo>(op);
    286 }
    287 
    288 MapsParameterInfo const& MapGuardMapsOf(Operator const* op) {
    289   DCHECK_EQ(IrOpcode::kMapGuard, op->opcode());
    290   return OpParameter<MapsParameterInfo>(op);
    291 }
    292 
    293 size_t hash_value(CheckTaggedInputMode mode) {
    294   return static_cast<size_t>(mode);
    295 }
    296 
    297 std::ostream& operator<<(std::ostream& os, CheckTaggedInputMode mode) {
    298   switch (mode) {
    299     case CheckTaggedInputMode::kNumber:
    300       return os << "Number";
    301     case CheckTaggedInputMode::kNumberOrOddball:
    302       return os << "NumberOrOddball";
    303   }
    304   UNREACHABLE();
    305 }
    306 
    307 std::ostream& operator<<(std::ostream& os, GrowFastElementsMode mode) {
    308   switch (mode) {
    309     case GrowFastElementsMode::kDoubleElements:
    310       return os << "DoubleElements";
    311     case GrowFastElementsMode::kSmiOrObjectElements:
    312       return os << "SmiOrObjectElements";
    313   }
    314   UNREACHABLE();
    315 }
    316 
    317 bool operator==(const GrowFastElementsParameters& lhs,
    318                 const GrowFastElementsParameters& rhs) {
    319   return lhs.mode() == rhs.mode() && lhs.feedback() == rhs.feedback();
    320 }
    321 
    322 inline size_t hash_value(const GrowFastElementsParameters& params) {
    323   return base::hash_combine(params.mode(), params.feedback());
    324 }
    325 
    326 std::ostream& operator<<(std::ostream& os,
    327                          const GrowFastElementsParameters& params) {
    328   os << params.mode();
    329   if (params.feedback().IsValid()) {
    330     os << params.feedback();
    331   }
    332   return os;
    333 }
    334 
    335 const GrowFastElementsParameters& GrowFastElementsParametersOf(
    336     const Operator* op) {
    337   DCHECK_EQ(IrOpcode::kMaybeGrowFastElements, op->opcode());
    338   return OpParameter<GrowFastElementsParameters>(op);
    339 }
    340 
    341 bool operator==(ElementsTransition const& lhs, ElementsTransition const& rhs) {
    342   return lhs.mode() == rhs.mode() &&
    343          lhs.source().address() == rhs.source().address() &&
    344          lhs.target().address() == rhs.target().address();
    345 }
    346 
    347 size_t hash_value(ElementsTransition transition) {
    348   return base::hash_combine(static_cast<uint8_t>(transition.mode()),
    349                             transition.source().address(),
    350                             transition.target().address());
    351 }
    352 
    353 std::ostream& operator<<(std::ostream& os, ElementsTransition transition) {
    354   switch (transition.mode()) {
    355     case ElementsTransition::kFastTransition:
    356       return os << "fast-transition from " << Brief(*transition.source())
    357                 << " to " << Brief(*transition.target());
    358     case ElementsTransition::kSlowTransition:
    359       return os << "slow-transition from " << Brief(*transition.source())
    360                 << " to " << Brief(*transition.target());
    361   }
    362   UNREACHABLE();
    363 }
    364 
    365 ElementsTransition const& ElementsTransitionOf(const Operator* op) {
    366   DCHECK_EQ(IrOpcode::kTransitionElementsKind, op->opcode());
    367   return OpParameter<ElementsTransition>(op);
    368 }
    369 
    370 namespace {
    371 
    372 // Parameters for the TransitionAndStoreElement opcode.
    373 class TransitionAndStoreElementParameters final {
    374  public:
    375   TransitionAndStoreElementParameters(Handle<Map> double_map,
    376                                       Handle<Map> fast_map);
    377 
    378   Handle<Map> double_map() const { return double_map_; }
    379   Handle<Map> fast_map() const { return fast_map_; }
    380 
    381  private:
    382   Handle<Map> const double_map_;
    383   Handle<Map> const fast_map_;
    384 };
    385 
    386 TransitionAndStoreElementParameters::TransitionAndStoreElementParameters(
    387     Handle<Map> double_map, Handle<Map> fast_map)
    388     : double_map_(double_map), fast_map_(fast_map) {}
    389 
    390 bool operator==(TransitionAndStoreElementParameters const& lhs,
    391                 TransitionAndStoreElementParameters const& rhs) {
    392   return lhs.fast_map().address() == rhs.fast_map().address() &&
    393          lhs.double_map().address() == rhs.double_map().address();
    394 }
    395 
    396 size_t hash_value(TransitionAndStoreElementParameters parameters) {
    397   return base::hash_combine(parameters.fast_map().address(),
    398                             parameters.double_map().address());
    399 }
    400 
    401 std::ostream& operator<<(std::ostream& os,
    402                          TransitionAndStoreElementParameters parameters) {
    403   return os << "fast-map" << Brief(*parameters.fast_map()) << " double-map"
    404             << Brief(*parameters.double_map());
    405 }
    406 
    407 }  // namespace
    408 
    409 namespace {
    410 
    411 // Parameters for the TransitionAndStoreNonNumberElement opcode.
    412 class TransitionAndStoreNonNumberElementParameters final {
    413  public:
    414   TransitionAndStoreNonNumberElementParameters(Handle<Map> fast_map,
    415                                                Type value_type);
    416 
    417   Handle<Map> fast_map() const { return fast_map_; }
    418   Type value_type() const { return value_type_; }
    419 
    420  private:
    421   Handle<Map> const fast_map_;
    422   Type value_type_;
    423 };
    424 
    425 TransitionAndStoreNonNumberElementParameters::
    426     TransitionAndStoreNonNumberElementParameters(Handle<Map> fast_map,
    427                                                  Type value_type)
    428     : fast_map_(fast_map), value_type_(value_type) {}
    429 
    430 bool operator==(TransitionAndStoreNonNumberElementParameters const& lhs,
    431                 TransitionAndStoreNonNumberElementParameters const& rhs) {
    432   return lhs.fast_map().address() == rhs.fast_map().address() &&
    433          lhs.value_type() == rhs.value_type();
    434 }
    435 
    436 size_t hash_value(TransitionAndStoreNonNumberElementParameters parameters) {
    437   return base::hash_combine(parameters.fast_map().address(),
    438                             parameters.value_type());
    439 }
    440 
    441 std::ostream& operator<<(
    442     std::ostream& os, TransitionAndStoreNonNumberElementParameters parameters) {
    443   return os << parameters.value_type() << ", fast-map"
    444             << Brief(*parameters.fast_map());
    445 }
    446 
    447 }  // namespace
    448 
    449 namespace {
    450 
    451 // Parameters for the TransitionAndStoreNumberElement opcode.
    452 class TransitionAndStoreNumberElementParameters final {
    453  public:
    454   explicit TransitionAndStoreNumberElementParameters(Handle<Map> double_map);
    455 
    456   Handle<Map> double_map() const { return double_map_; }
    457 
    458  private:
    459   Handle<Map> const double_map_;
    460 };
    461 
    462 TransitionAndStoreNumberElementParameters::
    463     TransitionAndStoreNumberElementParameters(Handle<Map> double_map)
    464     : double_map_(double_map) {}
    465 
    466 bool operator==(TransitionAndStoreNumberElementParameters const& lhs,
    467                 TransitionAndStoreNumberElementParameters const& rhs) {
    468   return lhs.double_map().address() == rhs.double_map().address();
    469 }
    470 
    471 size_t hash_value(TransitionAndStoreNumberElementParameters parameters) {
    472   return base::hash_combine(parameters.double_map().address());
    473 }
    474 
    475 std::ostream& operator<<(std::ostream& os,
    476                          TransitionAndStoreNumberElementParameters parameters) {
    477   return os << "double-map" << Brief(*parameters.double_map());
    478 }
    479 
    480 }  // namespace
    481 
    482 Handle<Map> DoubleMapParameterOf(const Operator* op) {
    483   if (op->opcode() == IrOpcode::kTransitionAndStoreElement) {
    484     return OpParameter<TransitionAndStoreElementParameters>(op).double_map();
    485   } else if (op->opcode() == IrOpcode::kTransitionAndStoreNumberElement) {
    486     return OpParameter<TransitionAndStoreNumberElementParameters>(op)
    487         .double_map();
    488   }
    489   UNREACHABLE();
    490   return Handle<Map>::null();
    491 }
    492 
    493 Type ValueTypeParameterOf(const Operator* op) {
    494   DCHECK_EQ(IrOpcode::kTransitionAndStoreNonNumberElement, op->opcode());
    495   return OpParameter<TransitionAndStoreNonNumberElementParameters>(op)
    496       .value_type();
    497 }
    498 
    499 Handle<Map> FastMapParameterOf(const Operator* op) {
    500   if (op->opcode() == IrOpcode::kTransitionAndStoreElement) {
    501     return OpParameter<TransitionAndStoreElementParameters>(op).fast_map();
    502   } else if (op->opcode() == IrOpcode::kTransitionAndStoreNonNumberElement) {
    503     return OpParameter<TransitionAndStoreNonNumberElementParameters>(op)
    504         .fast_map();
    505   }
    506   UNREACHABLE();
    507   return Handle<Map>::null();
    508 }
    509 
    510 std::ostream& operator<<(std::ostream& os, NumberOperationHint hint) {
    511   switch (hint) {
    512     case NumberOperationHint::kSignedSmall:
    513       return os << "SignedSmall";
    514     case NumberOperationHint::kSignedSmallInputs:
    515       return os << "SignedSmallInputs";
    516     case NumberOperationHint::kSigned32:
    517       return os << "Signed32";
    518     case NumberOperationHint::kNumber:
    519       return os << "Number";
    520     case NumberOperationHint::kNumberOrOddball:
    521       return os << "NumberOrOddball";
    522   }
    523   UNREACHABLE();
    524 }
    525 
    526 size_t hash_value(NumberOperationHint hint) {
    527   return static_cast<uint8_t>(hint);
    528 }
    529 
    530 NumberOperationHint NumberOperationHintOf(const Operator* op) {
    531   DCHECK(op->opcode() == IrOpcode::kSpeculativeNumberAdd ||
    532          op->opcode() == IrOpcode::kSpeculativeNumberSubtract ||
    533          op->opcode() == IrOpcode::kSpeculativeNumberMultiply ||
    534          op->opcode() == IrOpcode::kSpeculativeNumberDivide ||
    535          op->opcode() == IrOpcode::kSpeculativeNumberModulus ||
    536          op->opcode() == IrOpcode::kSpeculativeNumberShiftLeft ||
    537          op->opcode() == IrOpcode::kSpeculativeNumberShiftRight ||
    538          op->opcode() == IrOpcode::kSpeculativeNumberShiftRightLogical ||
    539          op->opcode() == IrOpcode::kSpeculativeNumberBitwiseAnd ||
    540          op->opcode() == IrOpcode::kSpeculativeNumberBitwiseOr ||
    541          op->opcode() == IrOpcode::kSpeculativeNumberBitwiseXor ||
    542          op->opcode() == IrOpcode::kSpeculativeNumberEqual ||
    543          op->opcode() == IrOpcode::kSpeculativeNumberLessThan ||
    544          op->opcode() == IrOpcode::kSpeculativeNumberLessThanOrEqual ||
    545          op->opcode() == IrOpcode::kSpeculativeSafeIntegerAdd ||
    546          op->opcode() == IrOpcode::kSpeculativeSafeIntegerSubtract);
    547   return OpParameter<NumberOperationHint>(op);
    548 }
    549 
    550 bool operator==(NumberOperationParameters const& lhs,
    551                 NumberOperationParameters const& rhs) {
    552   return lhs.hint() == rhs.hint() && lhs.feedback() == rhs.feedback();
    553 }
    554 
    555 size_t hash_value(NumberOperationParameters const& p) {
    556   return base::hash_combine(p.hint(), p.feedback());
    557 }
    558 
    559 std::ostream& operator<<(std::ostream& os, NumberOperationParameters const& p) {
    560   return os << p.hint() << " " << p.feedback();
    561 }
    562 
    563 NumberOperationParameters const& NumberOperationParametersOf(
    564     Operator const* op) {
    565   DCHECK_EQ(IrOpcode::kSpeculativeToNumber, op->opcode());
    566   return OpParameter<NumberOperationParameters>(op);
    567 }
    568 
    569 size_t hash_value(AllocateParameters info) {
    570   return base::hash_combine(info.type(), info.pretenure());
    571 }
    572 
    573 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
    574                                            AllocateParameters info) {
    575   return os << info.type() << ", " << info.pretenure();
    576 }
    577 
    578 bool operator==(AllocateParameters const& lhs, AllocateParameters const& rhs) {
    579   return lhs.pretenure() == rhs.pretenure() && lhs.type() == rhs.type();
    580 }
    581 
    582 PretenureFlag PretenureFlagOf(const Operator* op) {
    583   if (op->opcode() == IrOpcode::kNewDoubleElements ||
    584       op->opcode() == IrOpcode::kNewSmiOrObjectElements) {
    585     return OpParameter<PretenureFlag>(op);
    586   }
    587   DCHECK(op->opcode() == IrOpcode::kAllocate ||
    588          op->opcode() == IrOpcode::kAllocateRaw);
    589   return OpParameter<AllocateParameters>(op).pretenure();
    590 }
    591 
    592 Type AllocateTypeOf(const Operator* op) {
    593   DCHECK_EQ(IrOpcode::kAllocate, op->opcode());
    594   return OpParameter<AllocateParameters>(op).type();
    595 }
    596 
    597 UnicodeEncoding UnicodeEncodingOf(const Operator* op) {
    598   DCHECK(op->opcode() == IrOpcode::kStringFromSingleCodePoint ||
    599          op->opcode() == IrOpcode::kStringCodePointAt);
    600   return OpParameter<UnicodeEncoding>(op);
    601 }
    602 
    603 AbortReason AbortReasonOf(const Operator* op) {
    604   DCHECK_EQ(IrOpcode::kRuntimeAbort, op->opcode());
    605   return static_cast<AbortReason>(OpParameter<int>(op));
    606 }
    607 
    608 const CheckTaggedInputParameters& CheckTaggedInputParametersOf(
    609     const Operator* op) {
    610   DCHECK(op->opcode() == IrOpcode::kCheckedTruncateTaggedToWord32 ||
    611          op->opcode() == IrOpcode::kCheckedTaggedToFloat64);
    612   return OpParameter<CheckTaggedInputParameters>(op);
    613 }
    614 
    615 std::ostream& operator<<(std::ostream& os,
    616                          const CheckTaggedInputParameters& params) {
    617   os << params.mode();
    618   if (params.feedback().IsValid()) {
    619     os << "; " << params.feedback();
    620   }
    621   return os;
    622 }
    623 
    624 size_t hash_value(const CheckTaggedInputParameters& params) {
    625   return base::hash_combine(params.mode(), params.feedback());
    626 }
    627 
    628 bool operator==(CheckTaggedInputParameters const& lhs,
    629                 CheckTaggedInputParameters const& rhs) {
    630   return lhs.mode() == rhs.mode() && lhs.feedback() == rhs.feedback();
    631 }
    632 
    633 const CheckMinusZeroParameters& CheckMinusZeroParametersOf(const Operator* op) {
    634   DCHECK(IrOpcode::kCheckedTaggedToInt32 == op->opcode() ||
    635          IrOpcode::kCheckedFloat64ToInt32 == op->opcode());
    636   return OpParameter<CheckMinusZeroParameters>(op);
    637 }
    638 
    639 std::ostream& operator<<(std::ostream& os,
    640                          const CheckMinusZeroParameters& params) {
    641   os << params.mode();
    642   if (params.feedback().IsValid()) {
    643     os << "; " << params.feedback();
    644   }
    645   return os;
    646 }
    647 
    648 size_t hash_value(const CheckMinusZeroParameters& params) {
    649   return base::hash_combine(params.mode(), params.feedback());
    650 }
    651 
    652 bool operator==(CheckMinusZeroParameters const& lhs,
    653                 CheckMinusZeroParameters const& rhs) {
    654   return lhs.mode() == rhs.mode() && lhs.feedback() == rhs.feedback();
    655 }
    656 
    657 #define PURE_OP_LIST(V)                                          \
    658   V(BooleanNot, Operator::kNoProperties, 1, 0)                   \
    659   V(NumberEqual, Operator::kCommutative, 2, 0)                   \
    660   V(NumberLessThan, Operator::kNoProperties, 2, 0)               \
    661   V(NumberLessThanOrEqual, Operator::kNoProperties, 2, 0)        \
    662   V(NumberAdd, Operator::kCommutative, 2, 0)                     \
    663   V(NumberSubtract, Operator::kNoProperties, 2, 0)               \
    664   V(NumberMultiply, Operator::kCommutative, 2, 0)                \
    665   V(NumberDivide, Operator::kNoProperties, 2, 0)                 \
    666   V(NumberModulus, Operator::kNoProperties, 2, 0)                \
    667   V(NumberBitwiseOr, Operator::kCommutative, 2, 0)               \
    668   V(NumberBitwiseXor, Operator::kCommutative, 2, 0)              \
    669   V(NumberBitwiseAnd, Operator::kCommutative, 2, 0)              \
    670   V(NumberShiftLeft, Operator::kNoProperties, 2, 0)              \
    671   V(NumberShiftRight, Operator::kNoProperties, 2, 0)             \
    672   V(NumberShiftRightLogical, Operator::kNoProperties, 2, 0)      \
    673   V(NumberImul, Operator::kCommutative, 2, 0)                    \
    674   V(NumberAbs, Operator::kNoProperties, 1, 0)                    \
    675   V(NumberClz32, Operator::kNoProperties, 1, 0)                  \
    676   V(NumberCeil, Operator::kNoProperties, 1, 0)                   \
    677   V(NumberFloor, Operator::kNoProperties, 1, 0)                  \
    678   V(NumberFround, Operator::kNoProperties, 1, 0)                 \
    679   V(NumberAcos, Operator::kNoProperties, 1, 0)                   \
    680   V(NumberAcosh, Operator::kNoProperties, 1, 0)                  \
    681   V(NumberAsin, Operator::kNoProperties, 1, 0)                   \
    682   V(NumberAsinh, Operator::kNoProperties, 1, 0)                  \
    683   V(NumberAtan, Operator::kNoProperties, 1, 0)                   \
    684   V(NumberAtan2, Operator::kNoProperties, 2, 0)                  \
    685   V(NumberAtanh, Operator::kNoProperties, 1, 0)                  \
    686   V(NumberCbrt, Operator::kNoProperties, 1, 0)                   \
    687   V(NumberCos, Operator::kNoProperties, 1, 0)                    \
    688   V(NumberCosh, Operator::kNoProperties, 1, 0)                   \
    689   V(NumberExp, Operator::kNoProperties, 1, 0)                    \
    690   V(NumberExpm1, Operator::kNoProperties, 1, 0)                  \
    691   V(NumberLog, Operator::kNoProperties, 1, 0)                    \
    692   V(NumberLog1p, Operator::kNoProperties, 1, 0)                  \
    693   V(NumberLog10, Operator::kNoProperties, 1, 0)                  \
    694   V(NumberLog2, Operator::kNoProperties, 1, 0)                   \
    695   V(NumberMax, Operator::kNoProperties, 2, 0)                    \
    696   V(NumberMin, Operator::kNoProperties, 2, 0)                    \
    697   V(NumberPow, Operator::kNoProperties, 2, 0)                    \
    698   V(NumberRound, Operator::kNoProperties, 1, 0)                  \
    699   V(NumberSign, Operator::kNoProperties, 1, 0)                   \
    700   V(NumberSin, Operator::kNoProperties, 1, 0)                    \
    701   V(NumberSinh, Operator::kNoProperties, 1, 0)                   \
    702   V(NumberSqrt, Operator::kNoProperties, 1, 0)                   \
    703   V(NumberTan, Operator::kNoProperties, 1, 0)                    \
    704   V(NumberTanh, Operator::kNoProperties, 1, 0)                   \
    705   V(NumberTrunc, Operator::kNoProperties, 1, 0)                  \
    706   V(NumberToBoolean, Operator::kNoProperties, 1, 0)              \
    707   V(NumberToInt32, Operator::kNoProperties, 1, 0)                \
    708   V(NumberToString, Operator::kNoProperties, 1, 0)               \
    709   V(NumberToUint32, Operator::kNoProperties, 1, 0)               \
    710   V(NumberToUint8Clamped, Operator::kNoProperties, 1, 0)         \
    711   V(NumberSilenceNaN, Operator::kNoProperties, 1, 0)             \
    712   V(StringToNumber, Operator::kNoProperties, 1, 0)               \
    713   V(StringFromSingleCharCode, Operator::kNoProperties, 1, 0)     \
    714   V(StringIndexOf, Operator::kNoProperties, 3, 0)                \
    715   V(StringLength, Operator::kNoProperties, 1, 0)                 \
    716   V(StringToLowerCaseIntl, Operator::kNoProperties, 1, 0)        \
    717   V(StringToUpperCaseIntl, Operator::kNoProperties, 1, 0)        \
    718   V(TypeOf, Operator::kNoProperties, 1, 1)                       \
    719   V(PlainPrimitiveToNumber, Operator::kNoProperties, 1, 0)       \
    720   V(PlainPrimitiveToWord32, Operator::kNoProperties, 1, 0)       \
    721   V(PlainPrimitiveToFloat64, Operator::kNoProperties, 1, 0)      \
    722   V(ChangeTaggedSignedToInt32, Operator::kNoProperties, 1, 0)    \
    723   V(ChangeTaggedToInt32, Operator::kNoProperties, 1, 0)          \
    724   V(ChangeTaggedToUint32, Operator::kNoProperties, 1, 0)         \
    725   V(ChangeTaggedToFloat64, Operator::kNoProperties, 1, 0)        \
    726   V(ChangeTaggedToTaggedSigned, Operator::kNoProperties, 1, 0)   \
    727   V(ChangeFloat64ToTaggedPointer, Operator::kNoProperties, 1, 0) \
    728   V(ChangeInt31ToTaggedSigned, Operator::kNoProperties, 1, 0)    \
    729   V(ChangeInt32ToTagged, Operator::kNoProperties, 1, 0)          \
    730   V(ChangeUint32ToTagged, Operator::kNoProperties, 1, 0)         \
    731   V(ChangeTaggedToBit, Operator::kNoProperties, 1, 0)            \
    732   V(ChangeBitToTagged, Operator::kNoProperties, 1, 0)            \
    733   V(TruncateTaggedToBit, Operator::kNoProperties, 1, 0)          \
    734   V(TruncateTaggedPointerToBit, Operator::kNoProperties, 1, 0)   \
    735   V(TruncateTaggedToWord32, Operator::kNoProperties, 1, 0)       \
    736   V(TruncateTaggedToFloat64, Operator::kNoProperties, 1, 0)      \
    737   V(ObjectIsArrayBufferView, Operator::kNoProperties, 1, 0)      \
    738   V(ObjectIsBigInt, Operator::kNoProperties, 1, 0)               \
    739   V(ObjectIsCallable, Operator::kNoProperties, 1, 0)             \
    740   V(ObjectIsConstructor, Operator::kNoProperties, 1, 0)          \
    741   V(ObjectIsDetectableCallable, Operator::kNoProperties, 1, 0)   \
    742   V(ObjectIsMinusZero, Operator::kNoProperties, 1, 0)            \
    743   V(ObjectIsNaN, Operator::kNoProperties, 1, 0)                  \
    744   V(NumberIsNaN, Operator::kNoProperties, 1, 0)                  \
    745   V(ObjectIsNonCallable, Operator::kNoProperties, 1, 0)          \
    746   V(ObjectIsNumber, Operator::kNoProperties, 1, 0)               \
    747   V(ObjectIsReceiver, Operator::kNoProperties, 1, 0)             \
    748   V(ObjectIsSmi, Operator::kNoProperties, 1, 0)                  \
    749   V(ObjectIsString, Operator::kNoProperties, 1, 0)               \
    750   V(ObjectIsSymbol, Operator::kNoProperties, 1, 0)               \
    751   V(ObjectIsUndetectable, Operator::kNoProperties, 1, 0)         \
    752   V(NumberIsFloat64Hole, Operator::kNoProperties, 1, 0)          \
    753   V(NumberIsFinite, Operator::kNoProperties, 1, 0)               \
    754   V(ObjectIsFiniteNumber, Operator::kNoProperties, 1, 0)         \
    755   V(NumberIsInteger, Operator::kNoProperties, 1, 0)              \
    756   V(ObjectIsSafeInteger, Operator::kNoProperties, 1, 0)          \
    757   V(NumberIsSafeInteger, Operator::kNoProperties, 1, 0)          \
    758   V(ObjectIsInteger, Operator::kNoProperties, 1, 0)              \
    759   V(ConvertTaggedHoleToUndefined, Operator::kNoProperties, 1, 0) \
    760   V(SameValue, Operator::kCommutative, 2, 0)                     \
    761   V(ReferenceEqual, Operator::kCommutative, 2, 0)                \
    762   V(StringEqual, Operator::kCommutative, 2, 0)                   \
    763   V(StringLessThan, Operator::kNoProperties, 2, 0)               \
    764   V(StringLessThanOrEqual, Operator::kNoProperties, 2, 0)        \
    765   V(ToBoolean, Operator::kNoProperties, 1, 0)                    \
    766   V(NewConsString, Operator::kNoProperties, 3, 0)                \
    767   V(PoisonIndex, Operator::kNoProperties, 1, 0)
    768 
    769 #define EFFECT_DEPENDENT_OP_LIST(V)                  \
    770   V(StringCharCodeAt, Operator::kNoProperties, 2, 1) \
    771   V(StringSubstring, Operator::kNoProperties, 3, 1)  \
    772   V(DateNow, Operator::kNoProperties, 0, 1)
    773 
    774 #define SPECULATIVE_NUMBER_BINOP_LIST(V)      \
    775   SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(V) \
    776   V(SpeculativeNumberEqual)                   \
    777   V(SpeculativeNumberLessThan)                \
    778   V(SpeculativeNumberLessThanOrEqual)
    779 
    780 #define CHECKED_OP_LIST(V)               \
    781   V(CheckEqualsInternalizedString, 2, 0) \
    782   V(CheckEqualsSymbol, 2, 0)             \
    783   V(CheckHeapObject, 1, 1)               \
    784   V(CheckInternalizedString, 1, 1)       \
    785   V(CheckNotTaggedHole, 1, 1)            \
    786   V(CheckReceiver, 1, 1)                 \
    787   V(CheckSymbol, 1, 1)                   \
    788   V(CheckedInt32Add, 2, 1)               \
    789   V(CheckedInt32Div, 2, 1)               \
    790   V(CheckedInt32Mod, 2, 1)               \
    791   V(CheckedInt32Sub, 2, 1)               \
    792   V(CheckedUint32Div, 2, 1)              \
    793   V(CheckedUint32Mod, 2, 1)
    794 
    795 #define CHECKED_WITH_FEEDBACK_OP_LIST(V) \
    796   V(CheckBounds, 2, 1)                   \
    797   V(CheckNumber, 1, 1)                   \
    798   V(CheckSmi, 1, 1)                      \
    799   V(CheckString, 1, 1)                   \
    800   V(CheckedInt32ToTaggedSigned, 1, 1)    \
    801   V(CheckedTaggedSignedToInt32, 1, 1)    \
    802   V(CheckedTaggedToTaggedPointer, 1, 1)  \
    803   V(CheckedTaggedToTaggedSigned, 1, 1)   \
    804   V(CheckedUint32ToInt32, 1, 1)          \
    805   V(CheckedUint32ToTaggedSigned, 1, 1)
    806 
    807 struct SimplifiedOperatorGlobalCache final {
    808 #define PURE(Name, properties, value_input_count, control_input_count)     \
    809   struct Name##Operator final : public Operator {                          \
    810     Name##Operator()                                                       \
    811         : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \
    812                    value_input_count, 0, control_input_count, 1, 0, 0) {}  \
    813   };                                                                       \
    814   Name##Operator k##Name;
    815   PURE_OP_LIST(PURE)
    816 #undef PURE
    817 
    818 #define EFFECT_DEPENDENT(Name, properties, value_input_count,              \
    819                          control_input_count)                              \
    820   struct Name##Operator final : public Operator {                          \
    821     Name##Operator()                                                       \
    822         : Operator(IrOpcode::k##Name,                                      \
    823                    Operator::kNoDeopt | Operator::kNoWrite |               \
    824                        Operator::kNoThrow | properties,                    \
    825                    #Name, value_input_count, 1, control_input_count, 1, 1, \
    826                    0) {}                                                   \
    827   };                                                                       \
    828   Name##Operator k##Name;
    829   EFFECT_DEPENDENT_OP_LIST(EFFECT_DEPENDENT)
    830 #undef EFFECT_DEPENDENT
    831 
    832 #define CHECKED(Name, value_input_count, value_output_count)             \
    833   struct Name##Operator final : public Operator {                        \
    834     Name##Operator()                                                     \
    835         : Operator(IrOpcode::k##Name,                                    \
    836                    Operator::kFoldable | Operator::kNoThrow, #Name,      \
    837                    value_input_count, 1, 1, value_output_count, 1, 0) {} \
    838   };                                                                     \
    839   Name##Operator k##Name;
    840   CHECKED_OP_LIST(CHECKED)
    841 #undef CHECKED
    842 
    843 #define CHECKED_WITH_FEEDBACK(Name, value_input_count, value_output_count) \
    844   struct Name##Operator final : public Operator1<CheckParameters> {        \
    845     Name##Operator()                                                       \
    846         : Operator1<CheckParameters>(                                      \
    847               IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, \
    848               #Name, value_input_count, 1, 1, value_output_count, 1, 0,    \
    849               CheckParameters(VectorSlotPair())) {}                        \
    850   };                                                                       \
    851   Name##Operator k##Name;
    852   CHECKED_WITH_FEEDBACK_OP_LIST(CHECKED_WITH_FEEDBACK)
    853 #undef CHECKED_WITH_FEEDBACK
    854 
    855   template <DeoptimizeReason kDeoptimizeReason>
    856   struct CheckIfOperator final : public Operator1<CheckIfParameters> {
    857     CheckIfOperator()
    858         : Operator1<CheckIfParameters>(
    859               IrOpcode::kCheckIf, Operator::kFoldable | Operator::kNoThrow,
    860               "CheckIf", 1, 1, 1, 0, 1, 0,
    861               CheckIfParameters(kDeoptimizeReason, VectorSlotPair())) {}
    862   };
    863 #define CHECK_IF(Name, message) \
    864   CheckIfOperator<DeoptimizeReason::k##Name> kCheckIf##Name;
    865   DEOPTIMIZE_REASON_LIST(CHECK_IF)
    866 #undef CHECK_IF
    867 
    868   template <UnicodeEncoding kEncoding>
    869   struct StringCodePointAtOperator final : public Operator1<UnicodeEncoding> {
    870     StringCodePointAtOperator()
    871         : Operator1<UnicodeEncoding>(IrOpcode::kStringCodePointAt,
    872                                      Operator::kFoldable | Operator::kNoThrow,
    873                                      "StringCodePointAt", 2, 1, 1, 1, 1, 0,
    874                                      kEncoding) {}
    875   };
    876   StringCodePointAtOperator<UnicodeEncoding::UTF16>
    877       kStringCodePointAtOperatorUTF16;
    878   StringCodePointAtOperator<UnicodeEncoding::UTF32>
    879       kStringCodePointAtOperatorUTF32;
    880 
    881   template <UnicodeEncoding kEncoding>
    882   struct StringFromSingleCodePointOperator final
    883       : public Operator1<UnicodeEncoding> {
    884     StringFromSingleCodePointOperator()
    885         : Operator1<UnicodeEncoding>(
    886               IrOpcode::kStringFromSingleCodePoint, Operator::kPure,
    887               "StringFromSingleCodePoint", 1, 0, 0, 1, 0, 0, kEncoding) {}
    888   };
    889   StringFromSingleCodePointOperator<UnicodeEncoding::UTF16>
    890       kStringFromSingleCodePointOperatorUTF16;
    891   StringFromSingleCodePointOperator<UnicodeEncoding::UTF32>
    892       kStringFromSingleCodePointOperatorUTF32;
    893 
    894   struct ArrayBufferWasNeuteredOperator final : public Operator {
    895     ArrayBufferWasNeuteredOperator()
    896         : Operator(IrOpcode::kArrayBufferWasNeutered, Operator::kEliminatable,
    897                    "ArrayBufferWasNeutered", 1, 1, 1, 1, 1, 0) {}
    898   };
    899   ArrayBufferWasNeuteredOperator kArrayBufferWasNeutered;
    900 
    901   struct FindOrderedHashMapEntryOperator final : public Operator {
    902     FindOrderedHashMapEntryOperator()
    903         : Operator(IrOpcode::kFindOrderedHashMapEntry, Operator::kEliminatable,
    904                    "FindOrderedHashMapEntry", 2, 1, 1, 1, 1, 0) {}
    905   };
    906   FindOrderedHashMapEntryOperator kFindOrderedHashMapEntry;
    907 
    908   struct FindOrderedHashMapEntryForInt32KeyOperator final : public Operator {
    909     FindOrderedHashMapEntryForInt32KeyOperator()
    910         : Operator(IrOpcode::kFindOrderedHashMapEntryForInt32Key,
    911                    Operator::kEliminatable,
    912                    "FindOrderedHashMapEntryForInt32Key", 2, 1, 1, 1, 1, 0) {}
    913   };
    914   FindOrderedHashMapEntryForInt32KeyOperator
    915       kFindOrderedHashMapEntryForInt32Key;
    916 
    917   struct ArgumentsFrameOperator final : public Operator {
    918     ArgumentsFrameOperator()
    919         : Operator(IrOpcode::kArgumentsFrame, Operator::kPure, "ArgumentsFrame",
    920                    0, 0, 0, 1, 0, 0) {}
    921   };
    922   ArgumentsFrameOperator kArgumentsFrame;
    923 
    924   template <CheckForMinusZeroMode kMode>
    925   struct ChangeFloat64ToTaggedOperator final
    926       : public Operator1<CheckForMinusZeroMode> {
    927     ChangeFloat64ToTaggedOperator()
    928         : Operator1<CheckForMinusZeroMode>(
    929               IrOpcode::kChangeFloat64ToTagged, Operator::kPure,
    930               "ChangeFloat64ToTagged", 1, 0, 0, 1, 0, 0, kMode) {}
    931   };
    932   ChangeFloat64ToTaggedOperator<CheckForMinusZeroMode::kCheckForMinusZero>
    933       kChangeFloat64ToTaggedCheckForMinusZeroOperator;
    934   ChangeFloat64ToTaggedOperator<CheckForMinusZeroMode::kDontCheckForMinusZero>
    935       kChangeFloat64ToTaggedDontCheckForMinusZeroOperator;
    936 
    937   template <CheckForMinusZeroMode kMode>
    938   struct CheckedInt32MulOperator final
    939       : public Operator1<CheckForMinusZeroMode> {
    940     CheckedInt32MulOperator()
    941         : Operator1<CheckForMinusZeroMode>(
    942               IrOpcode::kCheckedInt32Mul,
    943               Operator::kFoldable | Operator::kNoThrow, "CheckedInt32Mul", 2, 1,
    944               1, 1, 1, 0, kMode) {}
    945   };
    946   CheckedInt32MulOperator<CheckForMinusZeroMode::kCheckForMinusZero>
    947       kCheckedInt32MulCheckForMinusZeroOperator;
    948   CheckedInt32MulOperator<CheckForMinusZeroMode::kDontCheckForMinusZero>
    949       kCheckedInt32MulDontCheckForMinusZeroOperator;
    950 
    951   template <CheckForMinusZeroMode kMode>
    952   struct CheckedFloat64ToInt32Operator final
    953       : public Operator1<CheckMinusZeroParameters> {
    954     CheckedFloat64ToInt32Operator()
    955         : Operator1<CheckMinusZeroParameters>(
    956               IrOpcode::kCheckedFloat64ToInt32,
    957               Operator::kFoldable | Operator::kNoThrow, "CheckedFloat64ToInt32",
    958               1, 1, 1, 1, 1, 0,
    959               CheckMinusZeroParameters(kMode, VectorSlotPair())) {}
    960   };
    961   CheckedFloat64ToInt32Operator<CheckForMinusZeroMode::kCheckForMinusZero>
    962       kCheckedFloat64ToInt32CheckForMinusZeroOperator;
    963   CheckedFloat64ToInt32Operator<CheckForMinusZeroMode::kDontCheckForMinusZero>
    964       kCheckedFloat64ToInt32DontCheckForMinusZeroOperator;
    965 
    966   template <CheckForMinusZeroMode kMode>
    967   struct CheckedTaggedToInt32Operator final
    968       : public Operator1<CheckMinusZeroParameters> {
    969     CheckedTaggedToInt32Operator()
    970         : Operator1<CheckMinusZeroParameters>(
    971               IrOpcode::kCheckedTaggedToInt32,
    972               Operator::kFoldable | Operator::kNoThrow, "CheckedTaggedToInt32",
    973               1, 1, 1, 1, 1, 0,
    974               CheckMinusZeroParameters(kMode, VectorSlotPair())) {}
    975   };
    976   CheckedTaggedToInt32Operator<CheckForMinusZeroMode::kCheckForMinusZero>
    977       kCheckedTaggedToInt32CheckForMinusZeroOperator;
    978   CheckedTaggedToInt32Operator<CheckForMinusZeroMode::kDontCheckForMinusZero>
    979       kCheckedTaggedToInt32DontCheckForMinusZeroOperator;
    980 
    981   template <CheckTaggedInputMode kMode>
    982   struct CheckedTaggedToFloat64Operator final
    983       : public Operator1<CheckTaggedInputParameters> {
    984     CheckedTaggedToFloat64Operator()
    985         : Operator1<CheckTaggedInputParameters>(
    986               IrOpcode::kCheckedTaggedToFloat64,
    987               Operator::kFoldable | Operator::kNoThrow,
    988               "CheckedTaggedToFloat64", 1, 1, 1, 1, 1, 0,
    989               CheckTaggedInputParameters(kMode, VectorSlotPair())) {}
    990   };
    991   CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumber>
    992       kCheckedTaggedToFloat64NumberOperator;
    993   CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumberOrOddball>
    994       kCheckedTaggedToFloat64NumberOrOddballOperator;
    995 
    996   template <CheckTaggedInputMode kMode>
    997   struct CheckedTruncateTaggedToWord32Operator final
    998       : public Operator1<CheckTaggedInputParameters> {
    999     CheckedTruncateTaggedToWord32Operator()
   1000         : Operator1<CheckTaggedInputParameters>(
   1001               IrOpcode::kCheckedTruncateTaggedToWord32,
   1002               Operator::kFoldable | Operator::kNoThrow,
   1003               "CheckedTruncateTaggedToWord32", 1, 1, 1, 1, 1, 0,
   1004               CheckTaggedInputParameters(kMode, VectorSlotPair())) {}
   1005   };
   1006   CheckedTruncateTaggedToWord32Operator<CheckTaggedInputMode::kNumber>
   1007       kCheckedTruncateTaggedToWord32NumberOperator;
   1008   CheckedTruncateTaggedToWord32Operator<CheckTaggedInputMode::kNumberOrOddball>
   1009       kCheckedTruncateTaggedToWord32NumberOrOddballOperator;
   1010 
   1011   template <ConvertReceiverMode kMode>
   1012   struct ConvertReceiverOperator final : public Operator1<ConvertReceiverMode> {
   1013     ConvertReceiverOperator()
   1014         : Operator1<ConvertReceiverMode>(  // --
   1015               IrOpcode::kConvertReceiver,  // opcode
   1016               Operator::kEliminatable,     // flags
   1017               "ConvertReceiver",           // name
   1018               2, 1, 1, 1, 1, 0,            // counts
   1019               kMode) {}                    // param
   1020   };
   1021   ConvertReceiverOperator<ConvertReceiverMode::kAny>
   1022       kConvertReceiverAnyOperator;
   1023   ConvertReceiverOperator<ConvertReceiverMode::kNullOrUndefined>
   1024       kConvertReceiverNullOrUndefinedOperator;
   1025   ConvertReceiverOperator<ConvertReceiverMode::kNotNullOrUndefined>
   1026       kConvertReceiverNotNullOrUndefinedOperator;
   1027 
   1028   template <CheckFloat64HoleMode kMode>
   1029   struct CheckFloat64HoleNaNOperator final
   1030       : public Operator1<CheckFloat64HoleParameters> {
   1031     CheckFloat64HoleNaNOperator()
   1032         : Operator1<CheckFloat64HoleParameters>(
   1033               IrOpcode::kCheckFloat64Hole,
   1034               Operator::kFoldable | Operator::kNoThrow, "CheckFloat64Hole", 1,
   1035               1, 1, 1, 1, 0,
   1036               CheckFloat64HoleParameters(kMode, VectorSlotPair())) {}
   1037   };
   1038   CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kAllowReturnHole>
   1039       kCheckFloat64HoleAllowReturnHoleOperator;
   1040   CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kNeverReturnHole>
   1041       kCheckFloat64HoleNeverReturnHoleOperator;
   1042 
   1043   struct EnsureWritableFastElementsOperator final : public Operator {
   1044     EnsureWritableFastElementsOperator()
   1045         : Operator(                                     // --
   1046               IrOpcode::kEnsureWritableFastElements,    // opcode
   1047               Operator::kNoDeopt | Operator::kNoThrow,  // flags
   1048               "EnsureWritableFastElements",             // name
   1049               2, 1, 1, 1, 1, 0) {}                      // counts
   1050   };
   1051   EnsureWritableFastElementsOperator kEnsureWritableFastElements;
   1052 
   1053   template <GrowFastElementsMode kMode>
   1054   struct GrowFastElementsOperator final
   1055       : public Operator1<GrowFastElementsParameters> {
   1056     GrowFastElementsOperator()
   1057         : Operator1(IrOpcode::kMaybeGrowFastElements, Operator::kNoThrow,
   1058                     "MaybeGrowFastElements", 4, 1, 1, 1, 1, 0,
   1059                     GrowFastElementsParameters(kMode, VectorSlotPair())) {}
   1060   };
   1061 
   1062   GrowFastElementsOperator<GrowFastElementsMode::kDoubleElements>
   1063       kGrowFastElementsOperatorDoubleElements;
   1064   GrowFastElementsOperator<GrowFastElementsMode::kSmiOrObjectElements>
   1065       kGrowFastElementsOperatorSmiOrObjectElements;
   1066 
   1067   struct LoadFieldByIndexOperator final : public Operator {
   1068     LoadFieldByIndexOperator()
   1069         : Operator(                         // --
   1070               IrOpcode::kLoadFieldByIndex,  // opcode
   1071               Operator::kEliminatable,      // flags,
   1072               "LoadFieldByIndex",           // name
   1073               2, 1, 1, 1, 1, 0) {}          // counts;
   1074   };
   1075   LoadFieldByIndexOperator kLoadFieldByIndex;
   1076 
   1077 #define SPECULATIVE_NUMBER_BINOP(Name)                                      \
   1078   template <NumberOperationHint kHint>                                      \
   1079   struct Name##Operator final : public Operator1<NumberOperationHint> {     \
   1080     Name##Operator()                                                        \
   1081         : Operator1<NumberOperationHint>(                                   \
   1082               IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow,  \
   1083               #Name, 2, 1, 1, 1, 1, 0, kHint) {}                            \
   1084   };                                                                        \
   1085   Name##Operator<NumberOperationHint::kSignedSmall>                         \
   1086       k##Name##SignedSmallOperator;                                         \
   1087   Name##Operator<NumberOperationHint::kSignedSmallInputs>                   \
   1088       k##Name##SignedSmallInputsOperator;                                   \
   1089   Name##Operator<NumberOperationHint::kSigned32> k##Name##Signed32Operator; \
   1090   Name##Operator<NumberOperationHint::kNumber> k##Name##NumberOperator;     \
   1091   Name##Operator<NumberOperationHint::kNumberOrOddball>                     \
   1092       k##Name##NumberOrOddballOperator;
   1093   SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP)
   1094 #undef SPECULATIVE_NUMBER_BINOP
   1095 
   1096   template <NumberOperationHint kHint>
   1097   struct SpeculativeToNumberOperator final
   1098       : public Operator1<NumberOperationParameters> {
   1099     SpeculativeToNumberOperator()
   1100         : Operator1<NumberOperationParameters>(
   1101               IrOpcode::kSpeculativeToNumber,
   1102               Operator::kFoldable | Operator::kNoThrow, "SpeculativeToNumber",
   1103               1, 1, 1, 1, 1, 0,
   1104               NumberOperationParameters(kHint, VectorSlotPair())) {}
   1105   };
   1106   SpeculativeToNumberOperator<NumberOperationHint::kSignedSmall>
   1107       kSpeculativeToNumberSignedSmallOperator;
   1108   SpeculativeToNumberOperator<NumberOperationHint::kSigned32>
   1109       kSpeculativeToNumberSigned32Operator;
   1110   SpeculativeToNumberOperator<NumberOperationHint::kNumber>
   1111       kSpeculativeToNumberNumberOperator;
   1112   SpeculativeToNumberOperator<NumberOperationHint::kNumberOrOddball>
   1113       kSpeculativeToNumberNumberOrOddballOperator;
   1114 };
   1115 
   1116 static base::LazyInstance<SimplifiedOperatorGlobalCache>::type
   1117     kSimplifiedOperatorGlobalCache = LAZY_INSTANCE_INITIALIZER;
   1118 
   1119 SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone)
   1120     : cache_(kSimplifiedOperatorGlobalCache.Get()), zone_(zone) {}
   1121 
   1122 #define GET_FROM_CACHE(Name, ...) \
   1123   const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
   1124 PURE_OP_LIST(GET_FROM_CACHE)
   1125 EFFECT_DEPENDENT_OP_LIST(GET_FROM_CACHE)
   1126 CHECKED_OP_LIST(GET_FROM_CACHE)
   1127 GET_FROM_CACHE(ArrayBufferWasNeutered)
   1128 GET_FROM_CACHE(ArgumentsFrame)
   1129 GET_FROM_CACHE(FindOrderedHashMapEntry)
   1130 GET_FROM_CACHE(FindOrderedHashMapEntryForInt32Key)
   1131 GET_FROM_CACHE(LoadFieldByIndex)
   1132 #undef GET_FROM_CACHE
   1133 
   1134 #define GET_FROM_CACHE_WITH_FEEDBACK(Name, value_input_count,               \
   1135                                      value_output_count)                    \
   1136   const Operator* SimplifiedOperatorBuilder::Name(                          \
   1137       const VectorSlotPair& feedback) {                                     \
   1138     if (!feedback.IsValid()) {                                              \
   1139       return &cache_.k##Name;                                               \
   1140     }                                                                       \
   1141     return new (zone()) Operator1<CheckParameters>(                         \
   1142         IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, #Name, \
   1143         value_input_count, 1, 1, value_output_count, 1, 0,                  \
   1144         CheckParameters(feedback));                                         \
   1145   }
   1146 CHECKED_WITH_FEEDBACK_OP_LIST(GET_FROM_CACHE_WITH_FEEDBACK)
   1147 #undef GET_FROM_CACHE_WITH_FEEDBACK
   1148 
   1149 bool IsCheckedWithFeedback(const Operator* op) {
   1150 #define CASE(Name, ...) case IrOpcode::k##Name:
   1151   switch (op->opcode()) {
   1152     CHECKED_WITH_FEEDBACK_OP_LIST(CASE) return true;
   1153     default:
   1154       return false;
   1155   }
   1156 #undef CASE
   1157 }
   1158 
   1159 const Operator* SimplifiedOperatorBuilder::RuntimeAbort(AbortReason reason) {
   1160   return new (zone()) Operator1<int>(           // --
   1161       IrOpcode::kRuntimeAbort,                  // opcode
   1162       Operator::kNoThrow | Operator::kNoDeopt,  // flags
   1163       "RuntimeAbort",                           // name
   1164       0, 1, 1, 0, 1, 0,                         // counts
   1165       static_cast<int>(reason));                // parameter
   1166 }
   1167 
   1168 const Operator* SimplifiedOperatorBuilder::CheckIf(
   1169     DeoptimizeReason reason, const VectorSlotPair& feedback) {
   1170   if (!feedback.IsValid()) {
   1171     switch (reason) {
   1172 #define CHECK_IF(Name, message)   \
   1173   case DeoptimizeReason::k##Name: \
   1174     return &cache_.kCheckIf##Name;
   1175     DEOPTIMIZE_REASON_LIST(CHECK_IF)
   1176 #undef CHECK_IF
   1177     }
   1178   }
   1179   return new (zone()) Operator1<CheckIfParameters>(
   1180       IrOpcode::kCheckIf, Operator::kFoldable | Operator::kNoThrow, "CheckIf",
   1181       1, 1, 1, 0, 1, 0, CheckIfParameters(reason, feedback));
   1182 }
   1183 
   1184 const Operator* SimplifiedOperatorBuilder::ChangeFloat64ToTagged(
   1185     CheckForMinusZeroMode mode) {
   1186   switch (mode) {
   1187     case CheckForMinusZeroMode::kCheckForMinusZero:
   1188       return &cache_.kChangeFloat64ToTaggedCheckForMinusZeroOperator;
   1189     case CheckForMinusZeroMode::kDontCheckForMinusZero:
   1190       return &cache_.kChangeFloat64ToTaggedDontCheckForMinusZeroOperator;
   1191   }
   1192   UNREACHABLE();
   1193 }
   1194 
   1195 const Operator* SimplifiedOperatorBuilder::CheckedInt32Mul(
   1196     CheckForMinusZeroMode mode) {
   1197   switch (mode) {
   1198     case CheckForMinusZeroMode::kCheckForMinusZero:
   1199       return &cache_.kCheckedInt32MulCheckForMinusZeroOperator;
   1200     case CheckForMinusZeroMode::kDontCheckForMinusZero:
   1201       return &cache_.kCheckedInt32MulDontCheckForMinusZeroOperator;
   1202   }
   1203   UNREACHABLE();
   1204 }
   1205 
   1206 const Operator* SimplifiedOperatorBuilder::CheckedFloat64ToInt32(
   1207     CheckForMinusZeroMode mode, const VectorSlotPair& feedback) {
   1208   if (!feedback.IsValid()) {
   1209     switch (mode) {
   1210       case CheckForMinusZeroMode::kCheckForMinusZero:
   1211         return &cache_.kCheckedFloat64ToInt32CheckForMinusZeroOperator;
   1212       case CheckForMinusZeroMode::kDontCheckForMinusZero:
   1213         return &cache_.kCheckedFloat64ToInt32DontCheckForMinusZeroOperator;
   1214     }
   1215   }
   1216   return new (zone()) Operator1<CheckMinusZeroParameters>(
   1217       IrOpcode::kCheckedFloat64ToInt32,
   1218       Operator::kFoldable | Operator::kNoThrow, "CheckedFloat64ToInt32", 1, 1,
   1219       1, 1, 1, 0, CheckMinusZeroParameters(mode, feedback));
   1220 }
   1221 
   1222 const Operator* SimplifiedOperatorBuilder::CheckedTaggedToInt32(
   1223     CheckForMinusZeroMode mode, const VectorSlotPair& feedback) {
   1224   if (!feedback.IsValid()) {
   1225     switch (mode) {
   1226       case CheckForMinusZeroMode::kCheckForMinusZero:
   1227         return &cache_.kCheckedTaggedToInt32CheckForMinusZeroOperator;
   1228       case CheckForMinusZeroMode::kDontCheckForMinusZero:
   1229         return &cache_.kCheckedTaggedToInt32DontCheckForMinusZeroOperator;
   1230     }
   1231   }
   1232   return new (zone()) Operator1<CheckMinusZeroParameters>(
   1233       IrOpcode::kCheckedTaggedToInt32, Operator::kFoldable | Operator::kNoThrow,
   1234       "CheckedTaggedToInt32", 1, 1, 1, 1, 1, 0,
   1235       CheckMinusZeroParameters(mode, feedback));
   1236 }
   1237 
   1238 const Operator* SimplifiedOperatorBuilder::CheckedTaggedToFloat64(
   1239     CheckTaggedInputMode mode, const VectorSlotPair& feedback) {
   1240   if (!feedback.IsValid()) {
   1241     switch (mode) {
   1242       case CheckTaggedInputMode::kNumber:
   1243         return &cache_.kCheckedTaggedToFloat64NumberOperator;
   1244       case CheckTaggedInputMode::kNumberOrOddball:
   1245         return &cache_.kCheckedTaggedToFloat64NumberOrOddballOperator;
   1246     }
   1247   }
   1248   return new (zone()) Operator1<CheckTaggedInputParameters>(
   1249       IrOpcode::kCheckedTaggedToFloat64,
   1250       Operator::kFoldable | Operator::kNoThrow, "CheckedTaggedToFloat64", 1, 1,
   1251       1, 1, 1, 0, CheckTaggedInputParameters(mode, feedback));
   1252 }
   1253 
   1254 const Operator* SimplifiedOperatorBuilder::CheckedTruncateTaggedToWord32(
   1255     CheckTaggedInputMode mode, const VectorSlotPair& feedback) {
   1256   if (!feedback.IsValid()) {
   1257     switch (mode) {
   1258       case CheckTaggedInputMode::kNumber:
   1259         return &cache_.kCheckedTruncateTaggedToWord32NumberOperator;
   1260       case CheckTaggedInputMode::kNumberOrOddball:
   1261         return &cache_.kCheckedTruncateTaggedToWord32NumberOrOddballOperator;
   1262     }
   1263   }
   1264   return new (zone()) Operator1<CheckTaggedInputParameters>(
   1265       IrOpcode::kCheckedTruncateTaggedToWord32,
   1266       Operator::kFoldable | Operator::kNoThrow, "CheckedTruncateTaggedToWord32",
   1267       1, 1, 1, 1, 1, 0, CheckTaggedInputParameters(mode, feedback));
   1268 }
   1269 
   1270 const Operator* SimplifiedOperatorBuilder::CheckMaps(
   1271     CheckMapsFlags flags, ZoneHandleSet<Map> maps,
   1272     const VectorSlotPair& feedback) {
   1273   CheckMapsParameters const parameters(flags, maps, feedback);
   1274   return new (zone()) Operator1<CheckMapsParameters>(  // --
   1275       IrOpcode::kCheckMaps,                            // opcode
   1276       Operator::kNoThrow | Operator::kNoWrite,         // flags
   1277       "CheckMaps",                                     // name
   1278       1, 1, 1, 0, 1, 0,                                // counts
   1279       parameters);                                     // parameter
   1280 }
   1281 
   1282 const Operator* SimplifiedOperatorBuilder::MapGuard(ZoneHandleSet<Map> maps) {
   1283   return new (zone()) Operator1<MapsParameterInfo>(  // --
   1284       IrOpcode::kMapGuard, Operator::kEliminatable,  // opcode
   1285       "MapGuard",                                    // name
   1286       1, 1, 1, 0, 1, 0,                              // counts
   1287       MapsParameterInfo(maps));                      // parameter
   1288 }
   1289 
   1290 const Operator* SimplifiedOperatorBuilder::CompareMaps(
   1291     ZoneHandleSet<Map> maps) {
   1292   return new (zone()) Operator1<MapsParameterInfo>(  // --
   1293       IrOpcode::kCompareMaps,                        // opcode
   1294       Operator::kEliminatable,                       // flags
   1295       "CompareMaps",                                 // name
   1296       1, 1, 1, 1, 1, 0,                              // counts
   1297       MapsParameterInfo(maps));                      // parameter
   1298 }
   1299 
   1300 const Operator* SimplifiedOperatorBuilder::ConvertReceiver(
   1301     ConvertReceiverMode mode) {
   1302   switch (mode) {
   1303     case ConvertReceiverMode::kAny:
   1304       return &cache_.kConvertReceiverAnyOperator;
   1305     case ConvertReceiverMode::kNullOrUndefined:
   1306       return &cache_.kConvertReceiverNullOrUndefinedOperator;
   1307     case ConvertReceiverMode::kNotNullOrUndefined:
   1308       return &cache_.kConvertReceiverNotNullOrUndefinedOperator;
   1309   }
   1310   UNREACHABLE();
   1311   return nullptr;
   1312 }
   1313 
   1314 const Operator* SimplifiedOperatorBuilder::CheckFloat64Hole(
   1315     CheckFloat64HoleMode mode, VectorSlotPair const& feedback) {
   1316   if (!feedback.IsValid()) {
   1317     switch (mode) {
   1318       case CheckFloat64HoleMode::kAllowReturnHole:
   1319         return &cache_.kCheckFloat64HoleAllowReturnHoleOperator;
   1320       case CheckFloat64HoleMode::kNeverReturnHole:
   1321         return &cache_.kCheckFloat64HoleNeverReturnHoleOperator;
   1322     }
   1323     UNREACHABLE();
   1324   }
   1325   return new (zone()) Operator1<CheckFloat64HoleParameters>(
   1326       IrOpcode::kCheckFloat64Hole, Operator::kFoldable | Operator::kNoThrow,
   1327       "CheckFloat64Hole", 1, 1, 1, 1, 1, 0,
   1328       CheckFloat64HoleParameters(mode, feedback));
   1329 }
   1330 
   1331 const Operator* SimplifiedOperatorBuilder::SpeculativeToNumber(
   1332     NumberOperationHint hint, const VectorSlotPair& feedback) {
   1333   if (!feedback.IsValid()) {
   1334     switch (hint) {
   1335       case NumberOperationHint::kSignedSmall:
   1336         return &cache_.kSpeculativeToNumberSignedSmallOperator;
   1337       case NumberOperationHint::kSignedSmallInputs:
   1338         break;
   1339       case NumberOperationHint::kSigned32:
   1340         return &cache_.kSpeculativeToNumberSigned32Operator;
   1341       case NumberOperationHint::kNumber:
   1342         return &cache_.kSpeculativeToNumberNumberOperator;
   1343       case NumberOperationHint::kNumberOrOddball:
   1344         return &cache_.kSpeculativeToNumberNumberOrOddballOperator;
   1345     }
   1346   }
   1347   return new (zone()) Operator1<NumberOperationParameters>(
   1348       IrOpcode::kSpeculativeToNumber, Operator::kFoldable | Operator::kNoThrow,
   1349       "SpeculativeToNumber", 1, 1, 1, 1, 1, 0,
   1350       NumberOperationParameters(hint, feedback));
   1351 }
   1352 
   1353 const Operator* SimplifiedOperatorBuilder::EnsureWritableFastElements() {
   1354   return &cache_.kEnsureWritableFastElements;
   1355 }
   1356 
   1357 const Operator* SimplifiedOperatorBuilder::MaybeGrowFastElements(
   1358     GrowFastElementsMode mode, const VectorSlotPair& feedback) {
   1359   if (!feedback.IsValid()) {
   1360     switch (mode) {
   1361       case GrowFastElementsMode::kDoubleElements:
   1362         return &cache_.kGrowFastElementsOperatorDoubleElements;
   1363       case GrowFastElementsMode::kSmiOrObjectElements:
   1364         return &cache_.kGrowFastElementsOperatorSmiOrObjectElements;
   1365     }
   1366   }
   1367   return new (zone()) Operator1<GrowFastElementsParameters>(  // --
   1368       IrOpcode::kMaybeGrowFastElements,                       // opcode
   1369       Operator::kNoThrow,                                     // flags
   1370       "MaybeGrowFastElements",                                // name
   1371       4, 1, 1, 1, 1, 0,                                       // counts
   1372       GrowFastElementsParameters(mode, feedback));            // parameter
   1373 }
   1374 
   1375 const Operator* SimplifiedOperatorBuilder::TransitionElementsKind(
   1376     ElementsTransition transition) {
   1377   return new (zone()) Operator1<ElementsTransition>(  // --
   1378       IrOpcode::kTransitionElementsKind,              // opcode
   1379       Operator::kNoDeopt | Operator::kNoThrow,        // flags
   1380       "TransitionElementsKind",                       // name
   1381       1, 1, 1, 0, 1, 0,                               // counts
   1382       transition);                                    // parameter
   1383 }
   1384 
   1385 namespace {
   1386 
   1387 struct ArgumentsLengthParameters {
   1388   int formal_parameter_count;
   1389   bool is_rest_length;
   1390 };
   1391 
   1392 bool operator==(ArgumentsLengthParameters first,
   1393                 ArgumentsLengthParameters second) {
   1394   return first.formal_parameter_count == second.formal_parameter_count &&
   1395          first.is_rest_length == second.is_rest_length;
   1396 }
   1397 
   1398 size_t hash_value(ArgumentsLengthParameters param) {
   1399   return base::hash_combine(param.formal_parameter_count, param.is_rest_length);
   1400 }
   1401 
   1402 std::ostream& operator<<(std::ostream& os, ArgumentsLengthParameters param) {
   1403   return os << param.formal_parameter_count << ", "
   1404             << (param.is_rest_length ? "rest length" : "not rest length");
   1405 }
   1406 
   1407 }  // namespace
   1408 
   1409 const Operator* SimplifiedOperatorBuilder::ArgumentsLength(
   1410     int formal_parameter_count, bool is_rest_length) {
   1411   return new (zone()) Operator1<ArgumentsLengthParameters>(  // --
   1412       IrOpcode::kArgumentsLength,                            // opcode
   1413       Operator::kPure,                                       // flags
   1414       "ArgumentsLength",                                     // name
   1415       1, 0, 0, 1, 0, 0,                                      // counts
   1416       ArgumentsLengthParameters{formal_parameter_count,
   1417                                 is_rest_length});  // parameter
   1418 }
   1419 
   1420 int FormalParameterCountOf(const Operator* op) {
   1421   DCHECK_EQ(IrOpcode::kArgumentsLength, op->opcode());
   1422   return OpParameter<ArgumentsLengthParameters>(op).formal_parameter_count;
   1423 }
   1424 
   1425 bool IsRestLengthOf(const Operator* op) {
   1426   DCHECK_EQ(IrOpcode::kArgumentsLength, op->opcode());
   1427   return OpParameter<ArgumentsLengthParameters>(op).is_rest_length;
   1428 }
   1429 
   1430 bool operator==(CheckParameters const& lhs, CheckParameters const& rhs) {
   1431   return lhs.feedback() == rhs.feedback();
   1432 }
   1433 
   1434 size_t hash_value(CheckParameters const& p) { return hash_value(p.feedback()); }
   1435 
   1436 std::ostream& operator<<(std::ostream& os, CheckParameters const& p) {
   1437   return os << p.feedback();
   1438 }
   1439 
   1440 CheckParameters const& CheckParametersOf(Operator const* op) {
   1441 #define MAKE_OR(name, arg2, arg3) op->opcode() == IrOpcode::k##name ||
   1442   CHECK((CHECKED_WITH_FEEDBACK_OP_LIST(MAKE_OR) false));
   1443 #undef MAKE_OR
   1444   return OpParameter<CheckParameters>(op);
   1445 }
   1446 
   1447 bool operator==(CheckIfParameters const& lhs, CheckIfParameters const& rhs) {
   1448   return lhs.reason() == rhs.reason() && lhs.feedback() == rhs.feedback();
   1449 }
   1450 
   1451 size_t hash_value(CheckIfParameters const& p) {
   1452   return base::hash_combine(p.reason(), p.feedback());
   1453 }
   1454 
   1455 std::ostream& operator<<(std::ostream& os, CheckIfParameters const& p) {
   1456   return os << p.reason() << p.feedback();
   1457 }
   1458 
   1459 CheckIfParameters const& CheckIfParametersOf(Operator const* op) {
   1460   CHECK(op->opcode() == IrOpcode::kCheckIf);
   1461   return OpParameter<CheckIfParameters>(op);
   1462 }
   1463 
   1464 const Operator* SimplifiedOperatorBuilder::NewDoubleElements(
   1465     PretenureFlag pretenure) {
   1466   return new (zone()) Operator1<PretenureFlag>(  // --
   1467       IrOpcode::kNewDoubleElements,              // opcode
   1468       Operator::kEliminatable,                   // flags
   1469       "NewDoubleElements",                       // name
   1470       1, 1, 1, 1, 1, 0,                          // counts
   1471       pretenure);                                // parameter
   1472 }
   1473 
   1474 const Operator* SimplifiedOperatorBuilder::NewSmiOrObjectElements(
   1475     PretenureFlag pretenure) {
   1476   return new (zone()) Operator1<PretenureFlag>(  // --
   1477       IrOpcode::kNewSmiOrObjectElements,         // opcode
   1478       Operator::kEliminatable,                   // flags
   1479       "NewSmiOrObjectElements",                  // name
   1480       1, 1, 1, 1, 1, 0,                          // counts
   1481       pretenure);                                // parameter
   1482 }
   1483 
   1484 const Operator* SimplifiedOperatorBuilder::NewArgumentsElements(
   1485     int mapped_count) {
   1486   return new (zone()) Operator1<int>(   // --
   1487       IrOpcode::kNewArgumentsElements,  // opcode
   1488       Operator::kEliminatable,          // flags
   1489       "NewArgumentsElements",           // name
   1490       2, 1, 0, 1, 1, 0,                 // counts
   1491       mapped_count);                    // parameter
   1492 }
   1493 
   1494 int NewArgumentsElementsMappedCountOf(const Operator* op) {
   1495   DCHECK_EQ(IrOpcode::kNewArgumentsElements, op->opcode());
   1496   return OpParameter<int>(op);
   1497 }
   1498 
   1499 const Operator* SimplifiedOperatorBuilder::Allocate(Type type,
   1500                                                     PretenureFlag pretenure) {
   1501   return new (zone()) Operator1<AllocateParameters>(
   1502       IrOpcode::kAllocate,
   1503       Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite, "Allocate",
   1504       1, 1, 1, 1, 1, 0, AllocateParameters(type, pretenure));
   1505 }
   1506 
   1507 const Operator* SimplifiedOperatorBuilder::AllocateRaw(
   1508     Type type, PretenureFlag pretenure) {
   1509   return new (zone()) Operator1<AllocateParameters>(
   1510       IrOpcode::kAllocateRaw,
   1511       Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite,
   1512       "AllocateRaw", 1, 1, 1, 1, 1, 1, AllocateParameters(type, pretenure));
   1513 }
   1514 
   1515 const Operator* SimplifiedOperatorBuilder::StringCodePointAt(
   1516     UnicodeEncoding encoding) {
   1517   switch (encoding) {
   1518     case UnicodeEncoding::UTF16:
   1519       return &cache_.kStringCodePointAtOperatorUTF16;
   1520     case UnicodeEncoding::UTF32:
   1521       return &cache_.kStringCodePointAtOperatorUTF32;
   1522   }
   1523   UNREACHABLE();
   1524 }
   1525 
   1526 const Operator* SimplifiedOperatorBuilder::StringFromSingleCodePoint(
   1527     UnicodeEncoding encoding) {
   1528   switch (encoding) {
   1529     case UnicodeEncoding::UTF16:
   1530       return &cache_.kStringFromSingleCodePointOperatorUTF16;
   1531     case UnicodeEncoding::UTF32:
   1532       return &cache_.kStringFromSingleCodePointOperatorUTF32;
   1533   }
   1534   UNREACHABLE();
   1535 }
   1536 
   1537 #define SPECULATIVE_NUMBER_BINOP(Name)                                        \
   1538   const Operator* SimplifiedOperatorBuilder::Name(NumberOperationHint hint) { \
   1539     switch (hint) {                                                           \
   1540       case NumberOperationHint::kSignedSmall:                                 \
   1541         return &cache_.k##Name##SignedSmallOperator;                          \
   1542       case NumberOperationHint::kSignedSmallInputs:                           \
   1543         return &cache_.k##Name##SignedSmallInputsOperator;                    \
   1544       case NumberOperationHint::kSigned32:                                    \
   1545         return &cache_.k##Name##Signed32Operator;                             \
   1546       case NumberOperationHint::kNumber:                                      \
   1547         return &cache_.k##Name##NumberOperator;                               \
   1548       case NumberOperationHint::kNumberOrOddball:                             \
   1549         return &cache_.k##Name##NumberOrOddballOperator;                      \
   1550     }                                                                         \
   1551     UNREACHABLE();                                                            \
   1552     return nullptr;                                                           \
   1553   }
   1554 SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP)
   1555 #undef SPECULATIVE_NUMBER_BINOP
   1556 
   1557 #define ACCESS_OP_LIST(V)                                                \
   1558   V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1)                 \
   1559   V(StoreField, FieldAccess, Operator::kNoRead, 2, 1, 0)                 \
   1560   V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1)             \
   1561   V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0)             \
   1562   V(LoadTypedElement, ExternalArrayType, Operator::kNoWrite, 4, 1, 1)    \
   1563   V(StoreTypedElement, ExternalArrayType, Operator::kNoRead, 5, 1, 0)    \
   1564   V(LoadDataViewElement, ExternalArrayType, Operator::kNoWrite, 4, 1, 1) \
   1565   V(StoreDataViewElement, ExternalArrayType, Operator::kNoRead, 5, 1, 0)
   1566 
   1567 #define ACCESS(Name, Type, properties, value_input_count, control_input_count, \
   1568                output_count)                                                   \
   1569   const Operator* SimplifiedOperatorBuilder::Name(const Type& access) {        \
   1570     return new (zone())                                                        \
   1571         Operator1<Type>(IrOpcode::k##Name,                                     \
   1572                         Operator::kNoDeopt | Operator::kNoThrow | properties,  \
   1573                         #Name, value_input_count, 1, control_input_count,      \
   1574                         output_count, 1, 0, access);                           \
   1575   }
   1576 ACCESS_OP_LIST(ACCESS)
   1577 #undef ACCESS
   1578 
   1579 const Operator* SimplifiedOperatorBuilder::TransitionAndStoreElement(
   1580     Handle<Map> double_map, Handle<Map> fast_map) {
   1581   TransitionAndStoreElementParameters parameters(double_map, fast_map);
   1582   return new (zone()) Operator1<TransitionAndStoreElementParameters>(
   1583       IrOpcode::kTransitionAndStoreElement,
   1584       Operator::kNoDeopt | Operator::kNoThrow, "TransitionAndStoreElement", 3,
   1585       1, 1, 0, 1, 0, parameters);
   1586 }
   1587 
   1588 const Operator* SimplifiedOperatorBuilder::StoreSignedSmallElement() {
   1589   return new (zone()) Operator(IrOpcode::kStoreSignedSmallElement,
   1590                                Operator::kNoDeopt | Operator::kNoThrow,
   1591                                "StoreSignedSmallElement", 3, 1, 1, 0, 1, 0);
   1592 }
   1593 
   1594 const Operator* SimplifiedOperatorBuilder::TransitionAndStoreNumberElement(
   1595     Handle<Map> double_map) {
   1596   TransitionAndStoreNumberElementParameters parameters(double_map);
   1597   return new (zone()) Operator1<TransitionAndStoreNumberElementParameters>(
   1598       IrOpcode::kTransitionAndStoreNumberElement,
   1599       Operator::kNoDeopt | Operator::kNoThrow,
   1600       "TransitionAndStoreNumberElement", 3, 1, 1, 0, 1, 0, parameters);
   1601 }
   1602 
   1603 const Operator* SimplifiedOperatorBuilder::TransitionAndStoreNonNumberElement(
   1604     Handle<Map> fast_map, Type value_type) {
   1605   TransitionAndStoreNonNumberElementParameters parameters(fast_map, value_type);
   1606   return new (zone()) Operator1<TransitionAndStoreNonNumberElementParameters>(
   1607       IrOpcode::kTransitionAndStoreNonNumberElement,
   1608       Operator::kNoDeopt | Operator::kNoThrow,
   1609       "TransitionAndStoreNonNumberElement", 3, 1, 1, 0, 1, 0, parameters);
   1610 }
   1611 
   1612 #undef PURE_OP_LIST
   1613 #undef EFFECT_DEPENDENT_OP_LIST
   1614 #undef SPECULATIVE_NUMBER_BINOP_LIST
   1615 #undef CHECKED_WITH_FEEDBACK_OP_LIST
   1616 #undef CHECKED_OP_LIST
   1617 #undef ACCESS_OP_LIST
   1618 
   1619 }  // namespace compiler
   1620 }  // namespace internal
   1621 }  // namespace v8
   1622