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