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