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