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 142048 : std::ostream& operator<<(std::ostream& os, BaseTaggedness base_taggedness) {
25 142048 : switch (base_taggedness) {
26 : case kUntaggedBase:
27 86464 : return os << "untagged base";
28 : case kTaggedBase:
29 55584 : 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 0 : std::ostream& operator<<(std::ostream& os, FieldAccess const& access) {
68 0 : 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 0 : os << access.type << ", " << access.machine_type << ", "
81 0 : << access.write_barrier_kind;
82 0 : if (FLAG_untrusted_code_mitigations) {
83 0 : os << ", " << access.load_sensitivity;
84 : }
85 0 : os << "]";
86 0 : return os;
87 : }
88 :
89 : template <>
90 0 : void Operator1<FieldAccess>::PrintParameter(std::ostream& os,
91 : PrintVerbosity verbose) const {
92 0 : if (verbose == PrintVerbosity::kVerbose) {
93 0 : os << parameter();
94 : } else {
95 0 : os << "[+" << parameter().offset << "]";
96 : }
97 0 : }
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 142048 : std::ostream& operator<<(std::ostream& os, ElementAccess const& access) {
118 284096 : os << access.base_is_tagged << ", " << access.header_size << ", "
119 284096 : << access.type << ", " << access.machine_type << ", "
120 284096 : << access.write_barrier_kind;
121 142048 : if (FLAG_untrusted_code_mitigations) {
122 0 : os << ", " << access.load_sensitivity;
123 : }
124 142048 : return os;
125 : }
126 :
127 29530559 : const FieldAccess& FieldAccessOf(const Operator* op) {
128 : DCHECK_NOT_NULL(op);
129 : DCHECK(op->opcode() == IrOpcode::kLoadField ||
130 : op->opcode() == IrOpcode::kStoreField);
131 29530559 : return OpParameter<FieldAccess>(op);
132 : }
133 :
134 :
135 396596 : const ElementAccess& ElementAccessOf(const Operator* op) {
136 : DCHECK_NOT_NULL(op);
137 : DCHECK(op->opcode() == IrOpcode::kLoadElement ||
138 : op->opcode() == IrOpcode::kStoreElement);
139 396596 : return OpParameter<ElementAccess>(op);
140 : }
141 :
142 49131 : 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 49131 : return OpParameter<ExternalArrayType>(op);
148 : }
149 :
150 875 : ConvertReceiverMode ConvertReceiverModeOf(Operator const* op) {
151 : DCHECK_EQ(IrOpcode::kConvertReceiver, op->opcode());
152 875 : 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 2377 : CheckFloat64HoleParameters const& CheckFloat64HoleParametersOf(
170 : Operator const* op) {
171 : DCHECK_EQ(IrOpcode::kCheckFloat64Hole, op->opcode());
172 2377 : 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 59320 : CheckForMinusZeroMode CheckMinusZeroModeOf(const Operator* op) {
197 : DCHECK(op->opcode() == IrOpcode::kChangeFloat64ToTagged ||
198 : op->opcode() == IrOpcode::kCheckedInt32Mul);
199 59320 : return OpParameter<CheckForMinusZeroMode>(op);
200 : }
201 :
202 0 : size_t hash_value(CheckForMinusZeroMode mode) {
203 73405 : 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 395361 : CheckMapsParameters const& CheckMapsParametersOf(Operator const* op) {
245 : DCHECK_EQ(IrOpcode::kCheckMaps, op->opcode());
246 395361 : return OpParameter<CheckMapsParameters>(op);
247 : }
248 :
249 23517 : ZoneHandleSet<Map> const& CompareMapsParametersOf(Operator const* op) {
250 : DCHECK_EQ(IrOpcode::kCompareMaps, op->opcode());
251 23517 : return OpParameter<ZoneHandleSet<Map>>(op);
252 : }
253 :
254 15649 : ZoneHandleSet<Map> const& MapGuardMapsOf(Operator const* op) {
255 : DCHECK_EQ(IrOpcode::kMapGuard, op->opcode());
256 15649 : 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 13624 : const GrowFastElementsParameters& GrowFastElementsParametersOf(
302 : const Operator* op) {
303 : DCHECK_EQ(IrOpcode::kMaybeGrowFastElements, op->opcode());
304 13624 : 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 1842 : ElementsTransition const& ElementsTransitionOf(const Operator* op) {
332 : DCHECK_EQ(IrOpcode::kTransitionElementsKind, op->opcode());
333 1842 : 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 28 : 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 695 : Handle<Map> DoubleMapParameterOf(const Operator* op) {
449 695 : if (op->opcode() == IrOpcode::kTransitionAndStoreElement) {
450 : return OpParameter<TransitionAndStoreElementParameters>(op).double_map();
451 28 : } 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 785 : Handle<Map> FastMapParameterOf(const Operator* op) {
466 785 : 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 1145945 : 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 1145945 : 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 133210 : NumberOperationParameters const& NumberOperationParametersOf(
530 : Operator const* op) {
531 : DCHECK_EQ(IrOpcode::kSpeculativeToNumber, op->opcode());
532 133210 : 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 0 : V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
541 : AllocateParameters info) {
542 0 : 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 397148 : AllocationType AllocationTypeOf(const Operator* op) {
551 397148 : if (op->opcode() == IrOpcode::kNewDoubleElements ||
552 : op->opcode() == IrOpcode::kNewSmiOrObjectElements) {
553 499 : return OpParameter<AllocationType>(op);
554 : }
555 : DCHECK(op->opcode() == IrOpcode::kAllocate ||
556 : op->opcode() == IrOpcode::kAllocateRaw);
557 396649 : return OpParameter<AllocateParameters>(op).allocation_type();
558 : }
559 :
560 143015 : Type AllocateTypeOf(const Operator* op) {
561 : DCHECK_EQ(IrOpcode::kAllocate, op->opcode());
562 143015 : return OpParameter<AllocateParameters>(op).type();
563 : }
564 :
565 430 : UnicodeEncoding UnicodeEncodingOf(const Operator* op) {
566 : DCHECK(op->opcode() == IrOpcode::kStringFromSingleCodePoint ||
567 : op->opcode() == IrOpcode::kStringCodePointAt);
568 430 : return OpParameter<UnicodeEncoding>(op);
569 : }
570 :
571 2539 : AbortReason AbortReasonOf(const Operator* op) {
572 : DCHECK_EQ(IrOpcode::kRuntimeAbort, op->opcode());
573 2539 : return static_cast<AbortReason>(OpParameter<int>(op));
574 : }
575 :
576 67943 : const CheckTaggedInputParameters& CheckTaggedInputParametersOf(
577 : const Operator* op) {
578 : DCHECK(op->opcode() == IrOpcode::kCheckedTruncateTaggedToWord32 ||
579 : op->opcode() == IrOpcode::kCheckedTaggedToFloat64);
580 67943 : 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 4955 : 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 4955 : 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(ChangeCompressedToTaggedSigned, Operator::kNoProperties, 1, 0) \
701 : V(ChangeTaggedToCompressedSigned, Operator::kNoProperties, 1, 0) \
702 : V(ChangeFloat64ToTaggedPointer, Operator::kNoProperties, 1, 0) \
703 : V(ChangeInt31ToTaggedSigned, Operator::kNoProperties, 1, 0) \
704 : V(ChangeInt32ToTagged, Operator::kNoProperties, 1, 0) \
705 : V(ChangeInt64ToTagged, Operator::kNoProperties, 1, 0) \
706 : V(ChangeUint32ToTagged, Operator::kNoProperties, 1, 0) \
707 : V(ChangeUint64ToTagged, Operator::kNoProperties, 1, 0) \
708 : V(ChangeTaggedToBit, Operator::kNoProperties, 1, 0) \
709 : V(ChangeBitToTagged, Operator::kNoProperties, 1, 0) \
710 : V(TruncateTaggedToBit, Operator::kNoProperties, 1, 0) \
711 : V(TruncateTaggedPointerToBit, Operator::kNoProperties, 1, 0) \
712 : V(TruncateTaggedToWord32, Operator::kNoProperties, 1, 0) \
713 : V(TruncateTaggedToFloat64, Operator::kNoProperties, 1, 0) \
714 : V(ObjectIsArrayBufferView, Operator::kNoProperties, 1, 0) \
715 : V(ObjectIsBigInt, Operator::kNoProperties, 1, 0) \
716 : V(ObjectIsCallable, Operator::kNoProperties, 1, 0) \
717 : V(ObjectIsConstructor, Operator::kNoProperties, 1, 0) \
718 : V(ObjectIsDetectableCallable, Operator::kNoProperties, 1, 0) \
719 : V(ObjectIsMinusZero, Operator::kNoProperties, 1, 0) \
720 : V(NumberIsMinusZero, Operator::kNoProperties, 1, 0) \
721 : V(ObjectIsNaN, Operator::kNoProperties, 1, 0) \
722 : V(NumberIsNaN, Operator::kNoProperties, 1, 0) \
723 : V(ObjectIsNonCallable, Operator::kNoProperties, 1, 0) \
724 : V(ObjectIsNumber, Operator::kNoProperties, 1, 0) \
725 : V(ObjectIsReceiver, Operator::kNoProperties, 1, 0) \
726 : V(ObjectIsSmi, Operator::kNoProperties, 1, 0) \
727 : V(ObjectIsString, Operator::kNoProperties, 1, 0) \
728 : V(ObjectIsSymbol, Operator::kNoProperties, 1, 0) \
729 : V(ObjectIsUndetectable, Operator::kNoProperties, 1, 0) \
730 : V(NumberIsFloat64Hole, Operator::kNoProperties, 1, 0) \
731 : V(NumberIsFinite, Operator::kNoProperties, 1, 0) \
732 : V(ObjectIsFiniteNumber, Operator::kNoProperties, 1, 0) \
733 : V(NumberIsInteger, Operator::kNoProperties, 1, 0) \
734 : V(ObjectIsSafeInteger, Operator::kNoProperties, 1, 0) \
735 : V(NumberIsSafeInteger, Operator::kNoProperties, 1, 0) \
736 : V(ObjectIsInteger, Operator::kNoProperties, 1, 0) \
737 : V(ConvertTaggedHoleToUndefined, Operator::kNoProperties, 1, 0) \
738 : V(SameValue, Operator::kCommutative, 2, 0) \
739 : V(SameValueNumbersOnly, Operator::kCommutative, 2, 0) \
740 : V(NumberSameValue, Operator::kCommutative, 2, 0) \
741 : V(ReferenceEqual, Operator::kCommutative, 2, 0) \
742 : V(StringEqual, Operator::kCommutative, 2, 0) \
743 : V(StringLessThan, Operator::kNoProperties, 2, 0) \
744 : V(StringLessThanOrEqual, Operator::kNoProperties, 2, 0) \
745 : V(ToBoolean, Operator::kNoProperties, 1, 0) \
746 : V(NewConsOneByteString, Operator::kNoProperties, 3, 0) \
747 : V(NewConsTwoByteString, Operator::kNoProperties, 3, 0) \
748 : V(NewConsString, Operator::kNoProperties, 3, 0) \
749 : V(PoisonIndex, Operator::kNoProperties, 1, 0)
750 :
751 : #define EFFECT_DEPENDENT_OP_LIST(V) \
752 : V(StringCharCodeAt, Operator::kNoProperties, 2, 1) \
753 : V(StringSubstring, Operator::kNoProperties, 3, 1) \
754 : V(DateNow, Operator::kNoProperties, 0, 1)
755 :
756 : #define SPECULATIVE_NUMBER_BINOP_LIST(V) \
757 : SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(V) \
758 : V(SpeculativeNumberEqual) \
759 : V(SpeculativeNumberLessThan) \
760 : V(SpeculativeNumberLessThanOrEqual)
761 :
762 : #define CHECKED_OP_LIST(V) \
763 : V(CheckEqualsInternalizedString, 2, 0) \
764 : V(CheckEqualsSymbol, 2, 0) \
765 : V(CheckHeapObject, 1, 1) \
766 : V(CheckNonEmptyString, 1, 1) \
767 : V(CheckNonEmptyOneByteString, 1, 1) \
768 : V(CheckNonEmptyTwoByteString, 1, 1) \
769 : V(CheckInternalizedString, 1, 1) \
770 : V(CheckNotTaggedHole, 1, 1) \
771 : V(CheckReceiver, 1, 1) \
772 : V(CheckReceiverOrNullOrUndefined, 1, 1) \
773 : V(CheckSymbol, 1, 1) \
774 : V(CheckedInt32Add, 2, 1) \
775 : V(CheckedInt32Div, 2, 1) \
776 : V(CheckedInt32Mod, 2, 1) \
777 : V(CheckedInt32Sub, 2, 1) \
778 : V(CheckedUint32Div, 2, 1) \
779 : V(CheckedUint32Mod, 2, 1)
780 :
781 : #define CHECKED_WITH_FEEDBACK_OP_LIST(V) \
782 : V(CheckBounds, 2, 1) \
783 : V(CheckNumber, 1, 1) \
784 : V(CheckSmi, 1, 1) \
785 : V(CheckString, 1, 1) \
786 : V(CheckedInt32ToTaggedSigned, 1, 1) \
787 : V(CheckedInt64ToInt32, 1, 1) \
788 : V(CheckedInt64ToTaggedSigned, 1, 1) \
789 : V(CheckedTaggedSignedToInt32, 1, 1) \
790 : V(CheckedTaggedToTaggedPointer, 1, 1) \
791 : V(CheckedTaggedToTaggedSigned, 1, 1) \
792 : V(CheckedCompressedToTaggedPointer, 1, 1) \
793 : V(CheckedCompressedToTaggedSigned, 1, 1) \
794 : V(CheckedTaggedToCompressedPointer, 1, 1) \
795 : V(CheckedTaggedToCompressedSigned, 1, 1) \
796 : V(CheckedUint32ToInt32, 1, 1) \
797 : V(CheckedUint32ToTaggedSigned, 1, 1) \
798 : V(CheckedUint64Bounds, 2, 1) \
799 : V(CheckedUint64ToInt32, 1, 1) \
800 : V(CheckedUint64ToTaggedSigned, 1, 1)
801 :
802 : #define CHECKED_BOUNDS_OP_LIST(V) V(CheckedUint32Bounds)
803 :
804 28938 : struct SimplifiedOperatorGlobalCache final {
805 : #define PURE(Name, properties, value_input_count, control_input_count) \
806 : struct Name##Operator final : public Operator { \
807 : Name##Operator() \
808 : : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \
809 : value_input_count, 0, control_input_count, 1, 0, 0) {} \
810 : }; \
811 : Name##Operator k##Name;
812 3530436 : PURE_OP_LIST(PURE)
813 : #undef PURE
814 :
815 : #define EFFECT_DEPENDENT(Name, properties, value_input_count, \
816 : control_input_count) \
817 : struct Name##Operator final : public Operator { \
818 : Name##Operator() \
819 : : Operator(IrOpcode::k##Name, \
820 : Operator::kNoDeopt | Operator::kNoWrite | \
821 : Operator::kNoThrow | properties, \
822 : #Name, value_input_count, 1, control_input_count, 1, 1, \
823 : 0) {} \
824 : }; \
825 : Name##Operator k##Name;
826 86814 : EFFECT_DEPENDENT_OP_LIST(EFFECT_DEPENDENT)
827 : #undef EFFECT_DEPENDENT
828 :
829 : #define CHECKED(Name, value_input_count, value_output_count) \
830 : struct Name##Operator final : public Operator { \
831 : Name##Operator() \
832 : : Operator(IrOpcode::k##Name, \
833 : Operator::kFoldable | Operator::kNoThrow, #Name, \
834 : value_input_count, 1, 1, value_output_count, 1, 0) {} \
835 : }; \
836 : Name##Operator k##Name;
837 491946 : CHECKED_OP_LIST(CHECKED)
838 : #undef CHECKED
839 :
840 : #define CHECKED_WITH_FEEDBACK(Name, value_input_count, value_output_count) \
841 : struct Name##Operator final : public Operator1<CheckParameters> { \
842 : Name##Operator() \
843 : : Operator1<CheckParameters>( \
844 : IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, \
845 : #Name, value_input_count, 1, 1, value_output_count, 1, 0, \
846 : CheckParameters(VectorSlotPair())) {} \
847 : }; \
848 : Name##Operator k##Name;
849 1099644 : CHECKED_WITH_FEEDBACK_OP_LIST(CHECKED_WITH_FEEDBACK)
850 : #undef CHECKED_WITH_FEEDBACK
851 :
852 : #define CHECKED_BOUNDS(Name) \
853 : struct Name##Operator final : public Operator1<CheckBoundsParameters> { \
854 : Name##Operator(VectorSlotPair feedback, CheckBoundsParameters::Mode mode) \
855 : : Operator1<CheckBoundsParameters>( \
856 : IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, \
857 : #Name, 2, 1, 1, 1, 1, 0, \
858 : CheckBoundsParameters(feedback, mode)) {} \
859 : }; \
860 : Name##Operator k##Name##Deopting = { \
861 : VectorSlotPair(), CheckBoundsParameters::kDeoptOnOutOfBounds}; \
862 : Name##Operator k##Name##Aborting = { \
863 : VectorSlotPair(), CheckBoundsParameters::kAbortOnOutOfBounds};
864 124646 : CHECKED_BOUNDS_OP_LIST(CHECKED_BOUNDS)
865 : #undef CHECKED_BOUNDS
866 :
867 : template <DeoptimizeReason kDeoptimizeReason>
868 0 : struct CheckIfOperator final : public Operator1<CheckIfParameters> {
869 1186458 : CheckIfOperator()
870 : : Operator1<CheckIfParameters>(
871 : IrOpcode::kCheckIf, Operator::kFoldable | Operator::kNoThrow,
872 : "CheckIf", 1, 1, 1, 0, 1, 0,
873 2372916 : CheckIfParameters(kDeoptimizeReason, VectorSlotPair())) {}
874 : };
875 : #define CHECK_IF(Name, message) \
876 : CheckIfOperator<DeoptimizeReason::k##Name> kCheckIf##Name;
877 : DEOPTIMIZE_REASON_LIST(CHECK_IF)
878 : #undef CHECK_IF
879 :
880 : template <UnicodeEncoding kEncoding>
881 0 : struct StringCodePointAtOperator final : public Operator1<UnicodeEncoding> {
882 57876 : StringCodePointAtOperator()
883 : : Operator1<UnicodeEncoding>(IrOpcode::kStringCodePointAt,
884 : Operator::kFoldable | Operator::kNoThrow,
885 : "StringCodePointAt", 2, 1, 1, 1, 1, 0,
886 57876 : kEncoding) {}
887 : };
888 : StringCodePointAtOperator<UnicodeEncoding::UTF16>
889 : kStringCodePointAtOperatorUTF16;
890 : StringCodePointAtOperator<UnicodeEncoding::UTF32>
891 : kStringCodePointAtOperatorUTF32;
892 :
893 : template <UnicodeEncoding kEncoding>
894 0 : struct StringFromSingleCodePointOperator final
895 : : public Operator1<UnicodeEncoding> {
896 57876 : StringFromSingleCodePointOperator()
897 : : Operator1<UnicodeEncoding>(
898 : IrOpcode::kStringFromSingleCodePoint, Operator::kPure,
899 57876 : "StringFromSingleCodePoint", 1, 0, 0, 1, 0, 0, kEncoding) {}
900 : };
901 : StringFromSingleCodePointOperator<UnicodeEncoding::UTF16>
902 : kStringFromSingleCodePointOperatorUTF16;
903 : StringFromSingleCodePointOperator<UnicodeEncoding::UTF32>
904 : kStringFromSingleCodePointOperatorUTF32;
905 :
906 0 : struct FindOrderedHashMapEntryOperator final : public Operator {
907 28938 : FindOrderedHashMapEntryOperator()
908 : : Operator(IrOpcode::kFindOrderedHashMapEntry, Operator::kEliminatable,
909 28938 : "FindOrderedHashMapEntry", 2, 1, 1, 1, 1, 0) {}
910 : };
911 : FindOrderedHashMapEntryOperator kFindOrderedHashMapEntry;
912 :
913 0 : struct FindOrderedHashMapEntryForInt32KeyOperator final : public Operator {
914 28938 : FindOrderedHashMapEntryForInt32KeyOperator()
915 : : Operator(IrOpcode::kFindOrderedHashMapEntryForInt32Key,
916 : Operator::kEliminatable,
917 28938 : "FindOrderedHashMapEntryForInt32Key", 2, 1, 1, 1, 1, 0) {}
918 : };
919 : FindOrderedHashMapEntryForInt32KeyOperator
920 : kFindOrderedHashMapEntryForInt32Key;
921 :
922 0 : struct ArgumentsFrameOperator final : public Operator {
923 28938 : ArgumentsFrameOperator()
924 : : Operator(IrOpcode::kArgumentsFrame, Operator::kPure, "ArgumentsFrame",
925 28938 : 0, 0, 0, 1, 0, 0) {}
926 : };
927 : ArgumentsFrameOperator kArgumentsFrame;
928 :
929 : template <CheckForMinusZeroMode kMode>
930 0 : struct ChangeFloat64ToTaggedOperator final
931 : : public Operator1<CheckForMinusZeroMode> {
932 57876 : ChangeFloat64ToTaggedOperator()
933 : : Operator1<CheckForMinusZeroMode>(
934 : IrOpcode::kChangeFloat64ToTagged, Operator::kPure,
935 57876 : "ChangeFloat64ToTagged", 1, 0, 0, 1, 0, 0, kMode) {}
936 : };
937 : ChangeFloat64ToTaggedOperator<CheckForMinusZeroMode::kCheckForMinusZero>
938 : kChangeFloat64ToTaggedCheckForMinusZeroOperator;
939 : ChangeFloat64ToTaggedOperator<CheckForMinusZeroMode::kDontCheckForMinusZero>
940 : kChangeFloat64ToTaggedDontCheckForMinusZeroOperator;
941 :
942 : template <CheckForMinusZeroMode kMode>
943 0 : struct CheckedInt32MulOperator final
944 : : public Operator1<CheckForMinusZeroMode> {
945 57876 : CheckedInt32MulOperator()
946 : : Operator1<CheckForMinusZeroMode>(
947 : IrOpcode::kCheckedInt32Mul,
948 : Operator::kFoldable | Operator::kNoThrow, "CheckedInt32Mul", 2, 1,
949 57876 : 1, 1, 1, 0, kMode) {}
950 : };
951 : CheckedInt32MulOperator<CheckForMinusZeroMode::kCheckForMinusZero>
952 : kCheckedInt32MulCheckForMinusZeroOperator;
953 : CheckedInt32MulOperator<CheckForMinusZeroMode::kDontCheckForMinusZero>
954 : kCheckedInt32MulDontCheckForMinusZeroOperator;
955 :
956 : template <CheckForMinusZeroMode kMode>
957 0 : struct CheckedFloat64ToInt32Operator final
958 : : public Operator1<CheckMinusZeroParameters> {
959 57876 : CheckedFloat64ToInt32Operator()
960 : : Operator1<CheckMinusZeroParameters>(
961 : IrOpcode::kCheckedFloat64ToInt32,
962 : Operator::kFoldable | Operator::kNoThrow, "CheckedFloat64ToInt32",
963 : 1, 1, 1, 1, 1, 0,
964 115752 : CheckMinusZeroParameters(kMode, VectorSlotPair())) {}
965 : };
966 : CheckedFloat64ToInt32Operator<CheckForMinusZeroMode::kCheckForMinusZero>
967 : kCheckedFloat64ToInt32CheckForMinusZeroOperator;
968 : CheckedFloat64ToInt32Operator<CheckForMinusZeroMode::kDontCheckForMinusZero>
969 : kCheckedFloat64ToInt32DontCheckForMinusZeroOperator;
970 :
971 : template <CheckForMinusZeroMode kMode>
972 0 : struct CheckedFloat64ToInt64Operator final
973 : : public Operator1<CheckMinusZeroParameters> {
974 57876 : CheckedFloat64ToInt64Operator()
975 : : Operator1<CheckMinusZeroParameters>(
976 : IrOpcode::kCheckedFloat64ToInt64,
977 : Operator::kFoldable | Operator::kNoThrow, "CheckedFloat64ToInt64",
978 : 1, 1, 1, 1, 1, 0,
979 115752 : CheckMinusZeroParameters(kMode, VectorSlotPair())) {}
980 : };
981 : CheckedFloat64ToInt64Operator<CheckForMinusZeroMode::kCheckForMinusZero>
982 : kCheckedFloat64ToInt64CheckForMinusZeroOperator;
983 : CheckedFloat64ToInt64Operator<CheckForMinusZeroMode::kDontCheckForMinusZero>
984 : kCheckedFloat64ToInt64DontCheckForMinusZeroOperator;
985 :
986 : template <CheckForMinusZeroMode kMode>
987 0 : struct CheckedTaggedToInt32Operator final
988 : : public Operator1<CheckMinusZeroParameters> {
989 57876 : CheckedTaggedToInt32Operator()
990 : : Operator1<CheckMinusZeroParameters>(
991 : IrOpcode::kCheckedTaggedToInt32,
992 : Operator::kFoldable | Operator::kNoThrow, "CheckedTaggedToInt32",
993 : 1, 1, 1, 1, 1, 0,
994 115752 : CheckMinusZeroParameters(kMode, VectorSlotPair())) {}
995 : };
996 : CheckedTaggedToInt32Operator<CheckForMinusZeroMode::kCheckForMinusZero>
997 : kCheckedTaggedToInt32CheckForMinusZeroOperator;
998 : CheckedTaggedToInt32Operator<CheckForMinusZeroMode::kDontCheckForMinusZero>
999 : kCheckedTaggedToInt32DontCheckForMinusZeroOperator;
1000 :
1001 : template <CheckForMinusZeroMode kMode>
1002 0 : struct CheckedTaggedToInt64Operator final
1003 : : public Operator1<CheckMinusZeroParameters> {
1004 57876 : CheckedTaggedToInt64Operator()
1005 : : Operator1<CheckMinusZeroParameters>(
1006 : IrOpcode::kCheckedTaggedToInt64,
1007 : Operator::kFoldable | Operator::kNoThrow, "CheckedTaggedToInt64",
1008 : 1, 1, 1, 1, 1, 0,
1009 115752 : CheckMinusZeroParameters(kMode, VectorSlotPair())) {}
1010 : };
1011 : CheckedTaggedToInt64Operator<CheckForMinusZeroMode::kCheckForMinusZero>
1012 : kCheckedTaggedToInt64CheckForMinusZeroOperator;
1013 : CheckedTaggedToInt64Operator<CheckForMinusZeroMode::kDontCheckForMinusZero>
1014 : kCheckedTaggedToInt64DontCheckForMinusZeroOperator;
1015 :
1016 : template <CheckTaggedInputMode kMode>
1017 0 : struct CheckedTaggedToFloat64Operator final
1018 : : public Operator1<CheckTaggedInputParameters> {
1019 57876 : CheckedTaggedToFloat64Operator()
1020 : : Operator1<CheckTaggedInputParameters>(
1021 : IrOpcode::kCheckedTaggedToFloat64,
1022 : Operator::kFoldable | Operator::kNoThrow,
1023 : "CheckedTaggedToFloat64", 1, 1, 1, 1, 1, 0,
1024 115752 : CheckTaggedInputParameters(kMode, VectorSlotPair())) {}
1025 : };
1026 : CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumber>
1027 : kCheckedTaggedToFloat64NumberOperator;
1028 : CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumberOrOddball>
1029 : kCheckedTaggedToFloat64NumberOrOddballOperator;
1030 :
1031 : template <CheckTaggedInputMode kMode>
1032 0 : struct CheckedTruncateTaggedToWord32Operator final
1033 : : public Operator1<CheckTaggedInputParameters> {
1034 57876 : CheckedTruncateTaggedToWord32Operator()
1035 : : Operator1<CheckTaggedInputParameters>(
1036 : IrOpcode::kCheckedTruncateTaggedToWord32,
1037 : Operator::kFoldable | Operator::kNoThrow,
1038 : "CheckedTruncateTaggedToWord32", 1, 1, 1, 1, 1, 0,
1039 115752 : CheckTaggedInputParameters(kMode, VectorSlotPair())) {}
1040 : };
1041 : CheckedTruncateTaggedToWord32Operator<CheckTaggedInputMode::kNumber>
1042 : kCheckedTruncateTaggedToWord32NumberOperator;
1043 : CheckedTruncateTaggedToWord32Operator<CheckTaggedInputMode::kNumberOrOddball>
1044 : kCheckedTruncateTaggedToWord32NumberOrOddballOperator;
1045 :
1046 : template <ConvertReceiverMode kMode>
1047 0 : struct ConvertReceiverOperator final : public Operator1<ConvertReceiverMode> {
1048 86814 : ConvertReceiverOperator()
1049 : : Operator1<ConvertReceiverMode>( // --
1050 : IrOpcode::kConvertReceiver, // opcode
1051 : Operator::kEliminatable, // flags
1052 : "ConvertReceiver", // name
1053 : 2, 1, 1, 1, 1, 0, // counts
1054 86814 : kMode) {} // param
1055 : };
1056 : ConvertReceiverOperator<ConvertReceiverMode::kAny>
1057 : kConvertReceiverAnyOperator;
1058 : ConvertReceiverOperator<ConvertReceiverMode::kNullOrUndefined>
1059 : kConvertReceiverNullOrUndefinedOperator;
1060 : ConvertReceiverOperator<ConvertReceiverMode::kNotNullOrUndefined>
1061 : kConvertReceiverNotNullOrUndefinedOperator;
1062 :
1063 : template <CheckFloat64HoleMode kMode>
1064 0 : struct CheckFloat64HoleNaNOperator final
1065 : : public Operator1<CheckFloat64HoleParameters> {
1066 57876 : CheckFloat64HoleNaNOperator()
1067 : : Operator1<CheckFloat64HoleParameters>(
1068 : IrOpcode::kCheckFloat64Hole,
1069 : Operator::kFoldable | Operator::kNoThrow, "CheckFloat64Hole", 1,
1070 : 1, 1, 1, 1, 0,
1071 115752 : CheckFloat64HoleParameters(kMode, VectorSlotPair())) {}
1072 : };
1073 : CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kAllowReturnHole>
1074 : kCheckFloat64HoleAllowReturnHoleOperator;
1075 : CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kNeverReturnHole>
1076 : kCheckFloat64HoleNeverReturnHoleOperator;
1077 :
1078 0 : struct EnsureWritableFastElementsOperator final : public Operator {
1079 28938 : EnsureWritableFastElementsOperator()
1080 : : Operator( // --
1081 : IrOpcode::kEnsureWritableFastElements, // opcode
1082 : Operator::kNoDeopt | Operator::kNoThrow, // flags
1083 : "EnsureWritableFastElements", // name
1084 28938 : 2, 1, 1, 1, 1, 0) {} // counts
1085 : };
1086 : EnsureWritableFastElementsOperator kEnsureWritableFastElements;
1087 :
1088 : template <GrowFastElementsMode kMode>
1089 0 : struct GrowFastElementsOperator final
1090 : : public Operator1<GrowFastElementsParameters> {
1091 57876 : GrowFastElementsOperator()
1092 : : Operator1(IrOpcode::kMaybeGrowFastElements, Operator::kNoThrow,
1093 : "MaybeGrowFastElements", 4, 1, 1, 1, 1, 0,
1094 115752 : GrowFastElementsParameters(kMode, VectorSlotPair())) {}
1095 : };
1096 :
1097 : GrowFastElementsOperator<GrowFastElementsMode::kDoubleElements>
1098 : kGrowFastElementsOperatorDoubleElements;
1099 : GrowFastElementsOperator<GrowFastElementsMode::kSmiOrObjectElements>
1100 : kGrowFastElementsOperatorSmiOrObjectElements;
1101 :
1102 0 : struct LoadFieldByIndexOperator final : public Operator {
1103 28938 : LoadFieldByIndexOperator()
1104 : : Operator( // --
1105 : IrOpcode::kLoadFieldByIndex, // opcode
1106 : Operator::kEliminatable, // flags,
1107 : "LoadFieldByIndex", // name
1108 28938 : 2, 1, 1, 1, 1, 0) {} // counts;
1109 : };
1110 : LoadFieldByIndexOperator kLoadFieldByIndex;
1111 :
1112 0 : struct LoadStackArgumentOperator final : public Operator {
1113 28938 : LoadStackArgumentOperator()
1114 : : Operator( // --
1115 : IrOpcode::kLoadStackArgument, // opcode
1116 : Operator::kNoDeopt | Operator::kNoThrow |
1117 : Operator::kNoWrite, // flags
1118 : "LoadStackArgument", // name
1119 28938 : 2, 1, 1, 1, 1, 0) {} // counts
1120 : };
1121 : LoadStackArgumentOperator kLoadStackArgument;
1122 :
1123 0 : struct LoadMessageOperator final : public Operator {
1124 28938 : LoadMessageOperator()
1125 : : Operator( // --
1126 : IrOpcode::kLoadMessage, // opcode
1127 : Operator::kNoDeopt | Operator::kNoThrow |
1128 : Operator::kNoWrite, // flags
1129 : "LoadMessage", // name
1130 28938 : 1, 1, 1, 1, 1, 0) {} // counts
1131 : };
1132 : LoadMessageOperator kLoadMessage;
1133 :
1134 0 : struct StoreMessageOperator final : public Operator {
1135 28938 : StoreMessageOperator()
1136 : : Operator( // --
1137 : IrOpcode::kStoreMessage, // opcode
1138 : Operator::kNoDeopt | Operator::kNoThrow |
1139 : Operator::kNoRead, // flags
1140 : "StoreMessage", // name
1141 28938 : 2, 1, 1, 0, 1, 0) {} // counts
1142 : };
1143 : StoreMessageOperator kStoreMessage;
1144 :
1145 : #define SPECULATIVE_NUMBER_BINOP(Name) \
1146 : template <NumberOperationHint kHint> \
1147 : struct Name##Operator final : public Operator1<NumberOperationHint> { \
1148 : Name##Operator() \
1149 : : Operator1<NumberOperationHint>( \
1150 : IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, \
1151 : #Name, 2, 1, 1, 1, 1, 0, kHint) {} \
1152 : }; \
1153 : Name##Operator<NumberOperationHint::kSignedSmall> \
1154 : k##Name##SignedSmallOperator; \
1155 : Name##Operator<NumberOperationHint::kSignedSmallInputs> \
1156 : k##Name##SignedSmallInputsOperator; \
1157 : Name##Operator<NumberOperationHint::kSigned32> k##Name##Signed32Operator; \
1158 : Name##Operator<NumberOperationHint::kNumber> k##Name##NumberOperator; \
1159 : Name##Operator<NumberOperationHint::kNumberOrOddball> \
1160 : k##Name##NumberOrOddballOperator;
1161 4630080 : SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP)
1162 : #undef SPECULATIVE_NUMBER_BINOP
1163 :
1164 : template <NumberOperationHint kHint>
1165 0 : struct SpeculativeToNumberOperator final
1166 : : public Operator1<NumberOperationParameters> {
1167 115752 : SpeculativeToNumberOperator()
1168 : : Operator1<NumberOperationParameters>(
1169 : IrOpcode::kSpeculativeToNumber,
1170 : Operator::kFoldable | Operator::kNoThrow, "SpeculativeToNumber",
1171 : 1, 1, 1, 1, 1, 0,
1172 231504 : NumberOperationParameters(kHint, VectorSlotPair())) {}
1173 : };
1174 : SpeculativeToNumberOperator<NumberOperationHint::kSignedSmall>
1175 : kSpeculativeToNumberSignedSmallOperator;
1176 : SpeculativeToNumberOperator<NumberOperationHint::kSigned32>
1177 : kSpeculativeToNumberSigned32Operator;
1178 : SpeculativeToNumberOperator<NumberOperationHint::kNumber>
1179 : kSpeculativeToNumberNumberOperator;
1180 : SpeculativeToNumberOperator<NumberOperationHint::kNumberOrOddball>
1181 : kSpeculativeToNumberNumberOrOddballOperator;
1182 : };
1183 :
1184 : namespace {
1185 4164287 : DEFINE_LAZY_LEAKY_OBJECT_GETTER(SimplifiedOperatorGlobalCache,
1186 : GetSimplifiedOperatorGlobalCache)
1187 : }
1188 :
1189 4135349 : SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone)
1190 4135349 : : cache_(*GetSimplifiedOperatorGlobalCache()), zone_(zone) {}
1191 :
1192 : #define GET_FROM_CACHE(Name, ...) \
1193 : const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
1194 1274633 : PURE_OP_LIST(GET_FROM_CACHE)
1195 4141 : EFFECT_DEPENDENT_OP_LIST(GET_FROM_CACHE)
1196 207639 : CHECKED_OP_LIST(GET_FROM_CACHE)
1197 17734 : GET_FROM_CACHE(ArgumentsFrame)
1198 197 : GET_FROM_CACHE(FindOrderedHashMapEntry)
1199 17 : GET_FROM_CACHE(FindOrderedHashMapEntryForInt32Key)
1200 311 : GET_FROM_CACHE(LoadFieldByIndex)
1201 : #undef GET_FROM_CACHE
1202 :
1203 : #define GET_FROM_CACHE_WITH_FEEDBACK(Name, value_input_count, \
1204 : value_output_count) \
1205 : const Operator* SimplifiedOperatorBuilder::Name( \
1206 : const VectorSlotPair& feedback) { \
1207 : if (!feedback.IsValid()) { \
1208 : return &cache_.k##Name; \
1209 : } \
1210 : return new (zone()) Operator1<CheckParameters>( \
1211 : IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, #Name, \
1212 : value_input_count, 1, 1, value_output_count, 1, 0, \
1213 : CheckParameters(feedback)); \
1214 : }
1215 653102 : CHECKED_WITH_FEEDBACK_OP_LIST(GET_FROM_CACHE_WITH_FEEDBACK)
1216 : #undef GET_FROM_CACHE_WITH_FEEDBACK
1217 :
1218 : #define GET_FROM_CACHE_WITH_FEEDBACK(Name) \
1219 : const Operator* SimplifiedOperatorBuilder::Name( \
1220 : const VectorSlotPair& feedback, CheckBoundsParameters::Mode mode) { \
1221 : if (!feedback.IsValid()) { \
1222 : switch (mode) { \
1223 : case CheckBoundsParameters::kDeoptOnOutOfBounds: \
1224 : return &cache_.k##Name##Deopting; \
1225 : case CheckBoundsParameters::kAbortOnOutOfBounds: \
1226 : return &cache_.k##Name##Aborting; \
1227 : } \
1228 : } \
1229 : return new (zone()) \
1230 : SimplifiedOperatorGlobalCache::Name##Operator(feedback, mode); \
1231 : }
1232 114207 : CHECKED_BOUNDS_OP_LIST(GET_FROM_CACHE_WITH_FEEDBACK)
1233 : #undef GET_FROM_CACHE_WITH_FEEDBACK
1234 :
1235 0 : bool IsCheckedWithFeedback(const Operator* op) {
1236 : #define CASE(Name, ...) case IrOpcode::k##Name:
1237 0 : switch (op->opcode()) {
1238 : CHECKED_WITH_FEEDBACK_OP_LIST(CASE) return true;
1239 : default:
1240 0 : return false;
1241 : }
1242 : #undef CASE
1243 : }
1244 :
1245 2730 : const Operator* SimplifiedOperatorBuilder::RuntimeAbort(AbortReason reason) {
1246 : return new (zone()) Operator1<int>( // --
1247 : IrOpcode::kRuntimeAbort, // opcode
1248 : Operator::kNoThrow | Operator::kNoDeopt, // flags
1249 : "RuntimeAbort", // name
1250 : 0, 1, 1, 0, 1, 0, // counts
1251 5460 : static_cast<int>(reason)); // parameter
1252 : }
1253 :
1254 18002 : const Operator* SimplifiedOperatorBuilder::CheckIf(
1255 : DeoptimizeReason reason, const VectorSlotPair& feedback) {
1256 18002 : if (!feedback.IsValid()) {
1257 17428 : switch (reason) {
1258 : #define CHECK_IF(Name, message) \
1259 : case DeoptimizeReason::k##Name: \
1260 : return &cache_.kCheckIf##Name;
1261 145 : DEOPTIMIZE_REASON_LIST(CHECK_IF)
1262 : #undef CHECK_IF
1263 : }
1264 : }
1265 : return new (zone()) Operator1<CheckIfParameters>(
1266 : IrOpcode::kCheckIf, Operator::kFoldable | Operator::kNoThrow, "CheckIf",
1267 : 1, 1, 1, 0, 1, 0, CheckIfParameters(reason, feedback));
1268 : }
1269 :
1270 71507 : const Operator* SimplifiedOperatorBuilder::ChangeFloat64ToTagged(
1271 : CheckForMinusZeroMode mode) {
1272 71507 : switch (mode) {
1273 : case CheckForMinusZeroMode::kCheckForMinusZero:
1274 41868 : return &cache_.kChangeFloat64ToTaggedCheckForMinusZeroOperator;
1275 : case CheckForMinusZeroMode::kDontCheckForMinusZero:
1276 29639 : return &cache_.kChangeFloat64ToTaggedDontCheckForMinusZeroOperator;
1277 : }
1278 0 : UNREACHABLE();
1279 : }
1280 :
1281 6216 : const Operator* SimplifiedOperatorBuilder::CheckedInt32Mul(
1282 : CheckForMinusZeroMode mode) {
1283 6216 : switch (mode) {
1284 : case CheckForMinusZeroMode::kCheckForMinusZero:
1285 4012 : return &cache_.kCheckedInt32MulCheckForMinusZeroOperator;
1286 : case CheckForMinusZeroMode::kDontCheckForMinusZero:
1287 2204 : return &cache_.kCheckedInt32MulDontCheckForMinusZeroOperator;
1288 : }
1289 0 : UNREACHABLE();
1290 : }
1291 :
1292 2586 : const Operator* SimplifiedOperatorBuilder::CheckedFloat64ToInt32(
1293 : CheckForMinusZeroMode mode, const VectorSlotPair& feedback) {
1294 2586 : if (!feedback.IsValid()) {
1295 2561 : switch (mode) {
1296 : case CheckForMinusZeroMode::kCheckForMinusZero:
1297 2177 : return &cache_.kCheckedFloat64ToInt32CheckForMinusZeroOperator;
1298 : case CheckForMinusZeroMode::kDontCheckForMinusZero:
1299 384 : return &cache_.kCheckedFloat64ToInt32DontCheckForMinusZeroOperator;
1300 : }
1301 : }
1302 : return new (zone()) Operator1<CheckMinusZeroParameters>(
1303 : IrOpcode::kCheckedFloat64ToInt32,
1304 : Operator::kFoldable | Operator::kNoThrow, "CheckedFloat64ToInt32", 1, 1,
1305 : 1, 1, 1, 0, CheckMinusZeroParameters(mode, feedback));
1306 : }
1307 :
1308 62 : const Operator* SimplifiedOperatorBuilder::CheckedFloat64ToInt64(
1309 : CheckForMinusZeroMode mode, const VectorSlotPair& feedback) {
1310 62 : if (!feedback.IsValid()) {
1311 22 : switch (mode) {
1312 : case CheckForMinusZeroMode::kCheckForMinusZero:
1313 6 : return &cache_.kCheckedFloat64ToInt64CheckForMinusZeroOperator;
1314 : case CheckForMinusZeroMode::kDontCheckForMinusZero:
1315 16 : return &cache_.kCheckedFloat64ToInt64DontCheckForMinusZeroOperator;
1316 : }
1317 : }
1318 : return new (zone()) Operator1<CheckMinusZeroParameters>(
1319 : IrOpcode::kCheckedFloat64ToInt64,
1320 : Operator::kFoldable | Operator::kNoThrow, "CheckedFloat64ToInt64", 1, 1,
1321 : 1, 1, 1, 0, CheckMinusZeroParameters(mode, feedback));
1322 : }
1323 :
1324 2614 : const Operator* SimplifiedOperatorBuilder::CheckedTaggedToInt32(
1325 : CheckForMinusZeroMode mode, const VectorSlotPair& feedback) {
1326 2614 : if (!feedback.IsValid()) {
1327 2262 : switch (mode) {
1328 : case CheckForMinusZeroMode::kCheckForMinusZero:
1329 9 : return &cache_.kCheckedTaggedToInt32CheckForMinusZeroOperator;
1330 : case CheckForMinusZeroMode::kDontCheckForMinusZero:
1331 2253 : return &cache_.kCheckedTaggedToInt32DontCheckForMinusZeroOperator;
1332 : }
1333 : }
1334 : return new (zone()) Operator1<CheckMinusZeroParameters>(
1335 : IrOpcode::kCheckedTaggedToInt32, Operator::kFoldable | Operator::kNoThrow,
1336 : "CheckedTaggedToInt32", 1, 1, 1, 1, 1, 0,
1337 : CheckMinusZeroParameters(mode, feedback));
1338 : }
1339 :
1340 133 : const Operator* SimplifiedOperatorBuilder::CheckedTaggedToInt64(
1341 : CheckForMinusZeroMode mode, const VectorSlotPair& feedback) {
1342 133 : if (!feedback.IsValid()) {
1343 22 : switch (mode) {
1344 : case CheckForMinusZeroMode::kCheckForMinusZero:
1345 6 : return &cache_.kCheckedTaggedToInt64CheckForMinusZeroOperator;
1346 : case CheckForMinusZeroMode::kDontCheckForMinusZero:
1347 16 : return &cache_.kCheckedTaggedToInt64DontCheckForMinusZeroOperator;
1348 : }
1349 : }
1350 : return new (zone()) Operator1<CheckMinusZeroParameters>(
1351 : IrOpcode::kCheckedTaggedToInt64, Operator::kFoldable | Operator::kNoThrow,
1352 : "CheckedTaggedToInt64", 1, 1, 1, 1, 1, 0,
1353 : CheckMinusZeroParameters(mode, feedback));
1354 : }
1355 :
1356 54416 : const Operator* SimplifiedOperatorBuilder::CheckedTaggedToFloat64(
1357 : CheckTaggedInputMode mode, const VectorSlotPair& feedback) {
1358 54416 : if (!feedback.IsValid()) {
1359 22557 : switch (mode) {
1360 : case CheckTaggedInputMode::kNumber:
1361 8085 : return &cache_.kCheckedTaggedToFloat64NumberOperator;
1362 : case CheckTaggedInputMode::kNumberOrOddball:
1363 14472 : return &cache_.kCheckedTaggedToFloat64NumberOrOddballOperator;
1364 : }
1365 : }
1366 : return new (zone()) Operator1<CheckTaggedInputParameters>(
1367 : IrOpcode::kCheckedTaggedToFloat64,
1368 : Operator::kFoldable | Operator::kNoThrow, "CheckedTaggedToFloat64", 1, 1,
1369 : 1, 1, 1, 0, CheckTaggedInputParameters(mode, feedback));
1370 : }
1371 :
1372 1388 : const Operator* SimplifiedOperatorBuilder::CheckedTruncateTaggedToWord32(
1373 : CheckTaggedInputMode mode, const VectorSlotPair& feedback) {
1374 1388 : if (!feedback.IsValid()) {
1375 1352 : switch (mode) {
1376 : case CheckTaggedInputMode::kNumber:
1377 876 : return &cache_.kCheckedTruncateTaggedToWord32NumberOperator;
1378 : case CheckTaggedInputMode::kNumberOrOddball:
1379 476 : return &cache_.kCheckedTruncateTaggedToWord32NumberOrOddballOperator;
1380 : }
1381 : }
1382 : return new (zone()) Operator1<CheckTaggedInputParameters>(
1383 : IrOpcode::kCheckedTruncateTaggedToWord32,
1384 : Operator::kFoldable | Operator::kNoThrow, "CheckedTruncateTaggedToWord32",
1385 : 1, 1, 1, 1, 1, 0, CheckTaggedInputParameters(mode, feedback));
1386 : }
1387 :
1388 91773 : const Operator* SimplifiedOperatorBuilder::CheckMaps(
1389 : CheckMapsFlags flags, ZoneHandleSet<Map> maps,
1390 : const VectorSlotPair& feedback) {
1391 : CheckMapsParameters const parameters(flags, maps, feedback);
1392 : return new (zone()) Operator1<CheckMapsParameters>( // --
1393 : IrOpcode::kCheckMaps, // opcode
1394 : Operator::kNoThrow | Operator::kNoWrite, // flags
1395 : "CheckMaps", // name
1396 : 1, 1, 1, 0, 1, 0, // counts
1397 91772 : parameters); // parameter
1398 : }
1399 :
1400 6780 : const Operator* SimplifiedOperatorBuilder::MapGuard(ZoneHandleSet<Map> maps) {
1401 : DCHECK_LT(0, maps.size());
1402 : return new (zone()) Operator1<ZoneHandleSet<Map>>( // --
1403 : IrOpcode::kMapGuard, Operator::kEliminatable, // opcode
1404 : "MapGuard", // name
1405 : 1, 1, 1, 0, 1, 0, // counts
1406 13560 : maps); // parameter
1407 : }
1408 :
1409 7043 : const Operator* SimplifiedOperatorBuilder::CompareMaps(
1410 : ZoneHandleSet<Map> maps) {
1411 : DCHECK_LT(0, maps.size());
1412 : return new (zone()) Operator1<ZoneHandleSet<Map>>( // --
1413 : IrOpcode::kCompareMaps, // opcode
1414 : Operator::kEliminatable, // flags
1415 : "CompareMaps", // name
1416 : 1, 1, 1, 1, 1, 0, // counts
1417 14086 : maps); // parameter
1418 : }
1419 :
1420 73900 : const Operator* SimplifiedOperatorBuilder::ConvertReceiver(
1421 : ConvertReceiverMode mode) {
1422 73900 : switch (mode) {
1423 : case ConvertReceiverMode::kAny:
1424 1181 : return &cache_.kConvertReceiverAnyOperator;
1425 : case ConvertReceiverMode::kNullOrUndefined:
1426 71881 : return &cache_.kConvertReceiverNullOrUndefinedOperator;
1427 : case ConvertReceiverMode::kNotNullOrUndefined:
1428 838 : return &cache_.kConvertReceiverNotNullOrUndefinedOperator;
1429 : }
1430 0 : UNREACHABLE();
1431 : return nullptr;
1432 : }
1433 :
1434 619 : const Operator* SimplifiedOperatorBuilder::CheckFloat64Hole(
1435 : CheckFloat64HoleMode mode, VectorSlotPair const& feedback) {
1436 619 : if (!feedback.IsValid()) {
1437 604 : switch (mode) {
1438 : case CheckFloat64HoleMode::kAllowReturnHole:
1439 429 : return &cache_.kCheckFloat64HoleAllowReturnHoleOperator;
1440 : case CheckFloat64HoleMode::kNeverReturnHole:
1441 175 : return &cache_.kCheckFloat64HoleNeverReturnHoleOperator;
1442 : }
1443 0 : UNREACHABLE();
1444 : }
1445 : return new (zone()) Operator1<CheckFloat64HoleParameters>(
1446 : IrOpcode::kCheckFloat64Hole, Operator::kFoldable | Operator::kNoThrow,
1447 : "CheckFloat64Hole", 1, 1, 1, 1, 1, 0,
1448 : CheckFloat64HoleParameters(mode, feedback));
1449 : }
1450 :
1451 75169 : const Operator* SimplifiedOperatorBuilder::SpeculativeToNumber(
1452 : NumberOperationHint hint, const VectorSlotPair& feedback) {
1453 75169 : if (!feedback.IsValid()) {
1454 17487 : switch (hint) {
1455 : case NumberOperationHint::kSignedSmall:
1456 7626 : return &cache_.kSpeculativeToNumberSignedSmallOperator;
1457 : case NumberOperationHint::kSignedSmallInputs:
1458 : break;
1459 : case NumberOperationHint::kSigned32:
1460 6 : return &cache_.kSpeculativeToNumberSigned32Operator;
1461 : case NumberOperationHint::kNumber:
1462 6432 : return &cache_.kSpeculativeToNumberNumberOperator;
1463 : case NumberOperationHint::kNumberOrOddball:
1464 3417 : return &cache_.kSpeculativeToNumberNumberOrOddballOperator;
1465 : }
1466 : }
1467 : return new (zone()) Operator1<NumberOperationParameters>(
1468 : IrOpcode::kSpeculativeToNumber, Operator::kFoldable | Operator::kNoThrow,
1469 : "SpeculativeToNumber", 1, 1, 1, 1, 1, 0,
1470 : NumberOperationParameters(hint, feedback));
1471 : }
1472 :
1473 1354 : const Operator* SimplifiedOperatorBuilder::EnsureWritableFastElements() {
1474 1354 : return &cache_.kEnsureWritableFastElements;
1475 : }
1476 :
1477 2887 : const Operator* SimplifiedOperatorBuilder::MaybeGrowFastElements(
1478 : GrowFastElementsMode mode, const VectorSlotPair& feedback) {
1479 2887 : if (!feedback.IsValid()) {
1480 1084 : switch (mode) {
1481 : case GrowFastElementsMode::kDoubleElements:
1482 143 : return &cache_.kGrowFastElementsOperatorDoubleElements;
1483 : case GrowFastElementsMode::kSmiOrObjectElements:
1484 941 : return &cache_.kGrowFastElementsOperatorSmiOrObjectElements;
1485 : }
1486 : }
1487 : return new (zone()) Operator1<GrowFastElementsParameters>( // --
1488 : IrOpcode::kMaybeGrowFastElements, // opcode
1489 : Operator::kNoThrow, // flags
1490 : "MaybeGrowFastElements", // name
1491 : 4, 1, 1, 1, 1, 0, // counts
1492 : GrowFastElementsParameters(mode, feedback)); // parameter
1493 : }
1494 :
1495 565 : const Operator* SimplifiedOperatorBuilder::TransitionElementsKind(
1496 : ElementsTransition transition) {
1497 : return new (zone()) Operator1<ElementsTransition>( // --
1498 : IrOpcode::kTransitionElementsKind, // opcode
1499 : Operator::kNoDeopt | Operator::kNoThrow, // flags
1500 : "TransitionElementsKind", // name
1501 : 1, 1, 1, 0, 1, 0, // counts
1502 1130 : transition); // parameter
1503 : }
1504 :
1505 : namespace {
1506 :
1507 : struct ArgumentsLengthParameters {
1508 : int formal_parameter_count;
1509 : bool is_rest_length;
1510 : };
1511 :
1512 : bool operator==(ArgumentsLengthParameters first,
1513 : ArgumentsLengthParameters second) {
1514 0 : return first.formal_parameter_count == second.formal_parameter_count &&
1515 : first.is_rest_length == second.is_rest_length;
1516 : }
1517 :
1518 41282 : size_t hash_value(ArgumentsLengthParameters param) {
1519 41282 : return base::hash_combine(param.formal_parameter_count, param.is_rest_length);
1520 : }
1521 :
1522 0 : std::ostream& operator<<(std::ostream& os, ArgumentsLengthParameters param) {
1523 0 : return os << param.formal_parameter_count << ", "
1524 0 : << (param.is_rest_length ? "rest length" : "not rest length");
1525 : }
1526 :
1527 : } // namespace
1528 :
1529 17734 : const Operator* SimplifiedOperatorBuilder::ArgumentsLength(
1530 : int formal_parameter_count, bool is_rest_length) {
1531 : return new (zone()) Operator1<ArgumentsLengthParameters>( // --
1532 : IrOpcode::kArgumentsLength, // opcode
1533 : Operator::kPure, // flags
1534 : "ArgumentsLength", // name
1535 : 1, 0, 0, 1, 0, 0, // counts
1536 : ArgumentsLengthParameters{formal_parameter_count,
1537 35468 : is_rest_length}); // parameter
1538 : }
1539 :
1540 16927 : int FormalParameterCountOf(const Operator* op) {
1541 : DCHECK_EQ(IrOpcode::kArgumentsLength, op->opcode());
1542 16927 : return OpParameter<ArgumentsLengthParameters>(op).formal_parameter_count;
1543 : }
1544 :
1545 35976 : bool IsRestLengthOf(const Operator* op) {
1546 : DCHECK_EQ(IrOpcode::kArgumentsLength, op->opcode());
1547 35976 : return OpParameter<ArgumentsLengthParameters>(op).is_rest_length;
1548 : }
1549 :
1550 0 : bool operator==(CheckParameters const& lhs, CheckParameters const& rhs) {
1551 0 : return lhs.feedback() == rhs.feedback();
1552 : }
1553 :
1554 0 : size_t hash_value(CheckParameters const& p) { return hash_value(p.feedback()); }
1555 :
1556 0 : std::ostream& operator<<(std::ostream& os, CheckParameters const& p) {
1557 26 : return os << p.feedback();
1558 : }
1559 :
1560 392135 : CheckParameters const& CheckParametersOf(Operator const* op) {
1561 392135 : if (op->opcode() == IrOpcode::kCheckedUint32Bounds) {
1562 0 : return OpParameter<CheckBoundsParameters>(op).check_parameters();
1563 : }
1564 : #define MAKE_OR(name, arg2, arg3) op->opcode() == IrOpcode::k##name ||
1565 392135 : CHECK((CHECKED_WITH_FEEDBACK_OP_LIST(MAKE_OR) false));
1566 : #undef MAKE_OR
1567 392135 : return OpParameter<CheckParameters>(op);
1568 : }
1569 :
1570 0 : bool operator==(CheckBoundsParameters const& lhs,
1571 : CheckBoundsParameters const& rhs) {
1572 0 : return lhs.check_parameters() == rhs.check_parameters() &&
1573 0 : lhs.mode() == rhs.mode();
1574 : }
1575 :
1576 0 : size_t hash_value(CheckBoundsParameters const& p) {
1577 0 : return base::hash_combine(hash_value(p.check_parameters()), p.mode());
1578 : }
1579 :
1580 0 : std::ostream& operator<<(std::ostream& os, CheckBoundsParameters const& p) {
1581 0 : os << p.check_parameters() << ",";
1582 0 : switch (p.mode()) {
1583 : case CheckBoundsParameters::kDeoptOnOutOfBounds:
1584 0 : os << "deopt";
1585 0 : break;
1586 : case CheckBoundsParameters::kAbortOnOutOfBounds:
1587 0 : os << "abort";
1588 0 : break;
1589 : }
1590 0 : return os;
1591 : }
1592 :
1593 52596 : CheckBoundsParameters const& CheckBoundsParametersOf(Operator const* op) {
1594 52596 : CHECK_EQ(op->opcode(), IrOpcode::kCheckedUint32Bounds);
1595 52596 : return OpParameter<CheckBoundsParameters>(op);
1596 : }
1597 :
1598 0 : bool operator==(CheckIfParameters const& lhs, CheckIfParameters const& rhs) {
1599 0 : return lhs.reason() == rhs.reason() && lhs.feedback() == rhs.feedback();
1600 : }
1601 :
1602 0 : size_t hash_value(CheckIfParameters const& p) {
1603 0 : return base::hash_combine(p.reason(), p.feedback());
1604 : }
1605 :
1606 0 : std::ostream& operator<<(std::ostream& os, CheckIfParameters const& p) {
1607 0 : return os << p.reason() << p.feedback();
1608 : }
1609 :
1610 16431 : CheckIfParameters const& CheckIfParametersOf(Operator const* op) {
1611 16431 : CHECK(op->opcode() == IrOpcode::kCheckIf);
1612 16431 : return OpParameter<CheckIfParameters>(op);
1613 : }
1614 :
1615 28 : const Operator* SimplifiedOperatorBuilder::NewDoubleElements(
1616 : AllocationType allocation) {
1617 : return new (zone()) Operator1<AllocationType>( // --
1618 : IrOpcode::kNewDoubleElements, // opcode
1619 : Operator::kEliminatable, // flags
1620 : "NewDoubleElements", // name
1621 : 1, 1, 1, 1, 1, 0, // counts
1622 28 : allocation); // parameter
1623 : }
1624 :
1625 454 : const Operator* SimplifiedOperatorBuilder::NewSmiOrObjectElements(
1626 : AllocationType allocation) {
1627 : return new (zone()) Operator1<AllocationType>( // --
1628 : IrOpcode::kNewSmiOrObjectElements, // opcode
1629 : Operator::kEliminatable, // flags
1630 : "NewSmiOrObjectElements", // name
1631 : 1, 1, 1, 1, 1, 0, // counts
1632 454 : allocation); // parameter
1633 : }
1634 :
1635 17734 : const Operator* SimplifiedOperatorBuilder::NewArgumentsElements(
1636 : int mapped_count) {
1637 : return new (zone()) Operator1<int>( // --
1638 : IrOpcode::kNewArgumentsElements, // opcode
1639 : Operator::kEliminatable, // flags
1640 : "NewArgumentsElements", // name
1641 : 2, 1, 0, 1, 1, 0, // counts
1642 17734 : mapped_count); // parameter
1643 : }
1644 :
1645 35472 : int NewArgumentsElementsMappedCountOf(const Operator* op) {
1646 : DCHECK_EQ(IrOpcode::kNewArgumentsElements, op->opcode());
1647 35472 : return OpParameter<int>(op);
1648 : }
1649 :
1650 140598 : const Operator* SimplifiedOperatorBuilder::Allocate(Type type,
1651 : AllocationType allocation) {
1652 : return new (zone()) Operator1<AllocateParameters>(
1653 : IrOpcode::kAllocate,
1654 : Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite, "Allocate",
1655 140598 : 1, 1, 1, 1, 1, 0, AllocateParameters(type, allocation));
1656 : }
1657 :
1658 236454 : const Operator* SimplifiedOperatorBuilder::AllocateRaw(
1659 : Type type, AllocationType allocation) {
1660 : return new (zone()) Operator1<AllocateParameters>(
1661 : IrOpcode::kAllocateRaw,
1662 : Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite,
1663 236454 : "AllocateRaw", 1, 1, 1, 1, 1, 1, AllocateParameters(type, allocation));
1664 : }
1665 :
1666 548 : const Operator* SimplifiedOperatorBuilder::StringCodePointAt(
1667 : UnicodeEncoding encoding) {
1668 548 : switch (encoding) {
1669 : case UnicodeEncoding::UTF16:
1670 87 : return &cache_.kStringCodePointAtOperatorUTF16;
1671 : case UnicodeEncoding::UTF32:
1672 461 : return &cache_.kStringCodePointAtOperatorUTF32;
1673 : }
1674 0 : UNREACHABLE();
1675 : }
1676 :
1677 215 : const Operator* SimplifiedOperatorBuilder::StringFromSingleCodePoint(
1678 : UnicodeEncoding encoding) {
1679 215 : switch (encoding) {
1680 : case UnicodeEncoding::UTF16:
1681 87 : return &cache_.kStringFromSingleCodePointOperatorUTF16;
1682 : case UnicodeEncoding::UTF32:
1683 128 : return &cache_.kStringFromSingleCodePointOperatorUTF32;
1684 : }
1685 0 : UNREACHABLE();
1686 : }
1687 :
1688 : #define SPECULATIVE_NUMBER_BINOP(Name) \
1689 : const Operator* SimplifiedOperatorBuilder::Name(NumberOperationHint hint) { \
1690 : switch (hint) { \
1691 : case NumberOperationHint::kSignedSmall: \
1692 : return &cache_.k##Name##SignedSmallOperator; \
1693 : case NumberOperationHint::kSignedSmallInputs: \
1694 : return &cache_.k##Name##SignedSmallInputsOperator; \
1695 : case NumberOperationHint::kSigned32: \
1696 : return &cache_.k##Name##Signed32Operator; \
1697 : case NumberOperationHint::kNumber: \
1698 : return &cache_.k##Name##NumberOperator; \
1699 : case NumberOperationHint::kNumberOrOddball: \
1700 : return &cache_.k##Name##NumberOrOddballOperator; \
1701 : } \
1702 : UNREACHABLE(); \
1703 : return nullptr; \
1704 : }
1705 325693 : SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP)
1706 : #undef SPECULATIVE_NUMBER_BINOP
1707 :
1708 : #define ACCESS_OP_LIST(V) \
1709 : V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1) \
1710 : V(StoreField, FieldAccess, Operator::kNoRead, 2, 1, 0) \
1711 : V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1) \
1712 : V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0) \
1713 : V(LoadTypedElement, ExternalArrayType, Operator::kNoWrite, 4, 1, 1) \
1714 : V(StoreTypedElement, ExternalArrayType, Operator::kNoRead, 5, 1, 0) \
1715 : V(LoadDataViewElement, ExternalArrayType, Operator::kNoWrite, 5, 1, 1) \
1716 : V(StoreDataViewElement, ExternalArrayType, Operator::kNoRead, 6, 1, 0)
1717 :
1718 : #define ACCESS(Name, Type, properties, value_input_count, control_input_count, \
1719 : output_count) \
1720 : const Operator* SimplifiedOperatorBuilder::Name(const Type& access) { \
1721 : return new (zone()) \
1722 : Operator1<Type>(IrOpcode::k##Name, \
1723 : Operator::kNoDeopt | Operator::kNoThrow | properties, \
1724 : #Name, value_input_count, 1, control_input_count, \
1725 : output_count, 1, 0, access); \
1726 : }
1727 10990243 : ACCESS_OP_LIST(ACCESS)
1728 : #undef ACCESS
1729 :
1730 29834 : const Operator* SimplifiedOperatorBuilder::LoadMessage() {
1731 29834 : return &cache_.kLoadMessage;
1732 : }
1733 :
1734 29836 : const Operator* SimplifiedOperatorBuilder::StoreMessage() {
1735 29836 : return &cache_.kStoreMessage;
1736 : }
1737 :
1738 586 : const Operator* SimplifiedOperatorBuilder::LoadStackArgument() {
1739 586 : return &cache_.kLoadStackArgument;
1740 : }
1741 :
1742 337 : const Operator* SimplifiedOperatorBuilder::TransitionAndStoreElement(
1743 : Handle<Map> double_map, Handle<Map> fast_map) {
1744 : TransitionAndStoreElementParameters parameters(double_map, fast_map);
1745 : return new (zone()) Operator1<TransitionAndStoreElementParameters>(
1746 : IrOpcode::kTransitionAndStoreElement,
1747 : Operator::kNoDeopt | Operator::kNoThrow, "TransitionAndStoreElement", 3,
1748 337 : 1, 1, 0, 1, 0, parameters);
1749 : }
1750 :
1751 71 : const Operator* SimplifiedOperatorBuilder::StoreSignedSmallElement() {
1752 : return new (zone()) Operator(IrOpcode::kStoreSignedSmallElement,
1753 142 : Operator::kNoDeopt | Operator::kNoThrow,
1754 142 : "StoreSignedSmallElement", 3, 1, 1, 0, 1, 0);
1755 : }
1756 :
1757 28 : const Operator* SimplifiedOperatorBuilder::TransitionAndStoreNumberElement(
1758 : Handle<Map> double_map) {
1759 : TransitionAndStoreNumberElementParameters parameters(double_map);
1760 : return new (zone()) Operator1<TransitionAndStoreNumberElementParameters>(
1761 : IrOpcode::kTransitionAndStoreNumberElement,
1762 : Operator::kNoDeopt | Operator::kNoThrow,
1763 28 : "TransitionAndStoreNumberElement", 3, 1, 1, 0, 1, 0, parameters);
1764 : }
1765 :
1766 20 : const Operator* SimplifiedOperatorBuilder::TransitionAndStoreNonNumberElement(
1767 : Handle<Map> fast_map, Type value_type) {
1768 : TransitionAndStoreNonNumberElementParameters parameters(fast_map, value_type);
1769 : return new (zone()) Operator1<TransitionAndStoreNonNumberElementParameters>(
1770 : IrOpcode::kTransitionAndStoreNonNumberElement,
1771 : Operator::kNoDeopt | Operator::kNoThrow,
1772 20 : "TransitionAndStoreNonNumberElement", 3, 1, 1, 0, 1, 0, parameters);
1773 : }
1774 :
1775 : #undef PURE_OP_LIST
1776 : #undef EFFECT_DEPENDENT_OP_LIST
1777 : #undef SPECULATIVE_NUMBER_BINOP_LIST
1778 : #undef CHECKED_WITH_FEEDBACK_OP_LIST
1779 : #undef CHECKED_BOUNDS_OP_LIST
1780 : #undef CHECKED_OP_LIST
1781 : #undef ACCESS_OP_LIST
1782 :
1783 : } // namespace compiler
1784 : } // namespace internal
1785 122028 : } // namespace v8
|