• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "include/v8-fast-api-calls.h"
8 #include "src/base/lazy-instance.h"
9 #include "src/compiler/linkage.h"
10 #include "src/compiler/opcodes.h"
11 #include "src/compiler/operator.h"
12 #include "src/compiler/types.h"
13 #include "src/handles/handles-inl.h"
14 #include "src/objects/feedback-cell.h"
15 #include "src/objects/map.h"
16 #include "src/objects/name.h"
17 #include "src/objects/objects-inl.h"
18 
19 namespace v8 {
20 namespace internal {
21 namespace compiler {
22 
hash_value(BaseTaggedness base_taggedness)23 size_t hash_value(BaseTaggedness base_taggedness) {
24   return static_cast<uint8_t>(base_taggedness);
25 }
26 
operator <<(std::ostream & os,BaseTaggedness base_taggedness)27 std::ostream& operator<<(std::ostream& os, BaseTaggedness base_taggedness) {
28   switch (base_taggedness) {
29     case kUntaggedBase:
30       return os << "untagged base";
31     case kTaggedBase:
32       return os << "tagged base";
33   }
34   UNREACHABLE();
35 }
36 
operator <<(std::ostream & os,ConstFieldInfo const & const_field_info)37 std::ostream& operator<<(std::ostream& os,
38                          ConstFieldInfo const& const_field_info) {
39   if (const_field_info.IsConst()) {
40     return os << "const (field owner: "
41               << Brief(*const_field_info.owner_map.ToHandleChecked()) << ")";
42   } else {
43     return os << "mutable";
44   }
45   UNREACHABLE();
46 }
47 
operator ==(ConstFieldInfo const & lhs,ConstFieldInfo const & rhs)48 bool operator==(ConstFieldInfo const& lhs, ConstFieldInfo const& rhs) {
49   return lhs.owner_map.address() == rhs.owner_map.address();
50 }
51 
hash_value(ConstFieldInfo const & const_field_info)52 size_t hash_value(ConstFieldInfo const& const_field_info) {
53   return static_cast<size_t>(const_field_info.owner_map.address());
54 }
55 
operator ==(FieldAccess const & lhs,FieldAccess const & rhs)56 bool operator==(FieldAccess const& lhs, FieldAccess const& rhs) {
57   // On purpose we don't include the write barrier kind here, as this method is
58   // really only relevant for eliminating loads and they don't care about the
59   // write barrier mode.
60   return lhs.base_is_tagged == rhs.base_is_tagged && lhs.offset == rhs.offset &&
61          lhs.map.address() == rhs.map.address() &&
62          lhs.machine_type == rhs.machine_type &&
63          lhs.const_field_info == rhs.const_field_info &&
64          lhs.is_store_in_literal == rhs.is_store_in_literal;
65 }
66 
hash_value(FieldAccess const & access)67 size_t hash_value(FieldAccess const& access) {
68   // On purpose we don't include the write barrier kind here, as this method is
69   // really only relevant for eliminating loads and they don't care about the
70   // write barrier mode.
71   return base::hash_combine(access.base_is_tagged, access.offset,
72                             access.machine_type, access.const_field_info,
73                             access.is_store_in_literal);
74 }
75 
operator <<(std::ostream & os,FieldAccess const & access)76 std::ostream& operator<<(std::ostream& os, FieldAccess const& access) {
77   os << "[" << access.base_is_tagged << ", " << access.offset << ", ";
78 #ifdef OBJECT_PRINT
79   Handle<Name> name;
80   if (access.name.ToHandle(&name)) {
81     name->NamePrint(os);
82     os << ", ";
83   }
84   Handle<Map> map;
85   if (access.map.ToHandle(&map)) {
86     os << Brief(*map) << ", ";
87   }
88 #endif
89   os << access.type << ", " << access.machine_type << ", "
90      << access.write_barrier_kind << ", " << access.const_field_info;
91   if (access.is_store_in_literal) {
92     os << " (store in literal)";
93   }
94   if (access.maybe_initializing_or_transitioning_store) {
95     os << " (initializing or transitioning store)";
96   }
97   os << "]";
98   return os;
99 }
100 
101 template <>
PrintParameter(std::ostream & os,PrintVerbosity verbose) const102 void Operator1<FieldAccess>::PrintParameter(std::ostream& os,
103                                             PrintVerbosity verbose) const {
104   if (verbose == PrintVerbosity::kVerbose) {
105     os << parameter();
106   } else {
107     os << "[+" << parameter().offset << "]";
108   }
109 }
110 
operator ==(ElementAccess const & lhs,ElementAccess const & rhs)111 bool operator==(ElementAccess const& lhs, ElementAccess const& rhs) {
112   // On purpose we don't include the write barrier kind here, as this method is
113   // really only relevant for eliminating loads and they don't care about the
114   // write barrier mode.
115   return lhs.base_is_tagged == rhs.base_is_tagged &&
116          lhs.header_size == rhs.header_size &&
117          lhs.machine_type == rhs.machine_type;
118 }
119 
hash_value(ElementAccess const & access)120 size_t hash_value(ElementAccess const& access) {
121   // On purpose we don't include the write barrier kind here, as this method is
122   // really only relevant for eliminating loads and they don't care about the
123   // write barrier mode.
124   return base::hash_combine(access.base_is_tagged, access.header_size,
125                             access.machine_type);
126 }
127 
operator <<(std::ostream & os,ElementAccess const & access)128 std::ostream& operator<<(std::ostream& os, ElementAccess const& access) {
129   os << access.base_is_tagged << ", " << access.header_size << ", "
130      << access.type << ", " << access.machine_type << ", "
131      << access.write_barrier_kind;
132   return os;
133 }
134 
operator ==(ObjectAccess const & lhs,ObjectAccess const & rhs)135 bool operator==(ObjectAccess const& lhs, ObjectAccess const& rhs) {
136   return lhs.machine_type == rhs.machine_type &&
137          lhs.write_barrier_kind == rhs.write_barrier_kind;
138 }
139 
hash_value(ObjectAccess const & access)140 size_t hash_value(ObjectAccess const& access) {
141   return base::hash_combine(access.machine_type, access.write_barrier_kind);
142 }
143 
operator <<(std::ostream & os,ObjectAccess const & access)144 std::ostream& operator<<(std::ostream& os, ObjectAccess const& access) {
145   os << access.machine_type << ", " << access.write_barrier_kind;
146   return os;
147 }
148 
FieldAccessOf(const Operator * op)149 const FieldAccess& FieldAccessOf(const Operator* op) {
150   DCHECK_NOT_NULL(op);
151   DCHECK(op->opcode() == IrOpcode::kLoadField ||
152          op->opcode() == IrOpcode::kStoreField);
153   return OpParameter<FieldAccess>(op);
154 }
155 
ElementAccessOf(const Operator * op)156 const ElementAccess& ElementAccessOf(const Operator* op) {
157   DCHECK_NOT_NULL(op);
158   DCHECK(op->opcode() == IrOpcode::kLoadElement ||
159          op->opcode() == IrOpcode::kStoreElement);
160   return OpParameter<ElementAccess>(op);
161 }
162 
ObjectAccessOf(const Operator * op)163 const ObjectAccess& ObjectAccessOf(const Operator* op) {
164   DCHECK_NOT_NULL(op);
165   DCHECK(op->opcode() == IrOpcode::kLoadFromObject ||
166          op->opcode() == IrOpcode::kLoadImmutableFromObject ||
167          op->opcode() == IrOpcode::kStoreToObject ||
168          op->opcode() == IrOpcode::kInitializeImmutableInObject);
169   return OpParameter<ObjectAccess>(op);
170 }
171 
ExternalArrayTypeOf(const Operator * op)172 ExternalArrayType ExternalArrayTypeOf(const Operator* op) {
173   DCHECK(op->opcode() == IrOpcode::kLoadTypedElement ||
174          op->opcode() == IrOpcode::kLoadDataViewElement ||
175          op->opcode() == IrOpcode::kStoreTypedElement ||
176          op->opcode() == IrOpcode::kStoreDataViewElement);
177   return OpParameter<ExternalArrayType>(op);
178 }
179 
ConvertReceiverModeOf(Operator const * op)180 ConvertReceiverMode ConvertReceiverModeOf(Operator const* op) {
181   DCHECK_EQ(IrOpcode::kConvertReceiver, op->opcode());
182   return OpParameter<ConvertReceiverMode>(op);
183 }
184 
hash_value(CheckFloat64HoleMode mode)185 size_t hash_value(CheckFloat64HoleMode mode) {
186   return static_cast<size_t>(mode);
187 }
188 
operator <<(std::ostream & os,CheckFloat64HoleMode mode)189 std::ostream& operator<<(std::ostream& os, CheckFloat64HoleMode mode) {
190   switch (mode) {
191     case CheckFloat64HoleMode::kAllowReturnHole:
192       return os << "allow-return-hole";
193     case CheckFloat64HoleMode::kNeverReturnHole:
194       return os << "never-return-hole";
195   }
196   UNREACHABLE();
197 }
198 
CheckFloat64HoleParametersOf(Operator const * op)199 CheckFloat64HoleParameters const& CheckFloat64HoleParametersOf(
200     Operator const* op) {
201   DCHECK_EQ(IrOpcode::kCheckFloat64Hole, op->opcode());
202   return OpParameter<CheckFloat64HoleParameters>(op);
203 }
204 
operator <<(std::ostream & os,CheckFloat64HoleParameters const & params)205 std::ostream& operator<<(std::ostream& os,
206                          CheckFloat64HoleParameters const& params) {
207   return os << params.mode() << ", " << params.feedback();
208 }
209 
hash_value(const CheckFloat64HoleParameters & params)210 size_t hash_value(const CheckFloat64HoleParameters& params) {
211   FeedbackSource::Hash feedback_hash;
212   return base::hash_combine(params.mode(), feedback_hash(params.feedback()));
213 }
214 
operator ==(CheckFloat64HoleParameters const & lhs,CheckFloat64HoleParameters const & rhs)215 bool operator==(CheckFloat64HoleParameters const& lhs,
216                 CheckFloat64HoleParameters const& rhs) {
217   return lhs.mode() == rhs.mode() && lhs.feedback() == rhs.feedback();
218 }
219 
operator !=(CheckFloat64HoleParameters const & lhs,CheckFloat64HoleParameters const & rhs)220 bool operator!=(CheckFloat64HoleParameters const& lhs,
221                 CheckFloat64HoleParameters const& rhs) {
222   return !(lhs == rhs);
223 }
224 
CheckMinusZeroModeOf(const Operator * op)225 CheckForMinusZeroMode CheckMinusZeroModeOf(const Operator* op) {
226   DCHECK(op->opcode() == IrOpcode::kChangeFloat64ToTagged ||
227          op->opcode() == IrOpcode::kCheckedInt32Mul);
228   return OpParameter<CheckForMinusZeroMode>(op);
229 }
230 
hash_value(CheckForMinusZeroMode mode)231 size_t hash_value(CheckForMinusZeroMode mode) {
232   return static_cast<size_t>(mode);
233 }
234 
operator <<(std::ostream & os,CheckForMinusZeroMode mode)235 std::ostream& operator<<(std::ostream& os, CheckForMinusZeroMode mode) {
236   switch (mode) {
237     case CheckForMinusZeroMode::kCheckForMinusZero:
238       return os << "check-for-minus-zero";
239     case CheckForMinusZeroMode::kDontCheckForMinusZero:
240       return os << "dont-check-for-minus-zero";
241   }
242   UNREACHABLE();
243 }
244 
operator <<(std::ostream & os,CheckMapsFlags flags)245 std::ostream& operator<<(std::ostream& os, CheckMapsFlags flags) {
246   if (flags & CheckMapsFlag::kTryMigrateInstance) {
247     return os << "TryMigrateInstance";
248   } else {
249     return os << "None";
250   }
251 }
252 
operator ==(CheckMapsParameters const & lhs,CheckMapsParameters const & rhs)253 bool operator==(CheckMapsParameters const& lhs,
254                 CheckMapsParameters const& rhs) {
255   return lhs.flags() == rhs.flags() && lhs.maps() == rhs.maps() &&
256          lhs.feedback() == rhs.feedback();
257 }
258 
hash_value(CheckMapsParameters const & p)259 size_t hash_value(CheckMapsParameters const& p) {
260   FeedbackSource::Hash feedback_hash;
261   return base::hash_combine(p.flags(), p.maps(), feedback_hash(p.feedback()));
262 }
263 
operator <<(std::ostream & os,CheckMapsParameters const & p)264 std::ostream& operator<<(std::ostream& os, CheckMapsParameters const& p) {
265   return os << p.flags() << ", " << p.maps() << ", " << p.feedback();
266 }
267 
CheckMapsParametersOf(Operator const * op)268 CheckMapsParameters const& CheckMapsParametersOf(Operator const* op) {
269   DCHECK_EQ(IrOpcode::kCheckMaps, op->opcode());
270   return OpParameter<CheckMapsParameters>(op);
271 }
272 
CompareMapsParametersOf(Operator const * op)273 ZoneHandleSet<Map> const& CompareMapsParametersOf(Operator const* op) {
274   DCHECK_EQ(IrOpcode::kCompareMaps, op->opcode());
275   return OpParameter<ZoneHandleSet<Map>>(op);
276 }
277 
MapGuardMapsOf(Operator const * op)278 ZoneHandleSet<Map> const& MapGuardMapsOf(Operator const* op) {
279   DCHECK_EQ(IrOpcode::kMapGuard, op->opcode());
280   return OpParameter<ZoneHandleSet<Map>>(op);
281 }
282 
hash_value(CheckTaggedInputMode mode)283 size_t hash_value(CheckTaggedInputMode mode) {
284   return static_cast<size_t>(mode);
285 }
286 
operator <<(std::ostream & os,CheckTaggedInputMode mode)287 std::ostream& operator<<(std::ostream& os, CheckTaggedInputMode mode) {
288   switch (mode) {
289     case CheckTaggedInputMode::kNumber:
290       return os << "Number";
291     case CheckTaggedInputMode::kNumberOrBoolean:
292       return os << "NumberOrBoolean";
293     case CheckTaggedInputMode::kNumberOrOddball:
294       return os << "NumberOrOddball";
295   }
296   UNREACHABLE();
297 }
298 
operator <<(std::ostream & os,GrowFastElementsMode mode)299 std::ostream& operator<<(std::ostream& os, GrowFastElementsMode mode) {
300   switch (mode) {
301     case GrowFastElementsMode::kDoubleElements:
302       return os << "DoubleElements";
303     case GrowFastElementsMode::kSmiOrObjectElements:
304       return os << "SmiOrObjectElements";
305   }
306   UNREACHABLE();
307 }
308 
operator ==(const GrowFastElementsParameters & lhs,const GrowFastElementsParameters & rhs)309 bool operator==(const GrowFastElementsParameters& lhs,
310                 const GrowFastElementsParameters& rhs) {
311   return lhs.mode() == rhs.mode() && lhs.feedback() == rhs.feedback();
312 }
313 
hash_value(const GrowFastElementsParameters & params)314 inline size_t hash_value(const GrowFastElementsParameters& params) {
315   FeedbackSource::Hash feedback_hash;
316   return base::hash_combine(params.mode(), feedback_hash(params.feedback()));
317 }
318 
operator <<(std::ostream & os,const GrowFastElementsParameters & params)319 std::ostream& operator<<(std::ostream& os,
320                          const GrowFastElementsParameters& params) {
321   return os << params.mode() << ", " << params.feedback();
322 }
323 
GrowFastElementsParametersOf(const Operator * op)324 const GrowFastElementsParameters& GrowFastElementsParametersOf(
325     const Operator* op) {
326   DCHECK_EQ(IrOpcode::kMaybeGrowFastElements, op->opcode());
327   return OpParameter<GrowFastElementsParameters>(op);
328 }
329 
operator ==(ElementsTransition const & lhs,ElementsTransition const & rhs)330 bool operator==(ElementsTransition const& lhs, ElementsTransition const& rhs) {
331   return lhs.mode() == rhs.mode() &&
332          lhs.source().address() == rhs.source().address() &&
333          lhs.target().address() == rhs.target().address();
334 }
335 
hash_value(ElementsTransition transition)336 size_t hash_value(ElementsTransition transition) {
337   return base::hash_combine(static_cast<uint8_t>(transition.mode()),
338                             transition.source().address(),
339                             transition.target().address());
340 }
341 
operator <<(std::ostream & os,ElementsTransition transition)342 std::ostream& operator<<(std::ostream& os, ElementsTransition transition) {
343   switch (transition.mode()) {
344     case ElementsTransition::kFastTransition:
345       return os << "fast-transition from " << Brief(*transition.source())
346                 << " to " << Brief(*transition.target());
347     case ElementsTransition::kSlowTransition:
348       return os << "slow-transition from " << Brief(*transition.source())
349                 << " to " << Brief(*transition.target());
350   }
351   UNREACHABLE();
352 }
353 
ElementsTransitionOf(const Operator * op)354 ElementsTransition const& ElementsTransitionOf(const Operator* op) {
355   DCHECK_EQ(IrOpcode::kTransitionElementsKind, op->opcode());
356   return OpParameter<ElementsTransition>(op);
357 }
358 
359 namespace {
360 
361 // Parameters for the TransitionAndStoreElement opcode.
362 class TransitionAndStoreElementParameters final {
363  public:
364   TransitionAndStoreElementParameters(Handle<Map> double_map,
365                                       Handle<Map> fast_map);
366 
double_map() const367   Handle<Map> double_map() const { return double_map_; }
fast_map() const368   Handle<Map> fast_map() const { return fast_map_; }
369 
370  private:
371   Handle<Map> const double_map_;
372   Handle<Map> const fast_map_;
373 };
374 
TransitionAndStoreElementParameters(Handle<Map> double_map,Handle<Map> fast_map)375 TransitionAndStoreElementParameters::TransitionAndStoreElementParameters(
376     Handle<Map> double_map, Handle<Map> fast_map)
377     : double_map_(double_map), fast_map_(fast_map) {}
378 
operator ==(TransitionAndStoreElementParameters const & lhs,TransitionAndStoreElementParameters const & rhs)379 bool operator==(TransitionAndStoreElementParameters const& lhs,
380                 TransitionAndStoreElementParameters const& rhs) {
381   return lhs.fast_map().address() == rhs.fast_map().address() &&
382          lhs.double_map().address() == rhs.double_map().address();
383 }
384 
hash_value(TransitionAndStoreElementParameters parameters)385 size_t hash_value(TransitionAndStoreElementParameters parameters) {
386   return base::hash_combine(parameters.fast_map().address(),
387                             parameters.double_map().address());
388 }
389 
operator <<(std::ostream & os,TransitionAndStoreElementParameters parameters)390 std::ostream& operator<<(std::ostream& os,
391                          TransitionAndStoreElementParameters parameters) {
392   return os << "fast-map" << Brief(*parameters.fast_map()) << " double-map"
393             << Brief(*parameters.double_map());
394 }
395 
396 }  // namespace
397 
398 namespace {
399 
400 // Parameters for the TransitionAndStoreNonNumberElement opcode.
401 class TransitionAndStoreNonNumberElementParameters final {
402  public:
403   TransitionAndStoreNonNumberElementParameters(Handle<Map> fast_map,
404                                                Type value_type);
405 
fast_map() const406   Handle<Map> fast_map() const { return fast_map_; }
value_type() const407   Type value_type() const { return value_type_; }
408 
409  private:
410   Handle<Map> const fast_map_;
411   Type value_type_;
412 };
413 
414 TransitionAndStoreNonNumberElementParameters::
TransitionAndStoreNonNumberElementParameters(Handle<Map> fast_map,Type value_type)415     TransitionAndStoreNonNumberElementParameters(Handle<Map> fast_map,
416                                                  Type value_type)
417     : fast_map_(fast_map), value_type_(value_type) {}
418 
operator ==(TransitionAndStoreNonNumberElementParameters const & lhs,TransitionAndStoreNonNumberElementParameters const & rhs)419 bool operator==(TransitionAndStoreNonNumberElementParameters const& lhs,
420                 TransitionAndStoreNonNumberElementParameters const& rhs) {
421   return lhs.fast_map().address() == rhs.fast_map().address() &&
422          lhs.value_type() == rhs.value_type();
423 }
424 
hash_value(TransitionAndStoreNonNumberElementParameters parameters)425 size_t hash_value(TransitionAndStoreNonNumberElementParameters parameters) {
426   return base::hash_combine(parameters.fast_map().address(),
427                             parameters.value_type());
428 }
429 
operator <<(std::ostream & os,TransitionAndStoreNonNumberElementParameters parameters)430 std::ostream& operator<<(
431     std::ostream& os, TransitionAndStoreNonNumberElementParameters parameters) {
432   return os << parameters.value_type() << ", fast-map"
433             << Brief(*parameters.fast_map());
434 }
435 
436 }  // namespace
437 
438 namespace {
439 
440 // Parameters for the TransitionAndStoreNumberElement opcode.
441 class TransitionAndStoreNumberElementParameters final {
442  public:
443   explicit TransitionAndStoreNumberElementParameters(Handle<Map> double_map);
444 
double_map() const445   Handle<Map> double_map() const { return double_map_; }
446 
447  private:
448   Handle<Map> const double_map_;
449 };
450 
451 TransitionAndStoreNumberElementParameters::
TransitionAndStoreNumberElementParameters(Handle<Map> double_map)452     TransitionAndStoreNumberElementParameters(Handle<Map> double_map)
453     : double_map_(double_map) {}
454 
operator ==(TransitionAndStoreNumberElementParameters const & lhs,TransitionAndStoreNumberElementParameters const & rhs)455 bool operator==(TransitionAndStoreNumberElementParameters const& lhs,
456                 TransitionAndStoreNumberElementParameters const& rhs) {
457   return lhs.double_map().address() == rhs.double_map().address();
458 }
459 
hash_value(TransitionAndStoreNumberElementParameters parameters)460 size_t hash_value(TransitionAndStoreNumberElementParameters parameters) {
461   return base::hash_combine(parameters.double_map().address());
462 }
463 
operator <<(std::ostream & os,TransitionAndStoreNumberElementParameters parameters)464 std::ostream& operator<<(std::ostream& os,
465                          TransitionAndStoreNumberElementParameters parameters) {
466   return os << "double-map" << Brief(*parameters.double_map());
467 }
468 
469 }  // namespace
470 
DoubleMapParameterOf(const Operator * op)471 Handle<Map> DoubleMapParameterOf(const Operator* op) {
472   if (op->opcode() == IrOpcode::kTransitionAndStoreElement) {
473     return OpParameter<TransitionAndStoreElementParameters>(op).double_map();
474   } else if (op->opcode() == IrOpcode::kTransitionAndStoreNumberElement) {
475     return OpParameter<TransitionAndStoreNumberElementParameters>(op)
476         .double_map();
477   }
478   UNREACHABLE();
479 }
480 
ValueTypeParameterOf(const Operator * op)481 Type ValueTypeParameterOf(const Operator* op) {
482   DCHECK_EQ(IrOpcode::kTransitionAndStoreNonNumberElement, op->opcode());
483   return OpParameter<TransitionAndStoreNonNumberElementParameters>(op)
484       .value_type();
485 }
486 
FastMapParameterOf(const Operator * op)487 Handle<Map> FastMapParameterOf(const Operator* op) {
488   if (op->opcode() == IrOpcode::kTransitionAndStoreElement) {
489     return OpParameter<TransitionAndStoreElementParameters>(op).fast_map();
490   } else if (op->opcode() == IrOpcode::kTransitionAndStoreNonNumberElement) {
491     return OpParameter<TransitionAndStoreNonNumberElementParameters>(op)
492         .fast_map();
493   }
494   UNREACHABLE();
495 }
496 
operator <<(std::ostream & os,BigIntOperationHint hint)497 std::ostream& operator<<(std::ostream& os, BigIntOperationHint hint) {
498   switch (hint) {
499     case BigIntOperationHint::kBigInt:
500       return os << "BigInt";
501   }
502   UNREACHABLE();
503 }
504 
hash_value(BigIntOperationHint hint)505 size_t hash_value(BigIntOperationHint hint) {
506   return static_cast<uint8_t>(hint);
507 }
508 
operator <<(std::ostream & os,NumberOperationHint hint)509 std::ostream& operator<<(std::ostream& os, NumberOperationHint hint) {
510   switch (hint) {
511     case NumberOperationHint::kSignedSmall:
512       return os << "SignedSmall";
513     case NumberOperationHint::kSignedSmallInputs:
514       return os << "SignedSmallInputs";
515     case NumberOperationHint::kNumber:
516       return os << "Number";
517     case NumberOperationHint::kNumberOrBoolean:
518       return os << "NumberOrBoolean";
519     case NumberOperationHint::kNumberOrOddball:
520       return os << "NumberOrOddball";
521   }
522   UNREACHABLE();
523 }
524 
hash_value(NumberOperationHint hint)525 size_t hash_value(NumberOperationHint hint) {
526   return static_cast<uint8_t>(hint);
527 }
528 
NumberOperationHintOf(const Operator * op)529 NumberOperationHint NumberOperationHintOf(const Operator* op) {
530   DCHECK(op->opcode() == IrOpcode::kSpeculativeNumberAdd ||
531          op->opcode() == IrOpcode::kSpeculativeNumberSubtract ||
532          op->opcode() == IrOpcode::kSpeculativeNumberMultiply ||
533          op->opcode() == IrOpcode::kSpeculativeNumberPow ||
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 
operator ==(NumberOperationParameters const & lhs,NumberOperationParameters const & rhs)550 bool operator==(NumberOperationParameters const& lhs,
551                 NumberOperationParameters const& rhs) {
552   return lhs.hint() == rhs.hint() && lhs.feedback() == rhs.feedback();
553 }
554 
hash_value(NumberOperationParameters const & p)555 size_t hash_value(NumberOperationParameters const& p) {
556   FeedbackSource::Hash feedback_hash;
557   return base::hash_combine(p.hint(), feedback_hash(p.feedback()));
558 }
559 
operator <<(std::ostream & os,NumberOperationParameters const & p)560 std::ostream& operator<<(std::ostream& os, NumberOperationParameters const& p) {
561   return os << p.hint() << ", " << p.feedback();
562 }
563 
NumberOperationParametersOf(Operator const * op)564 NumberOperationParameters const& NumberOperationParametersOf(
565     Operator const* op) {
566   DCHECK_EQ(IrOpcode::kSpeculativeToNumber, op->opcode());
567   return OpParameter<NumberOperationParameters>(op);
568 }
569 
operator ==(SpeculativeBigIntAsNParameters const & lhs,SpeculativeBigIntAsNParameters const & rhs)570 bool operator==(SpeculativeBigIntAsNParameters const& lhs,
571                 SpeculativeBigIntAsNParameters const& rhs) {
572   return lhs.bits() == rhs.bits() && lhs.feedback() == rhs.feedback();
573 }
574 
hash_value(SpeculativeBigIntAsNParameters const & p)575 size_t hash_value(SpeculativeBigIntAsNParameters const& p) {
576   FeedbackSource::Hash feedback_hash;
577   return base::hash_combine(p.bits(), feedback_hash(p.feedback()));
578 }
579 
operator <<(std::ostream & os,SpeculativeBigIntAsNParameters const & p)580 std::ostream& operator<<(std::ostream& os,
581                          SpeculativeBigIntAsNParameters const& p) {
582   return os << p.bits() << ", " << p.feedback();
583 }
584 
SpeculativeBigIntAsNParametersOf(Operator const * op)585 SpeculativeBigIntAsNParameters const& SpeculativeBigIntAsNParametersOf(
586     Operator const* op) {
587   DCHECK(op->opcode() == IrOpcode::kSpeculativeBigIntAsUintN ||
588          op->opcode() == IrOpcode::kSpeculativeBigIntAsIntN);
589   return OpParameter<SpeculativeBigIntAsNParameters>(op);
590 }
591 
hash_value(AllocateParameters info)592 size_t hash_value(AllocateParameters info) {
593   return base::hash_combine(info.type(),
594                             static_cast<int>(info.allocation_type()));
595 }
596 
operator <<(std::ostream & os,AllocateParameters info)597 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
598                                            AllocateParameters info) {
599   return os << info.type() << ", " << info.allocation_type();
600 }
601 
operator ==(AllocateParameters const & lhs,AllocateParameters const & rhs)602 bool operator==(AllocateParameters const& lhs, AllocateParameters const& rhs) {
603   return lhs.allocation_type() == rhs.allocation_type() &&
604          lhs.type() == rhs.type();
605 }
606 
AllocateParametersOf(const Operator * op)607 const AllocateParameters& AllocateParametersOf(const Operator* op) {
608   DCHECK(op->opcode() == IrOpcode::kAllocate ||
609          op->opcode() == IrOpcode::kAllocateRaw);
610   return OpParameter<AllocateParameters>(op);
611 }
612 
AllocationTypeOf(const Operator * op)613 AllocationType AllocationTypeOf(const Operator* op) {
614   if (op->opcode() == IrOpcode::kNewDoubleElements ||
615       op->opcode() == IrOpcode::kNewSmiOrObjectElements) {
616     return OpParameter<AllocationType>(op);
617   }
618   return AllocateParametersOf(op).allocation_type();
619 }
620 
AllocateTypeOf(const Operator * op)621 Type AllocateTypeOf(const Operator* op) {
622   DCHECK_EQ(IrOpcode::kAllocate, op->opcode());
623   return AllocateParametersOf(op).type();
624 }
625 
AbortReasonOf(const Operator * op)626 AbortReason AbortReasonOf(const Operator* op) {
627   DCHECK_EQ(IrOpcode::kRuntimeAbort, op->opcode());
628   return static_cast<AbortReason>(OpParameter<int>(op));
629 }
630 
CheckTaggedInputParametersOf(const Operator * op)631 const CheckTaggedInputParameters& CheckTaggedInputParametersOf(
632     const Operator* op) {
633   DCHECK(op->opcode() == IrOpcode::kCheckedTruncateTaggedToWord32 ||
634          op->opcode() == IrOpcode::kCheckedTaggedToFloat64);
635   return OpParameter<CheckTaggedInputParameters>(op);
636 }
637 
operator <<(std::ostream & os,const CheckTaggedInputParameters & params)638 std::ostream& operator<<(std::ostream& os,
639                          const CheckTaggedInputParameters& params) {
640   return os << params.mode() << ", " << params.feedback();
641 }
642 
hash_value(const CheckTaggedInputParameters & params)643 size_t hash_value(const CheckTaggedInputParameters& params) {
644   FeedbackSource::Hash feedback_hash;
645   return base::hash_combine(params.mode(), feedback_hash(params.feedback()));
646 }
647 
operator ==(CheckTaggedInputParameters const & lhs,CheckTaggedInputParameters const & rhs)648 bool operator==(CheckTaggedInputParameters const& lhs,
649                 CheckTaggedInputParameters const& rhs) {
650   return lhs.mode() == rhs.mode() && lhs.feedback() == rhs.feedback();
651 }
652 
CheckMinusZeroParametersOf(const Operator * op)653 const CheckMinusZeroParameters& CheckMinusZeroParametersOf(const Operator* op) {
654   DCHECK(op->opcode() == IrOpcode::kCheckedTaggedToInt32 ||
655          op->opcode() == IrOpcode::kCheckedTaggedToInt64 ||
656          op->opcode() == IrOpcode::kCheckedFloat64ToInt32 ||
657          op->opcode() == IrOpcode::kCheckedFloat64ToInt64);
658   return OpParameter<CheckMinusZeroParameters>(op);
659 }
660 
operator <<(std::ostream & os,const CheckMinusZeroParameters & params)661 std::ostream& operator<<(std::ostream& os,
662                          const CheckMinusZeroParameters& params) {
663   return os << params.mode() << ", " << params.feedback();
664 }
665 
hash_value(const CheckMinusZeroParameters & params)666 size_t hash_value(const CheckMinusZeroParameters& params) {
667   FeedbackSource::Hash feedback_hash;
668   return base::hash_combine(params.mode(), feedback_hash(params.feedback()));
669 }
670 
operator ==(CheckMinusZeroParameters const & lhs,CheckMinusZeroParameters const & rhs)671 bool operator==(CheckMinusZeroParameters const& lhs,
672                 CheckMinusZeroParameters const& rhs) {
673   return lhs.mode() == rhs.mode() && lhs.feedback() == rhs.feedback();
674 }
675 
676 #define PURE_OP_LIST(V)                                          \
677   V(BooleanNot, Operator::kNoProperties, 1, 0)                   \
678   V(NumberEqual, Operator::kCommutative, 2, 0)                   \
679   V(NumberLessThan, Operator::kNoProperties, 2, 0)               \
680   V(NumberLessThanOrEqual, Operator::kNoProperties, 2, 0)        \
681   V(NumberAdd, Operator::kCommutative, 2, 0)                     \
682   V(NumberSubtract, Operator::kNoProperties, 2, 0)               \
683   V(NumberMultiply, Operator::kCommutative, 2, 0)                \
684   V(NumberDivide, Operator::kNoProperties, 2, 0)                 \
685   V(NumberModulus, Operator::kNoProperties, 2, 0)                \
686   V(NumberBitwiseOr, Operator::kCommutative, 2, 0)               \
687   V(NumberBitwiseXor, Operator::kCommutative, 2, 0)              \
688   V(NumberBitwiseAnd, Operator::kCommutative, 2, 0)              \
689   V(NumberShiftLeft, Operator::kNoProperties, 2, 0)              \
690   V(NumberShiftRight, Operator::kNoProperties, 2, 0)             \
691   V(NumberShiftRightLogical, Operator::kNoProperties, 2, 0)      \
692   V(NumberImul, Operator::kCommutative, 2, 0)                    \
693   V(NumberAbs, Operator::kNoProperties, 1, 0)                    \
694   V(NumberClz32, Operator::kNoProperties, 1, 0)                  \
695   V(NumberCeil, Operator::kNoProperties, 1, 0)                   \
696   V(NumberFloor, Operator::kNoProperties, 1, 0)                  \
697   V(NumberFround, Operator::kNoProperties, 1, 0)                 \
698   V(NumberAcos, Operator::kNoProperties, 1, 0)                   \
699   V(NumberAcosh, Operator::kNoProperties, 1, 0)                  \
700   V(NumberAsin, Operator::kNoProperties, 1, 0)                   \
701   V(NumberAsinh, Operator::kNoProperties, 1, 0)                  \
702   V(NumberAtan, Operator::kNoProperties, 1, 0)                   \
703   V(NumberAtan2, Operator::kNoProperties, 2, 0)                  \
704   V(NumberAtanh, Operator::kNoProperties, 1, 0)                  \
705   V(NumberCbrt, Operator::kNoProperties, 1, 0)                   \
706   V(NumberCos, Operator::kNoProperties, 1, 0)                    \
707   V(NumberCosh, Operator::kNoProperties, 1, 0)                   \
708   V(NumberExp, Operator::kNoProperties, 1, 0)                    \
709   V(NumberExpm1, Operator::kNoProperties, 1, 0)                  \
710   V(NumberLog, Operator::kNoProperties, 1, 0)                    \
711   V(NumberLog1p, Operator::kNoProperties, 1, 0)                  \
712   V(NumberLog10, Operator::kNoProperties, 1, 0)                  \
713   V(NumberLog2, Operator::kNoProperties, 1, 0)                   \
714   V(NumberMax, Operator::kNoProperties, 2, 0)                    \
715   V(NumberMin, Operator::kNoProperties, 2, 0)                    \
716   V(NumberPow, Operator::kNoProperties, 2, 0)                    \
717   V(NumberRound, Operator::kNoProperties, 1, 0)                  \
718   V(NumberSign, Operator::kNoProperties, 1, 0)                   \
719   V(NumberSin, Operator::kNoProperties, 1, 0)                    \
720   V(NumberSinh, Operator::kNoProperties, 1, 0)                   \
721   V(NumberSqrt, Operator::kNoProperties, 1, 0)                   \
722   V(NumberTan, Operator::kNoProperties, 1, 0)                    \
723   V(NumberTanh, Operator::kNoProperties, 1, 0)                   \
724   V(NumberTrunc, Operator::kNoProperties, 1, 0)                  \
725   V(NumberToBoolean, Operator::kNoProperties, 1, 0)              \
726   V(NumberToInt32, Operator::kNoProperties, 1, 0)                \
727   V(NumberToString, Operator::kNoProperties, 1, 0)               \
728   V(NumberToUint32, Operator::kNoProperties, 1, 0)               \
729   V(NumberToUint8Clamped, Operator::kNoProperties, 1, 0)         \
730   V(NumberSilenceNaN, Operator::kNoProperties, 1, 0)             \
731   V(BigIntNegate, Operator::kNoProperties, 1, 0)                 \
732   V(StringConcat, Operator::kNoProperties, 3, 0)                 \
733   V(StringToNumber, Operator::kNoProperties, 1, 0)               \
734   V(StringFromSingleCharCode, Operator::kNoProperties, 1, 0)     \
735   V(StringFromSingleCodePoint, Operator::kNoProperties, 1, 0)    \
736   V(StringIndexOf, Operator::kNoProperties, 3, 0)                \
737   V(StringLength, Operator::kNoProperties, 1, 0)                 \
738   V(StringToLowerCaseIntl, Operator::kNoProperties, 1, 0)        \
739   V(StringToUpperCaseIntl, Operator::kNoProperties, 1, 0)        \
740   V(TypeOf, Operator::kNoProperties, 1, 1)                       \
741   V(PlainPrimitiveToNumber, Operator::kNoProperties, 1, 0)       \
742   V(PlainPrimitiveToWord32, Operator::kNoProperties, 1, 0)       \
743   V(PlainPrimitiveToFloat64, Operator::kNoProperties, 1, 0)      \
744   V(ChangeTaggedSignedToInt32, Operator::kNoProperties, 1, 0)    \
745   V(ChangeTaggedSignedToInt64, Operator::kNoProperties, 1, 0)    \
746   V(ChangeTaggedToInt32, Operator::kNoProperties, 1, 0)          \
747   V(ChangeTaggedToInt64, Operator::kNoProperties, 1, 0)          \
748   V(ChangeTaggedToUint32, Operator::kNoProperties, 1, 0)         \
749   V(ChangeTaggedToFloat64, Operator::kNoProperties, 1, 0)        \
750   V(ChangeTaggedToTaggedSigned, Operator::kNoProperties, 1, 0)   \
751   V(ChangeFloat64ToTaggedPointer, Operator::kNoProperties, 1, 0) \
752   V(ChangeInt31ToTaggedSigned, Operator::kNoProperties, 1, 0)    \
753   V(ChangeInt32ToTagged, Operator::kNoProperties, 1, 0)          \
754   V(ChangeInt64ToTagged, Operator::kNoProperties, 1, 0)          \
755   V(ChangeUint32ToTagged, Operator::kNoProperties, 1, 0)         \
756   V(ChangeUint64ToTagged, Operator::kNoProperties, 1, 0)         \
757   V(ChangeTaggedToBit, Operator::kNoProperties, 1, 0)            \
758   V(ChangeBitToTagged, Operator::kNoProperties, 1, 0)            \
759   V(TruncateBigIntToWord64, Operator::kNoProperties, 1, 0)       \
760   V(ChangeInt64ToBigInt, Operator::kNoProperties, 1, 0)          \
761   V(ChangeUint64ToBigInt, Operator::kNoProperties, 1, 0)         \
762   V(TruncateTaggedToBit, Operator::kNoProperties, 1, 0)          \
763   V(TruncateTaggedPointerToBit, Operator::kNoProperties, 1, 0)   \
764   V(TruncateTaggedToWord32, Operator::kNoProperties, 1, 0)       \
765   V(TruncateTaggedToFloat64, Operator::kNoProperties, 1, 0)      \
766   V(ObjectIsArrayBufferView, Operator::kNoProperties, 1, 0)      \
767   V(ObjectIsBigInt, Operator::kNoProperties, 1, 0)               \
768   V(ObjectIsCallable, Operator::kNoProperties, 1, 0)             \
769   V(ObjectIsConstructor, Operator::kNoProperties, 1, 0)          \
770   V(ObjectIsDetectableCallable, Operator::kNoProperties, 1, 0)   \
771   V(ObjectIsMinusZero, Operator::kNoProperties, 1, 0)            \
772   V(NumberIsMinusZero, Operator::kNoProperties, 1, 0)            \
773   V(ObjectIsNaN, Operator::kNoProperties, 1, 0)                  \
774   V(NumberIsNaN, Operator::kNoProperties, 1, 0)                  \
775   V(ObjectIsNonCallable, Operator::kNoProperties, 1, 0)          \
776   V(ObjectIsNumber, Operator::kNoProperties, 1, 0)               \
777   V(ObjectIsReceiver, Operator::kNoProperties, 1, 0)             \
778   V(ObjectIsSmi, Operator::kNoProperties, 1, 0)                  \
779   V(ObjectIsString, Operator::kNoProperties, 1, 0)               \
780   V(ObjectIsSymbol, Operator::kNoProperties, 1, 0)               \
781   V(ObjectIsUndetectable, Operator::kNoProperties, 1, 0)         \
782   V(NumberIsFloat64Hole, Operator::kNoProperties, 1, 0)          \
783   V(NumberIsFinite, Operator::kNoProperties, 1, 0)               \
784   V(ObjectIsFiniteNumber, Operator::kNoProperties, 1, 0)         \
785   V(NumberIsInteger, Operator::kNoProperties, 1, 0)              \
786   V(ObjectIsSafeInteger, Operator::kNoProperties, 1, 0)          \
787   V(NumberIsSafeInteger, Operator::kNoProperties, 1, 0)          \
788   V(ObjectIsInteger, Operator::kNoProperties, 1, 0)              \
789   V(ConvertTaggedHoleToUndefined, Operator::kNoProperties, 1, 0) \
790   V(SameValue, Operator::kCommutative, 2, 0)                     \
791   V(SameValueNumbersOnly, Operator::kCommutative, 2, 0)          \
792   V(NumberSameValue, Operator::kCommutative, 2, 0)               \
793   V(ReferenceEqual, Operator::kCommutative, 2, 0)                \
794   V(StringEqual, Operator::kCommutative, 2, 0)                   \
795   V(StringLessThan, Operator::kNoProperties, 2, 0)               \
796   V(StringLessThanOrEqual, Operator::kNoProperties, 2, 0)        \
797   V(ToBoolean, Operator::kNoProperties, 1, 0)                    \
798   V(NewConsString, Operator::kNoProperties, 3, 0)
799 
800 #define EFFECT_DEPENDENT_OP_LIST(V)                       \
801   V(BigIntAdd, Operator::kNoProperties, 2, 1)             \
802   V(BigIntSubtract, Operator::kNoProperties, 2, 1)        \
803   V(StringCharCodeAt, Operator::kNoProperties, 2, 1)      \
804   V(StringCodePointAt, Operator::kNoProperties, 2, 1)     \
805   V(StringFromCodePointAt, Operator::kNoProperties, 2, 1) \
806   V(StringSubstring, Operator::kNoProperties, 3, 1)       \
807   V(DateNow, Operator::kNoProperties, 0, 1)
808 
809 #define SPECULATIVE_NUMBER_BINOP_LIST(V)      \
810   SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(V) \
811   V(SpeculativeNumberEqual)                   \
812   V(SpeculativeNumberLessThan)                \
813   V(SpeculativeNumberLessThanOrEqual)
814 
815 #define CHECKED_OP_LIST(V)                \
816   V(CheckEqualsInternalizedString, 2, 0)  \
817   V(CheckEqualsSymbol, 2, 0)              \
818   V(CheckHeapObject, 1, 1)                \
819   V(CheckInternalizedString, 1, 1)        \
820   V(CheckNotTaggedHole, 1, 1)             \
821   V(CheckReceiver, 1, 1)                  \
822   V(CheckReceiverOrNullOrUndefined, 1, 1) \
823   V(CheckSymbol, 1, 1)                    \
824   V(CheckedInt32Add, 2, 1)                \
825   V(CheckedInt32Div, 2, 1)                \
826   V(CheckedInt32Mod, 2, 1)                \
827   V(CheckedInt32Sub, 2, 1)                \
828   V(CheckedUint32Div, 2, 1)               \
829   V(CheckedUint32Mod, 2, 1)
830 
831 #define CHECKED_WITH_FEEDBACK_OP_LIST(V)    \
832   V(CheckNumber, 1, 1)                      \
833   V(CheckSmi, 1, 1)                         \
834   V(CheckString, 1, 1)                      \
835   V(CheckBigInt, 1, 1)                      \
836   V(CheckedInt32ToTaggedSigned, 1, 1)       \
837   V(CheckedInt64ToInt32, 1, 1)              \
838   V(CheckedInt64ToTaggedSigned, 1, 1)       \
839   V(CheckedTaggedToArrayIndex, 1, 1)        \
840   V(CheckedTaggedSignedToInt32, 1, 1)       \
841   V(CheckedTaggedToTaggedPointer, 1, 1)     \
842   V(CheckedTaggedToTaggedSigned, 1, 1)      \
843   V(CheckedUint32ToInt32, 1, 1)             \
844   V(CheckedUint32ToTaggedSigned, 1, 1)      \
845   V(CheckedUint64ToInt32, 1, 1)             \
846   V(CheckedUint64ToTaggedSigned, 1, 1)
847 
848 #define CHECKED_BOUNDS_OP_LIST(V) \
849   V(CheckedUint32Bounds)          \
850   V(CheckedUint64Bounds)
851 
852 struct SimplifiedOperatorGlobalCache final {
853 #define PURE(Name, properties, value_input_count, control_input_count)     \
854   struct Name##Operator final : public Operator {                          \
855     Name##Operator()                                                       \
856         : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \
857                    value_input_count, 0, control_input_count, 1, 0, 0) {}  \
858   };                                                                       \
859   Name##Operator k##Name;
860   PURE_OP_LIST(PURE)
861 #undef PURE
862 
863 #define EFFECT_DEPENDENT(Name, properties, value_input_count,               \
864                          control_input_count)                               \
865   struct Name##Operator final : public Operator {                           \
866     Name##Operator()                                                        \
867         : Operator(IrOpcode::k##Name, Operator::kEliminatable | properties, \
868                    #Name, value_input_count, 1, control_input_count, 1, 1,  \
869                    0) {}                                                    \
870   };                                                                        \
871   Name##Operator k##Name;
872   EFFECT_DEPENDENT_OP_LIST(EFFECT_DEPENDENT)
873 #undef EFFECT_DEPENDENT
874 
875 #define CHECKED(Name, value_input_count, value_output_count)             \
876   struct Name##Operator final : public Operator {                        \
877     Name##Operator()                                                     \
878         : Operator(IrOpcode::k##Name,                                    \
879                    Operator::kFoldable | Operator::kNoThrow, #Name,      \
880                    value_input_count, 1, 1, value_output_count, 1, 0) {} \
881   };                                                                     \
882   Name##Operator k##Name;
883   CHECKED_OP_LIST(CHECKED)
884 #undef CHECKED
885 
886 #define CHECKED_WITH_FEEDBACK(Name, value_input_count, value_output_count) \
887   struct Name##Operator final : public Operator1<CheckParameters> {        \
888     Name##Operator()                                                       \
889         : Operator1<CheckParameters>(                                      \
890               IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, \
891               #Name, value_input_count, 1, 1, value_output_count, 1, 0,    \
892               CheckParameters(FeedbackSource())) {}                        \
893   };                                                                       \
894   Name##Operator k##Name;
895   CHECKED_WITH_FEEDBACK_OP_LIST(CHECKED_WITH_FEEDBACK)
896 #undef CHECKED_WITH_FEEDBACK
897 
898 #define CHECKED_BOUNDS(Name)                                               \
899   struct Name##Operator final : public Operator1<CheckBoundsParameters> {  \
900     Name##Operator(FeedbackSource feedback, CheckBoundsFlags flags)        \
901         : Operator1<CheckBoundsParameters>(                                \
902               IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, \
903               #Name, 2, 1, 1, 1, 1, 0,                                     \
904               CheckBoundsParameters(feedback, flags)) {}                   \
905   };                                                                       \
906   Name##Operator k##Name = {FeedbackSource(), CheckBoundsFlags()};         \
907   Name##Operator k##Name##Aborting = {FeedbackSource(),                    \
908                                       CheckBoundsFlag::kAbortOnOutOfBounds};
909   CHECKED_BOUNDS_OP_LIST(CHECKED_BOUNDS)
910   CHECKED_BOUNDS(CheckBounds)
911   // For IrOpcode::kCheckBounds, we allow additional flags:
912   CheckBoundsOperator kCheckBoundsConverting = {
913       FeedbackSource(), CheckBoundsFlag::kConvertStringAndMinusZero};
914   CheckBoundsOperator kCheckBoundsAbortingAndConverting = {
915       FeedbackSource(),
916       CheckBoundsFlags(CheckBoundsFlag::kAbortOnOutOfBounds) |
917           CheckBoundsFlags(CheckBoundsFlag::kConvertStringAndMinusZero)};
918 #undef CHECKED_BOUNDS
919 
920   template <DeoptimizeReason kDeoptimizeReason>
921   struct CheckIfOperator final : public Operator1<CheckIfParameters> {
CheckIfOperatorv8::internal::compiler::SimplifiedOperatorGlobalCache::CheckIfOperator922     CheckIfOperator()
923         : Operator1<CheckIfParameters>(
924               IrOpcode::kCheckIf, Operator::kFoldable | Operator::kNoThrow,
925               "CheckIf", 1, 1, 1, 0, 1, 0,
926               CheckIfParameters(kDeoptimizeReason, FeedbackSource())) {}
927   };
928 #define CHECK_IF(Name, message) \
929   CheckIfOperator<DeoptimizeReason::k##Name> kCheckIf##Name;
930   DEOPTIMIZE_REASON_LIST(CHECK_IF)
931 #undef CHECK_IF
932 
933   struct FindOrderedHashMapEntryOperator final : public Operator {
FindOrderedHashMapEntryOperatorv8::internal::compiler::SimplifiedOperatorGlobalCache::FindOrderedHashMapEntryOperator934     FindOrderedHashMapEntryOperator()
935         : Operator(IrOpcode::kFindOrderedHashMapEntry, Operator::kEliminatable,
936                    "FindOrderedHashMapEntry", 2, 1, 1, 1, 1, 0) {}
937   };
938   FindOrderedHashMapEntryOperator kFindOrderedHashMapEntry;
939 
940   struct FindOrderedHashMapEntryForInt32KeyOperator final : public Operator {
FindOrderedHashMapEntryForInt32KeyOperatorv8::internal::compiler::SimplifiedOperatorGlobalCache::FindOrderedHashMapEntryForInt32KeyOperator941     FindOrderedHashMapEntryForInt32KeyOperator()
942         : Operator(IrOpcode::kFindOrderedHashMapEntryForInt32Key,
943                    Operator::kEliminatable,
944                    "FindOrderedHashMapEntryForInt32Key", 2, 1, 1, 1, 1, 0) {}
945   };
946   FindOrderedHashMapEntryForInt32KeyOperator
947       kFindOrderedHashMapEntryForInt32Key;
948 
949   template <CheckForMinusZeroMode kMode>
950   struct ChangeFloat64ToTaggedOperator final
951       : public Operator1<CheckForMinusZeroMode> {
ChangeFloat64ToTaggedOperatorv8::internal::compiler::SimplifiedOperatorGlobalCache::ChangeFloat64ToTaggedOperator952     ChangeFloat64ToTaggedOperator()
953         : Operator1<CheckForMinusZeroMode>(
954               IrOpcode::kChangeFloat64ToTagged, Operator::kPure,
955               "ChangeFloat64ToTagged", 1, 0, 0, 1, 0, 0, kMode) {}
956   };
957   ChangeFloat64ToTaggedOperator<CheckForMinusZeroMode::kCheckForMinusZero>
958       kChangeFloat64ToTaggedCheckForMinusZeroOperator;
959   ChangeFloat64ToTaggedOperator<CheckForMinusZeroMode::kDontCheckForMinusZero>
960       kChangeFloat64ToTaggedDontCheckForMinusZeroOperator;
961 
962   template <CheckForMinusZeroMode kMode>
963   struct CheckedInt32MulOperator final
964       : public Operator1<CheckForMinusZeroMode> {
CheckedInt32MulOperatorv8::internal::compiler::SimplifiedOperatorGlobalCache::CheckedInt32MulOperator965     CheckedInt32MulOperator()
966         : Operator1<CheckForMinusZeroMode>(
967               IrOpcode::kCheckedInt32Mul,
968               Operator::kFoldable | Operator::kNoThrow, "CheckedInt32Mul", 2, 1,
969               1, 1, 1, 0, kMode) {}
970   };
971   CheckedInt32MulOperator<CheckForMinusZeroMode::kCheckForMinusZero>
972       kCheckedInt32MulCheckForMinusZeroOperator;
973   CheckedInt32MulOperator<CheckForMinusZeroMode::kDontCheckForMinusZero>
974       kCheckedInt32MulDontCheckForMinusZeroOperator;
975 
976   template <CheckForMinusZeroMode kMode>
977   struct CheckedFloat64ToInt32Operator final
978       : public Operator1<CheckMinusZeroParameters> {
CheckedFloat64ToInt32Operatorv8::internal::compiler::SimplifiedOperatorGlobalCache::CheckedFloat64ToInt32Operator979     CheckedFloat64ToInt32Operator()
980         : Operator1<CheckMinusZeroParameters>(
981               IrOpcode::kCheckedFloat64ToInt32,
982               Operator::kFoldable | Operator::kNoThrow, "CheckedFloat64ToInt32",
983               1, 1, 1, 1, 1, 0,
984               CheckMinusZeroParameters(kMode, FeedbackSource())) {}
985   };
986   CheckedFloat64ToInt32Operator<CheckForMinusZeroMode::kCheckForMinusZero>
987       kCheckedFloat64ToInt32CheckForMinusZeroOperator;
988   CheckedFloat64ToInt32Operator<CheckForMinusZeroMode::kDontCheckForMinusZero>
989       kCheckedFloat64ToInt32DontCheckForMinusZeroOperator;
990 
991   template <CheckForMinusZeroMode kMode>
992   struct CheckedFloat64ToInt64Operator final
993       : public Operator1<CheckMinusZeroParameters> {
CheckedFloat64ToInt64Operatorv8::internal::compiler::SimplifiedOperatorGlobalCache::CheckedFloat64ToInt64Operator994     CheckedFloat64ToInt64Operator()
995         : Operator1<CheckMinusZeroParameters>(
996               IrOpcode::kCheckedFloat64ToInt64,
997               Operator::kFoldable | Operator::kNoThrow, "CheckedFloat64ToInt64",
998               1, 1, 1, 1, 1, 0,
999               CheckMinusZeroParameters(kMode, FeedbackSource())) {}
1000   };
1001   CheckedFloat64ToInt64Operator<CheckForMinusZeroMode::kCheckForMinusZero>
1002       kCheckedFloat64ToInt64CheckForMinusZeroOperator;
1003   CheckedFloat64ToInt64Operator<CheckForMinusZeroMode::kDontCheckForMinusZero>
1004       kCheckedFloat64ToInt64DontCheckForMinusZeroOperator;
1005 
1006   template <CheckForMinusZeroMode kMode>
1007   struct CheckedTaggedToInt32Operator final
1008       : public Operator1<CheckMinusZeroParameters> {
CheckedTaggedToInt32Operatorv8::internal::compiler::SimplifiedOperatorGlobalCache::CheckedTaggedToInt32Operator1009     CheckedTaggedToInt32Operator()
1010         : Operator1<CheckMinusZeroParameters>(
1011               IrOpcode::kCheckedTaggedToInt32,
1012               Operator::kFoldable | Operator::kNoThrow, "CheckedTaggedToInt32",
1013               1, 1, 1, 1, 1, 0,
1014               CheckMinusZeroParameters(kMode, FeedbackSource())) {}
1015   };
1016   CheckedTaggedToInt32Operator<CheckForMinusZeroMode::kCheckForMinusZero>
1017       kCheckedTaggedToInt32CheckForMinusZeroOperator;
1018   CheckedTaggedToInt32Operator<CheckForMinusZeroMode::kDontCheckForMinusZero>
1019       kCheckedTaggedToInt32DontCheckForMinusZeroOperator;
1020 
1021   template <CheckForMinusZeroMode kMode>
1022   struct CheckedTaggedToInt64Operator final
1023       : public Operator1<CheckMinusZeroParameters> {
CheckedTaggedToInt64Operatorv8::internal::compiler::SimplifiedOperatorGlobalCache::CheckedTaggedToInt64Operator1024     CheckedTaggedToInt64Operator()
1025         : Operator1<CheckMinusZeroParameters>(
1026               IrOpcode::kCheckedTaggedToInt64,
1027               Operator::kFoldable | Operator::kNoThrow, "CheckedTaggedToInt64",
1028               1, 1, 1, 1, 1, 0,
1029               CheckMinusZeroParameters(kMode, FeedbackSource())) {}
1030   };
1031   CheckedTaggedToInt64Operator<CheckForMinusZeroMode::kCheckForMinusZero>
1032       kCheckedTaggedToInt64CheckForMinusZeroOperator;
1033   CheckedTaggedToInt64Operator<CheckForMinusZeroMode::kDontCheckForMinusZero>
1034       kCheckedTaggedToInt64DontCheckForMinusZeroOperator;
1035 
1036   template <CheckTaggedInputMode kMode>
1037   struct CheckedTaggedToFloat64Operator final
1038       : public Operator1<CheckTaggedInputParameters> {
CheckedTaggedToFloat64Operatorv8::internal::compiler::SimplifiedOperatorGlobalCache::CheckedTaggedToFloat64Operator1039     CheckedTaggedToFloat64Operator()
1040         : Operator1<CheckTaggedInputParameters>(
1041               IrOpcode::kCheckedTaggedToFloat64,
1042               Operator::kFoldable | Operator::kNoThrow,
1043               "CheckedTaggedToFloat64", 1, 1, 1, 1, 1, 0,
1044               CheckTaggedInputParameters(kMode, FeedbackSource())) {}
1045   };
1046   CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumber>
1047       kCheckedTaggedToFloat64NumberOperator;
1048   CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumberOrBoolean>
1049       kCheckedTaggedToFloat64NumberOrBooleanOperator;
1050   CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumberOrOddball>
1051       kCheckedTaggedToFloat64NumberOrOddballOperator;
1052 
1053   template <CheckTaggedInputMode kMode>
1054   struct CheckedTruncateTaggedToWord32Operator final
1055       : public Operator1<CheckTaggedInputParameters> {
CheckedTruncateTaggedToWord32Operatorv8::internal::compiler::SimplifiedOperatorGlobalCache::CheckedTruncateTaggedToWord32Operator1056     CheckedTruncateTaggedToWord32Operator()
1057         : Operator1<CheckTaggedInputParameters>(
1058               IrOpcode::kCheckedTruncateTaggedToWord32,
1059               Operator::kFoldable | Operator::kNoThrow,
1060               "CheckedTruncateTaggedToWord32", 1, 1, 1, 1, 1, 0,
1061               CheckTaggedInputParameters(kMode, FeedbackSource())) {}
1062   };
1063   CheckedTruncateTaggedToWord32Operator<CheckTaggedInputMode::kNumber>
1064       kCheckedTruncateTaggedToWord32NumberOperator;
1065   CheckedTruncateTaggedToWord32Operator<CheckTaggedInputMode::kNumberOrOddball>
1066       kCheckedTruncateTaggedToWord32NumberOrOddballOperator;
1067 
1068   template <ConvertReceiverMode kMode>
1069   struct ConvertReceiverOperator final : public Operator1<ConvertReceiverMode> {
ConvertReceiverOperatorv8::internal::compiler::SimplifiedOperatorGlobalCache::ConvertReceiverOperator1070     ConvertReceiverOperator()
1071         : Operator1<ConvertReceiverMode>(  // --
1072               IrOpcode::kConvertReceiver,  // opcode
1073               Operator::kEliminatable,     // flags
1074               "ConvertReceiver",           // name
1075               2, 1, 1, 1, 1, 0,            // counts
1076               kMode) {}                    // param
1077   };
1078   ConvertReceiverOperator<ConvertReceiverMode::kAny>
1079       kConvertReceiverAnyOperator;
1080   ConvertReceiverOperator<ConvertReceiverMode::kNullOrUndefined>
1081       kConvertReceiverNullOrUndefinedOperator;
1082   ConvertReceiverOperator<ConvertReceiverMode::kNotNullOrUndefined>
1083       kConvertReceiverNotNullOrUndefinedOperator;
1084 
1085   template <CheckFloat64HoleMode kMode>
1086   struct CheckFloat64HoleNaNOperator final
1087       : public Operator1<CheckFloat64HoleParameters> {
CheckFloat64HoleNaNOperatorv8::internal::compiler::SimplifiedOperatorGlobalCache::CheckFloat64HoleNaNOperator1088     CheckFloat64HoleNaNOperator()
1089         : Operator1<CheckFloat64HoleParameters>(
1090               IrOpcode::kCheckFloat64Hole,
1091               Operator::kFoldable | Operator::kNoThrow, "CheckFloat64Hole", 1,
1092               1, 1, 1, 1, 0,
1093               CheckFloat64HoleParameters(kMode, FeedbackSource())) {}
1094   };
1095   CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kAllowReturnHole>
1096       kCheckFloat64HoleAllowReturnHoleOperator;
1097   CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kNeverReturnHole>
1098       kCheckFloat64HoleNeverReturnHoleOperator;
1099 
1100   struct EnsureWritableFastElementsOperator final : public Operator {
EnsureWritableFastElementsOperatorv8::internal::compiler::SimplifiedOperatorGlobalCache::EnsureWritableFastElementsOperator1101     EnsureWritableFastElementsOperator()
1102         : Operator(                                     // --
1103               IrOpcode::kEnsureWritableFastElements,    // opcode
1104               Operator::kNoDeopt | Operator::kNoThrow,  // flags
1105               "EnsureWritableFastElements",             // name
1106               2, 1, 1, 1, 1, 0) {}                      // counts
1107   };
1108   EnsureWritableFastElementsOperator kEnsureWritableFastElements;
1109 
1110   template <GrowFastElementsMode kMode>
1111   struct GrowFastElementsOperator final
1112       : public Operator1<GrowFastElementsParameters> {
GrowFastElementsOperatorv8::internal::compiler::SimplifiedOperatorGlobalCache::GrowFastElementsOperator1113     GrowFastElementsOperator()
1114         : Operator1(IrOpcode::kMaybeGrowFastElements, Operator::kNoThrow,
1115                     "MaybeGrowFastElements", 4, 1, 1, 1, 1, 0,
1116                     GrowFastElementsParameters(kMode, FeedbackSource())) {}
1117   };
1118 
1119   GrowFastElementsOperator<GrowFastElementsMode::kDoubleElements>
1120       kGrowFastElementsOperatorDoubleElements;
1121   GrowFastElementsOperator<GrowFastElementsMode::kSmiOrObjectElements>
1122       kGrowFastElementsOperatorSmiOrObjectElements;
1123 
1124   struct LoadFieldByIndexOperator final : public Operator {
LoadFieldByIndexOperatorv8::internal::compiler::SimplifiedOperatorGlobalCache::LoadFieldByIndexOperator1125     LoadFieldByIndexOperator()
1126         : Operator(                         // --
1127               IrOpcode::kLoadFieldByIndex,  // opcode
1128               Operator::kEliminatable,      // flags,
1129               "LoadFieldByIndex",           // name
1130               2, 1, 1, 1, 1, 0) {}          // counts;
1131   };
1132   LoadFieldByIndexOperator kLoadFieldByIndex;
1133 
1134   struct LoadStackArgumentOperator final : public Operator {
LoadStackArgumentOperatorv8::internal::compiler::SimplifiedOperatorGlobalCache::LoadStackArgumentOperator1135     LoadStackArgumentOperator()
1136         : Operator(                          // --
1137               IrOpcode::kLoadStackArgument,  // opcode
1138               Operator::kEliminatable,       // flags
1139               "LoadStackArgument",           // name
1140               2, 1, 1, 1, 1, 0) {}           // counts
1141   };
1142   LoadStackArgumentOperator kLoadStackArgument;
1143 
1144 #define SPECULATIVE_NUMBER_BINOP(Name)                                      \
1145   template <NumberOperationHint kHint>                                      \
1146   struct Name##Operator final : public Operator1<NumberOperationHint> {     \
1147     Name##Operator()                                                        \
1148         : Operator1<NumberOperationHint>(                                   \
1149               IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow,  \
1150               #Name, 2, 1, 1, 1, 1, 0, kHint) {}                            \
1151   };                                                                        \
1152   Name##Operator<NumberOperationHint::kSignedSmall>                         \
1153       k##Name##SignedSmallOperator;                                         \
1154   Name##Operator<NumberOperationHint::kSignedSmallInputs>                   \
1155       k##Name##SignedSmallInputsOperator;                                   \
1156   Name##Operator<NumberOperationHint::kNumber> k##Name##NumberOperator;     \
1157   Name##Operator<NumberOperationHint::kNumberOrOddball>                     \
1158       k##Name##NumberOrOddballOperator;
1159   SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP)
1160 #undef SPECULATIVE_NUMBER_BINOP
1161   SpeculativeNumberEqualOperator<NumberOperationHint::kNumberOrBoolean>
1162       kSpeculativeNumberEqualNumberOrBooleanOperator;
1163 
1164   template <NumberOperationHint kHint>
1165   struct SpeculativeToNumberOperator final
1166       : public Operator1<NumberOperationParameters> {
SpeculativeToNumberOperatorv8::internal::compiler::SimplifiedOperatorGlobalCache::SpeculativeToNumberOperator1167     SpeculativeToNumberOperator()
1168         : Operator1<NumberOperationParameters>(
1169               IrOpcode::kSpeculativeToNumber,
1170               Operator::kFoldable | Operator::kNoThrow, "SpeculativeToNumber",
1171               1, 1, 1, 1, 1, 0,
1172               NumberOperationParameters(kHint, FeedbackSource())) {}
1173   };
1174   SpeculativeToNumberOperator<NumberOperationHint::kSignedSmall>
1175       kSpeculativeToNumberSignedSmallOperator;
1176   SpeculativeToNumberOperator<NumberOperationHint::kNumber>
1177       kSpeculativeToNumberNumberOperator;
1178   SpeculativeToNumberOperator<NumberOperationHint::kNumberOrOddball>
1179       kSpeculativeToNumberNumberOrOddballOperator;
1180 };
1181 
1182 namespace {
1183 DEFINE_LAZY_LEAKY_OBJECT_GETTER(SimplifiedOperatorGlobalCache,
1184                                 GetSimplifiedOperatorGlobalCache)
1185 }  // namespace
1186 
SimplifiedOperatorBuilder(Zone * zone)1187 SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone)
1188     : cache_(*GetSimplifiedOperatorGlobalCache()), zone_(zone) {}
1189 
1190 #define GET_FROM_CACHE(Name, ...) \
1191   const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
1192 PURE_OP_LIST(GET_FROM_CACHE)
EFFECT_DEPENDENT_OP_LIST(GET_FROM_CACHE)1193 EFFECT_DEPENDENT_OP_LIST(GET_FROM_CACHE)
1194 CHECKED_OP_LIST(GET_FROM_CACHE)
1195 GET_FROM_CACHE(FindOrderedHashMapEntry)
1196 GET_FROM_CACHE(FindOrderedHashMapEntryForInt32Key)
1197 GET_FROM_CACHE(LoadFieldByIndex)
1198 #undef GET_FROM_CACHE
1199 
1200 #define GET_FROM_CACHE_WITH_FEEDBACK(Name, value_input_count,               \
1201                                      value_output_count)                    \
1202   const Operator* SimplifiedOperatorBuilder::Name(                          \
1203       const FeedbackSource& feedback) {                                     \
1204     if (!feedback.IsValid()) {                                              \
1205       return &cache_.k##Name;                                               \
1206     }                                                                       \
1207     return zone()->New<Operator1<CheckParameters>>(                         \
1208         IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, #Name, \
1209         value_input_count, 1, 1, value_output_count, 1, 0,                  \
1210         CheckParameters(feedback));                                         \
1211   }
1212 CHECKED_WITH_FEEDBACK_OP_LIST(GET_FROM_CACHE_WITH_FEEDBACK)
1213 #undef GET_FROM_CACHE_WITH_FEEDBACK
1214 
1215 #define GET_FROM_CACHE_WITH_FEEDBACK(Name)                             \
1216   const Operator* SimplifiedOperatorBuilder::Name(                     \
1217       const FeedbackSource& feedback, CheckBoundsFlags flags) {        \
1218     DCHECK(!(flags & CheckBoundsFlag::kConvertStringAndMinusZero));    \
1219     if (!feedback.IsValid()) {                                         \
1220       if (flags & CheckBoundsFlag::kAbortOnOutOfBounds) {              \
1221         return &cache_.k##Name##Aborting;                              \
1222       } else {                                                         \
1223         return &cache_.k##Name;                                        \
1224       }                                                                \
1225     }                                                                  \
1226     return zone()->New<SimplifiedOperatorGlobalCache::Name##Operator>( \
1227         feedback, flags);                                              \
1228   }
1229 CHECKED_BOUNDS_OP_LIST(GET_FROM_CACHE_WITH_FEEDBACK)
1230 #undef GET_FROM_CACHE_WITH_FEEDBACK
1231 
1232 // For IrOpcode::kCheckBounds, we allow additional flags:
1233 const Operator* SimplifiedOperatorBuilder::CheckBounds(
1234     const FeedbackSource& feedback, CheckBoundsFlags flags) {
1235   if (!feedback.IsValid()) {
1236     if (flags & CheckBoundsFlag::kAbortOnOutOfBounds) {
1237       if (flags & CheckBoundsFlag::kConvertStringAndMinusZero) {
1238         return &cache_.kCheckBoundsAbortingAndConverting;
1239       } else {
1240         return &cache_.kCheckBoundsAborting;
1241       }
1242     } else {
1243       if (flags & CheckBoundsFlag::kConvertStringAndMinusZero) {
1244         return &cache_.kCheckBoundsConverting;
1245       } else {
1246         return &cache_.kCheckBounds;
1247       }
1248     }
1249   }
1250   return zone()->New<SimplifiedOperatorGlobalCache::CheckBoundsOperator>(
1251       feedback, flags);
1252 }
1253 
IsCheckedWithFeedback(const Operator * op)1254 bool IsCheckedWithFeedback(const Operator* op) {
1255 #define CASE(Name, ...) case IrOpcode::k##Name:
1256   switch (op->opcode()) {
1257     CHECKED_WITH_FEEDBACK_OP_LIST(CASE) return true;
1258     default:
1259       return false;
1260   }
1261 #undef CASE
1262 }
1263 
RuntimeAbort(AbortReason reason)1264 const Operator* SimplifiedOperatorBuilder::RuntimeAbort(AbortReason reason) {
1265   return zone()->New<Operator1<int>>(           // --
1266       IrOpcode::kRuntimeAbort,                  // opcode
1267       Operator::kNoThrow | Operator::kNoDeopt,  // flags
1268       "RuntimeAbort",                           // name
1269       0, 1, 1, 0, 1, 0,                         // counts
1270       static_cast<int>(reason));                // parameter
1271 }
1272 
SpeculativeBigIntAsIntN(int bits,const FeedbackSource & feedback)1273 const Operator* SimplifiedOperatorBuilder::SpeculativeBigIntAsIntN(
1274     int bits, const FeedbackSource& feedback) {
1275   CHECK(0 <= bits && bits <= 64);
1276 
1277   return zone()->New<Operator1<SpeculativeBigIntAsNParameters>>(
1278       IrOpcode::kSpeculativeBigIntAsIntN, Operator::kNoProperties,
1279       "SpeculativeBigIntAsIntN", 1, 1, 1, 1, 1, 0,
1280       SpeculativeBigIntAsNParameters(bits, feedback));
1281 }
1282 
SpeculativeBigIntAsUintN(int bits,const FeedbackSource & feedback)1283 const Operator* SimplifiedOperatorBuilder::SpeculativeBigIntAsUintN(
1284     int bits, const FeedbackSource& feedback) {
1285   CHECK(0 <= bits && bits <= 64);
1286 
1287   return zone()->New<Operator1<SpeculativeBigIntAsNParameters>>(
1288       IrOpcode::kSpeculativeBigIntAsUintN, Operator::kNoProperties,
1289       "SpeculativeBigIntAsUintN", 1, 1, 1, 1, 1, 0,
1290       SpeculativeBigIntAsNParameters(bits, feedback));
1291 }
1292 
AssertType(Type type)1293 const Operator* SimplifiedOperatorBuilder::AssertType(Type type) {
1294   DCHECK(type.CanBeAsserted());
1295   return zone()->New<Operator1<Type>>(IrOpcode::kAssertType,
1296                                       Operator::kNoThrow | Operator::kNoDeopt,
1297                                       "AssertType", 1, 0, 0, 1, 0, 0, type);
1298 }
1299 
VerifyType()1300 const Operator* SimplifiedOperatorBuilder::VerifyType() {
1301   return zone()->New<Operator>(IrOpcode::kVerifyType,
1302                                Operator::kNoThrow | Operator::kNoDeopt,
1303                                "VerifyType", 1, 0, 0, 1, 0, 0);
1304 }
1305 
CheckIf(DeoptimizeReason reason,const FeedbackSource & feedback)1306 const Operator* SimplifiedOperatorBuilder::CheckIf(
1307     DeoptimizeReason reason, const FeedbackSource& feedback) {
1308   if (!feedback.IsValid()) {
1309     switch (reason) {
1310 #define CHECK_IF(Name, message)   \
1311   case DeoptimizeReason::k##Name: \
1312     return &cache_.kCheckIf##Name;
1313     DEOPTIMIZE_REASON_LIST(CHECK_IF)
1314 #undef CHECK_IF
1315     }
1316   }
1317   return zone()->New<Operator1<CheckIfParameters>>(
1318       IrOpcode::kCheckIf, Operator::kFoldable | Operator::kNoThrow, "CheckIf",
1319       1, 1, 1, 0, 1, 0, CheckIfParameters(reason, feedback));
1320 }
1321 
ChangeFloat64ToTagged(CheckForMinusZeroMode mode)1322 const Operator* SimplifiedOperatorBuilder::ChangeFloat64ToTagged(
1323     CheckForMinusZeroMode mode) {
1324   switch (mode) {
1325     case CheckForMinusZeroMode::kCheckForMinusZero:
1326       return &cache_.kChangeFloat64ToTaggedCheckForMinusZeroOperator;
1327     case CheckForMinusZeroMode::kDontCheckForMinusZero:
1328       return &cache_.kChangeFloat64ToTaggedDontCheckForMinusZeroOperator;
1329   }
1330   UNREACHABLE();
1331 }
1332 
CheckedInt32Mul(CheckForMinusZeroMode mode)1333 const Operator* SimplifiedOperatorBuilder::CheckedInt32Mul(
1334     CheckForMinusZeroMode mode) {
1335   switch (mode) {
1336     case CheckForMinusZeroMode::kCheckForMinusZero:
1337       return &cache_.kCheckedInt32MulCheckForMinusZeroOperator;
1338     case CheckForMinusZeroMode::kDontCheckForMinusZero:
1339       return &cache_.kCheckedInt32MulDontCheckForMinusZeroOperator;
1340   }
1341   UNREACHABLE();
1342 }
1343 
CheckedFloat64ToInt32(CheckForMinusZeroMode mode,const FeedbackSource & feedback)1344 const Operator* SimplifiedOperatorBuilder::CheckedFloat64ToInt32(
1345     CheckForMinusZeroMode mode, const FeedbackSource& feedback) {
1346   if (!feedback.IsValid()) {
1347     switch (mode) {
1348       case CheckForMinusZeroMode::kCheckForMinusZero:
1349         return &cache_.kCheckedFloat64ToInt32CheckForMinusZeroOperator;
1350       case CheckForMinusZeroMode::kDontCheckForMinusZero:
1351         return &cache_.kCheckedFloat64ToInt32DontCheckForMinusZeroOperator;
1352     }
1353   }
1354   return zone()->New<Operator1<CheckMinusZeroParameters>>(
1355       IrOpcode::kCheckedFloat64ToInt32,
1356       Operator::kFoldable | Operator::kNoThrow, "CheckedFloat64ToInt32", 1, 1,
1357       1, 1, 1, 0, CheckMinusZeroParameters(mode, feedback));
1358 }
1359 
CheckedFloat64ToInt64(CheckForMinusZeroMode mode,const FeedbackSource & feedback)1360 const Operator* SimplifiedOperatorBuilder::CheckedFloat64ToInt64(
1361     CheckForMinusZeroMode mode, const FeedbackSource& feedback) {
1362   if (!feedback.IsValid()) {
1363     switch (mode) {
1364       case CheckForMinusZeroMode::kCheckForMinusZero:
1365         return &cache_.kCheckedFloat64ToInt64CheckForMinusZeroOperator;
1366       case CheckForMinusZeroMode::kDontCheckForMinusZero:
1367         return &cache_.kCheckedFloat64ToInt64DontCheckForMinusZeroOperator;
1368     }
1369   }
1370   return zone()->New<Operator1<CheckMinusZeroParameters>>(
1371       IrOpcode::kCheckedFloat64ToInt64,
1372       Operator::kFoldable | Operator::kNoThrow, "CheckedFloat64ToInt64", 1, 1,
1373       1, 1, 1, 0, CheckMinusZeroParameters(mode, feedback));
1374 }
1375 
CheckedTaggedToInt32(CheckForMinusZeroMode mode,const FeedbackSource & feedback)1376 const Operator* SimplifiedOperatorBuilder::CheckedTaggedToInt32(
1377     CheckForMinusZeroMode mode, const FeedbackSource& feedback) {
1378   if (!feedback.IsValid()) {
1379     switch (mode) {
1380       case CheckForMinusZeroMode::kCheckForMinusZero:
1381         return &cache_.kCheckedTaggedToInt32CheckForMinusZeroOperator;
1382       case CheckForMinusZeroMode::kDontCheckForMinusZero:
1383         return &cache_.kCheckedTaggedToInt32DontCheckForMinusZeroOperator;
1384     }
1385   }
1386   return zone()->New<Operator1<CheckMinusZeroParameters>>(
1387       IrOpcode::kCheckedTaggedToInt32, Operator::kFoldable | Operator::kNoThrow,
1388       "CheckedTaggedToInt32", 1, 1, 1, 1, 1, 0,
1389       CheckMinusZeroParameters(mode, feedback));
1390 }
1391 
CheckedTaggedToInt64(CheckForMinusZeroMode mode,const FeedbackSource & feedback)1392 const Operator* SimplifiedOperatorBuilder::CheckedTaggedToInt64(
1393     CheckForMinusZeroMode mode, const FeedbackSource& feedback) {
1394   if (!feedback.IsValid()) {
1395     switch (mode) {
1396       case CheckForMinusZeroMode::kCheckForMinusZero:
1397         return &cache_.kCheckedTaggedToInt64CheckForMinusZeroOperator;
1398       case CheckForMinusZeroMode::kDontCheckForMinusZero:
1399         return &cache_.kCheckedTaggedToInt64DontCheckForMinusZeroOperator;
1400     }
1401   }
1402   return zone()->New<Operator1<CheckMinusZeroParameters>>(
1403       IrOpcode::kCheckedTaggedToInt64, Operator::kFoldable | Operator::kNoThrow,
1404       "CheckedTaggedToInt64", 1, 1, 1, 1, 1, 0,
1405       CheckMinusZeroParameters(mode, feedback));
1406 }
1407 
CheckedTaggedToFloat64(CheckTaggedInputMode mode,const FeedbackSource & feedback)1408 const Operator* SimplifiedOperatorBuilder::CheckedTaggedToFloat64(
1409     CheckTaggedInputMode mode, const FeedbackSource& feedback) {
1410   if (!feedback.IsValid()) {
1411     switch (mode) {
1412       case CheckTaggedInputMode::kNumber:
1413         return &cache_.kCheckedTaggedToFloat64NumberOperator;
1414       case CheckTaggedInputMode::kNumberOrBoolean:
1415         return &cache_.kCheckedTaggedToFloat64NumberOrBooleanOperator;
1416       case CheckTaggedInputMode::kNumberOrOddball:
1417         return &cache_.kCheckedTaggedToFloat64NumberOrOddballOperator;
1418     }
1419   }
1420   return zone()->New<Operator1<CheckTaggedInputParameters>>(
1421       IrOpcode::kCheckedTaggedToFloat64,
1422       Operator::kFoldable | Operator::kNoThrow, "CheckedTaggedToFloat64", 1, 1,
1423       1, 1, 1, 0, CheckTaggedInputParameters(mode, feedback));
1424 }
1425 
CheckedTruncateTaggedToWord32(CheckTaggedInputMode mode,const FeedbackSource & feedback)1426 const Operator* SimplifiedOperatorBuilder::CheckedTruncateTaggedToWord32(
1427     CheckTaggedInputMode mode, const FeedbackSource& feedback) {
1428   if (!feedback.IsValid()) {
1429     switch (mode) {
1430       case CheckTaggedInputMode::kNumber:
1431         return &cache_.kCheckedTruncateTaggedToWord32NumberOperator;
1432       case CheckTaggedInputMode::kNumberOrBoolean:
1433         // Not used currently.
1434         UNREACHABLE();
1435       case CheckTaggedInputMode::kNumberOrOddball:
1436         return &cache_.kCheckedTruncateTaggedToWord32NumberOrOddballOperator;
1437     }
1438   }
1439   return zone()->New<Operator1<CheckTaggedInputParameters>>(
1440       IrOpcode::kCheckedTruncateTaggedToWord32,
1441       Operator::kFoldable | Operator::kNoThrow, "CheckedTruncateTaggedToWord32",
1442       1, 1, 1, 1, 1, 0, CheckTaggedInputParameters(mode, feedback));
1443 }
1444 
CheckMaps(CheckMapsFlags flags,ZoneHandleSet<Map> maps,const FeedbackSource & feedback)1445 const Operator* SimplifiedOperatorBuilder::CheckMaps(
1446     CheckMapsFlags flags, ZoneHandleSet<Map> maps,
1447     const FeedbackSource& feedback) {
1448   CheckMapsParameters const parameters(flags, maps, feedback);
1449   return zone()->New<Operator1<CheckMapsParameters>>(  // --
1450       IrOpcode::kCheckMaps,                            // opcode
1451       Operator::kNoThrow | Operator::kNoWrite,         // flags
1452       "CheckMaps",                                     // name
1453       1, 1, 1, 0, 1, 0,                                // counts
1454       parameters);                                     // parameter
1455 }
1456 
MapGuard(ZoneHandleSet<Map> maps)1457 const Operator* SimplifiedOperatorBuilder::MapGuard(ZoneHandleSet<Map> maps) {
1458   DCHECK_LT(0, maps.size());
1459   return zone()->New<Operator1<ZoneHandleSet<Map>>>(  // --
1460       IrOpcode::kMapGuard, Operator::kEliminatable,   // opcode
1461       "MapGuard",                                     // name
1462       1, 1, 1, 0, 1, 0,                               // counts
1463       maps);                                          // parameter
1464 }
1465 
CompareMaps(ZoneHandleSet<Map> maps)1466 const Operator* SimplifiedOperatorBuilder::CompareMaps(
1467     ZoneHandleSet<Map> maps) {
1468   DCHECK_LT(0, maps.size());
1469   return zone()->New<Operator1<ZoneHandleSet<Map>>>(  // --
1470       IrOpcode::kCompareMaps,                         // opcode
1471       Operator::kNoThrow | Operator::kNoWrite,        // flags
1472       "CompareMaps",                                  // name
1473       1, 1, 1, 1, 1, 0,                               // counts
1474       maps);                                          // parameter
1475 }
1476 
ConvertReceiver(ConvertReceiverMode mode)1477 const Operator* SimplifiedOperatorBuilder::ConvertReceiver(
1478     ConvertReceiverMode mode) {
1479   switch (mode) {
1480     case ConvertReceiverMode::kAny:
1481       return &cache_.kConvertReceiverAnyOperator;
1482     case ConvertReceiverMode::kNullOrUndefined:
1483       return &cache_.kConvertReceiverNullOrUndefinedOperator;
1484     case ConvertReceiverMode::kNotNullOrUndefined:
1485       return &cache_.kConvertReceiverNotNullOrUndefinedOperator;
1486   }
1487   UNREACHABLE();
1488 }
1489 
CheckFloat64Hole(CheckFloat64HoleMode mode,FeedbackSource const & feedback)1490 const Operator* SimplifiedOperatorBuilder::CheckFloat64Hole(
1491     CheckFloat64HoleMode mode, FeedbackSource const& feedback) {
1492   if (!feedback.IsValid()) {
1493     switch (mode) {
1494       case CheckFloat64HoleMode::kAllowReturnHole:
1495         return &cache_.kCheckFloat64HoleAllowReturnHoleOperator;
1496       case CheckFloat64HoleMode::kNeverReturnHole:
1497         return &cache_.kCheckFloat64HoleNeverReturnHoleOperator;
1498     }
1499     UNREACHABLE();
1500   }
1501   return zone()->New<Operator1<CheckFloat64HoleParameters>>(
1502       IrOpcode::kCheckFloat64Hole, Operator::kFoldable | Operator::kNoThrow,
1503       "CheckFloat64Hole", 1, 1, 1, 1, 1, 0,
1504       CheckFloat64HoleParameters(mode, feedback));
1505 }
1506 
SpeculativeBigIntAdd(BigIntOperationHint hint)1507 const Operator* SimplifiedOperatorBuilder::SpeculativeBigIntAdd(
1508     BigIntOperationHint hint) {
1509   return zone()->New<Operator1<BigIntOperationHint>>(
1510       IrOpcode::kSpeculativeBigIntAdd, Operator::kFoldable | Operator::kNoThrow,
1511       "SpeculativeBigIntAdd", 2, 1, 1, 1, 1, 0, hint);
1512 }
1513 
SpeculativeBigIntSubtract(BigIntOperationHint hint)1514 const Operator* SimplifiedOperatorBuilder::SpeculativeBigIntSubtract(
1515     BigIntOperationHint hint) {
1516   return zone()->New<Operator1<BigIntOperationHint>>(
1517       IrOpcode::kSpeculativeBigIntSubtract,
1518       Operator::kFoldable | Operator::kNoThrow, "SpeculativeBigIntSubtract", 2,
1519       1, 1, 1, 1, 0, hint);
1520 }
1521 
SpeculativeBigIntNegate(BigIntOperationHint hint)1522 const Operator* SimplifiedOperatorBuilder::SpeculativeBigIntNegate(
1523     BigIntOperationHint hint) {
1524   return zone()->New<Operator1<BigIntOperationHint>>(
1525       IrOpcode::kSpeculativeBigIntNegate,
1526       Operator::kFoldable | Operator::kNoThrow, "SpeculativeBigIntNegate", 1, 1,
1527       1, 1, 1, 0, hint);
1528 }
1529 
CheckClosure(const Handle<FeedbackCell> & feedback_cell)1530 const Operator* SimplifiedOperatorBuilder::CheckClosure(
1531     const Handle<FeedbackCell>& feedback_cell) {
1532   return zone()->New<Operator1<Handle<FeedbackCell>>>(  // --
1533       IrOpcode::kCheckClosure,                          // opcode
1534       Operator::kNoThrow | Operator::kNoWrite,          // flags
1535       "CheckClosure",                                   // name
1536       1, 1, 1, 1, 1, 0,                                 // counts
1537       feedback_cell);                                   // parameter
1538 }
1539 
FeedbackCellOf(const Operator * op)1540 Handle<FeedbackCell> FeedbackCellOf(const Operator* op) {
1541   DCHECK(IrOpcode::kCheckClosure == op->opcode());
1542   return OpParameter<Handle<FeedbackCell>>(op);
1543 }
1544 
SpeculativeToNumber(NumberOperationHint hint,const FeedbackSource & feedback)1545 const Operator* SimplifiedOperatorBuilder::SpeculativeToNumber(
1546     NumberOperationHint hint, const FeedbackSource& feedback) {
1547   if (!feedback.IsValid()) {
1548     switch (hint) {
1549       case NumberOperationHint::kSignedSmall:
1550         return &cache_.kSpeculativeToNumberSignedSmallOperator;
1551       case NumberOperationHint::kSignedSmallInputs:
1552         break;
1553       case NumberOperationHint::kNumber:
1554         return &cache_.kSpeculativeToNumberNumberOperator;
1555       case NumberOperationHint::kNumberOrBoolean:
1556         // Not used currently.
1557         UNREACHABLE();
1558       case NumberOperationHint::kNumberOrOddball:
1559         return &cache_.kSpeculativeToNumberNumberOrOddballOperator;
1560     }
1561   }
1562   return zone()->New<Operator1<NumberOperationParameters>>(
1563       IrOpcode::kSpeculativeToNumber, Operator::kFoldable | Operator::kNoThrow,
1564       "SpeculativeToNumber", 1, 1, 1, 1, 1, 0,
1565       NumberOperationParameters(hint, feedback));
1566 }
1567 
EnsureWritableFastElements()1568 const Operator* SimplifiedOperatorBuilder::EnsureWritableFastElements() {
1569   return &cache_.kEnsureWritableFastElements;
1570 }
1571 
MaybeGrowFastElements(GrowFastElementsMode mode,const FeedbackSource & feedback)1572 const Operator* SimplifiedOperatorBuilder::MaybeGrowFastElements(
1573     GrowFastElementsMode mode, const FeedbackSource& feedback) {
1574   if (!feedback.IsValid()) {
1575     switch (mode) {
1576       case GrowFastElementsMode::kDoubleElements:
1577         return &cache_.kGrowFastElementsOperatorDoubleElements;
1578       case GrowFastElementsMode::kSmiOrObjectElements:
1579         return &cache_.kGrowFastElementsOperatorSmiOrObjectElements;
1580     }
1581   }
1582   return zone()->New<Operator1<GrowFastElementsParameters>>(  // --
1583       IrOpcode::kMaybeGrowFastElements,                       // opcode
1584       Operator::kNoThrow,                                     // flags
1585       "MaybeGrowFastElements",                                // name
1586       4, 1, 1, 1, 1, 0,                                       // counts
1587       GrowFastElementsParameters(mode, feedback));            // parameter
1588 }
1589 
TransitionElementsKind(ElementsTransition transition)1590 const Operator* SimplifiedOperatorBuilder::TransitionElementsKind(
1591     ElementsTransition transition) {
1592   return zone()->New<Operator1<ElementsTransition>>(  // --
1593       IrOpcode::kTransitionElementsKind,              // opcode
1594       Operator::kNoThrow,                             // flags
1595       "TransitionElementsKind",                       // name
1596       1, 1, 1, 0, 1, 0,                               // counts
1597       transition);                                    // parameter
1598 }
1599 
ArgumentsLength()1600 const Operator* SimplifiedOperatorBuilder::ArgumentsLength() {
1601   return zone()->New<Operator>(    // --
1602       IrOpcode::kArgumentsLength,  // opcode
1603       Operator::kPure,             // flags
1604       "ArgumentsLength",           // name
1605       0, 0, 0, 1, 0, 0);           // counts
1606 }
1607 
RestLength(int formal_parameter_count)1608 const Operator* SimplifiedOperatorBuilder::RestLength(
1609     int formal_parameter_count) {
1610   return zone()->New<Operator1<int>>(  // --
1611       IrOpcode::kRestLength,           // opcode
1612       Operator::kPure,                 // flags
1613       "RestLength",                    // name
1614       0, 0, 0, 1, 0, 0,                // counts
1615       formal_parameter_count);         // parameter
1616 }
1617 
FormalParameterCountOf(const Operator * op)1618 int FormalParameterCountOf(const Operator* op) {
1619   DCHECK(op->opcode() == IrOpcode::kArgumentsLength ||
1620          op->opcode() == IrOpcode::kRestLength);
1621   return OpParameter<int>(op);
1622 }
1623 
operator ==(CheckParameters const & lhs,CheckParameters const & rhs)1624 bool operator==(CheckParameters const& lhs, CheckParameters const& rhs) {
1625   return lhs.feedback() == rhs.feedback();
1626 }
1627 
hash_value(CheckParameters const & p)1628 size_t hash_value(CheckParameters const& p) {
1629   FeedbackSource::Hash feedback_hash;
1630   return feedback_hash(p.feedback());
1631 }
1632 
operator <<(std::ostream & os,CheckParameters const & p)1633 std::ostream& operator<<(std::ostream& os, CheckParameters const& p) {
1634   return os << p.feedback();
1635 }
1636 
CheckParametersOf(Operator const * op)1637 CheckParameters const& CheckParametersOf(Operator const* op) {
1638   if (op->opcode() == IrOpcode::kCheckBounds ||
1639       op->opcode() == IrOpcode::kCheckedUint32Bounds ||
1640       op->opcode() == IrOpcode::kCheckedUint64Bounds) {
1641     return OpParameter<CheckBoundsParameters>(op).check_parameters();
1642   }
1643 #define MAKE_OR(name, arg2, arg3) op->opcode() == IrOpcode::k##name ||
1644   CHECK((CHECKED_WITH_FEEDBACK_OP_LIST(MAKE_OR) false));
1645 #undef MAKE_OR
1646   return OpParameter<CheckParameters>(op);
1647 }
1648 
operator ==(CheckBoundsParameters const & lhs,CheckBoundsParameters const & rhs)1649 bool operator==(CheckBoundsParameters const& lhs,
1650                 CheckBoundsParameters const& rhs) {
1651   return lhs.check_parameters() == rhs.check_parameters() &&
1652          lhs.flags() == rhs.flags();
1653 }
1654 
hash_value(CheckBoundsParameters const & p)1655 size_t hash_value(CheckBoundsParameters const& p) {
1656   return base::hash_combine(hash_value(p.check_parameters()), p.flags());
1657 }
1658 
operator <<(std::ostream & os,CheckBoundsParameters const & p)1659 std::ostream& operator<<(std::ostream& os, CheckBoundsParameters const& p) {
1660   os << p.check_parameters() << ", " << p.flags();
1661   return os;
1662 }
1663 
CheckBoundsParametersOf(Operator const * op)1664 CheckBoundsParameters const& CheckBoundsParametersOf(Operator const* op) {
1665   DCHECK(op->opcode() == IrOpcode::kCheckBounds ||
1666          op->opcode() == IrOpcode::kCheckedUint32Bounds ||
1667          op->opcode() == IrOpcode::kCheckedUint64Bounds);
1668   return OpParameter<CheckBoundsParameters>(op);
1669 }
1670 
operator ==(CheckIfParameters const & lhs,CheckIfParameters const & rhs)1671 bool operator==(CheckIfParameters const& lhs, CheckIfParameters const& rhs) {
1672   return lhs.reason() == rhs.reason() && lhs.feedback() == rhs.feedback();
1673 }
1674 
hash_value(CheckIfParameters const & p)1675 size_t hash_value(CheckIfParameters const& p) {
1676   FeedbackSource::Hash feedback_hash;
1677   return base::hash_combine(p.reason(), feedback_hash(p.feedback()));
1678 }
1679 
operator <<(std::ostream & os,CheckIfParameters const & p)1680 std::ostream& operator<<(std::ostream& os, CheckIfParameters const& p) {
1681   return os << p.reason() << ", " << p.feedback();
1682 }
1683 
CheckIfParametersOf(Operator const * op)1684 CheckIfParameters const& CheckIfParametersOf(Operator const* op) {
1685   CHECK(op->opcode() == IrOpcode::kCheckIf);
1686   return OpParameter<CheckIfParameters>(op);
1687 }
1688 
FastApiCallParametersOf(const Operator * op)1689 FastApiCallParameters const& FastApiCallParametersOf(const Operator* op) {
1690   DCHECK_EQ(IrOpcode::kFastApiCall, op->opcode());
1691   return OpParameter<FastApiCallParameters>(op);
1692 }
1693 
operator <<(std::ostream & os,FastApiCallParameters const & p)1694 std::ostream& operator<<(std::ostream& os, FastApiCallParameters const& p) {
1695   const auto& c_functions = p.c_functions();
1696   for (size_t i = 0; i < c_functions.size(); i++) {
1697     os << c_functions[i].address << ":" << c_functions[i].signature << ", ";
1698   }
1699   return os << p.feedback() << ", " << p.descriptor();
1700 }
1701 
hash_value(FastApiCallParameters const & p)1702 size_t hash_value(FastApiCallParameters const& p) {
1703   const auto& c_functions = p.c_functions();
1704   size_t hash = 0;
1705   for (size_t i = 0; i < c_functions.size(); i++) {
1706     hash = base::hash_combine(c_functions[i].address, c_functions[i].signature);
1707   }
1708   return base::hash_combine(hash, FeedbackSource::Hash()(p.feedback()),
1709                             p.descriptor());
1710 }
1711 
operator ==(FastApiCallParameters const & lhs,FastApiCallParameters const & rhs)1712 bool operator==(FastApiCallParameters const& lhs,
1713                 FastApiCallParameters const& rhs) {
1714   return lhs.c_functions() == rhs.c_functions() &&
1715          lhs.feedback() == rhs.feedback() &&
1716          lhs.descriptor() == rhs.descriptor();
1717 }
1718 
NewDoubleElements(AllocationType allocation)1719 const Operator* SimplifiedOperatorBuilder::NewDoubleElements(
1720     AllocationType allocation) {
1721   return zone()->New<Operator1<AllocationType>>(  // --
1722       IrOpcode::kNewDoubleElements,               // opcode
1723       Operator::kEliminatable,                    // flags
1724       "NewDoubleElements",                        // name
1725       1, 1, 1, 1, 1, 0,                           // counts
1726       allocation);                                // parameter
1727 }
1728 
NewSmiOrObjectElements(AllocationType allocation)1729 const Operator* SimplifiedOperatorBuilder::NewSmiOrObjectElements(
1730     AllocationType allocation) {
1731   return zone()->New<Operator1<AllocationType>>(  // --
1732       IrOpcode::kNewSmiOrObjectElements,          // opcode
1733       Operator::kEliminatable,                    // flags
1734       "NewSmiOrObjectElements",                   // name
1735       1, 1, 1, 1, 1, 0,                           // counts
1736       allocation);                                // parameter
1737 }
1738 
NewArgumentsElements(CreateArgumentsType type,int formal_parameter_count)1739 const Operator* SimplifiedOperatorBuilder::NewArgumentsElements(
1740     CreateArgumentsType type, int formal_parameter_count) {
1741   return zone()->New<Operator1<NewArgumentsElementsParameters>>(  // --
1742       IrOpcode::kNewArgumentsElements,                            // opcode
1743       Operator::kEliminatable,                                    // flags
1744       "NewArgumentsElements",                                     // name
1745       1, 1, 0, 1, 1, 0,                                           // counts
1746       NewArgumentsElementsParameters(type,
1747                                      formal_parameter_count));  // parameter
1748 }
1749 
operator ==(const NewArgumentsElementsParameters & lhs,const NewArgumentsElementsParameters & rhs)1750 bool operator==(const NewArgumentsElementsParameters& lhs,
1751                 const NewArgumentsElementsParameters& rhs) {
1752   return lhs.arguments_type() == rhs.arguments_type() &&
1753          lhs.formal_parameter_count() == rhs.formal_parameter_count();
1754 }
1755 
hash_value(const NewArgumentsElementsParameters & params)1756 inline size_t hash_value(const NewArgumentsElementsParameters& params) {
1757   return base::hash_combine(params.arguments_type(),
1758                             params.formal_parameter_count());
1759 }
1760 
operator <<(std::ostream & os,const NewArgumentsElementsParameters & params)1761 std::ostream& operator<<(std::ostream& os,
1762                          const NewArgumentsElementsParameters& params) {
1763   return os << params.arguments_type()
1764             << ", parameter_count = " << params.formal_parameter_count();
1765 }
1766 
NewArgumentsElementsParametersOf(const Operator * op)1767 const NewArgumentsElementsParameters& NewArgumentsElementsParametersOf(
1768     const Operator* op) {
1769   DCHECK_EQ(IrOpcode::kNewArgumentsElements, op->opcode());
1770   return OpParameter<NewArgumentsElementsParameters>(op);
1771 }
1772 
Allocate(Type type,AllocationType allocation)1773 const Operator* SimplifiedOperatorBuilder::Allocate(Type type,
1774                                                     AllocationType allocation) {
1775   return zone()->New<Operator1<AllocateParameters>>(
1776       IrOpcode::kAllocate, Operator::kEliminatable, "Allocate", 1, 1, 1, 1, 1,
1777       0, AllocateParameters(type, allocation));
1778 }
1779 
AllocateRaw(Type type,AllocationType allocation,AllowLargeObjects allow_large_objects)1780 const Operator* SimplifiedOperatorBuilder::AllocateRaw(
1781     Type type, AllocationType allocation,
1782     AllowLargeObjects allow_large_objects) {
1783   return zone()->New<Operator1<AllocateParameters>>(
1784       IrOpcode::kAllocateRaw, Operator::kEliminatable, "AllocateRaw", 1, 1, 1,
1785       1, 1, 1, AllocateParameters(type, allocation, allow_large_objects));
1786 }
1787 
1788 #define SPECULATIVE_NUMBER_BINOP(Name)                                        \
1789   const Operator* SimplifiedOperatorBuilder::Name(NumberOperationHint hint) { \
1790     switch (hint) {                                                           \
1791       case NumberOperationHint::kSignedSmall:                                 \
1792         return &cache_.k##Name##SignedSmallOperator;                          \
1793       case NumberOperationHint::kSignedSmallInputs:                           \
1794         return &cache_.k##Name##SignedSmallInputsOperator;                    \
1795       case NumberOperationHint::kNumber:                                      \
1796         return &cache_.k##Name##NumberOperator;                               \
1797       case NumberOperationHint::kNumberOrBoolean:                             \
1798         /* Not used currenly. */                                              \
1799         UNREACHABLE();                                                        \
1800       case NumberOperationHint::kNumberOrOddball:                             \
1801         return &cache_.k##Name##NumberOrOddballOperator;                      \
1802     }                                                                         \
1803     UNREACHABLE();                                                            \
1804     return nullptr;                                                           \
1805   }
1806 SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP)
SPECULATIVE_NUMBER_BINOP(SpeculativeNumberLessThan)1807 SPECULATIVE_NUMBER_BINOP(SpeculativeNumberLessThan)
1808 SPECULATIVE_NUMBER_BINOP(SpeculativeNumberLessThanOrEqual)
1809 #undef SPECULATIVE_NUMBER_BINOP
1810 const Operator* SimplifiedOperatorBuilder::SpeculativeNumberEqual(
1811     NumberOperationHint hint) {
1812   switch (hint) {
1813     case NumberOperationHint::kSignedSmall:
1814       return &cache_.kSpeculativeNumberEqualSignedSmallOperator;
1815     case NumberOperationHint::kSignedSmallInputs:
1816       return &cache_.kSpeculativeNumberEqualSignedSmallInputsOperator;
1817     case NumberOperationHint::kNumber:
1818       return &cache_.kSpeculativeNumberEqualNumberOperator;
1819     case NumberOperationHint::kNumberOrBoolean:
1820       return &cache_.kSpeculativeNumberEqualNumberOrBooleanOperator;
1821     case NumberOperationHint::kNumberOrOddball:
1822       return &cache_.kSpeculativeNumberEqualNumberOrOddballOperator;
1823   }
1824   UNREACHABLE();
1825 }
1826 
1827 #define ACCESS_OP_LIST(V)                                                  \
1828   V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1)                   \
1829   V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1)               \
1830   V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0)               \
1831   V(LoadTypedElement, ExternalArrayType, Operator::kNoWrite, 4, 1, 1)      \
1832   V(StoreTypedElement, ExternalArrayType, Operator::kNoRead, 5, 1, 0)      \
1833   V(LoadFromObject, ObjectAccess, Operator::kNoWrite, 2, 1, 1)             \
1834   V(StoreToObject, ObjectAccess, Operator::kNoRead, 3, 1, 0)               \
1835   V(LoadImmutableFromObject, ObjectAccess, Operator::kNoWrite, 2, 1, 1)    \
1836   V(InitializeImmutableInObject, ObjectAccess, Operator::kNoRead, 3, 1, 0) \
1837   V(LoadDataViewElement, ExternalArrayType, Operator::kNoWrite, 4, 1, 1)   \
1838   V(StoreDataViewElement, ExternalArrayType, Operator::kNoRead, 5, 1, 0)
1839 
1840 #define ACCESS(Name, Type, properties, value_input_count, control_input_count, \
1841                output_count)                                                   \
1842   const Operator* SimplifiedOperatorBuilder::Name(const Type& access) {        \
1843     return zone()->New<Operator1<Type>>(                                       \
1844         IrOpcode::k##Name,                                                     \
1845         Operator::kNoDeopt | Operator::kNoThrow | properties, #Name,           \
1846         value_input_count, 1, control_input_count, output_count, 1, 0,         \
1847         access);                                                               \
1848   }
ACCESS_OP_LIST(ACCESS) const1849 ACCESS_OP_LIST(ACCESS)
1850 #undef ACCESS
1851 
1852 const Operator* SimplifiedOperatorBuilder::StoreField(
1853     const FieldAccess& access, bool maybe_initializing_or_transitioning) {
1854   FieldAccess store_access = access;
1855   store_access.maybe_initializing_or_transitioning_store =
1856       maybe_initializing_or_transitioning;
1857   return zone()->New<Operator1<FieldAccess>>(
1858       IrOpcode::kStoreField,
1859       Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoRead, "StoreField",
1860       2, 1, 1, 0, 1, 0, store_access);
1861 }
1862 
LoadMessage()1863 const Operator* SimplifiedOperatorBuilder::LoadMessage() {
1864   return zone()->New<Operator>(IrOpcode::kLoadMessage, Operator::kEliminatable,
1865                                "LoadMessage", 1, 1, 1, 1, 1, 0);
1866 }
1867 
StoreMessage()1868 const Operator* SimplifiedOperatorBuilder::StoreMessage() {
1869   return zone()->New<Operator>(
1870       IrOpcode::kStoreMessage,
1871       Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoRead,
1872       "StoreMessage", 2, 1, 1, 0, 1, 0);
1873 }
1874 
LoadStackArgument()1875 const Operator* SimplifiedOperatorBuilder::LoadStackArgument() {
1876   return &cache_.kLoadStackArgument;
1877 }
1878 
TransitionAndStoreElement(Handle<Map> double_map,Handle<Map> fast_map)1879 const Operator* SimplifiedOperatorBuilder::TransitionAndStoreElement(
1880     Handle<Map> double_map, Handle<Map> fast_map) {
1881   TransitionAndStoreElementParameters parameters(double_map, fast_map);
1882   return zone()->New<Operator1<TransitionAndStoreElementParameters>>(
1883       IrOpcode::kTransitionAndStoreElement,
1884       Operator::kNoDeopt | Operator::kNoThrow, "TransitionAndStoreElement", 3,
1885       1, 1, 0, 1, 0, parameters);
1886 }
1887 
StoreSignedSmallElement()1888 const Operator* SimplifiedOperatorBuilder::StoreSignedSmallElement() {
1889   return zone()->New<Operator>(IrOpcode::kStoreSignedSmallElement,
1890                                Operator::kNoDeopt | Operator::kNoThrow,
1891                                "StoreSignedSmallElement", 3, 1, 1, 0, 1, 0);
1892 }
1893 
TransitionAndStoreNumberElement(Handle<Map> double_map)1894 const Operator* SimplifiedOperatorBuilder::TransitionAndStoreNumberElement(
1895     Handle<Map> double_map) {
1896   TransitionAndStoreNumberElementParameters parameters(double_map);
1897   return zone()->New<Operator1<TransitionAndStoreNumberElementParameters>>(
1898       IrOpcode::kTransitionAndStoreNumberElement,
1899       Operator::kNoDeopt | Operator::kNoThrow,
1900       "TransitionAndStoreNumberElement", 3, 1, 1, 0, 1, 0, parameters);
1901 }
1902 
TransitionAndStoreNonNumberElement(Handle<Map> fast_map,Type value_type)1903 const Operator* SimplifiedOperatorBuilder::TransitionAndStoreNonNumberElement(
1904     Handle<Map> fast_map, Type value_type) {
1905   TransitionAndStoreNonNumberElementParameters parameters(fast_map, value_type);
1906   return zone()->New<Operator1<TransitionAndStoreNonNumberElementParameters>>(
1907       IrOpcode::kTransitionAndStoreNonNumberElement,
1908       Operator::kNoDeopt | Operator::kNoThrow,
1909       "TransitionAndStoreNonNumberElement", 3, 1, 1, 0, 1, 0, parameters);
1910 }
1911 
FastApiCall(const FastApiCallFunctionVector & c_functions,FeedbackSource const & feedback,CallDescriptor * descriptor)1912 const Operator* SimplifiedOperatorBuilder::FastApiCall(
1913     const FastApiCallFunctionVector& c_functions,
1914     FeedbackSource const& feedback, CallDescriptor* descriptor) {
1915   DCHECK(!c_functions.empty());
1916 
1917   // All function overloads have the same number of arguments and options.
1918   const CFunctionInfo* signature = c_functions[0].signature;
1919   const int argument_count = signature->ArgumentCount();
1920   for (size_t i = 1; i < c_functions.size(); i++) {
1921     CHECK_NOT_NULL(c_functions[i].signature);
1922     DCHECK_EQ(c_functions[i].signature->ArgumentCount(), argument_count);
1923     DCHECK_EQ(c_functions[i].signature->HasOptions(),
1924               c_functions[0].signature->HasOptions());
1925   }
1926 
1927   int value_input_count =
1928       argument_count +
1929       static_cast<int>(descriptor->ParameterCount()) +  // slow call
1930       FastApiCallNode::kEffectAndControlInputCount;
1931   return zone()->New<Operator1<FastApiCallParameters>>(
1932       IrOpcode::kFastApiCall, Operator::kNoThrow, "FastApiCall",
1933       value_input_count, 1, 1, 1, 1, 0,
1934       FastApiCallParameters(c_functions, feedback, descriptor));
1935 }
1936 
FastCallExtraInputCount() const1937 int FastApiCallNode::FastCallExtraInputCount() const {
1938   const CFunctionInfo* signature = Parameters().c_functions()[0].signature;
1939   CHECK_NOT_NULL(signature);
1940   return kEffectAndControlInputCount + (signature->HasOptions() ? 1 : 0);
1941 }
1942 
FastCallArgumentCount() const1943 int FastApiCallNode::FastCallArgumentCount() const {
1944   FastApiCallParameters p = FastApiCallParametersOf(node()->op());
1945   const CFunctionInfo* signature = p.c_functions()[0].signature;
1946   CHECK_NOT_NULL(signature);
1947   return signature->ArgumentCount();
1948 }
1949 
SlowCallArgumentCount() const1950 int FastApiCallNode::SlowCallArgumentCount() const {
1951   FastApiCallParameters p = FastApiCallParametersOf(node()->op());
1952   CallDescriptor* descriptor = p.descriptor();
1953   CHECK_NOT_NULL(descriptor);
1954   return static_cast<int>(descriptor->ParameterCount()) +
1955          kContextAndFrameStateInputCount;
1956 }
1957 
1958 #undef PURE_OP_LIST
1959 #undef EFFECT_DEPENDENT_OP_LIST
1960 #undef SPECULATIVE_NUMBER_BINOP_LIST
1961 #undef CHECKED_WITH_FEEDBACK_OP_LIST
1962 #undef CHECKED_BOUNDS_OP_LIST
1963 #undef CHECKED_OP_LIST
1964 #undef ACCESS_OP_LIST
1965 
1966 }  // namespace compiler
1967 }  // namespace internal
1968 }  // namespace v8
1969