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