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