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