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