LCOV - code coverage report
Current view: top level - src/compiler - simplified-operator.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 212 360 58.9 %
Date: 2017-10-20 Functions: 487 1107 44.0 %

          Line data    Source code
       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           0 : size_t hash_value(BaseTaggedness base_taggedness) {
      21           0 :   return static_cast<uint8_t>(base_taggedness);
      22             : }
      23             : 
      24      121026 : std::ostream& operator<<(std::ostream& os, BaseTaggedness base_taggedness) {
      25      121026 :   switch (base_taggedness) {
      26             :     case kUntaggedBase:
      27       73668 :       return os << "untagged base";
      28             :     case kTaggedBase:
      29       47358 :       return os << "tagged base";
      30             :   }
      31           0 :   UNREACHABLE();
      32             : }
      33             : 
      34         127 : 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         254 :   return lhs.base_is_tagged == rhs.base_is_tagged && lhs.offset == rhs.offset &&
      39         254 :          lhs.map.address() == rhs.map.address() &&
      40         127 :          lhs.machine_type == rhs.machine_type;
      41             : }
      42             : 
      43           0 : 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           0 :                             access.machine_type);
      49             : }
      50             : 
      51             : 
      52           0 : std::ostream& operator<<(std::ostream& os, FieldAccess const& access) {
      53           0 :   os << "[" << access.base_is_tagged << ", " << access.offset << ", ";
      54             : #ifdef OBJECT_PRINT
      55             :   Handle<Name> name;
      56             :   if (access.name.ToHandle(&name)) {
      57             :     name->Print(os);
      58             :     os << ", ";
      59             :   }
      60             :   Handle<Map> map;
      61             :   if (access.map.ToHandle(&map)) {
      62             :     os << Brief(*map) << ", ";
      63             :   }
      64             : #endif
      65           0 :   access.type->PrintTo(os);
      66           0 :   os << ", " << access.machine_type << ", " << access.write_barrier_kind << "]";
      67           0 :   return os;
      68             : }
      69             : 
      70             : template <>
      71           0 : void Operator1<FieldAccess>::PrintParameter(std::ostream& os,
      72             :                                             PrintVerbosity verbose) const {
      73           0 :   if (verbose == PrintVerbosity::kVerbose) {
      74           0 :     os << parameter();
      75             :   } else {
      76           0 :     os << "[+" << parameter().offset << "]";
      77             :   }
      78           0 : }
      79             : 
      80          46 : bool operator==(ElementAccess const& lhs, ElementAccess const& rhs) {
      81             :   // On purpose we don't include the write barrier kind here, as this method is
      82             :   // really only relevant for eliminating loads and they don't care about the
      83             :   // write barrier mode.
      84          46 :   return lhs.base_is_tagged == rhs.base_is_tagged &&
      85          92 :          lhs.header_size == rhs.header_size &&
      86          46 :          lhs.machine_type == rhs.machine_type;
      87             : }
      88             : 
      89           0 : size_t hash_value(ElementAccess const& access) {
      90             :   // On purpose we don't include the write barrier kind here, as this method is
      91             :   // really only relevant for eliminating loads and they don't care about the
      92             :   // write barrier mode.
      93             :   return base::hash_combine(access.base_is_tagged, access.header_size,
      94           0 :                             access.machine_type);
      95             : }
      96             : 
      97             : 
      98      121026 : std::ostream& operator<<(std::ostream& os, ElementAccess const& access) {
      99      121026 :   os << access.base_is_tagged << ", " << access.header_size << ", ";
     100      121026 :   access.type->PrintTo(os);
     101      121026 :   os << ", " << access.machine_type << ", " << access.write_barrier_kind;
     102      121026 :   return os;
     103             : }
     104             : 
     105           0 : ToBooleanHints ToBooleanHintsOf(Operator const* op) {
     106             :   DCHECK_EQ(IrOpcode::kToBoolean, op->opcode());
     107           0 :   return OpParameter<ToBooleanHints>(op);
     108             : }
     109             : 
     110    15070227 : const FieldAccess& FieldAccessOf(const Operator* op) {
     111             :   DCHECK_NOT_NULL(op);
     112             :   DCHECK(op->opcode() == IrOpcode::kLoadField ||
     113             :          op->opcode() == IrOpcode::kStoreField);
     114    15070227 :   return OpParameter<FieldAccess>(op);
     115             : }
     116             : 
     117             : 
     118      409374 : const ElementAccess& ElementAccessOf(const Operator* op) {
     119             :   DCHECK_NOT_NULL(op);
     120             :   DCHECK(op->opcode() == IrOpcode::kLoadElement ||
     121             :          op->opcode() == IrOpcode::kStoreElement);
     122      409374 :   return OpParameter<ElementAccess>(op);
     123             : }
     124             : 
     125       62923 : ExternalArrayType ExternalArrayTypeOf(const Operator* op) {
     126             :   DCHECK(op->opcode() == IrOpcode::kLoadTypedElement ||
     127             :          op->opcode() == IrOpcode::kStoreTypedElement);
     128       62923 :   return OpParameter<ExternalArrayType>(op);
     129             : }
     130             : 
     131           0 : size_t hash_value(CheckFloat64HoleMode mode) {
     132           0 :   return static_cast<size_t>(mode);
     133             : }
     134             : 
     135           0 : std::ostream& operator<<(std::ostream& os, CheckFloat64HoleMode mode) {
     136           0 :   switch (mode) {
     137             :     case CheckFloat64HoleMode::kAllowReturnHole:
     138           0 :       return os << "allow-return-hole";
     139             :     case CheckFloat64HoleMode::kNeverReturnHole:
     140           0 :       return os << "never-return-hole";
     141             :   }
     142           0 :   UNREACHABLE();
     143             : }
     144             : 
     145        2232 : CheckFloat64HoleMode CheckFloat64HoleModeOf(const Operator* op) {
     146             :   DCHECK_EQ(IrOpcode::kCheckFloat64Hole, op->opcode());
     147        2232 :   return OpParameter<CheckFloat64HoleMode>(op);
     148             : }
     149             : 
     150       53412 : CheckForMinusZeroMode CheckMinusZeroModeOf(const Operator* op) {
     151             :   DCHECK(op->opcode() == IrOpcode::kChangeFloat64ToTagged ||
     152             :          op->opcode() == IrOpcode::kCheckedInt32Mul ||
     153             :          op->opcode() == IrOpcode::kCheckedFloat64ToInt32 ||
     154             :          op->opcode() == IrOpcode::kCheckedTaggedToInt32);
     155       53412 :   return OpParameter<CheckForMinusZeroMode>(op);
     156             : }
     157             : 
     158       63315 : size_t hash_value(CheckForMinusZeroMode mode) {
     159       63315 :   return static_cast<size_t>(mode);
     160             : }
     161             : 
     162          10 : std::ostream& operator<<(std::ostream& os, CheckForMinusZeroMode mode) {
     163          10 :   switch (mode) {
     164             :     case CheckForMinusZeroMode::kCheckForMinusZero:
     165           5 :       return os << "check-for-minus-zero";
     166             :     case CheckForMinusZeroMode::kDontCheckForMinusZero:
     167           5 :       return os << "dont-check-for-minus-zero";
     168             :   }
     169           0 :   UNREACHABLE();
     170             : }
     171             : 
     172           0 : std::ostream& operator<<(std::ostream& os, CheckMapsFlags flags) {
     173             :   bool empty = true;
     174           0 :   if (flags & CheckMapsFlag::kTryMigrateInstance) {
     175           0 :     os << "TryMigrateInstance";
     176             :     empty = false;
     177             :   }
     178           0 :   if (empty) os << "None";
     179           0 :   return os;
     180             : }
     181             : 
     182      101928 : MapsParameterInfo::MapsParameterInfo(ZoneHandleSet<Map> const& maps)
     183      101928 :     : maps_(maps), instance_type_(Nothing<InstanceType>()) {
     184             :   DCHECK_LT(0, maps.size());
     185      101928 :   instance_type_ = Just(maps.at(0)->instance_type());
     186      215762 :   for (size_t i = 1; i < maps.size(); ++i) {
     187        6131 :     if (instance_type_.FromJust() != maps.at(i)->instance_type()) {
     188         178 :       instance_type_ = Nothing<InstanceType>();
     189         178 :       break;
     190             :     }
     191             :   }
     192      101928 : }
     193             : 
     194           0 : std::ostream& operator<<(std::ostream& os, MapsParameterInfo const& p) {
     195             :   ZoneHandleSet<Map> const& maps = p.maps();
     196             :   InstanceType instance_type;
     197           0 :   if (p.instance_type().To(&instance_type)) {
     198           0 :     os << ", " << instance_type;
     199             :   }
     200           0 :   for (size_t i = 0; i < maps.size(); ++i) {
     201           0 :     os << ", " << Brief(*maps[i]);
     202             :   }
     203           0 :   return os;
     204             : }
     205             : 
     206           0 : bool operator==(MapsParameterInfo const& lhs, MapsParameterInfo const& rhs) {
     207           0 :   return lhs.maps() == rhs.maps();
     208             : }
     209             : 
     210           0 : bool operator!=(MapsParameterInfo const& lhs, MapsParameterInfo const& rhs) {
     211           0 :   return !(lhs == rhs);
     212             : }
     213             : 
     214           0 : size_t hash_value(MapsParameterInfo const& p) { return hash_value(p.maps()); }
     215             : 
     216           0 : bool operator==(CheckMapsParameters const& lhs,
     217             :                 CheckMapsParameters const& rhs) {
     218           0 :   return lhs.flags() == rhs.flags() && lhs.maps() == rhs.maps();
     219             : }
     220             : 
     221           0 : size_t hash_value(CheckMapsParameters const& p) {
     222           0 :   return base::hash_combine(p.flags(), p.maps());
     223             : }
     224             : 
     225           0 : std::ostream& operator<<(std::ostream& os, CheckMapsParameters const& p) {
     226           0 :   return os << p.flags() << p.maps_info();
     227             : }
     228             : 
     229      285659 : CheckMapsParameters const& CheckMapsParametersOf(Operator const* op) {
     230             :   DCHECK_EQ(IrOpcode::kCheckMaps, op->opcode());
     231      285659 :   return OpParameter<CheckMapsParameters>(op);
     232             : }
     233             : 
     234       21752 : MapsParameterInfo const& CompareMapsParametersOf(Operator const* op) {
     235             :   DCHECK_EQ(IrOpcode::kCompareMaps, op->opcode());
     236       21752 :   return OpParameter<MapsParameterInfo>(op);
     237             : }
     238             : 
     239       11698 : MapsParameterInfo const& MapGuardMapsOf(Operator const* op) {
     240             :   DCHECK_EQ(IrOpcode::kMapGuard, op->opcode());
     241       11698 :   return OpParameter<MapsParameterInfo>(op);
     242             : }
     243             : 
     244           0 : size_t hash_value(CheckTaggedInputMode mode) {
     245           0 :   return static_cast<size_t>(mode);
     246             : }
     247             : 
     248           0 : std::ostream& operator<<(std::ostream& os, CheckTaggedInputMode mode) {
     249           0 :   switch (mode) {
     250             :     case CheckTaggedInputMode::kNumber:
     251           0 :       return os << "Number";
     252             :     case CheckTaggedInputMode::kNumberOrOddball:
     253           0 :       return os << "NumberOrOddball";
     254             :   }
     255           0 :   UNREACHABLE();
     256             : }
     257             : 
     258       23148 : CheckTaggedInputMode CheckTaggedInputModeOf(const Operator* op) {
     259             :   DCHECK(op->opcode() == IrOpcode::kCheckedTaggedToFloat64 ||
     260             :          op->opcode() == IrOpcode::kCheckedTruncateTaggedToWord32);
     261       23148 :   return OpParameter<CheckTaggedInputMode>(op);
     262             : }
     263             : 
     264           0 : std::ostream& operator<<(std::ostream& os, GrowFastElementsMode mode) {
     265           0 :   switch (mode) {
     266             :     case GrowFastElementsMode::kDoubleElements:
     267           0 :       return os << "DoubleElements";
     268             :     case GrowFastElementsMode::kSmiOrObjectElements:
     269           0 :       return os << "SmiOrObjectElements";
     270             :   }
     271           0 :   UNREACHABLE();
     272             : }
     273             : 
     274        7533 : GrowFastElementsMode GrowFastElementsModeOf(const Operator* op) {
     275             :   DCHECK_EQ(IrOpcode::kMaybeGrowFastElements, op->opcode());
     276        7533 :   return OpParameter<GrowFastElementsMode>(op);
     277             : }
     278             : 
     279           0 : bool operator==(ElementsTransition const& lhs, ElementsTransition const& rhs) {
     280           0 :   return lhs.mode() == rhs.mode() &&
     281           0 :          lhs.source().address() == rhs.source().address() &&
     282           0 :          lhs.target().address() == rhs.target().address();
     283             : }
     284             : 
     285           0 : size_t hash_value(ElementsTransition transition) {
     286           0 :   return base::hash_combine(static_cast<uint8_t>(transition.mode()),
     287             :                             transition.source().address(),
     288           0 :                             transition.target().address());
     289             : }
     290             : 
     291           0 : std::ostream& operator<<(std::ostream& os, ElementsTransition transition) {
     292           0 :   switch (transition.mode()) {
     293             :     case ElementsTransition::kFastTransition:
     294           0 :       return os << "fast-transition from " << Brief(*transition.source())
     295           0 :                 << " to " << Brief(*transition.target());
     296             :     case ElementsTransition::kSlowTransition:
     297           0 :       return os << "slow-transition from " << Brief(*transition.source())
     298           0 :                 << " to " << Brief(*transition.target());
     299             :   }
     300           0 :   UNREACHABLE();
     301             : }
     302             : 
     303        2189 : ElementsTransition const& ElementsTransitionOf(const Operator* op) {
     304             :   DCHECK_EQ(IrOpcode::kTransitionElementsKind, op->opcode());
     305        2189 :   return OpParameter<ElementsTransition>(op);
     306             : }
     307             : 
     308             : namespace {
     309             : 
     310             : // Parameters for the TransitionAndStoreElement opcode.
     311             : class TransitionAndStoreElementParameters final {
     312             :  public:
     313             :   TransitionAndStoreElementParameters(Handle<Map> double_map,
     314             :                                       Handle<Map> fast_map);
     315             : 
     316             :   Handle<Map> double_map() const { return double_map_; }
     317             :   Handle<Map> fast_map() const { return fast_map_; }
     318             : 
     319             :  private:
     320             :   Handle<Map> const double_map_;
     321             :   Handle<Map> const fast_map_;
     322             : };
     323             : 
     324             : TransitionAndStoreElementParameters::TransitionAndStoreElementParameters(
     325             :     Handle<Map> double_map, Handle<Map> fast_map)
     326             :     : double_map_(double_map), fast_map_(fast_map) {}
     327             : 
     328             : bool operator==(TransitionAndStoreElementParameters const& lhs,
     329             :                 TransitionAndStoreElementParameters const& rhs) {
     330           0 :   return lhs.fast_map().address() == rhs.fast_map().address() &&
     331             :          lhs.double_map().address() == rhs.double_map().address();
     332             : }
     333             : 
     334           0 : size_t hash_value(TransitionAndStoreElementParameters parameters) {
     335             :   return base::hash_combine(parameters.fast_map().address(),
     336           0 :                             parameters.double_map().address());
     337             : }
     338             : 
     339           0 : std::ostream& operator<<(std::ostream& os,
     340             :                          TransitionAndStoreElementParameters parameters) {
     341           0 :   return os << "fast-map" << Brief(*parameters.fast_map()) << " double-map"
     342           0 :             << Brief(*parameters.double_map());
     343             : }
     344             : 
     345             : }  // namespace
     346             : 
     347             : namespace {
     348             : 
     349             : // Parameters for the TransitionAndStoreNonNumberElement opcode.
     350             : class TransitionAndStoreNonNumberElementParameters final {
     351             :  public:
     352             :   TransitionAndStoreNonNumberElementParameters(Handle<Map> fast_map,
     353             :                                                Type* value_type);
     354             : 
     355             :   Handle<Map> fast_map() const { return fast_map_; }
     356             :   Type* value_type() const { return value_type_; }
     357             : 
     358             :  private:
     359             :   Handle<Map> const fast_map_;
     360             :   Type* value_type_;
     361             : };
     362             : 
     363             : TransitionAndStoreNonNumberElementParameters::
     364             :     TransitionAndStoreNonNumberElementParameters(Handle<Map> fast_map,
     365             :                                                  Type* value_type)
     366             :     : fast_map_(fast_map), value_type_(value_type) {}
     367             : 
     368           0 : bool operator==(TransitionAndStoreNonNumberElementParameters const& lhs,
     369           0 :                 TransitionAndStoreNonNumberElementParameters const& rhs) {
     370           0 :   return lhs.fast_map().address() == rhs.fast_map().address() &&
     371             :          lhs.value_type() == rhs.value_type();
     372             : }
     373             : 
     374           0 : size_t hash_value(TransitionAndStoreNonNumberElementParameters parameters) {
     375             :   return base::hash_combine(parameters.fast_map().address(),
     376           0 :                             parameters.value_type());
     377             : }
     378             : 
     379           0 : std::ostream& operator<<(
     380             :     std::ostream& os, TransitionAndStoreNonNumberElementParameters parameters) {
     381           0 :   parameters.value_type()->PrintTo(os);
     382           0 :   return os << ", fast-map" << Brief(*parameters.fast_map());
     383             : }
     384             : 
     385             : }  // namespace
     386             : 
     387             : namespace {
     388             : 
     389             : // Parameters for the TransitionAndStoreNumberElement opcode.
     390             : class TransitionAndStoreNumberElementParameters final {
     391             :  public:
     392             :   explicit TransitionAndStoreNumberElementParameters(Handle<Map> double_map);
     393             : 
     394          20 :   Handle<Map> double_map() const { return double_map_; }
     395             : 
     396             :  private:
     397             :   Handle<Map> const double_map_;
     398             : };
     399             : 
     400             : TransitionAndStoreNumberElementParameters::
     401             :     TransitionAndStoreNumberElementParameters(Handle<Map> double_map)
     402             :     : double_map_(double_map) {}
     403             : 
     404             : bool operator==(TransitionAndStoreNumberElementParameters const& lhs,
     405             :                 TransitionAndStoreNumberElementParameters const& rhs) {
     406           0 :   return lhs.double_map().address() == rhs.double_map().address();
     407             : }
     408             : 
     409           0 : size_t hash_value(TransitionAndStoreNumberElementParameters parameters) {
     410           0 :   return base::hash_combine(parameters.double_map().address());
     411             : }
     412             : 
     413           0 : std::ostream& operator<<(std::ostream& os,
     414             :                          TransitionAndStoreNumberElementParameters parameters) {
     415           0 :   return os << "double-map" << Brief(*parameters.double_map());
     416             : }
     417             : 
     418             : }  // namespace
     419             : 
     420         584 : Handle<Map> DoubleMapParameterOf(const Operator* op) {
     421         584 :   if (op->opcode() == IrOpcode::kTransitionAndStoreElement) {
     422             :     return OpParameter<TransitionAndStoreElementParameters>(op).double_map();
     423          20 :   } else if (op->opcode() == IrOpcode::kTransitionAndStoreNumberElement) {
     424             :     return OpParameter<TransitionAndStoreNumberElementParameters>(op)
     425             :         .double_map();
     426             :   }
     427           0 :   UNREACHABLE();
     428             :   return Handle<Map>::null();
     429             : }
     430             : 
     431           6 : Type* ValueTypeParameterOf(const Operator* op) {
     432             :   DCHECK_EQ(IrOpcode::kTransitionAndStoreNonNumberElement, op->opcode());
     433             :   return OpParameter<TransitionAndStoreNonNumberElementParameters>(op)
     434           6 :       .value_type();
     435             : }
     436             : 
     437         632 : Handle<Map> FastMapParameterOf(const Operator* op) {
     438         632 :   if (op->opcode() == IrOpcode::kTransitionAndStoreElement) {
     439             :     return OpParameter<TransitionAndStoreElementParameters>(op).fast_map();
     440          12 :   } else if (op->opcode() == IrOpcode::kTransitionAndStoreNonNumberElement) {
     441             :     return OpParameter<TransitionAndStoreNonNumberElementParameters>(op)
     442             :         .fast_map();
     443             :   }
     444           0 :   UNREACHABLE();
     445             :   return Handle<Map>::null();
     446             : }
     447             : 
     448           0 : std::ostream& operator<<(std::ostream& os, NumberOperationHint hint) {
     449           0 :   switch (hint) {
     450             :     case NumberOperationHint::kSignedSmall:
     451           0 :       return os << "SignedSmall";
     452             :     case NumberOperationHint::kSignedSmallInputs:
     453           0 :       return os << "SignedSmallInputs";
     454             :     case NumberOperationHint::kSigned32:
     455           0 :       return os << "Signed32";
     456             :     case NumberOperationHint::kNumber:
     457           0 :       return os << "Number";
     458             :     case NumberOperationHint::kNumberOrOddball:
     459           0 :       return os << "NumberOrOddball";
     460             :   }
     461           0 :   UNREACHABLE();
     462             : }
     463             : 
     464           0 : size_t hash_value(NumberOperationHint hint) {
     465           0 :   return static_cast<uint8_t>(hint);
     466             : }
     467             : 
     468     1026115 : NumberOperationHint NumberOperationHintOf(const Operator* op) {
     469             :   DCHECK(op->opcode() == IrOpcode::kSpeculativeToNumber ||
     470             :          op->opcode() == IrOpcode::kSpeculativeNumberAdd ||
     471             :          op->opcode() == IrOpcode::kSpeculativeNumberSubtract ||
     472             :          op->opcode() == IrOpcode::kSpeculativeNumberMultiply ||
     473             :          op->opcode() == IrOpcode::kSpeculativeNumberDivide ||
     474             :          op->opcode() == IrOpcode::kSpeculativeNumberModulus ||
     475             :          op->opcode() == IrOpcode::kSpeculativeNumberShiftLeft ||
     476             :          op->opcode() == IrOpcode::kSpeculativeNumberShiftRight ||
     477             :          op->opcode() == IrOpcode::kSpeculativeNumberShiftRightLogical ||
     478             :          op->opcode() == IrOpcode::kSpeculativeNumberBitwiseAnd ||
     479             :          op->opcode() == IrOpcode::kSpeculativeNumberBitwiseOr ||
     480             :          op->opcode() == IrOpcode::kSpeculativeNumberBitwiseXor ||
     481             :          op->opcode() == IrOpcode::kSpeculativeNumberEqual ||
     482             :          op->opcode() == IrOpcode::kSpeculativeNumberLessThan ||
     483             :          op->opcode() == IrOpcode::kSpeculativeNumberLessThanOrEqual ||
     484             :          op->opcode() == IrOpcode::kSpeculativeSafeIntegerAdd ||
     485             :          op->opcode() == IrOpcode::kSpeculativeSafeIntegerSubtract);
     486     1026115 :   return OpParameter<NumberOperationHint>(op);
     487             : }
     488             : 
     489           0 : size_t hash_value(AllocateParameters info) {
     490           0 :   return base::hash_combine(info.type(), info.pretenure());
     491             : }
     492             : 
     493           0 : V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
     494             :                                            AllocateParameters info) {
     495           0 :   info.type()->PrintTo(os);
     496           0 :   return os << ", " << info.pretenure();
     497             : }
     498             : 
     499           0 : bool operator==(AllocateParameters const& lhs, AllocateParameters const& rhs) {
     500           0 :   return lhs.pretenure() == rhs.pretenure() && lhs.type() == rhs.type();
     501             : }
     502             : 
     503      162897 : PretenureFlag PretenureFlagOf(const Operator* op) {
     504      162897 :   if (op->opcode() == IrOpcode::kNewDoubleElements ||
     505             :       op->opcode() == IrOpcode::kNewSmiOrObjectElements) {
     506         354 :     return OpParameter<PretenureFlag>(op);
     507             :   }
     508             :   DCHECK_EQ(IrOpcode::kAllocate, op->opcode());
     509      162543 :   return OpParameter<AllocateParameters>(op).pretenure();
     510             : }
     511             : 
     512      121824 : Type* AllocateTypeOf(const Operator* op) {
     513             :   DCHECK_EQ(IrOpcode::kAllocate, op->opcode());
     514      121824 :   return OpParameter<AllocateParameters>(op).type();
     515             : }
     516             : 
     517          39 : UnicodeEncoding UnicodeEncodingOf(const Operator* op) {
     518             :   DCHECK_EQ(IrOpcode::kStringFromCodePoint, op->opcode());
     519          39 :   return OpParameter<UnicodeEncoding>(op);
     520             : }
     521             : 
     522        1920 : BailoutReason BailoutReasonOf(const Operator* op) {
     523             :   DCHECK_EQ(IrOpcode::kRuntimeAbort, op->opcode());
     524        1920 :   return OpParameter<BailoutReason>(op);
     525             : }
     526             : 
     527       28990 : DeoptimizeReason DeoptimizeReasonOf(const Operator* op) {
     528             :   DCHECK_EQ(IrOpcode::kCheckIf, op->opcode());
     529       28990 :   return OpParameter<DeoptimizeReason>(op);
     530             : }
     531             : 
     532             : #define PURE_OP_LIST(V)                                          \
     533             :   V(BooleanNot, Operator::kNoProperties, 1, 0)                   \
     534             :   V(NumberEqual, Operator::kCommutative, 2, 0)                   \
     535             :   V(NumberLessThan, Operator::kNoProperties, 2, 0)               \
     536             :   V(NumberLessThanOrEqual, Operator::kNoProperties, 2, 0)        \
     537             :   V(NumberAdd, Operator::kCommutative, 2, 0)                     \
     538             :   V(NumberSubtract, Operator::kNoProperties, 2, 0)               \
     539             :   V(NumberMultiply, Operator::kCommutative, 2, 0)                \
     540             :   V(NumberDivide, Operator::kNoProperties, 2, 0)                 \
     541             :   V(NumberModulus, Operator::kNoProperties, 2, 0)                \
     542             :   V(NumberBitwiseOr, Operator::kCommutative, 2, 0)               \
     543             :   V(NumberBitwiseXor, Operator::kCommutative, 2, 0)              \
     544             :   V(NumberBitwiseAnd, Operator::kCommutative, 2, 0)              \
     545             :   V(NumberShiftLeft, Operator::kNoProperties, 2, 0)              \
     546             :   V(NumberShiftRight, Operator::kNoProperties, 2, 0)             \
     547             :   V(NumberShiftRightLogical, Operator::kNoProperties, 2, 0)      \
     548             :   V(NumberImul, Operator::kCommutative, 2, 0)                    \
     549             :   V(NumberAbs, Operator::kNoProperties, 1, 0)                    \
     550             :   V(NumberClz32, Operator::kNoProperties, 1, 0)                  \
     551             :   V(NumberCeil, Operator::kNoProperties, 1, 0)                   \
     552             :   V(NumberFloor, Operator::kNoProperties, 1, 0)                  \
     553             :   V(NumberFround, Operator::kNoProperties, 1, 0)                 \
     554             :   V(NumberAcos, Operator::kNoProperties, 1, 0)                   \
     555             :   V(NumberAcosh, Operator::kNoProperties, 1, 0)                  \
     556             :   V(NumberAsin, Operator::kNoProperties, 1, 0)                   \
     557             :   V(NumberAsinh, Operator::kNoProperties, 1, 0)                  \
     558             :   V(NumberAtan, Operator::kNoProperties, 1, 0)                   \
     559             :   V(NumberAtan2, Operator::kNoProperties, 2, 0)                  \
     560             :   V(NumberAtanh, Operator::kNoProperties, 1, 0)                  \
     561             :   V(NumberCbrt, Operator::kNoProperties, 1, 0)                   \
     562             :   V(NumberCos, Operator::kNoProperties, 1, 0)                    \
     563             :   V(NumberCosh, Operator::kNoProperties, 1, 0)                   \
     564             :   V(NumberExp, Operator::kNoProperties, 1, 0)                    \
     565             :   V(NumberExpm1, Operator::kNoProperties, 1, 0)                  \
     566             :   V(NumberLog, Operator::kNoProperties, 1, 0)                    \
     567             :   V(NumberLog1p, Operator::kNoProperties, 1, 0)                  \
     568             :   V(NumberLog10, Operator::kNoProperties, 1, 0)                  \
     569             :   V(NumberLog2, Operator::kNoProperties, 1, 0)                   \
     570             :   V(NumberMax, Operator::kNoProperties, 2, 0)                    \
     571             :   V(NumberMin, Operator::kNoProperties, 2, 0)                    \
     572             :   V(NumberPow, Operator::kNoProperties, 2, 0)                    \
     573             :   V(NumberRound, Operator::kNoProperties, 1, 0)                  \
     574             :   V(NumberSign, Operator::kNoProperties, 1, 0)                   \
     575             :   V(NumberSin, Operator::kNoProperties, 1, 0)                    \
     576             :   V(NumberSinh, Operator::kNoProperties, 1, 0)                   \
     577             :   V(NumberSqrt, Operator::kNoProperties, 1, 0)                   \
     578             :   V(NumberTan, Operator::kNoProperties, 1, 0)                    \
     579             :   V(NumberTanh, Operator::kNoProperties, 1, 0)                   \
     580             :   V(NumberTrunc, Operator::kNoProperties, 1, 0)                  \
     581             :   V(NumberToBoolean, Operator::kNoProperties, 1, 0)              \
     582             :   V(NumberToInt32, Operator::kNoProperties, 1, 0)                \
     583             :   V(NumberToUint32, Operator::kNoProperties, 1, 0)               \
     584             :   V(NumberToUint8Clamped, Operator::kNoProperties, 1, 0)         \
     585             :   V(NumberSilenceNaN, Operator::kNoProperties, 1, 0)             \
     586             :   V(StringToNumber, Operator::kNoProperties, 1, 0)               \
     587             :   V(StringCharAt, Operator::kNoProperties, 2, 1)                 \
     588             :   V(StringCharCodeAt, Operator::kNoProperties, 2, 1)             \
     589             :   V(SeqStringCharCodeAt, Operator::kNoProperties, 2, 1)          \
     590             :   V(StringFromCharCode, Operator::kNoProperties, 1, 0)           \
     591             :   V(StringIndexOf, Operator::kNoProperties, 3, 0)                \
     592             :   V(StringToLowerCaseIntl, Operator::kNoProperties, 1, 0)        \
     593             :   V(StringToUpperCaseIntl, Operator::kNoProperties, 1, 0)        \
     594             :   V(TypeOf, Operator::kNoProperties, 1, 1)                       \
     595             :   V(ClassOf, Operator::kNoProperties, 1, 1)                      \
     596             :   V(PlainPrimitiveToNumber, Operator::kNoProperties, 1, 0)       \
     597             :   V(PlainPrimitiveToWord32, Operator::kNoProperties, 1, 0)       \
     598             :   V(PlainPrimitiveToFloat64, Operator::kNoProperties, 1, 0)      \
     599             :   V(ChangeTaggedSignedToInt32, Operator::kNoProperties, 1, 0)    \
     600             :   V(ChangeTaggedToInt32, Operator::kNoProperties, 1, 0)          \
     601             :   V(ChangeTaggedToUint32, Operator::kNoProperties, 1, 0)         \
     602             :   V(ChangeTaggedToFloat64, Operator::kNoProperties, 1, 0)        \
     603             :   V(ChangeTaggedToTaggedSigned, Operator::kNoProperties, 1, 0)   \
     604             :   V(ChangeFloat64ToTaggedPointer, Operator::kNoProperties, 1, 0) \
     605             :   V(ChangeInt31ToTaggedSigned, Operator::kNoProperties, 1, 0)    \
     606             :   V(ChangeInt32ToTagged, Operator::kNoProperties, 1, 0)          \
     607             :   V(ChangeUint32ToTagged, Operator::kNoProperties, 1, 0)         \
     608             :   V(ChangeTaggedToBit, Operator::kNoProperties, 1, 0)            \
     609             :   V(ChangeBitToTagged, Operator::kNoProperties, 1, 0)            \
     610             :   V(TruncateTaggedToBit, Operator::kNoProperties, 1, 0)          \
     611             :   V(TruncateTaggedPointerToBit, Operator::kNoProperties, 1, 0)   \
     612             :   V(TruncateTaggedToWord32, Operator::kNoProperties, 1, 0)       \
     613             :   V(TruncateTaggedToFloat64, Operator::kNoProperties, 1, 0)      \
     614             :   V(ObjectIsArrayBufferView, Operator::kNoProperties, 1, 0)      \
     615             :   V(ObjectIsCallable, Operator::kNoProperties, 1, 0)             \
     616             :   V(ObjectIsConstructor, Operator::kNoProperties, 1, 0)          \
     617             :   V(ObjectIsDetectableCallable, Operator::kNoProperties, 1, 0)   \
     618             :   V(ObjectIsMinusZero, Operator::kNoProperties, 1, 0)            \
     619             :   V(ObjectIsNaN, Operator::kNoProperties, 1, 0)                  \
     620             :   V(ObjectIsNonCallable, Operator::kNoProperties, 1, 0)          \
     621             :   V(ObjectIsNumber, Operator::kNoProperties, 1, 0)               \
     622             :   V(ObjectIsReceiver, Operator::kNoProperties, 1, 0)             \
     623             :   V(ObjectIsSmi, Operator::kNoProperties, 1, 0)                  \
     624             :   V(ObjectIsString, Operator::kNoProperties, 1, 0)               \
     625             :   V(ObjectIsSymbol, Operator::kNoProperties, 1, 0)               \
     626             :   V(ObjectIsUndetectable, Operator::kNoProperties, 1, 0)         \
     627             :   V(ConvertTaggedHoleToUndefined, Operator::kNoProperties, 1, 0) \
     628             :   V(ReferenceEqual, Operator::kCommutative, 2, 0)                \
     629             :   V(StringEqual, Operator::kCommutative, 2, 0)                   \
     630             :   V(StringLessThan, Operator::kNoProperties, 2, 0)               \
     631             :   V(StringLessThanOrEqual, Operator::kNoProperties, 2, 0)
     632             : 
     633             : #define SPECULATIVE_NUMBER_BINOP_LIST(V)      \
     634             :   SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(V) \
     635             :   V(SpeculativeNumberEqual)                   \
     636             :   V(SpeculativeNumberLessThan)                \
     637             :   V(SpeculativeNumberLessThanOrEqual)
     638             : 
     639             : #define CHECKED_OP_LIST(V)               \
     640             :   V(CheckBounds, 2, 1)                   \
     641             :   V(CheckHeapObject, 1, 1)               \
     642             :   V(CheckInternalizedString, 1, 1)       \
     643             :   V(CheckNumber, 1, 1)                   \
     644             :   V(CheckReceiver, 1, 1)                 \
     645             :   V(CheckSmi, 1, 1)                      \
     646             :   V(CheckString, 1, 1)                   \
     647             :   V(CheckSeqString, 1, 1)                \
     648             :   V(CheckSymbol, 1, 1)                   \
     649             :   V(CheckNotTaggedHole, 1, 1)            \
     650             :   V(CheckEqualsInternalizedString, 2, 0) \
     651             :   V(CheckEqualsSymbol, 2, 0)             \
     652             :   V(CheckedInt32Add, 2, 1)               \
     653             :   V(CheckedInt32Sub, 2, 1)               \
     654             :   V(CheckedInt32Div, 2, 1)               \
     655             :   V(CheckedInt32Mod, 2, 1)               \
     656             :   V(CheckedUint32Div, 2, 1)              \
     657             :   V(CheckedUint32Mod, 2, 1)              \
     658             :   V(CheckedUint32ToInt32, 1, 1)          \
     659             :   V(CheckedUint32ToTaggedSigned, 1, 1)   \
     660             :   V(CheckedInt32ToTaggedSigned, 1, 1)    \
     661             :   V(CheckedTaggedSignedToInt32, 1, 1)    \
     662             :   V(CheckedTaggedToTaggedSigned, 1, 1)   \
     663             :   V(CheckedTaggedToTaggedPointer, 1, 1)
     664             : 
     665       22009 : struct SimplifiedOperatorGlobalCache final {
     666             : #define PURE(Name, properties, value_input_count, control_input_count)     \
     667             :   struct Name##Operator final : public Operator {                          \
     668             :     Name##Operator()                                                       \
     669             :         : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \
     670             :                    value_input_count, 0, control_input_count, 1, 0, 0) {}  \
     671             :   };                                                                       \
     672             :   Name##Operator k##Name;
     673     2178891 :   PURE_OP_LIST(PURE)
     674             : #undef PURE
     675             : 
     676             : #define CHECKED(Name, value_input_count, value_output_count)             \
     677             :   struct Name##Operator final : public Operator {                        \
     678             :     Name##Operator()                                                     \
     679             :         : Operator(IrOpcode::k##Name,                                    \
     680             :                    Operator::kFoldable | Operator::kNoThrow, #Name,      \
     681             :                    value_input_count, 1, 1, value_output_count, 1, 0) {} \
     682             :   };                                                                     \
     683             :   Name##Operator k##Name;
     684      528216 :   CHECKED_OP_LIST(CHECKED)
     685             : #undef CHECKED
     686             : 
     687             :   template <DeoptimizeReason kDeoptimizeReason>
     688           0 :   struct CheckIfOperator final : public Operator1<DeoptimizeReason> {
     689     1298531 :     CheckIfOperator()
     690             :         : Operator1<DeoptimizeReason>(
     691             :               IrOpcode::kCheckIf, Operator::kFoldable | Operator::kNoThrow,
     692     1298531 :               "CheckIf", 1, 1, 1, 0, 1, 0, kDeoptimizeReason) {}
     693             :   };
     694             : #define CHECK_IF(Name, message) \
     695             :   CheckIfOperator<DeoptimizeReason::k##Name> kCheckIf##Name;
     696             :   DEOPTIMIZE_REASON_LIST(CHECK_IF)
     697             : #undef CHECK_IF
     698             : 
     699             :   template <UnicodeEncoding kEncoding>
     700           0 :   struct StringFromCodePointOperator final : public Operator1<UnicodeEncoding> {
     701       44018 :     StringFromCodePointOperator()
     702             :         : Operator1<UnicodeEncoding>(IrOpcode::kStringFromCodePoint,
     703             :                                      Operator::kPure, "StringFromCodePoint", 1,
     704       44018 :                                      0, 0, 1, 0, 0, kEncoding) {}
     705             :   };
     706             :   StringFromCodePointOperator<UnicodeEncoding::UTF16>
     707             :       kStringFromCodePointOperatorUTF16;
     708             :   StringFromCodePointOperator<UnicodeEncoding::UTF32>
     709             :       kStringFromCodePointOperatorUTF32;
     710             : 
     711           0 :   struct ArrayBufferWasNeuteredOperator final : public Operator {
     712       22009 :     ArrayBufferWasNeuteredOperator()
     713             :         : Operator(IrOpcode::kArrayBufferWasNeutered, Operator::kEliminatable,
     714       22009 :                    "ArrayBufferWasNeutered", 1, 1, 1, 1, 1, 0) {}
     715             :   };
     716             :   ArrayBufferWasNeuteredOperator kArrayBufferWasNeutered;
     717             : 
     718           0 :   struct FindOrderedHashMapEntryOperator final : public Operator {
     719       22009 :     FindOrderedHashMapEntryOperator()
     720             :         : Operator(IrOpcode::kFindOrderedHashMapEntry, Operator::kEliminatable,
     721       22009 :                    "FindOrderedHashMapEntry", 2, 1, 1, 1, 1, 0) {}
     722             :   };
     723             :   FindOrderedHashMapEntryOperator kFindOrderedHashMapEntry;
     724             : 
     725           0 :   struct FindOrderedHashMapEntryForInt32KeyOperator final : public Operator {
     726       22009 :     FindOrderedHashMapEntryForInt32KeyOperator()
     727             :         : Operator(IrOpcode::kFindOrderedHashMapEntryForInt32Key,
     728             :                    Operator::kEliminatable,
     729       22009 :                    "FindOrderedHashMapEntryForInt32Key", 2, 1, 1, 1, 1, 0) {}
     730             :   };
     731             :   FindOrderedHashMapEntryForInt32KeyOperator
     732             :       kFindOrderedHashMapEntryForInt32Key;
     733             : 
     734           0 :   struct ArgumentsFrameOperator final : public Operator {
     735       22009 :     ArgumentsFrameOperator()
     736             :         : Operator(IrOpcode::kArgumentsFrame, Operator::kPure, "ArgumentsFrame",
     737       22009 :                    0, 0, 0, 1, 0, 0) {}
     738             :   };
     739             :   ArgumentsFrameOperator kArgumentsFrame;
     740             : 
     741             :   template <CheckForMinusZeroMode kMode>
     742           0 :   struct ChangeFloat64ToTaggedOperator final
     743             :       : public Operator1<CheckForMinusZeroMode> {
     744       44018 :     ChangeFloat64ToTaggedOperator()
     745             :         : Operator1<CheckForMinusZeroMode>(
     746             :               IrOpcode::kChangeFloat64ToTagged, Operator::kPure,
     747       44018 :               "ChangeFloat64ToTagged", 1, 0, 0, 1, 0, 0, kMode) {}
     748             :   };
     749             :   ChangeFloat64ToTaggedOperator<CheckForMinusZeroMode::kCheckForMinusZero>
     750             :       kChangeFloat64ToTaggedCheckForMinusZeroOperator;
     751             :   ChangeFloat64ToTaggedOperator<CheckForMinusZeroMode::kDontCheckForMinusZero>
     752             :       kChangeFloat64ToTaggedDontCheckForMinusZeroOperator;
     753             : 
     754             :   template <CheckForMinusZeroMode kMode>
     755           0 :   struct CheckedInt32MulOperator final
     756             :       : public Operator1<CheckForMinusZeroMode> {
     757       44018 :     CheckedInt32MulOperator()
     758             :         : Operator1<CheckForMinusZeroMode>(
     759             :               IrOpcode::kCheckedInt32Mul,
     760             :               Operator::kFoldable | Operator::kNoThrow, "CheckedInt32Mul", 2, 1,
     761       44018 :               1, 1, 1, 0, kMode) {}
     762             :   };
     763             :   CheckedInt32MulOperator<CheckForMinusZeroMode::kCheckForMinusZero>
     764             :       kCheckedInt32MulCheckForMinusZeroOperator;
     765             :   CheckedInt32MulOperator<CheckForMinusZeroMode::kDontCheckForMinusZero>
     766             :       kCheckedInt32MulDontCheckForMinusZeroOperator;
     767             : 
     768             :   template <CheckForMinusZeroMode kMode>
     769           0 :   struct CheckedFloat64ToInt32Operator final
     770             :       : public Operator1<CheckForMinusZeroMode> {
     771       44018 :     CheckedFloat64ToInt32Operator()
     772             :         : Operator1<CheckForMinusZeroMode>(
     773             :               IrOpcode::kCheckedFloat64ToInt32,
     774             :               Operator::kFoldable | Operator::kNoThrow, "CheckedFloat64ToInt32",
     775       44018 :               1, 1, 1, 1, 1, 0, kMode) {}
     776             :   };
     777             :   CheckedFloat64ToInt32Operator<CheckForMinusZeroMode::kCheckForMinusZero>
     778             :       kCheckedFloat64ToInt32CheckForMinusZeroOperator;
     779             :   CheckedFloat64ToInt32Operator<CheckForMinusZeroMode::kDontCheckForMinusZero>
     780             :       kCheckedFloat64ToInt32DontCheckForMinusZeroOperator;
     781             : 
     782             :   template <CheckForMinusZeroMode kMode>
     783           0 :   struct CheckedTaggedToInt32Operator final
     784             :       : public Operator1<CheckForMinusZeroMode> {
     785       44018 :     CheckedTaggedToInt32Operator()
     786             :         : Operator1<CheckForMinusZeroMode>(
     787             :               IrOpcode::kCheckedTaggedToInt32,
     788             :               Operator::kFoldable | Operator::kNoThrow, "CheckedTaggedToInt32",
     789       44018 :               1, 1, 1, 1, 1, 0, kMode) {}
     790             :   };
     791             :   CheckedTaggedToInt32Operator<CheckForMinusZeroMode::kCheckForMinusZero>
     792             :       kCheckedTaggedToInt32CheckForMinusZeroOperator;
     793             :   CheckedTaggedToInt32Operator<CheckForMinusZeroMode::kDontCheckForMinusZero>
     794             :       kCheckedTaggedToInt32DontCheckForMinusZeroOperator;
     795             : 
     796             :   template <CheckTaggedInputMode kMode>
     797           0 :   struct CheckedTaggedToFloat64Operator final
     798             :       : public Operator1<CheckTaggedInputMode> {
     799       44018 :     CheckedTaggedToFloat64Operator()
     800             :         : Operator1<CheckTaggedInputMode>(
     801             :               IrOpcode::kCheckedTaggedToFloat64,
     802             :               Operator::kFoldable | Operator::kNoThrow,
     803       44018 :               "CheckedTaggedToFloat64", 1, 1, 1, 1, 1, 0, kMode) {}
     804             :   };
     805             :   CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumber>
     806             :       kCheckedTaggedToFloat64NumberOperator;
     807             :   CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumberOrOddball>
     808             :       kCheckedTaggedToFloat64NumberOrOddballOperator;
     809             : 
     810             :   template <CheckTaggedInputMode kMode>
     811           0 :   struct CheckedTruncateTaggedToWord32Operator final
     812             :       : public Operator1<CheckTaggedInputMode> {
     813       44018 :     CheckedTruncateTaggedToWord32Operator()
     814             :         : Operator1<CheckTaggedInputMode>(
     815             :               IrOpcode::kCheckedTruncateTaggedToWord32,
     816             :               Operator::kFoldable | Operator::kNoThrow,
     817       44018 :               "CheckedTruncateTaggedToWord32", 1, 1, 1, 1, 1, 0, kMode) {}
     818             :   };
     819             :   CheckedTruncateTaggedToWord32Operator<CheckTaggedInputMode::kNumber>
     820             :       kCheckedTruncateTaggedToWord32NumberOperator;
     821             :   CheckedTruncateTaggedToWord32Operator<CheckTaggedInputMode::kNumberOrOddball>
     822             :       kCheckedTruncateTaggedToWord32NumberOrOddballOperator;
     823             : 
     824             :   template <CheckFloat64HoleMode kMode>
     825           0 :   struct CheckFloat64HoleNaNOperator final
     826             :       : public Operator1<CheckFloat64HoleMode> {
     827       44018 :     CheckFloat64HoleNaNOperator()
     828             :         : Operator1<CheckFloat64HoleMode>(
     829             :               IrOpcode::kCheckFloat64Hole,
     830             :               Operator::kFoldable | Operator::kNoThrow, "CheckFloat64Hole", 1,
     831       44018 :               1, 1, 1, 1, 0, kMode) {}
     832             :   };
     833             :   CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kAllowReturnHole>
     834             :       kCheckFloat64HoleAllowReturnHoleOperator;
     835             :   CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kNeverReturnHole>
     836             :       kCheckFloat64HoleNeverReturnHoleOperator;
     837             : 
     838           0 :   struct EnsureWritableFastElementsOperator final : public Operator {
     839       22009 :     EnsureWritableFastElementsOperator()
     840             :         : Operator(                                     // --
     841             :               IrOpcode::kEnsureWritableFastElements,    // opcode
     842             :               Operator::kNoDeopt | Operator::kNoThrow,  // flags
     843             :               "EnsureWritableFastElements",             // name
     844       22009 :               2, 1, 1, 1, 1, 0) {}                      // counts
     845             :   };
     846             :   EnsureWritableFastElementsOperator kEnsureWritableFastElements;
     847             : 
     848           0 :   struct LoadFieldByIndexOperator final : public Operator {
     849       22009 :     LoadFieldByIndexOperator()
     850             :         : Operator(                         // --
     851             :               IrOpcode::kLoadFieldByIndex,  // opcode
     852             :               Operator::kEliminatable,      // flags,
     853             :               "LoadFieldByIndex",           // name
     854       22009 :               2, 1, 1, 1, 1, 0) {}          // counts;
     855             :   };
     856             :   LoadFieldByIndexOperator kLoadFieldByIndex;
     857             : 
     858             : #define SPECULATIVE_NUMBER_BINOP(Name)                                      \
     859             :   template <NumberOperationHint kHint>                                      \
     860             :   struct Name##Operator final : public Operator1<NumberOperationHint> {     \
     861             :     Name##Operator()                                                        \
     862             :         : Operator1<NumberOperationHint>(                                   \
     863             :               IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow,  \
     864             :               #Name, 2, 1, 1, 1, 1, 0, kHint) {}                            \
     865             :   };                                                                        \
     866             :   Name##Operator<NumberOperationHint::kSignedSmall>                         \
     867             :       k##Name##SignedSmallOperator;                                         \
     868             :   Name##Operator<NumberOperationHint::kSignedSmallInputs>                   \
     869             :       k##Name##SignedSmallInputsOperator;                                   \
     870             :   Name##Operator<NumberOperationHint::kSigned32> k##Name##Signed32Operator; \
     871             :   Name##Operator<NumberOperationHint::kNumber> k##Name##NumberOperator;     \
     872             :   Name##Operator<NumberOperationHint::kNumberOrOddball>                     \
     873             :       k##Name##NumberOrOddballOperator;
     874     3521440 :   SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP)
     875             : #undef SPECULATIVE_NUMBER_BINOP
     876             : 
     877             :   template <NumberOperationHint kHint>
     878           0 :   struct SpeculativeToNumberOperator final
     879             :       : public Operator1<NumberOperationHint> {
     880       88036 :     SpeculativeToNumberOperator()
     881             :         : Operator1<NumberOperationHint>(
     882             :               IrOpcode::kSpeculativeToNumber,            // opcode
     883             :               Operator::kFoldable | Operator::kNoThrow,  // flags
     884             :               "SpeculativeToNumber",                     // name
     885             :               1, 1, 1, 1, 1, 0,                          // counts
     886       88036 :               kHint) {}                                  // parameter
     887             :   };
     888             :   SpeculativeToNumberOperator<NumberOperationHint::kSignedSmall>
     889             :       kSpeculativeToNumberSignedSmallOperator;
     890             :   SpeculativeToNumberOperator<NumberOperationHint::kSigned32>
     891             :       kSpeculativeToNumberSigned32Operator;
     892             :   SpeculativeToNumberOperator<NumberOperationHint::kNumber>
     893             :       kSpeculativeToNumberNumberOperator;
     894             :   SpeculativeToNumberOperator<NumberOperationHint::kNumberOrOddball>
     895             :       kSpeculativeToNumberNumberOrOddballOperator;
     896             : };
     897             : 
     898             : static base::LazyInstance<SimplifiedOperatorGlobalCache>::type
     899             :     kSimplifiedOperatorGlobalCache = LAZY_INSTANCE_INITIALIZER;
     900             : 
     901      646989 : SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone)
     902      646990 :     : cache_(kSimplifiedOperatorGlobalCache.Get()), zone_(zone) {}
     903             : 
     904             : #define GET_FROM_CACHE(Name, ...) \
     905             :   const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
     906     1136964 : PURE_OP_LIST(GET_FROM_CACHE)
     907      507793 : CHECKED_OP_LIST(GET_FROM_CACHE)
     908         498 : GET_FROM_CACHE(ArrayBufferWasNeutered)
     909       16652 : GET_FROM_CACHE(ArgumentsFrame)
     910           8 : GET_FROM_CACHE(FindOrderedHashMapEntry)
     911           0 : GET_FROM_CACHE(FindOrderedHashMapEntryForInt32Key)
     912        1087 : GET_FROM_CACHE(LoadFieldByIndex)
     913             : #undef GET_FROM_CACHE
     914             : 
     915        1983 : const Operator* SimplifiedOperatorBuilder::RuntimeAbort(BailoutReason reason) {
     916             :   return new (zone()) Operator1<BailoutReason>(  // --
     917             :       IrOpcode::kRuntimeAbort,                   // opcode
     918             :       Operator::kNoThrow | Operator::kNoDeopt,   // flags
     919             :       "RuntimeAbort",                            // name
     920             :       0, 1, 1, 0, 1, 0,                          // counts
     921        1983 :       reason);                                   // parameter
     922             : }
     923             : 
     924       34939 : const Operator* SimplifiedOperatorBuilder::CheckIf(DeoptimizeReason reason) {
     925       34939 :   switch (reason) {
     926             : #define CHECK_IF(Name, message)   \
     927             :   case DeoptimizeReason::k##Name: \
     928             :     return &cache_.kCheckIf##Name;
     929           0 :     DEOPTIMIZE_REASON_LIST(CHECK_IF)
     930             : #undef CHECK_IF
     931             :   }
     932           0 :   UNREACHABLE();
     933             : }
     934             : 
     935       61901 : const Operator* SimplifiedOperatorBuilder::ChangeFloat64ToTagged(
     936             :     CheckForMinusZeroMode mode) {
     937       61901 :   switch (mode) {
     938             :     case CheckForMinusZeroMode::kCheckForMinusZero:
     939       24462 :       return &cache_.kChangeFloat64ToTaggedCheckForMinusZeroOperator;
     940             :     case CheckForMinusZeroMode::kDontCheckForMinusZero:
     941       37439 :       return &cache_.kChangeFloat64ToTaggedDontCheckForMinusZeroOperator;
     942             :   }
     943           0 :   UNREACHABLE();
     944             : }
     945             : 
     946        6120 : const Operator* SimplifiedOperatorBuilder::CheckedInt32Mul(
     947             :     CheckForMinusZeroMode mode) {
     948        6120 :   switch (mode) {
     949             :     case CheckForMinusZeroMode::kCheckForMinusZero:
     950        4310 :       return &cache_.kCheckedInt32MulCheckForMinusZeroOperator;
     951             :     case CheckForMinusZeroMode::kDontCheckForMinusZero:
     952        1810 :       return &cache_.kCheckedInt32MulDontCheckForMinusZeroOperator;
     953             :   }
     954           0 :   UNREACHABLE();
     955             : }
     956             : 
     957        4920 : const Operator* SimplifiedOperatorBuilder::CheckedFloat64ToInt32(
     958             :     CheckForMinusZeroMode mode) {
     959        4920 :   switch (mode) {
     960             :     case CheckForMinusZeroMode::kCheckForMinusZero:
     961        2290 :       return &cache_.kCheckedFloat64ToInt32CheckForMinusZeroOperator;
     962             :     case CheckForMinusZeroMode::kDontCheckForMinusZero:
     963        2630 :       return &cache_.kCheckedFloat64ToInt32DontCheckForMinusZeroOperator;
     964             :   }
     965           0 :   UNREACHABLE();
     966             : }
     967             : 
     968        3651 : const Operator* SimplifiedOperatorBuilder::CheckedTaggedToInt32(
     969             :     CheckForMinusZeroMode mode) {
     970        3651 :   switch (mode) {
     971             :     case CheckForMinusZeroMode::kCheckForMinusZero:
     972           0 :       return &cache_.kCheckedTaggedToInt32CheckForMinusZeroOperator;
     973             :     case CheckForMinusZeroMode::kDontCheckForMinusZero:
     974        3651 :       return &cache_.kCheckedTaggedToInt32DontCheckForMinusZeroOperator;
     975             :   }
     976           0 :   UNREACHABLE();
     977             : }
     978             : 
     979       22842 : const Operator* SimplifiedOperatorBuilder::CheckedTaggedToFloat64(
     980             :     CheckTaggedInputMode mode) {
     981       22842 :   switch (mode) {
     982             :     case CheckTaggedInputMode::kNumber:
     983        8532 :       return &cache_.kCheckedTaggedToFloat64NumberOperator;
     984             :     case CheckTaggedInputMode::kNumberOrOddball:
     985       14310 :       return &cache_.kCheckedTaggedToFloat64NumberOrOddballOperator;
     986             :   }
     987           0 :   UNREACHABLE();
     988             : }
     989             : 
     990        2445 : const Operator* SimplifiedOperatorBuilder::CheckedTruncateTaggedToWord32(
     991             :     CheckTaggedInputMode mode) {
     992        2445 :   switch (mode) {
     993             :     case CheckTaggedInputMode::kNumber:
     994        1686 :       return &cache_.kCheckedTruncateTaggedToWord32NumberOperator;
     995             :     case CheckTaggedInputMode::kNumberOrOddball:
     996         759 :       return &cache_.kCheckedTruncateTaggedToWord32NumberOrOddballOperator;
     997             :   }
     998           0 :   UNREACHABLE();
     999             : }
    1000             : 
    1001       84532 : const Operator* SimplifiedOperatorBuilder::CheckMaps(CheckMapsFlags flags,
    1002       84532 :                                                      ZoneHandleSet<Map> maps) {
    1003             :   CheckMapsParameters const parameters(flags, maps);
    1004             :   return new (zone()) Operator1<CheckMapsParameters>(  // --
    1005             :       IrOpcode::kCheckMaps,                            // opcode
    1006             :       Operator::kNoThrow | Operator::kNoWrite,         // flags
    1007             :       "CheckMaps",                                     // name
    1008             :       1, 1, 1, 0, 1, 0,                                // counts
    1009      169064 :       parameters);                                     // parameter
    1010             : }
    1011             : 
    1012       16978 : const Operator* SimplifiedOperatorBuilder::MapGuard(ZoneHandleSet<Map> maps) {
    1013             :   return new (zone()) Operator1<MapsParameterInfo>(  // --
    1014             :       IrOpcode::kMapGuard, Operator::kEliminatable,  // opcode
    1015             :       "MapGuard",                                    // name
    1016             :       1, 1, 1, 0, 1, 0,                              // counts
    1017       16978 :       MapsParameterInfo(maps));                      // parameter
    1018             : }
    1019             : 
    1020        8907 : const Operator* SimplifiedOperatorBuilder::CompareMaps(
    1021        8907 :     ZoneHandleSet<Map> maps) {
    1022             :   return new (zone()) Operator1<MapsParameterInfo>(  // --
    1023             :       IrOpcode::kCompareMaps,                        // opcode
    1024             :       Operator::kEliminatable,                       // flags
    1025             :       "CompareMaps",                                 // name
    1026             :       1, 1, 1, 1, 1, 0,                              // counts
    1027       17814 :       MapsParameterInfo(maps));                      // parameter
    1028             : }
    1029             : 
    1030         775 : const Operator* SimplifiedOperatorBuilder::CheckFloat64Hole(
    1031             :     CheckFloat64HoleMode mode) {
    1032         775 :   switch (mode) {
    1033             :     case CheckFloat64HoleMode::kAllowReturnHole:
    1034         723 :       return &cache_.kCheckFloat64HoleAllowReturnHoleOperator;
    1035             :     case CheckFloat64HoleMode::kNeverReturnHole:
    1036          52 :       return &cache_.kCheckFloat64HoleNeverReturnHoleOperator;
    1037             :   }
    1038           0 :   UNREACHABLE();
    1039             : }
    1040             : 
    1041       24311 : const Operator* SimplifiedOperatorBuilder::SpeculativeToNumber(
    1042             :     NumberOperationHint hint) {
    1043       24311 :   switch (hint) {
    1044             :     case NumberOperationHint::kSignedSmall:
    1045       12505 :       return &cache_.kSpeculativeToNumberSignedSmallOperator;
    1046             :     case NumberOperationHint::kSignedSmallInputs:
    1047             :       break;
    1048             :     case NumberOperationHint::kSigned32:
    1049           0 :       return &cache_.kSpeculativeToNumberSigned32Operator;
    1050             :     case NumberOperationHint::kNumber:
    1051        7421 :       return &cache_.kSpeculativeToNumberNumberOperator;
    1052             :     case NumberOperationHint::kNumberOrOddball:
    1053        4385 :       return &cache_.kSpeculativeToNumberNumberOrOddballOperator;
    1054             :   }
    1055           0 :   UNREACHABLE();
    1056             : }
    1057             : 
    1058         348 : const Operator* SimplifiedOperatorBuilder::EnsureWritableFastElements() {
    1059         348 :   return &cache_.kEnsureWritableFastElements;
    1060             : }
    1061             : 
    1062        2122 : const Operator* SimplifiedOperatorBuilder::MaybeGrowFastElements(
    1063        2122 :     GrowFastElementsMode mode) {
    1064             :   return new (zone()) Operator1<GrowFastElementsMode>(  // --
    1065             :       IrOpcode::kMaybeGrowFastElements,                 // opcode
    1066             :       Operator::kNoThrow,                               // flags
    1067             :       "MaybeGrowFastElements",                          // name
    1068             :       4, 1, 1, 1, 1, 0,                                 // counts
    1069        2122 :       mode);                                            // parameter
    1070             : }
    1071             : 
    1072         619 : const Operator* SimplifiedOperatorBuilder::TransitionElementsKind(
    1073         619 :     ElementsTransition transition) {
    1074             :   return new (zone()) Operator1<ElementsTransition>(  // --
    1075             :       IrOpcode::kTransitionElementsKind,              // opcode
    1076             :       Operator::kNoDeopt | Operator::kNoThrow,        // flags
    1077             :       "TransitionElementsKind",                       // name
    1078             :       1, 1, 1, 0, 1, 0,                               // counts
    1079        1238 :       transition);                                    // parameter
    1080             : }
    1081             : 
    1082      208666 : const Operator* SimplifiedOperatorBuilder::ToBoolean(ToBooleanHints hints) {
    1083             :   // TODO(turbofan): Cache most important versions of this operator.
    1084             :   return new (zone()) Operator1<ToBooleanHints>(  //--
    1085             :       IrOpcode::kToBoolean, Operator::kPure,      // opcode
    1086             :       "ToBoolean",                                // name
    1087             :       1, 0, 0, 1, 0, 0,                           // inputs/outputs
    1088      208666 :       hints);                                     // parameter
    1089             : }
    1090             : 
    1091             : namespace {
    1092             : 
    1093             : struct ArgumentsLengthParameters {
    1094             :   int formal_parameter_count;
    1095             :   bool is_rest_length;
    1096             : };
    1097             : 
    1098             : bool operator==(ArgumentsLengthParameters first,
    1099             :                 ArgumentsLengthParameters second) {
    1100           0 :   return first.formal_parameter_count == second.formal_parameter_count &&
    1101             :          first.is_rest_length == second.is_rest_length;
    1102             : }
    1103             : 
    1104       41550 : size_t hash_value(ArgumentsLengthParameters param) {
    1105       41550 :   return base::hash_combine(param.formal_parameter_count, param.is_rest_length);
    1106             : }
    1107             : 
    1108           0 : std::ostream& operator<<(std::ostream& os, ArgumentsLengthParameters param) {
    1109           0 :   return os << param.formal_parameter_count << ", "
    1110           0 :             << (param.is_rest_length ? "rest length" : "not rest length");
    1111             : }
    1112             : 
    1113             : }  // namespace
    1114             : 
    1115       16652 : const Operator* SimplifiedOperatorBuilder::ArgumentsLength(
    1116       16652 :     int formal_parameter_count, bool is_rest_length) {
    1117             :   return new (zone()) Operator1<ArgumentsLengthParameters>(  // --
    1118             :       IrOpcode::kArgumentsLength,                            // opcode
    1119             :       Operator::kPure,                                       // flags
    1120             :       "ArgumentsLength",                                     // name
    1121             :       1, 0, 0, 1, 0, 0,                                      // counts
    1122             :       ArgumentsLengthParameters{formal_parameter_count,
    1123       33304 :                                 is_rest_length});  // parameter
    1124             : }
    1125             : 
    1126       15855 : int FormalParameterCountOf(const Operator* op) {
    1127             :   DCHECK_EQ(IrOpcode::kArgumentsLength, op->opcode());
    1128       15855 :   return OpParameter<ArgumentsLengthParameters>(op).formal_parameter_count;
    1129             : }
    1130             : 
    1131       34052 : bool IsRestLengthOf(const Operator* op) {
    1132             :   DCHECK_EQ(IrOpcode::kArgumentsLength, op->opcode());
    1133       34052 :   return OpParameter<ArgumentsLengthParameters>(op).is_rest_length;
    1134             : }
    1135             : 
    1136          32 : const Operator* SimplifiedOperatorBuilder::NewDoubleElements(
    1137          32 :     PretenureFlag pretenure) {
    1138             :   return new (zone()) Operator1<PretenureFlag>(  // --
    1139             :       IrOpcode::kNewDoubleElements,              // opcode
    1140             :       Operator::kEliminatable,                   // flags
    1141             :       "NewDoubleElements",                       // name
    1142             :       1, 1, 1, 1, 1, 0,                          // counts
    1143          32 :       pretenure);                                // parameter
    1144             : }
    1145             : 
    1146         307 : const Operator* SimplifiedOperatorBuilder::NewSmiOrObjectElements(
    1147         307 :     PretenureFlag pretenure) {
    1148             :   return new (zone()) Operator1<PretenureFlag>(  // --
    1149             :       IrOpcode::kNewSmiOrObjectElements,         // opcode
    1150             :       Operator::kEliminatable,                   // flags
    1151             :       "NewSmiOrObjectElements",                  // name
    1152             :       1, 1, 1, 1, 1, 0,                          // counts
    1153         307 :       pretenure);                                // parameter
    1154             : }
    1155             : 
    1156       16652 : const Operator* SimplifiedOperatorBuilder::NewArgumentsElements(
    1157       16652 :     int mapped_count) {
    1158             :   return new (zone()) Operator1<int>(   // --
    1159             :       IrOpcode::kNewArgumentsElements,  // opcode
    1160             :       Operator::kEliminatable,          // flags
    1161             :       "NewArgumentsElements",           // name
    1162             :       2, 1, 0, 1, 1, 0,                 // counts
    1163       16652 :       mapped_count);                    // parameter
    1164             : }
    1165             : 
    1166      165037 : const Operator* SimplifiedOperatorBuilder::Allocate(Type* type,
    1167      165037 :                                                     PretenureFlag pretenure) {
    1168             :   return new (zone()) Operator1<AllocateParameters>(
    1169             :       IrOpcode::kAllocate,
    1170             :       Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite, "Allocate",
    1171      165037 :       1, 1, 1, 1, 1, 0, AllocateParameters(type, pretenure));
    1172             : }
    1173             : 
    1174          32 : const Operator* SimplifiedOperatorBuilder::StringFromCodePoint(
    1175             :     UnicodeEncoding encoding) {
    1176          32 :   switch (encoding) {
    1177             :     case UnicodeEncoding::UTF16:
    1178          32 :       return &cache_.kStringFromCodePointOperatorUTF16;
    1179             :     case UnicodeEncoding::UTF32:
    1180           0 :       return &cache_.kStringFromCodePointOperatorUTF32;
    1181             :   }
    1182           0 :   UNREACHABLE();
    1183             : }
    1184             : 
    1185             : #define SPECULATIVE_NUMBER_BINOP(Name)                                        \
    1186             :   const Operator* SimplifiedOperatorBuilder::Name(NumberOperationHint hint) { \
    1187             :     switch (hint) {                                                           \
    1188             :       case NumberOperationHint::kSignedSmall:                                 \
    1189             :         return &cache_.k##Name##SignedSmallOperator;                          \
    1190             :       case NumberOperationHint::kSignedSmallInputs:                           \
    1191             :         return &cache_.k##Name##SignedSmallInputsOperator;                    \
    1192             :       case NumberOperationHint::kSigned32:                                    \
    1193             :         return &cache_.k##Name##Signed32Operator;                             \
    1194             :       case NumberOperationHint::kNumber:                                      \
    1195             :         return &cache_.k##Name##NumberOperator;                               \
    1196             :       case NumberOperationHint::kNumberOrOddball:                             \
    1197             :         return &cache_.k##Name##NumberOrOddballOperator;                      \
    1198             :     }                                                                         \
    1199             :     UNREACHABLE();                                                            \
    1200             :     return nullptr;                                                           \
    1201             :   }
    1202      351972 : SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP)
    1203             : #undef SPECULATIVE_NUMBER_BINOP
    1204             : 
    1205             : #define ACCESS_OP_LIST(V)                                             \
    1206             :   V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1)              \
    1207             :   V(StoreField, FieldAccess, Operator::kNoRead, 2, 1, 0)              \
    1208             :   V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1)          \
    1209             :   V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0)          \
    1210             :   V(LoadTypedElement, ExternalArrayType, Operator::kNoWrite, 4, 1, 1) \
    1211             :   V(StoreTypedElement, ExternalArrayType, Operator::kNoRead, 5, 1, 0)
    1212             : 
    1213             : #define ACCESS(Name, Type, properties, value_input_count, control_input_count, \
    1214             :                output_count)                                                   \
    1215             :   const Operator* SimplifiedOperatorBuilder::Name(const Type& access) {        \
    1216             :     return new (zone())                                                        \
    1217             :         Operator1<Type>(IrOpcode::k##Name,                                     \
    1218             :                         Operator::kNoDeopt | Operator::kNoThrow | properties,  \
    1219             :                         #Name, value_input_count, 1, control_input_count,      \
    1220             :                         output_count, 1, 0, access);                           \
    1221             :   }
    1222     7332309 : ACCESS_OP_LIST(ACCESS)
    1223             : #undef ACCESS
    1224             : 
    1225         173 : const Operator* SimplifiedOperatorBuilder::TransitionAndStoreElement(
    1226         173 :     Handle<Map> double_map, Handle<Map> fast_map) {
    1227             :   TransitionAndStoreElementParameters parameters(double_map, fast_map);
    1228             :   return new (zone()) Operator1<TransitionAndStoreElementParameters>(
    1229             :       IrOpcode::kTransitionAndStoreElement,
    1230             :       Operator::kNoDeopt | Operator::kNoThrow, "TransitionAndStoreElement", 3,
    1231         173 :       1, 1, 0, 1, 0, parameters);
    1232             : }
    1233             : 
    1234         122 : const Operator* SimplifiedOperatorBuilder::StoreSignedSmallElement() {
    1235             :   return new (zone()) Operator(IrOpcode::kStoreSignedSmallElement,
    1236         122 :                                Operator::kNoDeopt | Operator::kNoThrow,
    1237         122 :                                "StoreSignedSmallElement", 3, 1, 1, 0, 1, 0);
    1238             : }
    1239             : 
    1240          20 : const Operator* SimplifiedOperatorBuilder::TransitionAndStoreNumberElement(
    1241          20 :     Handle<Map> double_map) {
    1242             :   TransitionAndStoreNumberElementParameters parameters(double_map);
    1243             :   return new (zone()) Operator1<TransitionAndStoreNumberElementParameters>(
    1244             :       IrOpcode::kTransitionAndStoreNumberElement,
    1245             :       Operator::kNoDeopt | Operator::kNoThrow,
    1246          20 :       "TransitionAndStoreNumberElement", 3, 1, 1, 0, 1, 0, parameters);
    1247             : }
    1248             : 
    1249           6 : const Operator* SimplifiedOperatorBuilder::TransitionAndStoreNonNumberElement(
    1250           6 :     Handle<Map> fast_map, Type* value_type) {
    1251             :   TransitionAndStoreNonNumberElementParameters parameters(fast_map, value_type);
    1252             :   return new (zone()) Operator1<TransitionAndStoreNonNumberElementParameters>(
    1253             :       IrOpcode::kTransitionAndStoreNonNumberElement,
    1254             :       Operator::kNoDeopt | Operator::kNoThrow,
    1255           6 :       "TransitionAndStoreNonNumberElement", 3, 1, 1, 0, 1, 0, parameters);
    1256             : }
    1257             : 
    1258             : #undef PURE_OP_LIST
    1259             : #undef SPECULATIVE_NUMBER_BINOP_LIST
    1260             : #undef CHECKED_OP_LIST
    1261             : #undef ACCESS_OP_LIST
    1262             : 
    1263             : }  // namespace compiler
    1264             : }  // namespace internal
    1265             : }  // namespace v8

Generated by: LCOV version 1.10