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 121026 : std::ostream& operator<<(std::ostream& os, BaseTaggedness base_taggedness) {
25 121026 : switch (base_taggedness) {
26 : case kUntaggedBase:
27 73668 : return os << "untagged base";
28 : case kTaggedBase:
29 47358 : return os << "tagged base";
30 : }
31 0 : UNREACHABLE();
32 : }
33 :
34 127 : 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 254 : return lhs.base_is_tagged == rhs.base_is_tagged && lhs.offset == rhs.offset &&
39 254 : lhs.map.address() == rhs.map.address() &&
40 127 : 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 :
52 0 : std::ostream& operator<<(std::ostream& os, FieldAccess const& access) {
53 0 : os << "[" << access.base_is_tagged << ", " << access.offset << ", ";
54 : #ifdef OBJECT_PRINT
55 : Handle<Name> name;
56 : if (access.name.ToHandle(&name)) {
57 : name->Print(os);
58 : os << ", ";
59 : }
60 : Handle<Map> map;
61 : if (access.map.ToHandle(&map)) {
62 : os << Brief(*map) << ", ";
63 : }
64 : #endif
65 0 : access.type->PrintTo(os);
66 0 : os << ", " << access.machine_type << ", " << access.write_barrier_kind << "]";
67 0 : return os;
68 : }
69 :
70 : template <>
71 0 : void Operator1<FieldAccess>::PrintParameter(std::ostream& os,
72 : PrintVerbosity verbose) const {
73 0 : if (verbose == PrintVerbosity::kVerbose) {
74 0 : os << parameter();
75 : } else {
76 0 : os << "[+" << parameter().offset << "]";
77 : }
78 0 : }
79 :
80 46 : bool operator==(ElementAccess const& lhs, ElementAccess const& rhs) {
81 : // On purpose we don't include the write barrier kind here, as this method is
82 : // really only relevant for eliminating loads and they don't care about the
83 : // write barrier mode.
84 46 : return lhs.base_is_tagged == rhs.base_is_tagged &&
85 92 : lhs.header_size == rhs.header_size &&
86 46 : lhs.machine_type == rhs.machine_type;
87 : }
88 :
89 0 : size_t hash_value(ElementAccess const& access) {
90 : // On purpose we don't include the write barrier kind here, as this method is
91 : // really only relevant for eliminating loads and they don't care about the
92 : // write barrier mode.
93 : return base::hash_combine(access.base_is_tagged, access.header_size,
94 0 : access.machine_type);
95 : }
96 :
97 :
98 121026 : std::ostream& operator<<(std::ostream& os, ElementAccess const& access) {
99 121026 : os << access.base_is_tagged << ", " << access.header_size << ", ";
100 121026 : access.type->PrintTo(os);
101 121026 : os << ", " << access.machine_type << ", " << access.write_barrier_kind;
102 121026 : return os;
103 : }
104 :
105 0 : ToBooleanHints ToBooleanHintsOf(Operator const* op) {
106 : DCHECK_EQ(IrOpcode::kToBoolean, op->opcode());
107 0 : return OpParameter<ToBooleanHints>(op);
108 : }
109 :
110 15070227 : const FieldAccess& FieldAccessOf(const Operator* op) {
111 : DCHECK_NOT_NULL(op);
112 : DCHECK(op->opcode() == IrOpcode::kLoadField ||
113 : op->opcode() == IrOpcode::kStoreField);
114 15070227 : return OpParameter<FieldAccess>(op);
115 : }
116 :
117 :
118 409374 : const ElementAccess& ElementAccessOf(const Operator* op) {
119 : DCHECK_NOT_NULL(op);
120 : DCHECK(op->opcode() == IrOpcode::kLoadElement ||
121 : op->opcode() == IrOpcode::kStoreElement);
122 409374 : return OpParameter<ElementAccess>(op);
123 : }
124 :
125 62923 : ExternalArrayType ExternalArrayTypeOf(const Operator* op) {
126 : DCHECK(op->opcode() == IrOpcode::kLoadTypedElement ||
127 : op->opcode() == IrOpcode::kStoreTypedElement);
128 62923 : return OpParameter<ExternalArrayType>(op);
129 : }
130 :
131 0 : size_t hash_value(CheckFloat64HoleMode mode) {
132 0 : return static_cast<size_t>(mode);
133 : }
134 :
135 0 : std::ostream& operator<<(std::ostream& os, CheckFloat64HoleMode mode) {
136 0 : switch (mode) {
137 : case CheckFloat64HoleMode::kAllowReturnHole:
138 0 : return os << "allow-return-hole";
139 : case CheckFloat64HoleMode::kNeverReturnHole:
140 0 : return os << "never-return-hole";
141 : }
142 0 : UNREACHABLE();
143 : }
144 :
145 2232 : CheckFloat64HoleMode CheckFloat64HoleModeOf(const Operator* op) {
146 : DCHECK_EQ(IrOpcode::kCheckFloat64Hole, op->opcode());
147 2232 : return OpParameter<CheckFloat64HoleMode>(op);
148 : }
149 :
150 53412 : CheckForMinusZeroMode CheckMinusZeroModeOf(const Operator* op) {
151 : DCHECK(op->opcode() == IrOpcode::kChangeFloat64ToTagged ||
152 : op->opcode() == IrOpcode::kCheckedInt32Mul ||
153 : op->opcode() == IrOpcode::kCheckedFloat64ToInt32 ||
154 : op->opcode() == IrOpcode::kCheckedTaggedToInt32);
155 53412 : return OpParameter<CheckForMinusZeroMode>(op);
156 : }
157 :
158 63315 : size_t hash_value(CheckForMinusZeroMode mode) {
159 63315 : return static_cast<size_t>(mode);
160 : }
161 :
162 10 : std::ostream& operator<<(std::ostream& os, CheckForMinusZeroMode mode) {
163 10 : switch (mode) {
164 : case CheckForMinusZeroMode::kCheckForMinusZero:
165 5 : return os << "check-for-minus-zero";
166 : case CheckForMinusZeroMode::kDontCheckForMinusZero:
167 5 : return os << "dont-check-for-minus-zero";
168 : }
169 0 : UNREACHABLE();
170 : }
171 :
172 0 : std::ostream& operator<<(std::ostream& os, CheckMapsFlags flags) {
173 : bool empty = true;
174 0 : if (flags & CheckMapsFlag::kTryMigrateInstance) {
175 0 : os << "TryMigrateInstance";
176 : empty = false;
177 : }
178 0 : if (empty) os << "None";
179 0 : return os;
180 : }
181 :
182 101928 : MapsParameterInfo::MapsParameterInfo(ZoneHandleSet<Map> const& maps)
183 101928 : : maps_(maps), instance_type_(Nothing<InstanceType>()) {
184 : DCHECK_LT(0, maps.size());
185 101928 : instance_type_ = Just(maps.at(0)->instance_type());
186 215762 : for (size_t i = 1; i < maps.size(); ++i) {
187 6131 : if (instance_type_.FromJust() != maps.at(i)->instance_type()) {
188 178 : instance_type_ = Nothing<InstanceType>();
189 178 : break;
190 : }
191 : }
192 101928 : }
193 :
194 0 : std::ostream& operator<<(std::ostream& os, MapsParameterInfo const& p) {
195 : ZoneHandleSet<Map> const& maps = p.maps();
196 : InstanceType instance_type;
197 0 : if (p.instance_type().To(&instance_type)) {
198 0 : os << ", " << instance_type;
199 : }
200 0 : for (size_t i = 0; i < maps.size(); ++i) {
201 0 : os << ", " << Brief(*maps[i]);
202 : }
203 0 : return os;
204 : }
205 :
206 0 : bool operator==(MapsParameterInfo const& lhs, MapsParameterInfo const& rhs) {
207 0 : return lhs.maps() == rhs.maps();
208 : }
209 :
210 0 : bool operator!=(MapsParameterInfo const& lhs, MapsParameterInfo const& rhs) {
211 0 : return !(lhs == rhs);
212 : }
213 :
214 0 : size_t hash_value(MapsParameterInfo const& p) { return hash_value(p.maps()); }
215 :
216 0 : bool operator==(CheckMapsParameters const& lhs,
217 : CheckMapsParameters const& rhs) {
218 0 : return lhs.flags() == rhs.flags() && lhs.maps() == rhs.maps();
219 : }
220 :
221 0 : size_t hash_value(CheckMapsParameters const& p) {
222 0 : return base::hash_combine(p.flags(), p.maps());
223 : }
224 :
225 0 : std::ostream& operator<<(std::ostream& os, CheckMapsParameters const& p) {
226 0 : return os << p.flags() << p.maps_info();
227 : }
228 :
229 285659 : CheckMapsParameters const& CheckMapsParametersOf(Operator const* op) {
230 : DCHECK_EQ(IrOpcode::kCheckMaps, op->opcode());
231 285659 : return OpParameter<CheckMapsParameters>(op);
232 : }
233 :
234 21752 : MapsParameterInfo const& CompareMapsParametersOf(Operator const* op) {
235 : DCHECK_EQ(IrOpcode::kCompareMaps, op->opcode());
236 21752 : return OpParameter<MapsParameterInfo>(op);
237 : }
238 :
239 11698 : MapsParameterInfo const& MapGuardMapsOf(Operator const* op) {
240 : DCHECK_EQ(IrOpcode::kMapGuard, op->opcode());
241 11698 : return OpParameter<MapsParameterInfo>(op);
242 : }
243 :
244 0 : size_t hash_value(CheckTaggedInputMode mode) {
245 0 : return static_cast<size_t>(mode);
246 : }
247 :
248 0 : std::ostream& operator<<(std::ostream& os, CheckTaggedInputMode mode) {
249 0 : switch (mode) {
250 : case CheckTaggedInputMode::kNumber:
251 0 : return os << "Number";
252 : case CheckTaggedInputMode::kNumberOrOddball:
253 0 : return os << "NumberOrOddball";
254 : }
255 0 : UNREACHABLE();
256 : }
257 :
258 23148 : CheckTaggedInputMode CheckTaggedInputModeOf(const Operator* op) {
259 : DCHECK(op->opcode() == IrOpcode::kCheckedTaggedToFloat64 ||
260 : op->opcode() == IrOpcode::kCheckedTruncateTaggedToWord32);
261 23148 : return OpParameter<CheckTaggedInputMode>(op);
262 : }
263 :
264 0 : std::ostream& operator<<(std::ostream& os, GrowFastElementsMode mode) {
265 0 : switch (mode) {
266 : case GrowFastElementsMode::kDoubleElements:
267 0 : return os << "DoubleElements";
268 : case GrowFastElementsMode::kSmiOrObjectElements:
269 0 : return os << "SmiOrObjectElements";
270 : }
271 0 : UNREACHABLE();
272 : }
273 :
274 7533 : GrowFastElementsMode GrowFastElementsModeOf(const Operator* op) {
275 : DCHECK_EQ(IrOpcode::kMaybeGrowFastElements, op->opcode());
276 7533 : return OpParameter<GrowFastElementsMode>(op);
277 : }
278 :
279 0 : bool operator==(ElementsTransition const& lhs, ElementsTransition const& rhs) {
280 0 : return lhs.mode() == rhs.mode() &&
281 0 : lhs.source().address() == rhs.source().address() &&
282 0 : lhs.target().address() == rhs.target().address();
283 : }
284 :
285 0 : size_t hash_value(ElementsTransition transition) {
286 0 : return base::hash_combine(static_cast<uint8_t>(transition.mode()),
287 : transition.source().address(),
288 0 : transition.target().address());
289 : }
290 :
291 0 : std::ostream& operator<<(std::ostream& os, ElementsTransition transition) {
292 0 : switch (transition.mode()) {
293 : case ElementsTransition::kFastTransition:
294 0 : return os << "fast-transition from " << Brief(*transition.source())
295 0 : << " to " << Brief(*transition.target());
296 : case ElementsTransition::kSlowTransition:
297 0 : return os << "slow-transition from " << Brief(*transition.source())
298 0 : << " to " << Brief(*transition.target());
299 : }
300 0 : UNREACHABLE();
301 : }
302 :
303 2189 : ElementsTransition const& ElementsTransitionOf(const Operator* op) {
304 : DCHECK_EQ(IrOpcode::kTransitionElementsKind, op->opcode());
305 2189 : return OpParameter<ElementsTransition>(op);
306 : }
307 :
308 : namespace {
309 :
310 : // Parameters for the TransitionAndStoreElement opcode.
311 : class TransitionAndStoreElementParameters final {
312 : public:
313 : TransitionAndStoreElementParameters(Handle<Map> double_map,
314 : Handle<Map> fast_map);
315 :
316 : Handle<Map> double_map() const { return double_map_; }
317 : Handle<Map> fast_map() const { return fast_map_; }
318 :
319 : private:
320 : Handle<Map> const double_map_;
321 : Handle<Map> const fast_map_;
322 : };
323 :
324 : TransitionAndStoreElementParameters::TransitionAndStoreElementParameters(
325 : Handle<Map> double_map, Handle<Map> fast_map)
326 : : double_map_(double_map), fast_map_(fast_map) {}
327 :
328 : bool operator==(TransitionAndStoreElementParameters const& lhs,
329 : TransitionAndStoreElementParameters const& rhs) {
330 0 : return lhs.fast_map().address() == rhs.fast_map().address() &&
331 : lhs.double_map().address() == rhs.double_map().address();
332 : }
333 :
334 0 : size_t hash_value(TransitionAndStoreElementParameters parameters) {
335 : return base::hash_combine(parameters.fast_map().address(),
336 0 : parameters.double_map().address());
337 : }
338 :
339 0 : std::ostream& operator<<(std::ostream& os,
340 : TransitionAndStoreElementParameters parameters) {
341 0 : return os << "fast-map" << Brief(*parameters.fast_map()) << " double-map"
342 0 : << Brief(*parameters.double_map());
343 : }
344 :
345 : } // namespace
346 :
347 : namespace {
348 :
349 : // Parameters for the TransitionAndStoreNonNumberElement opcode.
350 : class TransitionAndStoreNonNumberElementParameters final {
351 : public:
352 : TransitionAndStoreNonNumberElementParameters(Handle<Map> fast_map,
353 : Type* value_type);
354 :
355 : Handle<Map> fast_map() const { return fast_map_; }
356 : Type* value_type() const { return value_type_; }
357 :
358 : private:
359 : Handle<Map> const fast_map_;
360 : Type* value_type_;
361 : };
362 :
363 : TransitionAndStoreNonNumberElementParameters::
364 : TransitionAndStoreNonNumberElementParameters(Handle<Map> fast_map,
365 : Type* value_type)
366 : : fast_map_(fast_map), value_type_(value_type) {}
367 :
368 0 : bool operator==(TransitionAndStoreNonNumberElementParameters const& lhs,
369 0 : TransitionAndStoreNonNumberElementParameters const& rhs) {
370 0 : return lhs.fast_map().address() == rhs.fast_map().address() &&
371 : lhs.value_type() == rhs.value_type();
372 : }
373 :
374 0 : size_t hash_value(TransitionAndStoreNonNumberElementParameters parameters) {
375 : return base::hash_combine(parameters.fast_map().address(),
376 0 : parameters.value_type());
377 : }
378 :
379 0 : std::ostream& operator<<(
380 : std::ostream& os, TransitionAndStoreNonNumberElementParameters parameters) {
381 0 : parameters.value_type()->PrintTo(os);
382 0 : return os << ", fast-map" << Brief(*parameters.fast_map());
383 : }
384 :
385 : } // namespace
386 :
387 : namespace {
388 :
389 : // Parameters for the TransitionAndStoreNumberElement opcode.
390 : class TransitionAndStoreNumberElementParameters final {
391 : public:
392 : explicit TransitionAndStoreNumberElementParameters(Handle<Map> double_map);
393 :
394 20 : Handle<Map> double_map() const { return double_map_; }
395 :
396 : private:
397 : Handle<Map> const double_map_;
398 : };
399 :
400 : TransitionAndStoreNumberElementParameters::
401 : TransitionAndStoreNumberElementParameters(Handle<Map> double_map)
402 : : double_map_(double_map) {}
403 :
404 : bool operator==(TransitionAndStoreNumberElementParameters const& lhs,
405 : TransitionAndStoreNumberElementParameters const& rhs) {
406 0 : return lhs.double_map().address() == rhs.double_map().address();
407 : }
408 :
409 0 : size_t hash_value(TransitionAndStoreNumberElementParameters parameters) {
410 0 : return base::hash_combine(parameters.double_map().address());
411 : }
412 :
413 0 : std::ostream& operator<<(std::ostream& os,
414 : TransitionAndStoreNumberElementParameters parameters) {
415 0 : return os << "double-map" << Brief(*parameters.double_map());
416 : }
417 :
418 : } // namespace
419 :
420 584 : Handle<Map> DoubleMapParameterOf(const Operator* op) {
421 584 : if (op->opcode() == IrOpcode::kTransitionAndStoreElement) {
422 : return OpParameter<TransitionAndStoreElementParameters>(op).double_map();
423 20 : } else if (op->opcode() == IrOpcode::kTransitionAndStoreNumberElement) {
424 : return OpParameter<TransitionAndStoreNumberElementParameters>(op)
425 : .double_map();
426 : }
427 0 : UNREACHABLE();
428 : return Handle<Map>::null();
429 : }
430 :
431 6 : Type* ValueTypeParameterOf(const Operator* op) {
432 : DCHECK_EQ(IrOpcode::kTransitionAndStoreNonNumberElement, op->opcode());
433 : return OpParameter<TransitionAndStoreNonNumberElementParameters>(op)
434 6 : .value_type();
435 : }
436 :
437 632 : Handle<Map> FastMapParameterOf(const Operator* op) {
438 632 : if (op->opcode() == IrOpcode::kTransitionAndStoreElement) {
439 : return OpParameter<TransitionAndStoreElementParameters>(op).fast_map();
440 12 : } else if (op->opcode() == IrOpcode::kTransitionAndStoreNonNumberElement) {
441 : return OpParameter<TransitionAndStoreNonNumberElementParameters>(op)
442 : .fast_map();
443 : }
444 0 : UNREACHABLE();
445 : return Handle<Map>::null();
446 : }
447 :
448 0 : std::ostream& operator<<(std::ostream& os, NumberOperationHint hint) {
449 0 : switch (hint) {
450 : case NumberOperationHint::kSignedSmall:
451 0 : return os << "SignedSmall";
452 : case NumberOperationHint::kSignedSmallInputs:
453 0 : return os << "SignedSmallInputs";
454 : case NumberOperationHint::kSigned32:
455 0 : return os << "Signed32";
456 : case NumberOperationHint::kNumber:
457 0 : return os << "Number";
458 : case NumberOperationHint::kNumberOrOddball:
459 0 : return os << "NumberOrOddball";
460 : }
461 0 : UNREACHABLE();
462 : }
463 :
464 0 : size_t hash_value(NumberOperationHint hint) {
465 0 : return static_cast<uint8_t>(hint);
466 : }
467 :
468 1026115 : NumberOperationHint NumberOperationHintOf(const Operator* op) {
469 : DCHECK(op->opcode() == IrOpcode::kSpeculativeToNumber ||
470 : op->opcode() == IrOpcode::kSpeculativeNumberAdd ||
471 : op->opcode() == IrOpcode::kSpeculativeNumberSubtract ||
472 : op->opcode() == IrOpcode::kSpeculativeNumberMultiply ||
473 : op->opcode() == IrOpcode::kSpeculativeNumberDivide ||
474 : op->opcode() == IrOpcode::kSpeculativeNumberModulus ||
475 : op->opcode() == IrOpcode::kSpeculativeNumberShiftLeft ||
476 : op->opcode() == IrOpcode::kSpeculativeNumberShiftRight ||
477 : op->opcode() == IrOpcode::kSpeculativeNumberShiftRightLogical ||
478 : op->opcode() == IrOpcode::kSpeculativeNumberBitwiseAnd ||
479 : op->opcode() == IrOpcode::kSpeculativeNumberBitwiseOr ||
480 : op->opcode() == IrOpcode::kSpeculativeNumberBitwiseXor ||
481 : op->opcode() == IrOpcode::kSpeculativeNumberEqual ||
482 : op->opcode() == IrOpcode::kSpeculativeNumberLessThan ||
483 : op->opcode() == IrOpcode::kSpeculativeNumberLessThanOrEqual ||
484 : op->opcode() == IrOpcode::kSpeculativeSafeIntegerAdd ||
485 : op->opcode() == IrOpcode::kSpeculativeSafeIntegerSubtract);
486 1026115 : return OpParameter<NumberOperationHint>(op);
487 : }
488 :
489 0 : size_t hash_value(AllocateParameters info) {
490 0 : return base::hash_combine(info.type(), info.pretenure());
491 : }
492 :
493 0 : V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
494 : AllocateParameters info) {
495 0 : info.type()->PrintTo(os);
496 0 : return os << ", " << info.pretenure();
497 : }
498 :
499 0 : bool operator==(AllocateParameters const& lhs, AllocateParameters const& rhs) {
500 0 : return lhs.pretenure() == rhs.pretenure() && lhs.type() == rhs.type();
501 : }
502 :
503 162897 : PretenureFlag PretenureFlagOf(const Operator* op) {
504 162897 : if (op->opcode() == IrOpcode::kNewDoubleElements ||
505 : op->opcode() == IrOpcode::kNewSmiOrObjectElements) {
506 354 : return OpParameter<PretenureFlag>(op);
507 : }
508 : DCHECK_EQ(IrOpcode::kAllocate, op->opcode());
509 162543 : return OpParameter<AllocateParameters>(op).pretenure();
510 : }
511 :
512 121824 : Type* AllocateTypeOf(const Operator* op) {
513 : DCHECK_EQ(IrOpcode::kAllocate, op->opcode());
514 121824 : return OpParameter<AllocateParameters>(op).type();
515 : }
516 :
517 39 : UnicodeEncoding UnicodeEncodingOf(const Operator* op) {
518 : DCHECK_EQ(IrOpcode::kStringFromCodePoint, op->opcode());
519 39 : return OpParameter<UnicodeEncoding>(op);
520 : }
521 :
522 1920 : BailoutReason BailoutReasonOf(const Operator* op) {
523 : DCHECK_EQ(IrOpcode::kRuntimeAbort, op->opcode());
524 1920 : return OpParameter<BailoutReason>(op);
525 : }
526 :
527 28990 : DeoptimizeReason DeoptimizeReasonOf(const Operator* op) {
528 : DCHECK_EQ(IrOpcode::kCheckIf, op->opcode());
529 28990 : return OpParameter<DeoptimizeReason>(op);
530 : }
531 :
532 : #define PURE_OP_LIST(V) \
533 : V(BooleanNot, Operator::kNoProperties, 1, 0) \
534 : V(NumberEqual, Operator::kCommutative, 2, 0) \
535 : V(NumberLessThan, Operator::kNoProperties, 2, 0) \
536 : V(NumberLessThanOrEqual, Operator::kNoProperties, 2, 0) \
537 : V(NumberAdd, Operator::kCommutative, 2, 0) \
538 : V(NumberSubtract, Operator::kNoProperties, 2, 0) \
539 : V(NumberMultiply, Operator::kCommutative, 2, 0) \
540 : V(NumberDivide, Operator::kNoProperties, 2, 0) \
541 : V(NumberModulus, Operator::kNoProperties, 2, 0) \
542 : V(NumberBitwiseOr, Operator::kCommutative, 2, 0) \
543 : V(NumberBitwiseXor, Operator::kCommutative, 2, 0) \
544 : V(NumberBitwiseAnd, Operator::kCommutative, 2, 0) \
545 : V(NumberShiftLeft, Operator::kNoProperties, 2, 0) \
546 : V(NumberShiftRight, Operator::kNoProperties, 2, 0) \
547 : V(NumberShiftRightLogical, Operator::kNoProperties, 2, 0) \
548 : V(NumberImul, Operator::kCommutative, 2, 0) \
549 : V(NumberAbs, Operator::kNoProperties, 1, 0) \
550 : V(NumberClz32, Operator::kNoProperties, 1, 0) \
551 : V(NumberCeil, Operator::kNoProperties, 1, 0) \
552 : V(NumberFloor, Operator::kNoProperties, 1, 0) \
553 : V(NumberFround, Operator::kNoProperties, 1, 0) \
554 : V(NumberAcos, Operator::kNoProperties, 1, 0) \
555 : V(NumberAcosh, Operator::kNoProperties, 1, 0) \
556 : V(NumberAsin, Operator::kNoProperties, 1, 0) \
557 : V(NumberAsinh, Operator::kNoProperties, 1, 0) \
558 : V(NumberAtan, Operator::kNoProperties, 1, 0) \
559 : V(NumberAtan2, Operator::kNoProperties, 2, 0) \
560 : V(NumberAtanh, Operator::kNoProperties, 1, 0) \
561 : V(NumberCbrt, Operator::kNoProperties, 1, 0) \
562 : V(NumberCos, Operator::kNoProperties, 1, 0) \
563 : V(NumberCosh, Operator::kNoProperties, 1, 0) \
564 : V(NumberExp, Operator::kNoProperties, 1, 0) \
565 : V(NumberExpm1, Operator::kNoProperties, 1, 0) \
566 : V(NumberLog, Operator::kNoProperties, 1, 0) \
567 : V(NumberLog1p, Operator::kNoProperties, 1, 0) \
568 : V(NumberLog10, Operator::kNoProperties, 1, 0) \
569 : V(NumberLog2, Operator::kNoProperties, 1, 0) \
570 : V(NumberMax, Operator::kNoProperties, 2, 0) \
571 : V(NumberMin, Operator::kNoProperties, 2, 0) \
572 : V(NumberPow, Operator::kNoProperties, 2, 0) \
573 : V(NumberRound, Operator::kNoProperties, 1, 0) \
574 : V(NumberSign, Operator::kNoProperties, 1, 0) \
575 : V(NumberSin, Operator::kNoProperties, 1, 0) \
576 : V(NumberSinh, Operator::kNoProperties, 1, 0) \
577 : V(NumberSqrt, Operator::kNoProperties, 1, 0) \
578 : V(NumberTan, Operator::kNoProperties, 1, 0) \
579 : V(NumberTanh, Operator::kNoProperties, 1, 0) \
580 : V(NumberTrunc, Operator::kNoProperties, 1, 0) \
581 : V(NumberToBoolean, Operator::kNoProperties, 1, 0) \
582 : V(NumberToInt32, Operator::kNoProperties, 1, 0) \
583 : V(NumberToUint32, Operator::kNoProperties, 1, 0) \
584 : V(NumberToUint8Clamped, Operator::kNoProperties, 1, 0) \
585 : V(NumberSilenceNaN, Operator::kNoProperties, 1, 0) \
586 : V(StringToNumber, Operator::kNoProperties, 1, 0) \
587 : V(StringCharAt, Operator::kNoProperties, 2, 1) \
588 : V(StringCharCodeAt, Operator::kNoProperties, 2, 1) \
589 : V(SeqStringCharCodeAt, Operator::kNoProperties, 2, 1) \
590 : V(StringFromCharCode, Operator::kNoProperties, 1, 0) \
591 : V(StringIndexOf, Operator::kNoProperties, 3, 0) \
592 : V(StringToLowerCaseIntl, Operator::kNoProperties, 1, 0) \
593 : V(StringToUpperCaseIntl, Operator::kNoProperties, 1, 0) \
594 : V(TypeOf, Operator::kNoProperties, 1, 1) \
595 : V(ClassOf, Operator::kNoProperties, 1, 1) \
596 : V(PlainPrimitiveToNumber, Operator::kNoProperties, 1, 0) \
597 : V(PlainPrimitiveToWord32, Operator::kNoProperties, 1, 0) \
598 : V(PlainPrimitiveToFloat64, Operator::kNoProperties, 1, 0) \
599 : V(ChangeTaggedSignedToInt32, Operator::kNoProperties, 1, 0) \
600 : V(ChangeTaggedToInt32, Operator::kNoProperties, 1, 0) \
601 : V(ChangeTaggedToUint32, Operator::kNoProperties, 1, 0) \
602 : V(ChangeTaggedToFloat64, Operator::kNoProperties, 1, 0) \
603 : V(ChangeTaggedToTaggedSigned, Operator::kNoProperties, 1, 0) \
604 : V(ChangeFloat64ToTaggedPointer, Operator::kNoProperties, 1, 0) \
605 : V(ChangeInt31ToTaggedSigned, Operator::kNoProperties, 1, 0) \
606 : V(ChangeInt32ToTagged, Operator::kNoProperties, 1, 0) \
607 : V(ChangeUint32ToTagged, Operator::kNoProperties, 1, 0) \
608 : V(ChangeTaggedToBit, Operator::kNoProperties, 1, 0) \
609 : V(ChangeBitToTagged, Operator::kNoProperties, 1, 0) \
610 : V(TruncateTaggedToBit, Operator::kNoProperties, 1, 0) \
611 : V(TruncateTaggedPointerToBit, Operator::kNoProperties, 1, 0) \
612 : V(TruncateTaggedToWord32, Operator::kNoProperties, 1, 0) \
613 : V(TruncateTaggedToFloat64, Operator::kNoProperties, 1, 0) \
614 : V(ObjectIsArrayBufferView, Operator::kNoProperties, 1, 0) \
615 : V(ObjectIsCallable, Operator::kNoProperties, 1, 0) \
616 : V(ObjectIsConstructor, Operator::kNoProperties, 1, 0) \
617 : V(ObjectIsDetectableCallable, Operator::kNoProperties, 1, 0) \
618 : V(ObjectIsMinusZero, Operator::kNoProperties, 1, 0) \
619 : V(ObjectIsNaN, Operator::kNoProperties, 1, 0) \
620 : V(ObjectIsNonCallable, Operator::kNoProperties, 1, 0) \
621 : V(ObjectIsNumber, Operator::kNoProperties, 1, 0) \
622 : V(ObjectIsReceiver, Operator::kNoProperties, 1, 0) \
623 : V(ObjectIsSmi, Operator::kNoProperties, 1, 0) \
624 : V(ObjectIsString, Operator::kNoProperties, 1, 0) \
625 : V(ObjectIsSymbol, Operator::kNoProperties, 1, 0) \
626 : V(ObjectIsUndetectable, Operator::kNoProperties, 1, 0) \
627 : V(ConvertTaggedHoleToUndefined, Operator::kNoProperties, 1, 0) \
628 : V(ReferenceEqual, Operator::kCommutative, 2, 0) \
629 : V(StringEqual, Operator::kCommutative, 2, 0) \
630 : V(StringLessThan, Operator::kNoProperties, 2, 0) \
631 : V(StringLessThanOrEqual, Operator::kNoProperties, 2, 0)
632 :
633 : #define SPECULATIVE_NUMBER_BINOP_LIST(V) \
634 : SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(V) \
635 : V(SpeculativeNumberEqual) \
636 : V(SpeculativeNumberLessThan) \
637 : V(SpeculativeNumberLessThanOrEqual)
638 :
639 : #define CHECKED_OP_LIST(V) \
640 : V(CheckBounds, 2, 1) \
641 : V(CheckHeapObject, 1, 1) \
642 : V(CheckInternalizedString, 1, 1) \
643 : V(CheckNumber, 1, 1) \
644 : V(CheckReceiver, 1, 1) \
645 : V(CheckSmi, 1, 1) \
646 : V(CheckString, 1, 1) \
647 : V(CheckSeqString, 1, 1) \
648 : V(CheckSymbol, 1, 1) \
649 : V(CheckNotTaggedHole, 1, 1) \
650 : V(CheckEqualsInternalizedString, 2, 0) \
651 : V(CheckEqualsSymbol, 2, 0) \
652 : V(CheckedInt32Add, 2, 1) \
653 : V(CheckedInt32Sub, 2, 1) \
654 : V(CheckedInt32Div, 2, 1) \
655 : V(CheckedInt32Mod, 2, 1) \
656 : V(CheckedUint32Div, 2, 1) \
657 : V(CheckedUint32Mod, 2, 1) \
658 : V(CheckedUint32ToInt32, 1, 1) \
659 : V(CheckedUint32ToTaggedSigned, 1, 1) \
660 : V(CheckedInt32ToTaggedSigned, 1, 1) \
661 : V(CheckedTaggedSignedToInt32, 1, 1) \
662 : V(CheckedTaggedToTaggedSigned, 1, 1) \
663 : V(CheckedTaggedToTaggedPointer, 1, 1)
664 :
665 22009 : struct SimplifiedOperatorGlobalCache final {
666 : #define PURE(Name, properties, value_input_count, control_input_count) \
667 : struct Name##Operator final : public Operator { \
668 : Name##Operator() \
669 : : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \
670 : value_input_count, 0, control_input_count, 1, 0, 0) {} \
671 : }; \
672 : Name##Operator k##Name;
673 2178891 : PURE_OP_LIST(PURE)
674 : #undef PURE
675 :
676 : #define CHECKED(Name, value_input_count, value_output_count) \
677 : struct Name##Operator final : public Operator { \
678 : Name##Operator() \
679 : : Operator(IrOpcode::k##Name, \
680 : Operator::kFoldable | Operator::kNoThrow, #Name, \
681 : value_input_count, 1, 1, value_output_count, 1, 0) {} \
682 : }; \
683 : Name##Operator k##Name;
684 528216 : CHECKED_OP_LIST(CHECKED)
685 : #undef CHECKED
686 :
687 : template <DeoptimizeReason kDeoptimizeReason>
688 0 : struct CheckIfOperator final : public Operator1<DeoptimizeReason> {
689 1298531 : CheckIfOperator()
690 : : Operator1<DeoptimizeReason>(
691 : IrOpcode::kCheckIf, Operator::kFoldable | Operator::kNoThrow,
692 1298531 : "CheckIf", 1, 1, 1, 0, 1, 0, kDeoptimizeReason) {}
693 : };
694 : #define CHECK_IF(Name, message) \
695 : CheckIfOperator<DeoptimizeReason::k##Name> kCheckIf##Name;
696 : DEOPTIMIZE_REASON_LIST(CHECK_IF)
697 : #undef CHECK_IF
698 :
699 : template <UnicodeEncoding kEncoding>
700 0 : struct StringFromCodePointOperator final : public Operator1<UnicodeEncoding> {
701 44018 : StringFromCodePointOperator()
702 : : Operator1<UnicodeEncoding>(IrOpcode::kStringFromCodePoint,
703 : Operator::kPure, "StringFromCodePoint", 1,
704 44018 : 0, 0, 1, 0, 0, kEncoding) {}
705 : };
706 : StringFromCodePointOperator<UnicodeEncoding::UTF16>
707 : kStringFromCodePointOperatorUTF16;
708 : StringFromCodePointOperator<UnicodeEncoding::UTF32>
709 : kStringFromCodePointOperatorUTF32;
710 :
711 0 : struct ArrayBufferWasNeuteredOperator final : public Operator {
712 22009 : ArrayBufferWasNeuteredOperator()
713 : : Operator(IrOpcode::kArrayBufferWasNeutered, Operator::kEliminatable,
714 22009 : "ArrayBufferWasNeutered", 1, 1, 1, 1, 1, 0) {}
715 : };
716 : ArrayBufferWasNeuteredOperator kArrayBufferWasNeutered;
717 :
718 0 : struct FindOrderedHashMapEntryOperator final : public Operator {
719 22009 : FindOrderedHashMapEntryOperator()
720 : : Operator(IrOpcode::kFindOrderedHashMapEntry, Operator::kEliminatable,
721 22009 : "FindOrderedHashMapEntry", 2, 1, 1, 1, 1, 0) {}
722 : };
723 : FindOrderedHashMapEntryOperator kFindOrderedHashMapEntry;
724 :
725 0 : struct FindOrderedHashMapEntryForInt32KeyOperator final : public Operator {
726 22009 : FindOrderedHashMapEntryForInt32KeyOperator()
727 : : Operator(IrOpcode::kFindOrderedHashMapEntryForInt32Key,
728 : Operator::kEliminatable,
729 22009 : "FindOrderedHashMapEntryForInt32Key", 2, 1, 1, 1, 1, 0) {}
730 : };
731 : FindOrderedHashMapEntryForInt32KeyOperator
732 : kFindOrderedHashMapEntryForInt32Key;
733 :
734 0 : struct ArgumentsFrameOperator final : public Operator {
735 22009 : ArgumentsFrameOperator()
736 : : Operator(IrOpcode::kArgumentsFrame, Operator::kPure, "ArgumentsFrame",
737 22009 : 0, 0, 0, 1, 0, 0) {}
738 : };
739 : ArgumentsFrameOperator kArgumentsFrame;
740 :
741 : template <CheckForMinusZeroMode kMode>
742 0 : struct ChangeFloat64ToTaggedOperator final
743 : : public Operator1<CheckForMinusZeroMode> {
744 44018 : ChangeFloat64ToTaggedOperator()
745 : : Operator1<CheckForMinusZeroMode>(
746 : IrOpcode::kChangeFloat64ToTagged, Operator::kPure,
747 44018 : "ChangeFloat64ToTagged", 1, 0, 0, 1, 0, 0, kMode) {}
748 : };
749 : ChangeFloat64ToTaggedOperator<CheckForMinusZeroMode::kCheckForMinusZero>
750 : kChangeFloat64ToTaggedCheckForMinusZeroOperator;
751 : ChangeFloat64ToTaggedOperator<CheckForMinusZeroMode::kDontCheckForMinusZero>
752 : kChangeFloat64ToTaggedDontCheckForMinusZeroOperator;
753 :
754 : template <CheckForMinusZeroMode kMode>
755 0 : struct CheckedInt32MulOperator final
756 : : public Operator1<CheckForMinusZeroMode> {
757 44018 : CheckedInt32MulOperator()
758 : : Operator1<CheckForMinusZeroMode>(
759 : IrOpcode::kCheckedInt32Mul,
760 : Operator::kFoldable | Operator::kNoThrow, "CheckedInt32Mul", 2, 1,
761 44018 : 1, 1, 1, 0, kMode) {}
762 : };
763 : CheckedInt32MulOperator<CheckForMinusZeroMode::kCheckForMinusZero>
764 : kCheckedInt32MulCheckForMinusZeroOperator;
765 : CheckedInt32MulOperator<CheckForMinusZeroMode::kDontCheckForMinusZero>
766 : kCheckedInt32MulDontCheckForMinusZeroOperator;
767 :
768 : template <CheckForMinusZeroMode kMode>
769 0 : struct CheckedFloat64ToInt32Operator final
770 : : public Operator1<CheckForMinusZeroMode> {
771 44018 : CheckedFloat64ToInt32Operator()
772 : : Operator1<CheckForMinusZeroMode>(
773 : IrOpcode::kCheckedFloat64ToInt32,
774 : Operator::kFoldable | Operator::kNoThrow, "CheckedFloat64ToInt32",
775 44018 : 1, 1, 1, 1, 1, 0, kMode) {}
776 : };
777 : CheckedFloat64ToInt32Operator<CheckForMinusZeroMode::kCheckForMinusZero>
778 : kCheckedFloat64ToInt32CheckForMinusZeroOperator;
779 : CheckedFloat64ToInt32Operator<CheckForMinusZeroMode::kDontCheckForMinusZero>
780 : kCheckedFloat64ToInt32DontCheckForMinusZeroOperator;
781 :
782 : template <CheckForMinusZeroMode kMode>
783 0 : struct CheckedTaggedToInt32Operator final
784 : : public Operator1<CheckForMinusZeroMode> {
785 44018 : CheckedTaggedToInt32Operator()
786 : : Operator1<CheckForMinusZeroMode>(
787 : IrOpcode::kCheckedTaggedToInt32,
788 : Operator::kFoldable | Operator::kNoThrow, "CheckedTaggedToInt32",
789 44018 : 1, 1, 1, 1, 1, 0, kMode) {}
790 : };
791 : CheckedTaggedToInt32Operator<CheckForMinusZeroMode::kCheckForMinusZero>
792 : kCheckedTaggedToInt32CheckForMinusZeroOperator;
793 : CheckedTaggedToInt32Operator<CheckForMinusZeroMode::kDontCheckForMinusZero>
794 : kCheckedTaggedToInt32DontCheckForMinusZeroOperator;
795 :
796 : template <CheckTaggedInputMode kMode>
797 0 : struct CheckedTaggedToFloat64Operator final
798 : : public Operator1<CheckTaggedInputMode> {
799 44018 : CheckedTaggedToFloat64Operator()
800 : : Operator1<CheckTaggedInputMode>(
801 : IrOpcode::kCheckedTaggedToFloat64,
802 : Operator::kFoldable | Operator::kNoThrow,
803 44018 : "CheckedTaggedToFloat64", 1, 1, 1, 1, 1, 0, kMode) {}
804 : };
805 : CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumber>
806 : kCheckedTaggedToFloat64NumberOperator;
807 : CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumberOrOddball>
808 : kCheckedTaggedToFloat64NumberOrOddballOperator;
809 :
810 : template <CheckTaggedInputMode kMode>
811 0 : struct CheckedTruncateTaggedToWord32Operator final
812 : : public Operator1<CheckTaggedInputMode> {
813 44018 : CheckedTruncateTaggedToWord32Operator()
814 : : Operator1<CheckTaggedInputMode>(
815 : IrOpcode::kCheckedTruncateTaggedToWord32,
816 : Operator::kFoldable | Operator::kNoThrow,
817 44018 : "CheckedTruncateTaggedToWord32", 1, 1, 1, 1, 1, 0, kMode) {}
818 : };
819 : CheckedTruncateTaggedToWord32Operator<CheckTaggedInputMode::kNumber>
820 : kCheckedTruncateTaggedToWord32NumberOperator;
821 : CheckedTruncateTaggedToWord32Operator<CheckTaggedInputMode::kNumberOrOddball>
822 : kCheckedTruncateTaggedToWord32NumberOrOddballOperator;
823 :
824 : template <CheckFloat64HoleMode kMode>
825 0 : struct CheckFloat64HoleNaNOperator final
826 : : public Operator1<CheckFloat64HoleMode> {
827 44018 : CheckFloat64HoleNaNOperator()
828 : : Operator1<CheckFloat64HoleMode>(
829 : IrOpcode::kCheckFloat64Hole,
830 : Operator::kFoldable | Operator::kNoThrow, "CheckFloat64Hole", 1,
831 44018 : 1, 1, 1, 1, 0, kMode) {}
832 : };
833 : CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kAllowReturnHole>
834 : kCheckFloat64HoleAllowReturnHoleOperator;
835 : CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kNeverReturnHole>
836 : kCheckFloat64HoleNeverReturnHoleOperator;
837 :
838 0 : struct EnsureWritableFastElementsOperator final : public Operator {
839 22009 : EnsureWritableFastElementsOperator()
840 : : Operator( // --
841 : IrOpcode::kEnsureWritableFastElements, // opcode
842 : Operator::kNoDeopt | Operator::kNoThrow, // flags
843 : "EnsureWritableFastElements", // name
844 22009 : 2, 1, 1, 1, 1, 0) {} // counts
845 : };
846 : EnsureWritableFastElementsOperator kEnsureWritableFastElements;
847 :
848 0 : struct LoadFieldByIndexOperator final : public Operator {
849 22009 : LoadFieldByIndexOperator()
850 : : Operator( // --
851 : IrOpcode::kLoadFieldByIndex, // opcode
852 : Operator::kEliminatable, // flags,
853 : "LoadFieldByIndex", // name
854 22009 : 2, 1, 1, 1, 1, 0) {} // counts;
855 : };
856 : LoadFieldByIndexOperator kLoadFieldByIndex;
857 :
858 : #define SPECULATIVE_NUMBER_BINOP(Name) \
859 : template <NumberOperationHint kHint> \
860 : struct Name##Operator final : public Operator1<NumberOperationHint> { \
861 : Name##Operator() \
862 : : Operator1<NumberOperationHint>( \
863 : IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, \
864 : #Name, 2, 1, 1, 1, 1, 0, kHint) {} \
865 : }; \
866 : Name##Operator<NumberOperationHint::kSignedSmall> \
867 : k##Name##SignedSmallOperator; \
868 : Name##Operator<NumberOperationHint::kSignedSmallInputs> \
869 : k##Name##SignedSmallInputsOperator; \
870 : Name##Operator<NumberOperationHint::kSigned32> k##Name##Signed32Operator; \
871 : Name##Operator<NumberOperationHint::kNumber> k##Name##NumberOperator; \
872 : Name##Operator<NumberOperationHint::kNumberOrOddball> \
873 : k##Name##NumberOrOddballOperator;
874 3521440 : SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP)
875 : #undef SPECULATIVE_NUMBER_BINOP
876 :
877 : template <NumberOperationHint kHint>
878 0 : struct SpeculativeToNumberOperator final
879 : : public Operator1<NumberOperationHint> {
880 88036 : SpeculativeToNumberOperator()
881 : : Operator1<NumberOperationHint>(
882 : IrOpcode::kSpeculativeToNumber, // opcode
883 : Operator::kFoldable | Operator::kNoThrow, // flags
884 : "SpeculativeToNumber", // name
885 : 1, 1, 1, 1, 1, 0, // counts
886 88036 : kHint) {} // parameter
887 : };
888 : SpeculativeToNumberOperator<NumberOperationHint::kSignedSmall>
889 : kSpeculativeToNumberSignedSmallOperator;
890 : SpeculativeToNumberOperator<NumberOperationHint::kSigned32>
891 : kSpeculativeToNumberSigned32Operator;
892 : SpeculativeToNumberOperator<NumberOperationHint::kNumber>
893 : kSpeculativeToNumberNumberOperator;
894 : SpeculativeToNumberOperator<NumberOperationHint::kNumberOrOddball>
895 : kSpeculativeToNumberNumberOrOddballOperator;
896 : };
897 :
898 : static base::LazyInstance<SimplifiedOperatorGlobalCache>::type
899 : kSimplifiedOperatorGlobalCache = LAZY_INSTANCE_INITIALIZER;
900 :
901 646989 : SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone)
902 646990 : : cache_(kSimplifiedOperatorGlobalCache.Get()), zone_(zone) {}
903 :
904 : #define GET_FROM_CACHE(Name, ...) \
905 : const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
906 1136964 : PURE_OP_LIST(GET_FROM_CACHE)
907 507793 : CHECKED_OP_LIST(GET_FROM_CACHE)
908 498 : GET_FROM_CACHE(ArrayBufferWasNeutered)
909 16652 : GET_FROM_CACHE(ArgumentsFrame)
910 8 : GET_FROM_CACHE(FindOrderedHashMapEntry)
911 0 : GET_FROM_CACHE(FindOrderedHashMapEntryForInt32Key)
912 1087 : GET_FROM_CACHE(LoadFieldByIndex)
913 : #undef GET_FROM_CACHE
914 :
915 1983 : const Operator* SimplifiedOperatorBuilder::RuntimeAbort(BailoutReason reason) {
916 : return new (zone()) Operator1<BailoutReason>( // --
917 : IrOpcode::kRuntimeAbort, // opcode
918 : Operator::kNoThrow | Operator::kNoDeopt, // flags
919 : "RuntimeAbort", // name
920 : 0, 1, 1, 0, 1, 0, // counts
921 1983 : reason); // parameter
922 : }
923 :
924 34939 : const Operator* SimplifiedOperatorBuilder::CheckIf(DeoptimizeReason reason) {
925 34939 : switch (reason) {
926 : #define CHECK_IF(Name, message) \
927 : case DeoptimizeReason::k##Name: \
928 : return &cache_.kCheckIf##Name;
929 0 : DEOPTIMIZE_REASON_LIST(CHECK_IF)
930 : #undef CHECK_IF
931 : }
932 0 : UNREACHABLE();
933 : }
934 :
935 61901 : const Operator* SimplifiedOperatorBuilder::ChangeFloat64ToTagged(
936 : CheckForMinusZeroMode mode) {
937 61901 : switch (mode) {
938 : case CheckForMinusZeroMode::kCheckForMinusZero:
939 24462 : return &cache_.kChangeFloat64ToTaggedCheckForMinusZeroOperator;
940 : case CheckForMinusZeroMode::kDontCheckForMinusZero:
941 37439 : return &cache_.kChangeFloat64ToTaggedDontCheckForMinusZeroOperator;
942 : }
943 0 : UNREACHABLE();
944 : }
945 :
946 6120 : const Operator* SimplifiedOperatorBuilder::CheckedInt32Mul(
947 : CheckForMinusZeroMode mode) {
948 6120 : switch (mode) {
949 : case CheckForMinusZeroMode::kCheckForMinusZero:
950 4310 : return &cache_.kCheckedInt32MulCheckForMinusZeroOperator;
951 : case CheckForMinusZeroMode::kDontCheckForMinusZero:
952 1810 : return &cache_.kCheckedInt32MulDontCheckForMinusZeroOperator;
953 : }
954 0 : UNREACHABLE();
955 : }
956 :
957 4920 : const Operator* SimplifiedOperatorBuilder::CheckedFloat64ToInt32(
958 : CheckForMinusZeroMode mode) {
959 4920 : switch (mode) {
960 : case CheckForMinusZeroMode::kCheckForMinusZero:
961 2290 : return &cache_.kCheckedFloat64ToInt32CheckForMinusZeroOperator;
962 : case CheckForMinusZeroMode::kDontCheckForMinusZero:
963 2630 : return &cache_.kCheckedFloat64ToInt32DontCheckForMinusZeroOperator;
964 : }
965 0 : UNREACHABLE();
966 : }
967 :
968 3651 : const Operator* SimplifiedOperatorBuilder::CheckedTaggedToInt32(
969 : CheckForMinusZeroMode mode) {
970 3651 : switch (mode) {
971 : case CheckForMinusZeroMode::kCheckForMinusZero:
972 0 : return &cache_.kCheckedTaggedToInt32CheckForMinusZeroOperator;
973 : case CheckForMinusZeroMode::kDontCheckForMinusZero:
974 3651 : return &cache_.kCheckedTaggedToInt32DontCheckForMinusZeroOperator;
975 : }
976 0 : UNREACHABLE();
977 : }
978 :
979 22842 : const Operator* SimplifiedOperatorBuilder::CheckedTaggedToFloat64(
980 : CheckTaggedInputMode mode) {
981 22842 : switch (mode) {
982 : case CheckTaggedInputMode::kNumber:
983 8532 : return &cache_.kCheckedTaggedToFloat64NumberOperator;
984 : case CheckTaggedInputMode::kNumberOrOddball:
985 14310 : return &cache_.kCheckedTaggedToFloat64NumberOrOddballOperator;
986 : }
987 0 : UNREACHABLE();
988 : }
989 :
990 2445 : const Operator* SimplifiedOperatorBuilder::CheckedTruncateTaggedToWord32(
991 : CheckTaggedInputMode mode) {
992 2445 : switch (mode) {
993 : case CheckTaggedInputMode::kNumber:
994 1686 : return &cache_.kCheckedTruncateTaggedToWord32NumberOperator;
995 : case CheckTaggedInputMode::kNumberOrOddball:
996 759 : return &cache_.kCheckedTruncateTaggedToWord32NumberOrOddballOperator;
997 : }
998 0 : UNREACHABLE();
999 : }
1000 :
1001 84532 : const Operator* SimplifiedOperatorBuilder::CheckMaps(CheckMapsFlags flags,
1002 84532 : ZoneHandleSet<Map> maps) {
1003 : CheckMapsParameters const parameters(flags, maps);
1004 : return new (zone()) Operator1<CheckMapsParameters>( // --
1005 : IrOpcode::kCheckMaps, // opcode
1006 : Operator::kNoThrow | Operator::kNoWrite, // flags
1007 : "CheckMaps", // name
1008 : 1, 1, 1, 0, 1, 0, // counts
1009 169064 : parameters); // parameter
1010 : }
1011 :
1012 16978 : const Operator* SimplifiedOperatorBuilder::MapGuard(ZoneHandleSet<Map> maps) {
1013 : return new (zone()) Operator1<MapsParameterInfo>( // --
1014 : IrOpcode::kMapGuard, Operator::kEliminatable, // opcode
1015 : "MapGuard", // name
1016 : 1, 1, 1, 0, 1, 0, // counts
1017 16978 : MapsParameterInfo(maps)); // parameter
1018 : }
1019 :
1020 8907 : const Operator* SimplifiedOperatorBuilder::CompareMaps(
1021 8907 : ZoneHandleSet<Map> maps) {
1022 : return new (zone()) Operator1<MapsParameterInfo>( // --
1023 : IrOpcode::kCompareMaps, // opcode
1024 : Operator::kEliminatable, // flags
1025 : "CompareMaps", // name
1026 : 1, 1, 1, 1, 1, 0, // counts
1027 17814 : MapsParameterInfo(maps)); // parameter
1028 : }
1029 :
1030 775 : const Operator* SimplifiedOperatorBuilder::CheckFloat64Hole(
1031 : CheckFloat64HoleMode mode) {
1032 775 : switch (mode) {
1033 : case CheckFloat64HoleMode::kAllowReturnHole:
1034 723 : return &cache_.kCheckFloat64HoleAllowReturnHoleOperator;
1035 : case CheckFloat64HoleMode::kNeverReturnHole:
1036 52 : return &cache_.kCheckFloat64HoleNeverReturnHoleOperator;
1037 : }
1038 0 : UNREACHABLE();
1039 : }
1040 :
1041 24311 : const Operator* SimplifiedOperatorBuilder::SpeculativeToNumber(
1042 : NumberOperationHint hint) {
1043 24311 : switch (hint) {
1044 : case NumberOperationHint::kSignedSmall:
1045 12505 : return &cache_.kSpeculativeToNumberSignedSmallOperator;
1046 : case NumberOperationHint::kSignedSmallInputs:
1047 : break;
1048 : case NumberOperationHint::kSigned32:
1049 0 : return &cache_.kSpeculativeToNumberSigned32Operator;
1050 : case NumberOperationHint::kNumber:
1051 7421 : return &cache_.kSpeculativeToNumberNumberOperator;
1052 : case NumberOperationHint::kNumberOrOddball:
1053 4385 : return &cache_.kSpeculativeToNumberNumberOrOddballOperator;
1054 : }
1055 0 : UNREACHABLE();
1056 : }
1057 :
1058 348 : const Operator* SimplifiedOperatorBuilder::EnsureWritableFastElements() {
1059 348 : return &cache_.kEnsureWritableFastElements;
1060 : }
1061 :
1062 2122 : const Operator* SimplifiedOperatorBuilder::MaybeGrowFastElements(
1063 2122 : GrowFastElementsMode mode) {
1064 : return new (zone()) Operator1<GrowFastElementsMode>( // --
1065 : IrOpcode::kMaybeGrowFastElements, // opcode
1066 : Operator::kNoThrow, // flags
1067 : "MaybeGrowFastElements", // name
1068 : 4, 1, 1, 1, 1, 0, // counts
1069 2122 : mode); // parameter
1070 : }
1071 :
1072 619 : const Operator* SimplifiedOperatorBuilder::TransitionElementsKind(
1073 619 : ElementsTransition transition) {
1074 : return new (zone()) Operator1<ElementsTransition>( // --
1075 : IrOpcode::kTransitionElementsKind, // opcode
1076 : Operator::kNoDeopt | Operator::kNoThrow, // flags
1077 : "TransitionElementsKind", // name
1078 : 1, 1, 1, 0, 1, 0, // counts
1079 1238 : transition); // parameter
1080 : }
1081 :
1082 208666 : const Operator* SimplifiedOperatorBuilder::ToBoolean(ToBooleanHints hints) {
1083 : // TODO(turbofan): Cache most important versions of this operator.
1084 : return new (zone()) Operator1<ToBooleanHints>( //--
1085 : IrOpcode::kToBoolean, Operator::kPure, // opcode
1086 : "ToBoolean", // name
1087 : 1, 0, 0, 1, 0, 0, // inputs/outputs
1088 208666 : hints); // parameter
1089 : }
1090 :
1091 : namespace {
1092 :
1093 : struct ArgumentsLengthParameters {
1094 : int formal_parameter_count;
1095 : bool is_rest_length;
1096 : };
1097 :
1098 : bool operator==(ArgumentsLengthParameters first,
1099 : ArgumentsLengthParameters second) {
1100 0 : return first.formal_parameter_count == second.formal_parameter_count &&
1101 : first.is_rest_length == second.is_rest_length;
1102 : }
1103 :
1104 41550 : size_t hash_value(ArgumentsLengthParameters param) {
1105 41550 : return base::hash_combine(param.formal_parameter_count, param.is_rest_length);
1106 : }
1107 :
1108 0 : std::ostream& operator<<(std::ostream& os, ArgumentsLengthParameters param) {
1109 0 : return os << param.formal_parameter_count << ", "
1110 0 : << (param.is_rest_length ? "rest length" : "not rest length");
1111 : }
1112 :
1113 : } // namespace
1114 :
1115 16652 : const Operator* SimplifiedOperatorBuilder::ArgumentsLength(
1116 16652 : int formal_parameter_count, bool is_rest_length) {
1117 : return new (zone()) Operator1<ArgumentsLengthParameters>( // --
1118 : IrOpcode::kArgumentsLength, // opcode
1119 : Operator::kPure, // flags
1120 : "ArgumentsLength", // name
1121 : 1, 0, 0, 1, 0, 0, // counts
1122 : ArgumentsLengthParameters{formal_parameter_count,
1123 33304 : is_rest_length}); // parameter
1124 : }
1125 :
1126 15855 : int FormalParameterCountOf(const Operator* op) {
1127 : DCHECK_EQ(IrOpcode::kArgumentsLength, op->opcode());
1128 15855 : return OpParameter<ArgumentsLengthParameters>(op).formal_parameter_count;
1129 : }
1130 :
1131 34052 : bool IsRestLengthOf(const Operator* op) {
1132 : DCHECK_EQ(IrOpcode::kArgumentsLength, op->opcode());
1133 34052 : return OpParameter<ArgumentsLengthParameters>(op).is_rest_length;
1134 : }
1135 :
1136 32 : const Operator* SimplifiedOperatorBuilder::NewDoubleElements(
1137 32 : PretenureFlag pretenure) {
1138 : return new (zone()) Operator1<PretenureFlag>( // --
1139 : IrOpcode::kNewDoubleElements, // opcode
1140 : Operator::kEliminatable, // flags
1141 : "NewDoubleElements", // name
1142 : 1, 1, 1, 1, 1, 0, // counts
1143 32 : pretenure); // parameter
1144 : }
1145 :
1146 307 : const Operator* SimplifiedOperatorBuilder::NewSmiOrObjectElements(
1147 307 : PretenureFlag pretenure) {
1148 : return new (zone()) Operator1<PretenureFlag>( // --
1149 : IrOpcode::kNewSmiOrObjectElements, // opcode
1150 : Operator::kEliminatable, // flags
1151 : "NewSmiOrObjectElements", // name
1152 : 1, 1, 1, 1, 1, 0, // counts
1153 307 : pretenure); // parameter
1154 : }
1155 :
1156 16652 : const Operator* SimplifiedOperatorBuilder::NewArgumentsElements(
1157 16652 : int mapped_count) {
1158 : return new (zone()) Operator1<int>( // --
1159 : IrOpcode::kNewArgumentsElements, // opcode
1160 : Operator::kEliminatable, // flags
1161 : "NewArgumentsElements", // name
1162 : 2, 1, 0, 1, 1, 0, // counts
1163 16652 : mapped_count); // parameter
1164 : }
1165 :
1166 165037 : const Operator* SimplifiedOperatorBuilder::Allocate(Type* type,
1167 165037 : PretenureFlag pretenure) {
1168 : return new (zone()) Operator1<AllocateParameters>(
1169 : IrOpcode::kAllocate,
1170 : Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite, "Allocate",
1171 165037 : 1, 1, 1, 1, 1, 0, AllocateParameters(type, pretenure));
1172 : }
1173 :
1174 32 : const Operator* SimplifiedOperatorBuilder::StringFromCodePoint(
1175 : UnicodeEncoding encoding) {
1176 32 : switch (encoding) {
1177 : case UnicodeEncoding::UTF16:
1178 32 : return &cache_.kStringFromCodePointOperatorUTF16;
1179 : case UnicodeEncoding::UTF32:
1180 0 : return &cache_.kStringFromCodePointOperatorUTF32;
1181 : }
1182 0 : UNREACHABLE();
1183 : }
1184 :
1185 : #define SPECULATIVE_NUMBER_BINOP(Name) \
1186 : const Operator* SimplifiedOperatorBuilder::Name(NumberOperationHint hint) { \
1187 : switch (hint) { \
1188 : case NumberOperationHint::kSignedSmall: \
1189 : return &cache_.k##Name##SignedSmallOperator; \
1190 : case NumberOperationHint::kSignedSmallInputs: \
1191 : return &cache_.k##Name##SignedSmallInputsOperator; \
1192 : case NumberOperationHint::kSigned32: \
1193 : return &cache_.k##Name##Signed32Operator; \
1194 : case NumberOperationHint::kNumber: \
1195 : return &cache_.k##Name##NumberOperator; \
1196 : case NumberOperationHint::kNumberOrOddball: \
1197 : return &cache_.k##Name##NumberOrOddballOperator; \
1198 : } \
1199 : UNREACHABLE(); \
1200 : return nullptr; \
1201 : }
1202 351972 : SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP)
1203 : #undef SPECULATIVE_NUMBER_BINOP
1204 :
1205 : #define ACCESS_OP_LIST(V) \
1206 : V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1) \
1207 : V(StoreField, FieldAccess, Operator::kNoRead, 2, 1, 0) \
1208 : V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1) \
1209 : V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0) \
1210 : V(LoadTypedElement, ExternalArrayType, Operator::kNoWrite, 4, 1, 1) \
1211 : V(StoreTypedElement, ExternalArrayType, Operator::kNoRead, 5, 1, 0)
1212 :
1213 : #define ACCESS(Name, Type, properties, value_input_count, control_input_count, \
1214 : output_count) \
1215 : const Operator* SimplifiedOperatorBuilder::Name(const Type& access) { \
1216 : return new (zone()) \
1217 : Operator1<Type>(IrOpcode::k##Name, \
1218 : Operator::kNoDeopt | Operator::kNoThrow | properties, \
1219 : #Name, value_input_count, 1, control_input_count, \
1220 : output_count, 1, 0, access); \
1221 : }
1222 7332309 : ACCESS_OP_LIST(ACCESS)
1223 : #undef ACCESS
1224 :
1225 173 : const Operator* SimplifiedOperatorBuilder::TransitionAndStoreElement(
1226 173 : Handle<Map> double_map, Handle<Map> fast_map) {
1227 : TransitionAndStoreElementParameters parameters(double_map, fast_map);
1228 : return new (zone()) Operator1<TransitionAndStoreElementParameters>(
1229 : IrOpcode::kTransitionAndStoreElement,
1230 : Operator::kNoDeopt | Operator::kNoThrow, "TransitionAndStoreElement", 3,
1231 173 : 1, 1, 0, 1, 0, parameters);
1232 : }
1233 :
1234 122 : const Operator* SimplifiedOperatorBuilder::StoreSignedSmallElement() {
1235 : return new (zone()) Operator(IrOpcode::kStoreSignedSmallElement,
1236 122 : Operator::kNoDeopt | Operator::kNoThrow,
1237 122 : "StoreSignedSmallElement", 3, 1, 1, 0, 1, 0);
1238 : }
1239 :
1240 20 : const Operator* SimplifiedOperatorBuilder::TransitionAndStoreNumberElement(
1241 20 : Handle<Map> double_map) {
1242 : TransitionAndStoreNumberElementParameters parameters(double_map);
1243 : return new (zone()) Operator1<TransitionAndStoreNumberElementParameters>(
1244 : IrOpcode::kTransitionAndStoreNumberElement,
1245 : Operator::kNoDeopt | Operator::kNoThrow,
1246 20 : "TransitionAndStoreNumberElement", 3, 1, 1, 0, 1, 0, parameters);
1247 : }
1248 :
1249 6 : const Operator* SimplifiedOperatorBuilder::TransitionAndStoreNonNumberElement(
1250 6 : Handle<Map> fast_map, Type* value_type) {
1251 : TransitionAndStoreNonNumberElementParameters parameters(fast_map, value_type);
1252 : return new (zone()) Operator1<TransitionAndStoreNonNumberElementParameters>(
1253 : IrOpcode::kTransitionAndStoreNonNumberElement,
1254 : Operator::kNoDeopt | Operator::kNoThrow,
1255 6 : "TransitionAndStoreNonNumberElement", 3, 1, 1, 0, 1, 0, parameters);
1256 : }
1257 :
1258 : #undef PURE_OP_LIST
1259 : #undef SPECULATIVE_NUMBER_BINOP_LIST
1260 : #undef CHECKED_OP_LIST
1261 : #undef ACCESS_OP_LIST
1262 :
1263 : } // namespace compiler
1264 : } // namespace internal
1265 : } // namespace v8
|