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