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