1// Copyright 2013 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#ifndef V8_COMPILER_JS_OPERATOR_H_
6#define V8_COMPILER_JS_OPERATOR_H_
7
8#include "src/base/compiler-specific.h"
9#include "src/codegen/tnode.h"
10#include "src/compiler/common-operator.h"
11#include "src/compiler/feedback-source.h"
12#include "src/compiler/globals.h"
13#include "src/compiler/node-properties.h"
14#include "src/compiler/node.h"
15#include "src/compiler/opcodes.h"
16#include "src/handles/maybe-handles.h"
17#include "src/objects/type-hints.h"
18#include "src/runtime/runtime.h"
19
20namespace v8 {
21namespace internal {
22
23class AllocationSite;
24class ObjectBoilerplateDescription;
25class ArrayBoilerplateDescription;
26class FeedbackCell;
27class SharedFunctionInfo;
28
29namespace wasm {
30class ValueType;
31}
32
33namespace compiler {
34
35// Forward declarations.
36class JSGraph;
37class Operator;
38struct JSOperatorGlobalCache;
39
40// Macro lists.
41#define JS_UNOP_WITH_FEEDBACK(V) \
42  JS_BITWISE_UNOP_LIST(V)        \
43  JS_ARITH_UNOP_LIST(V)
44
45#define JS_BINOP_WITH_FEEDBACK(V) \
46  JS_ARITH_BINOP_LIST(V)          \
47  JS_BITWISE_BINOP_LIST(V)        \
48  JS_COMPARE_BINOP_LIST(V)        \
49  V(JSInstanceOf, InstanceOf)
50
51// Predicates.
52class JSOperator final : public AllStatic {
53 public:
54  static constexpr bool IsUnaryWithFeedback(Operator::Opcode opcode) {
55#define CASE(Name, ...)   \
56  case IrOpcode::k##Name: \
57    return true;
58    switch (opcode) {
59      JS_UNOP_WITH_FEEDBACK(CASE);
60      default:
61        return false;
62    }
63#undef CASE
64    return false;
65  }
66
67  static constexpr bool IsBinaryWithFeedback(Operator::Opcode opcode) {
68#define CASE(Name, ...)   \
69  case IrOpcode::k##Name: \
70    return true;
71    switch (opcode) {
72      JS_BINOP_WITH_FEEDBACK(CASE);
73      default:
74        return false;
75    }
76#undef CASE
77    return false;
78  }
79};
80
81// Defines the frequency a given Call/Construct site was executed. For some
82// call sites the frequency is not known.
83class CallFrequency final {
84 public:
85  CallFrequency() : value_(std::numeric_limits<float>::quiet_NaN()) {}
86  explicit CallFrequency(float value) : value_(value) {
87    DCHECK(!std::isnan(value));
88  }
89
90  bool IsKnown() const { return !IsUnknown(); }
91  bool IsUnknown() const { return std::isnan(value_); }
92  float value() const {
93    DCHECK(IsKnown());
94    return value_;
95  }
96
97  bool operator==(CallFrequency const& that) const {
98    return bit_cast<uint32_t>(this->value_) == bit_cast<uint32_t>(that.value_);
99  }
100  bool operator!=(CallFrequency const& that) const { return !(*this == that); }
101
102  friend size_t hash_value(CallFrequency const& f) {
103    return bit_cast<uint32_t>(f.value_);
104  }
105
106  static constexpr float kNoFeedbackCallFrequency = -1;
107
108 private:
109  float value_;
110};
111
112std::ostream& operator<<(std::ostream&, CallFrequency const&);
113
114// Defines the flags for a JavaScript call forwarding parameters. This
115// is used as parameter by JSConstructForwardVarargs operators.
116class ConstructForwardVarargsParameters final {
117 public:
118  ConstructForwardVarargsParameters(size_t arity, uint32_t start_index)
119      : bit_field_(ArityField::encode(arity) |
120                   StartIndexField::encode(start_index)) {}
121
122  size_t arity() const { return ArityField::decode(bit_field_); }
123  uint32_t start_index() const { return StartIndexField::decode(bit_field_); }
124
125  bool operator==(ConstructForwardVarargsParameters const& that) const {
126    return this->bit_field_ == that.bit_field_;
127  }
128  bool operator!=(ConstructForwardVarargsParameters const& that) const {
129    return !(*this == that);
130  }
131
132 private:
133  friend size_t hash_value(ConstructForwardVarargsParameters const& p) {
134    return p.bit_field_;
135  }
136
137  using ArityField = base::BitField<size_t, 0, 16>;
138  using StartIndexField = base::BitField<uint32_t, 16, 16>;
139
140  uint32_t const bit_field_;
141};
142
143std::ostream& operator<<(std::ostream&,
144                         ConstructForwardVarargsParameters const&);
145
146ConstructForwardVarargsParameters const& ConstructForwardVarargsParametersOf(
147    Operator const*) V8_WARN_UNUSED_RESULT;
148
149// Defines the arity (parameters plus the target and new target) and the
150// feedback for a JavaScript constructor call. This is used as a parameter by
151// JSConstruct, JSConstructWithArrayLike, and JSConstructWithSpread operators.
152class ConstructParameters final {
153 public:
154  // A separate declaration to get around circular declaration dependencies.
155  // Checked to equal JSConstructNode::kExtraInputCount below.
156  static constexpr int kExtraConstructInputCount = 3;
157
158  ConstructParameters(uint32_t arity, CallFrequency const& frequency,
159                      FeedbackSource const& feedback)
160      : arity_(arity), frequency_(frequency), feedback_(feedback) {
161    DCHECK_GE(arity, kExtraConstructInputCount);
162    DCHECK(is_int32(arity));
163  }
164
165  // TODO(jgruber): Consider removing `arity()` and just storing the arity
166  // without extra args in ConstructParameters. Every spot that creates
167  // ConstructParameters artifically adds the extra args. Every spot that uses
168  // ConstructParameters artificially subtracts the extra args.
169  // We keep them for now for consistency with other spots
170  // that expect `arity()` to include extra args.
171  uint32_t arity() const { return arity_; }
172  int arity_without_implicit_args() const {
173    return static_cast<int>(arity_ - kExtraConstructInputCount);
174  }
175
176  CallFrequency const& frequency() const { return frequency_; }
177  FeedbackSource const& feedback() const { return feedback_; }
178
179 private:
180  uint32_t const arity_;
181  CallFrequency const frequency_;
182  FeedbackSource const feedback_;
183};
184
185bool operator==(ConstructParameters const&, ConstructParameters const&);
186bool operator!=(ConstructParameters const&, ConstructParameters const&);
187
188size_t hash_value(ConstructParameters const&);
189
190std::ostream& operator<<(std::ostream&, ConstructParameters const&);
191
192ConstructParameters const& ConstructParametersOf(Operator const*);
193
194// Defines the flags for a JavaScript call forwarding parameters. This
195// is used as parameter by JSCallForwardVarargs operators.
196class CallForwardVarargsParameters final {
197 public:
198  CallForwardVarargsParameters(size_t arity, uint32_t start_index)
199      : bit_field_(ArityField::encode(arity) |
200                   StartIndexField::encode(start_index)) {}
201
202  size_t arity() const { return ArityField::decode(bit_field_); }
203  uint32_t start_index() const { return StartIndexField::decode(bit_field_); }
204
205  bool operator==(CallForwardVarargsParameters const& that) const {
206    return this->bit_field_ == that.bit_field_;
207  }
208  bool operator!=(CallForwardVarargsParameters const& that) const {
209    return !(*this == that);
210  }
211
212 private:
213  friend size_t hash_value(CallForwardVarargsParameters const& p) {
214    return p.bit_field_;
215  }
216
217  using ArityField = base::BitField<size_t, 0, 15>;
218  using StartIndexField = base::BitField<uint32_t, 15, 15>;
219
220  uint32_t const bit_field_;
221};
222
223std::ostream& operator<<(std::ostream&, CallForwardVarargsParameters const&);
224
225CallForwardVarargsParameters const& CallForwardVarargsParametersOf(
226    Operator const*) V8_WARN_UNUSED_RESULT;
227
228// Defines the arity (parameters plus the target and receiver) and the call
229// flags for a JavaScript function call. This is used as a parameter by JSCall,
230// JSCallWithArrayLike and JSCallWithSpread operators.
231class CallParameters final {
232 public:
233  // A separate declaration to get around circular declaration dependencies.
234  // Checked to equal JSCallNode::kExtraInputCount below.
235  static constexpr int kExtraCallInputCount = 3;
236
237  CallParameters(size_t arity, CallFrequency const& frequency,
238                 FeedbackSource const& feedback,
239                 ConvertReceiverMode convert_mode,
240                 SpeculationMode speculation_mode,
241                 CallFeedbackRelation feedback_relation)
242      : bit_field_(ArityField::encode(arity) |
243                   CallFeedbackRelationField::encode(feedback_relation) |
244                   SpeculationModeField::encode(speculation_mode) |
245                   ConvertReceiverModeField::encode(convert_mode)),
246        frequency_(frequency),
247        feedback_(feedback) {
248    // CallFeedbackRelation is ignored if the feedback slot is invalid.
249    DCHECK_IMPLIES(speculation_mode == SpeculationMode::kAllowSpeculation,
250                   feedback.IsValid());
251    DCHECK_IMPLIES(!feedback.IsValid(),
252                   feedback_relation == CallFeedbackRelation::kUnrelated);
253    DCHECK_GE(arity, kExtraCallInputCount);
254    DCHECK(is_int32(arity));
255  }
256
257  // TODO(jgruber): Consider removing `arity()` and just storing the arity
258  // without extra args in CallParameters.
259  size_t arity() const { return ArityField::decode(bit_field_); }
260  int arity_without_implicit_args() const {
261    return static_cast<int>(arity() - kExtraCallInputCount);
262  }
263
264  CallFrequency const& frequency() const { return frequency_; }
265  ConvertReceiverMode convert_mode() const {
266    return ConvertReceiverModeField::decode(bit_field_);
267  }
268  FeedbackSource const& feedback() const { return feedback_; }
269
270  SpeculationMode speculation_mode() const {
271    return SpeculationModeField::decode(bit_field_);
272  }
273
274  CallFeedbackRelation feedback_relation() const {
275    return CallFeedbackRelationField::decode(bit_field_);
276  }
277
278  bool operator==(CallParameters const& that) const {
279    return this->bit_field_ == that.bit_field_ &&
280           this->frequency_ == that.frequency_ &&
281           this->feedback_ == that.feedback_;
282  }
283  bool operator!=(CallParameters const& that) const { return !(*this == that); }
284
285 private:
286  friend size_t hash_value(CallParameters const& p) {
287    FeedbackSource::Hash feedback_hash;
288    return base::hash_combine(p.bit_field_, p.frequency_,
289                              feedback_hash(p.feedback_));
290  }
291
292  using ArityField = base::BitField<size_t, 0, 27>;
293  using CallFeedbackRelationField = base::BitField<CallFeedbackRelation, 27, 2>;
294  using SpeculationModeField = base::BitField<SpeculationMode, 29, 1>;
295  using ConvertReceiverModeField = base::BitField<ConvertReceiverMode, 30, 2>;
296
297  uint32_t const bit_field_;
298  CallFrequency const frequency_;
299  FeedbackSource const feedback_;
300};
301
302size_t hash_value(CallParameters const&);
303
304std::ostream& operator<<(std::ostream&, CallParameters const&);
305
306const CallParameters& CallParametersOf(const Operator* op);
307
308
309// Defines the arity and the ID for a runtime function call. This is used as a
310// parameter by JSCallRuntime operators.
311class V8_EXPORT_PRIVATE CallRuntimeParameters final {
312 public:
313  CallRuntimeParameters(Runtime::FunctionId id, size_t arity)
314      : id_(id), arity_(arity) {}
315
316  Runtime::FunctionId id() const { return id_; }
317  size_t arity() const { return arity_; }
318
319 private:
320  const Runtime::FunctionId id_;
321  const size_t arity_;
322};
323
324bool operator==(CallRuntimeParameters const&, CallRuntimeParameters const&);
325bool operator!=(CallRuntimeParameters const&, CallRuntimeParameters const&);
326
327size_t hash_value(CallRuntimeParameters const&);
328
329std::ostream& operator<<(std::ostream&, CallRuntimeParameters const&);
330
331V8_EXPORT_PRIVATE const CallRuntimeParameters& CallRuntimeParametersOf(
332    const Operator* op);
333
334// Defines the location of a context slot relative to a specific scope. This is
335// used as a parameter by JSLoadContext and JSStoreContext operators and allows
336// accessing a context-allocated variable without keeping track of the scope.
337class ContextAccess final {
338 public:
339  ContextAccess(size_t depth, size_t index, bool immutable);
340
341  size_t depth() const { return depth_; }
342  size_t index() const { return index_; }
343  bool immutable() const { return immutable_; }
344
345 private:
346  // For space reasons, we keep this tightly packed, otherwise we could just use
347  // a simple int/int/bool POD.
348  const bool immutable_;
349  const uint16_t depth_;
350  const uint32_t index_;
351};
352
353bool operator==(ContextAccess const&, ContextAccess const&);
354bool operator!=(ContextAccess const&, ContextAccess const&);
355
356size_t hash_value(ContextAccess const&);
357
358V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, ContextAccess const&);
359
360V8_EXPORT_PRIVATE ContextAccess const& ContextAccessOf(Operator const*);
361
362// Defines the slot count and ScopeType for a new function or eval context. This
363// is used as a parameter by the JSCreateFunctionContext operator.
364class CreateFunctionContextParameters final {
365 public:
366  CreateFunctionContextParameters(const ScopeInfoRef& scope_info,
367                                  int slot_count, ScopeType scope_type)
368      : scope_info_(scope_info),
369        slot_count_(slot_count),
370        scope_type_(scope_type) {}
371
372  ScopeInfoRef scope_info(JSHeapBroker* broker) const {
373    return scope_info_.AsRef(broker);
374  }
375  int slot_count() const { return slot_count_; }
376  ScopeType scope_type() const { return scope_type_; }
377
378 private:
379  const ScopeInfoTinyRef scope_info_;
380  int const slot_count_;
381  ScopeType const scope_type_;
382
383  friend bool operator==(CreateFunctionContextParameters const& lhs,
384                         CreateFunctionContextParameters const& rhs);
385  friend bool operator!=(CreateFunctionContextParameters const& lhs,
386                         CreateFunctionContextParameters const& rhs);
387
388  friend size_t hash_value(CreateFunctionContextParameters const& parameters);
389
390  friend std::ostream& operator<<(
391      std::ostream& os, CreateFunctionContextParameters const& parameters);
392};
393
394CreateFunctionContextParameters const& CreateFunctionContextParametersOf(
395    Operator const*);
396
397// Defines parameters for JSDefineNamedOwnProperty operator.
398class DefineNamedOwnPropertyParameters final {
399 public:
400  DefineNamedOwnPropertyParameters(const NameRef& name,
401                                   FeedbackSource const& feedback)
402      : name_(name), feedback_(feedback) {}
403
404  NameRef name(JSHeapBroker* broker) const { return name_.AsRef(broker); }
405  FeedbackSource const& feedback() const { return feedback_; }
406
407 private:
408  const NameTinyRef name_;
409  FeedbackSource const feedback_;
410
411  friend bool operator==(DefineNamedOwnPropertyParameters const&,
412                         DefineNamedOwnPropertyParameters const&);
413  friend bool operator!=(DefineNamedOwnPropertyParameters const&,
414                         DefineNamedOwnPropertyParameters const&);
415  friend size_t hash_value(DefineNamedOwnPropertyParameters const&);
416  friend std::ostream& operator<<(std::ostream&,
417                                  DefineNamedOwnPropertyParameters const&);
418};
419
420const DefineNamedOwnPropertyParameters& DefineNamedOwnPropertyParametersOf(
421    const Operator* op);
422
423// Defines the feedback, i.e., vector and index, for storing a data property in
424// an object literal. This is used as a parameter by JSCreateEmptyLiteralArray
425// and JSDefineKeyedOwnPropertyInLiteral operators.
426class FeedbackParameter final {
427 public:
428  explicit FeedbackParameter(FeedbackSource const& feedback)
429      : feedback_(feedback) {}
430
431  FeedbackSource const& feedback() const { return feedback_; }
432
433 private:
434  FeedbackSource const feedback_;
435};
436
437bool operator==(FeedbackParameter const&, FeedbackParameter const&);
438bool operator!=(FeedbackParameter const&, FeedbackParameter const&);
439
440size_t hash_value(FeedbackParameter const&);
441
442std::ostream& operator<<(std::ostream&, FeedbackParameter const&);
443
444const FeedbackParameter& FeedbackParameterOf(const Operator* op);
445
446// Defines the property of an object for a named access. This is
447// used as a parameter by the JSLoadNamed and JSSetNamedProperty operators.
448class NamedAccess final {
449 public:
450  NamedAccess(LanguageMode language_mode, const NameRef& name,
451              FeedbackSource const& feedback)
452      : name_(name), feedback_(feedback), language_mode_(language_mode) {}
453
454  NameRef name(JSHeapBroker* broker) const { return name_.AsRef(broker); }
455  LanguageMode language_mode() const { return language_mode_; }
456  FeedbackSource const& feedback() const { return feedback_; }
457
458 private:
459  const NameTinyRef name_;
460  FeedbackSource const feedback_;
461  LanguageMode const language_mode_;
462
463  friend bool operator==(NamedAccess const&, NamedAccess const&);
464  friend bool operator!=(NamedAccess const&, NamedAccess const&);
465
466  friend size_t hash_value(NamedAccess const&);
467
468  friend std::ostream& operator<<(std::ostream&, NamedAccess const&);
469};
470
471const NamedAccess& NamedAccessOf(const Operator* op);
472
473
474// Defines the property being loaded from an object by a named load. This is
475// used as a parameter by JSLoadGlobal operator.
476class LoadGlobalParameters final {
477 public:
478  LoadGlobalParameters(const NameRef& name, const FeedbackSource& feedback,
479                       TypeofMode typeof_mode)
480      : name_(name), feedback_(feedback), typeof_mode_(typeof_mode) {}
481
482  NameRef name(JSHeapBroker* broker) const { return name_.AsRef(broker); }
483  TypeofMode typeof_mode() const { return typeof_mode_; }
484
485  const FeedbackSource& feedback() const { return feedback_; }
486
487 private:
488  const NameTinyRef name_;
489  const FeedbackSource feedback_;
490  const TypeofMode typeof_mode_;
491
492  friend bool operator==(LoadGlobalParameters const&,
493                         LoadGlobalParameters const&);
494  friend bool operator!=(LoadGlobalParameters const&,
495                         LoadGlobalParameters const&);
496
497  friend size_t hash_value(LoadGlobalParameters const&);
498
499  friend std::ostream& operator<<(std::ostream&, LoadGlobalParameters const&);
500};
501
502const LoadGlobalParameters& LoadGlobalParametersOf(const Operator* op);
503
504
505// Defines the property being stored to an object by a named store. This is
506// used as a parameter by JSStoreGlobal operator.
507class StoreGlobalParameters final {
508 public:
509  StoreGlobalParameters(LanguageMode language_mode,
510                        const FeedbackSource& feedback, const NameRef& name)
511      : language_mode_(language_mode), name_(name), feedback_(feedback) {}
512
513  LanguageMode language_mode() const { return language_mode_; }
514  FeedbackSource const& feedback() const { return feedback_; }
515  NameRef name(JSHeapBroker* broker) const { return name_.AsRef(broker); }
516
517 private:
518  LanguageMode const language_mode_;
519  const NameTinyRef name_;
520  FeedbackSource const feedback_;
521
522  friend bool operator==(StoreGlobalParameters const&,
523                         StoreGlobalParameters const&);
524  friend bool operator!=(StoreGlobalParameters const&,
525                         StoreGlobalParameters const&);
526
527  friend size_t hash_value(StoreGlobalParameters const&);
528
529  friend std::ostream& operator<<(std::ostream&, StoreGlobalParameters const&);
530};
531
532const StoreGlobalParameters& StoreGlobalParametersOf(const Operator* op);
533
534// Defines the property of an object for a keyed access. This is used
535// as a parameter by the JSLoadProperty and JSSetKeyedProperty
536// operators.
537class PropertyAccess final {
538 public:
539  PropertyAccess(LanguageMode language_mode, FeedbackSource const& feedback)
540      : feedback_(feedback), language_mode_(language_mode) {}
541
542  LanguageMode language_mode() const { return language_mode_; }
543  FeedbackSource const& feedback() const { return feedback_; }
544
545 private:
546  FeedbackSource const feedback_;
547  LanguageMode const language_mode_;
548};
549
550bool operator==(PropertyAccess const&, PropertyAccess const&);
551bool operator!=(PropertyAccess const&, PropertyAccess const&);
552
553size_t hash_value(PropertyAccess const&);
554
555V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
556                                           PropertyAccess const&);
557
558PropertyAccess const& PropertyAccessOf(const Operator* op);
559
560
561// CreateArgumentsType is used as parameter to JSCreateArguments nodes.
562CreateArgumentsType const& CreateArgumentsTypeOf(const Operator* op);
563
564
565// Defines shared information for the array that should be created. This is
566// used as parameter by JSCreateArray operators.
567class CreateArrayParameters final {
568 public:
569  CreateArrayParameters(size_t arity, base::Optional<AllocationSiteRef> site)
570      : arity_(arity), site_(site) {}
571
572  size_t arity() const { return arity_; }
573  base::Optional<AllocationSiteRef> site(JSHeapBroker* broker) const {
574    return AllocationSiteTinyRef::AsOptionalRef(broker, site_);
575  }
576
577 private:
578  size_t const arity_;
579  base::Optional<AllocationSiteTinyRef> const site_;
580
581  friend bool operator==(CreateArrayParameters const&,
582                         CreateArrayParameters const&);
583  friend bool operator!=(CreateArrayParameters const&,
584                         CreateArrayParameters const&);
585  friend size_t hash_value(CreateArrayParameters const&);
586  friend std::ostream& operator<<(std::ostream&, CreateArrayParameters const&);
587};
588
589const CreateArrayParameters& CreateArrayParametersOf(const Operator* op);
590
591// Defines shared information for the array iterator that should be created.
592// This is used as parameter by JSCreateArrayIterator operators.
593class CreateArrayIteratorParameters final {
594 public:
595  explicit CreateArrayIteratorParameters(IterationKind kind) : kind_(kind) {}
596
597  IterationKind kind() const { return kind_; }
598
599 private:
600  IterationKind const kind_;
601};
602
603bool operator==(CreateArrayIteratorParameters const&,
604                CreateArrayIteratorParameters const&);
605bool operator!=(CreateArrayIteratorParameters const&,
606                CreateArrayIteratorParameters const&);
607
608size_t hash_value(CreateArrayIteratorParameters const&);
609
610std::ostream& operator<<(std::ostream&, CreateArrayIteratorParameters const&);
611
612const CreateArrayIteratorParameters& CreateArrayIteratorParametersOf(
613    const Operator* op);
614
615// Defines shared information for the array iterator that should be created.
616// This is used as parameter by JSCreateCollectionIterator operators.
617class CreateCollectionIteratorParameters final {
618 public:
619  explicit CreateCollectionIteratorParameters(CollectionKind collection_kind,
620                                              IterationKind iteration_kind)
621      : collection_kind_(collection_kind), iteration_kind_(iteration_kind) {
622    CHECK(!(collection_kind == CollectionKind::kSet &&
623            iteration_kind == IterationKind::kKeys));
624  }
625
626  CollectionKind collection_kind() const { return collection_kind_; }
627  IterationKind iteration_kind() const { return iteration_kind_; }
628
629 private:
630  CollectionKind const collection_kind_;
631  IterationKind const iteration_kind_;
632};
633
634bool operator==(CreateCollectionIteratorParameters const&,
635                CreateCollectionIteratorParameters const&);
636bool operator!=(CreateCollectionIteratorParameters const&,
637                CreateCollectionIteratorParameters const&);
638
639size_t hash_value(CreateCollectionIteratorParameters const&);
640
641std::ostream& operator<<(std::ostream&,
642                         CreateCollectionIteratorParameters const&);
643
644const CreateCollectionIteratorParameters& CreateCollectionIteratorParametersOf(
645    const Operator* op);
646
647// Defines shared information for the bound function that should be created.
648// This is used as parameter by JSCreateBoundFunction operators.
649class CreateBoundFunctionParameters final {
650 public:
651  CreateBoundFunctionParameters(size_t arity, const MapRef& map)
652      : arity_(arity), map_(map) {}
653
654  size_t arity() const { return arity_; }
655  MapRef map(JSHeapBroker* broker) const { return map_.AsRef(broker); }
656
657 private:
658  size_t const arity_;
659  const MapTinyRef map_;
660
661  friend bool operator==(CreateBoundFunctionParameters const&,
662                         CreateBoundFunctionParameters const&);
663  friend bool operator!=(CreateBoundFunctionParameters const&,
664                         CreateBoundFunctionParameters const&);
665
666  friend size_t hash_value(CreateBoundFunctionParameters const&);
667
668  friend std::ostream& operator<<(std::ostream&,
669                                  CreateBoundFunctionParameters const&);
670};
671
672const CreateBoundFunctionParameters& CreateBoundFunctionParametersOf(
673    const Operator* op);
674
675// Defines shared information for the closure that should be created. This is
676// used as a parameter by JSCreateClosure operators.
677class CreateClosureParameters final {
678 public:
679  CreateClosureParameters(const SharedFunctionInfoRef& shared_info,
680                          const CodeTRef& code, AllocationType allocation)
681      : shared_info_(shared_info), code_(code), allocation_(allocation) {}
682
683  SharedFunctionInfoRef shared_info(JSHeapBroker* broker) const {
684    return shared_info_.AsRef(broker);
685  }
686  CodeTRef code(JSHeapBroker* broker) const { return code_.AsRef(broker); }
687  AllocationType allocation() const { return allocation_; }
688
689 private:
690  const SharedFunctionInfoTinyRef shared_info_;
691  const CodeTTinyRef code_;
692  AllocationType const allocation_;
693
694  friend bool operator==(CreateClosureParameters const&,
695                         CreateClosureParameters const&);
696  friend bool operator!=(CreateClosureParameters const&,
697                         CreateClosureParameters const&);
698
699  friend size_t hash_value(CreateClosureParameters const&);
700
701  friend std::ostream& operator<<(std::ostream&,
702                                  CreateClosureParameters const&);
703};
704
705const CreateClosureParameters& CreateClosureParametersOf(const Operator* op);
706
707class GetTemplateObjectParameters final {
708 public:
709  GetTemplateObjectParameters(const TemplateObjectDescriptionRef& description,
710                              const SharedFunctionInfoRef& shared,
711                              FeedbackSource const& feedback)
712      : description_(description), shared_(shared), feedback_(feedback) {}
713
714  TemplateObjectDescriptionRef description(JSHeapBroker* broker) const {
715    return description_.AsRef(broker);
716  }
717  SharedFunctionInfoRef shared(JSHeapBroker* broker) const {
718    return shared_.AsRef(broker);
719  }
720  FeedbackSource const& feedback() const { return feedback_; }
721
722 private:
723  const TemplateObjectDescriptionTinyRef description_;
724  const SharedFunctionInfoTinyRef shared_;
725  FeedbackSource const feedback_;
726
727  friend bool operator==(GetTemplateObjectParameters const&,
728                         GetTemplateObjectParameters const&);
729  friend bool operator!=(GetTemplateObjectParameters const&,
730                         GetTemplateObjectParameters const&);
731
732  friend size_t hash_value(GetTemplateObjectParameters const&);
733
734  friend std::ostream& operator<<(std::ostream&,
735                                  GetTemplateObjectParameters const&);
736};
737
738const GetTemplateObjectParameters& GetTemplateObjectParametersOf(
739    const Operator* op);
740
741// Defines shared information for the literal that should be created. This is
742// used as parameter by JSCreateLiteralArray, JSCreateLiteralObject and
743// JSCreateLiteralRegExp operators.
744class CreateLiteralParameters final {
745 public:
746  CreateLiteralParameters(const HeapObjectRef& constant,
747                          FeedbackSource const& feedback, int length, int flags)
748      : constant_(constant),
749        feedback_(feedback),
750        length_(length),
751        flags_(flags) {}
752
753  HeapObjectRef constant(JSHeapBroker* broker) const {
754    return constant_.AsRef(broker);
755  }
756  FeedbackSource const& feedback() const { return feedback_; }
757  int length() const { return length_; }
758  int flags() const { return flags_; }
759
760 private:
761  const HeapObjectTinyRef constant_;
762  FeedbackSource const feedback_;
763  int const length_;
764  int const flags_;
765
766  friend bool operator==(CreateLiteralParameters const&,
767                         CreateLiteralParameters const&);
768  friend bool operator!=(CreateLiteralParameters const&,
769                         CreateLiteralParameters const&);
770
771  friend size_t hash_value(CreateLiteralParameters const&);
772
773  friend std::ostream& operator<<(std::ostream&,
774                                  CreateLiteralParameters const&);
775};
776
777const CreateLiteralParameters& CreateLiteralParametersOf(const Operator* op);
778
779class CloneObjectParameters final {
780 public:
781  CloneObjectParameters(FeedbackSource const& feedback, int flags)
782      : feedback_(feedback), flags_(flags) {}
783
784  FeedbackSource const& feedback() const { return feedback_; }
785  int flags() const { return flags_; }
786
787 private:
788  FeedbackSource const feedback_;
789  int const flags_;
790};
791
792bool operator==(CloneObjectParameters const&, CloneObjectParameters const&);
793bool operator!=(CloneObjectParameters const&, CloneObjectParameters const&);
794
795size_t hash_value(CloneObjectParameters const&);
796
797std::ostream& operator<<(std::ostream&, CloneObjectParameters const&);
798
799const CloneObjectParameters& CloneObjectParametersOf(const Operator* op);
800
801// Defines the shared information for the iterator symbol thats loaded and
802// called. This is used as a parameter by JSGetIterator operator.
803class GetIteratorParameters final {
804 public:
805  GetIteratorParameters(const FeedbackSource& load_feedback,
806                        const FeedbackSource& call_feedback)
807      : load_feedback_(load_feedback), call_feedback_(call_feedback) {}
808
809  FeedbackSource const& loadFeedback() const { return load_feedback_; }
810  FeedbackSource const& callFeedback() const { return call_feedback_; }
811
812 private:
813  FeedbackSource const load_feedback_;
814  FeedbackSource const call_feedback_;
815};
816
817bool operator==(GetIteratorParameters const&, GetIteratorParameters const&);
818bool operator!=(GetIteratorParameters const&, GetIteratorParameters const&);
819
820size_t hash_value(GetIteratorParameters const&);
821
822std::ostream& operator<<(std::ostream&, GetIteratorParameters const&);
823
824const GetIteratorParameters& GetIteratorParametersOf(const Operator* op);
825
826enum class ForInMode : uint8_t {
827  kUseEnumCacheKeysAndIndices,
828  kUseEnumCacheKeys,
829  kGeneric
830};
831size_t hash_value(ForInMode const&);
832std::ostream& operator<<(std::ostream&, ForInMode const&);
833
834class ForInParameters final {
835 public:
836  ForInParameters(const FeedbackSource& feedback, ForInMode mode)
837      : feedback_(feedback), mode_(mode) {}
838
839  const FeedbackSource& feedback() const { return feedback_; }
840  ForInMode mode() const { return mode_; }
841
842 private:
843  const FeedbackSource feedback_;
844  const ForInMode mode_;
845};
846
847bool operator==(ForInParameters const&, ForInParameters const&);
848bool operator!=(ForInParameters const&, ForInParameters const&);
849size_t hash_value(ForInParameters const&);
850std::ostream& operator<<(std::ostream&, ForInParameters const&);
851const ForInParameters& ForInParametersOf(const Operator* op);
852
853#if V8_ENABLE_WEBASSEMBLY
854class JSWasmCallParameters {
855 public:
856  explicit JSWasmCallParameters(const wasm::WasmModule* module,
857                                const wasm::FunctionSig* signature,
858                                FeedbackSource const& feedback)
859      : module_(module), signature_(signature), feedback_(feedback) {
860    DCHECK_NOT_NULL(module);
861    DCHECK_NOT_NULL(signature);
862  }
863
864  const wasm::WasmModule* module() const { return module_; }
865  const wasm::FunctionSig* signature() const { return signature_; }
866  FeedbackSource const& feedback() const { return feedback_; }
867  int input_count() const;
868  int arity_without_implicit_args() const;
869
870 private:
871  const wasm::WasmModule* const module_;
872  const wasm::FunctionSig* const signature_;
873  const FeedbackSource feedback_;
874};
875
876JSWasmCallParameters const& JSWasmCallParametersOf(const Operator* op)
877    V8_WARN_UNUSED_RESULT;
878V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
879                                           JSWasmCallParameters const&);
880size_t hash_value(JSWasmCallParameters const&);
881bool operator==(JSWasmCallParameters const&, JSWasmCallParameters const&);
882#endif  // V8_ENABLE_WEBASSEMBLY
883
884int RegisterCountOf(Operator const* op) V8_WARN_UNUSED_RESULT;
885
886int GeneratorStoreValueCountOf(const Operator* op) V8_WARN_UNUSED_RESULT;
887int RestoreRegisterIndexOf(const Operator* op) V8_WARN_UNUSED_RESULT;
888
889ScopeInfoRef ScopeInfoOf(JSHeapBroker* broker,
890                         const Operator* op) V8_WARN_UNUSED_RESULT;
891
892bool operator==(ScopeInfoTinyRef const&, ScopeInfoTinyRef const&);
893bool operator!=(ScopeInfoTinyRef const&, ScopeInfoTinyRef const&);
894
895size_t hash_value(ScopeInfoTinyRef const&);
896
897V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
898                                           ScopeInfoTinyRef const&);
899
900// Interface for building JavaScript-level operators, e.g. directly from the
901// AST. Most operators have no parameters, thus can be globally shared for all
902// graphs.
903class V8_EXPORT_PRIVATE JSOperatorBuilder final
904    : public NON_EXPORTED_BASE(ZoneObject) {
905 public:
906  explicit JSOperatorBuilder(Zone* zone);
907  JSOperatorBuilder(const JSOperatorBuilder&) = delete;
908  JSOperatorBuilder& operator=(const JSOperatorBuilder&) = delete;
909
910  const Operator* Equal(FeedbackSource const& feedback);
911  const Operator* StrictEqual(FeedbackSource const& feedback);
912  const Operator* LessThan(FeedbackSource const& feedback);
913  const Operator* GreaterThan(FeedbackSource const& feedback);
914  const Operator* LessThanOrEqual(FeedbackSource const& feedback);
915  const Operator* GreaterThanOrEqual(FeedbackSource const& feedback);
916
917  const Operator* BitwiseOr(FeedbackSource const& feedback);
918  const Operator* BitwiseXor(FeedbackSource const& feedback);
919  const Operator* BitwiseAnd(FeedbackSource const& feedback);
920  const Operator* ShiftLeft(FeedbackSource const& feedback);
921  const Operator* ShiftRight(FeedbackSource const& feedback);
922  const Operator* ShiftRightLogical(FeedbackSource const& feedback);
923  const Operator* Add(FeedbackSource const& feedback);
924  const Operator* Subtract(FeedbackSource const& feedback);
925  const Operator* Multiply(FeedbackSource const& feedback);
926  const Operator* Divide(FeedbackSource const& feedback);
927  const Operator* Modulus(FeedbackSource const& feedback);
928  const Operator* Exponentiate(FeedbackSource const& feedback);
929
930  const Operator* BitwiseNot(FeedbackSource const& feedback);
931  const Operator* Decrement(FeedbackSource const& feedback);
932  const Operator* Increment(FeedbackSource const& feedback);
933  const Operator* Negate(FeedbackSource const& feedback);
934
935  const Operator* ToLength();
936  const Operator* ToName();
937  const Operator* ToNumber();
938  const Operator* ToNumberConvertBigInt();
939  const Operator* ToNumeric();
940  const Operator* ToObject();
941  const Operator* ToString();
942
943  const Operator* Create();
944  const Operator* CreateArguments(CreateArgumentsType type);
945  const Operator* CreateArray(size_t arity,
946                              base::Optional<AllocationSiteRef> site);
947  const Operator* CreateArrayIterator(IterationKind);
948  const Operator* CreateAsyncFunctionObject(int register_count);
949  const Operator* CreateCollectionIterator(CollectionKind, IterationKind);
950  const Operator* CreateBoundFunction(size_t arity, const MapRef& map);
951  const Operator* CreateClosure(
952      const SharedFunctionInfoRef& shared_info, const CodeTRef& code,
953      AllocationType allocation = AllocationType::kYoung);
954  const Operator* CreateIterResultObject();
955  const Operator* CreateStringIterator();
956  const Operator* CreateKeyValueArray();
957  const Operator* CreateObject();
958  const Operator* CreatePromise();
959  const Operator* CreateTypedArray();
960  const Operator* CreateLiteralArray(
961      const ArrayBoilerplateDescriptionRef& constant,
962      FeedbackSource const& feedback, int literal_flags,
963      int number_of_elements);
964  const Operator* CreateEmptyLiteralArray(FeedbackSource const& feedback);
965  const Operator* CreateArrayFromIterable();
966  const Operator* CreateEmptyLiteralObject();
967  const Operator* CreateLiteralObject(
968      const ObjectBoilerplateDescriptionRef& constant,
969      FeedbackSource const& feedback, int literal_flags,
970      int number_of_properties);
971  const Operator* CloneObject(FeedbackSource const& feedback,
972                              int literal_flags);
973  const Operator* CreateLiteralRegExp(const StringRef& constant_pattern,
974                                      FeedbackSource const& feedback,
975                                      int literal_flags);
976
977  const Operator* GetTemplateObject(
978      const TemplateObjectDescriptionRef& description,
979      const SharedFunctionInfoRef& shared, FeedbackSource const& feedback);
980
981  const Operator* CallForwardVarargs(size_t arity, uint32_t start_index);
982  const Operator* Call(
983      size_t arity, CallFrequency const& frequency = CallFrequency(),
984      FeedbackSource const& feedback = FeedbackSource(),
985      ConvertReceiverMode convert_mode = ConvertReceiverMode::kAny,
986      SpeculationMode speculation_mode = SpeculationMode::kDisallowSpeculation,
987      CallFeedbackRelation feedback_relation =
988          CallFeedbackRelation::kUnrelated);
989  const Operator* CallWithArrayLike(
990      CallFrequency const& frequency,
991      const FeedbackSource& feedback = FeedbackSource{},
992      SpeculationMode speculation_mode = SpeculationMode::kDisallowSpeculation,
993      CallFeedbackRelation feedback_relation = CallFeedbackRelation::kTarget);
994  const Operator* CallWithSpread(
995      uint32_t arity, CallFrequency const& frequency = CallFrequency(),
996      FeedbackSource const& feedback = FeedbackSource(),
997      SpeculationMode speculation_mode = SpeculationMode::kDisallowSpeculation,
998      CallFeedbackRelation feedback_relation = CallFeedbackRelation::kTarget);
999  const Operator* CallRuntime(Runtime::FunctionId id);
1000  const Operator* CallRuntime(Runtime::FunctionId id, size_t arity);
1001  const Operator* CallRuntime(const Runtime::Function* function, size_t arity);
1002
1003#if V8_ENABLE_WEBASSEMBLY
1004  const Operator* CallWasm(const wasm::WasmModule* wasm_module,
1005                           const wasm::FunctionSig* wasm_signature,
1006                           FeedbackSource const& feedback);
1007#endif  // V8_ENABLE_WEBASSEMBLY
1008
1009  const Operator* ConstructForwardVarargs(size_t arity, uint32_t start_index);
1010  const Operator* Construct(uint32_t arity,
1011                            CallFrequency const& frequency = CallFrequency(),
1012                            FeedbackSource const& feedback = FeedbackSource());
1013  const Operator* ConstructWithArrayLike(CallFrequency const& frequency,
1014                                         FeedbackSource const& feedback);
1015  const Operator* ConstructWithSpread(
1016      uint32_t arity, CallFrequency const& frequency = CallFrequency(),
1017      FeedbackSource const& feedback = FeedbackSource());
1018
1019  const Operator* LoadProperty(FeedbackSource const& feedback);
1020  const Operator* LoadNamed(const NameRef& name,
1021                            FeedbackSource const& feedback);
1022  const Operator* LoadNamedFromSuper(const NameRef& name,
1023                                     FeedbackSource const& feedback);
1024
1025  const Operator* SetKeyedProperty(LanguageMode language_mode,
1026                                   FeedbackSource const& feedback);
1027  const Operator* DefineKeyedOwnProperty(LanguageMode language_mode,
1028                                         FeedbackSource const& feedback);
1029  const Operator* SetNamedProperty(LanguageMode language_mode,
1030                                   const NameRef& name,
1031                                   FeedbackSource const& feedback);
1032
1033  const Operator* DefineNamedOwnProperty(const NameRef& name,
1034                                         FeedbackSource const& feedback);
1035  const Operator* DefineKeyedOwnPropertyInLiteral(
1036      const FeedbackSource& feedback);
1037  const Operator* StoreInArrayLiteral(const FeedbackSource& feedback);
1038
1039  const Operator* DeleteProperty();
1040
1041  const Operator* HasProperty(FeedbackSource const& feedback);
1042
1043  const Operator* GetSuperConstructor();
1044
1045  const Operator* CreateGeneratorObject();
1046
1047  const Operator* LoadGlobal(const NameRef& name,
1048                             const FeedbackSource& feedback,
1049                             TypeofMode typeof_mode = TypeofMode::kNotInside);
1050  const Operator* StoreGlobal(LanguageMode language_mode, const NameRef& name,
1051                              const FeedbackSource& feedback);
1052
1053  const Operator* HasContextExtension(size_t depth);
1054  const Operator* LoadContext(size_t depth, size_t index, bool immutable);
1055  const Operator* StoreContext(size_t depth, size_t index);
1056
1057  const Operator* LoadModule(int32_t cell_index);
1058  const Operator* StoreModule(int32_t cell_index);
1059
1060  const Operator* GetImportMeta();
1061
1062  const Operator* HasInPrototypeChain();
1063  const Operator* InstanceOf(const FeedbackSource& feedback);
1064  const Operator* OrdinaryHasInstance();
1065
1066  const Operator* AsyncFunctionEnter();
1067  const Operator* AsyncFunctionReject();
1068  const Operator* AsyncFunctionResolve();
1069
1070  const Operator* ForInEnumerate();
1071  const Operator* ForInNext(ForInMode mode, const FeedbackSource& feedback);
1072  const Operator* ForInPrepare(ForInMode mode, const FeedbackSource& feedback);
1073
1074  const Operator* LoadMessage();
1075  const Operator* StoreMessage();
1076
1077  // Used to implement Ignition's SuspendGenerator bytecode.
1078  const Operator* GeneratorStore(int value_count);
1079
1080  // Used to implement Ignition's SwitchOnGeneratorState bytecode.
1081  const Operator* GeneratorRestoreContinuation();
1082  const Operator* GeneratorRestoreContext();
1083
1084  // Used to implement Ignition's ResumeGenerator bytecode.
1085  const Operator* GeneratorRestoreRegister(int index);
1086  const Operator* GeneratorRestoreInputOrDebugPos();
1087
1088  const Operator* StackCheck(StackCheckKind kind);
1089  const Operator* Debugger();
1090
1091  const Operator* FulfillPromise();
1092  const Operator* PerformPromiseThen();
1093  const Operator* PromiseResolve();
1094  const Operator* RejectPromise();
1095  const Operator* ResolvePromise();
1096
1097  const Operator* CreateFunctionContext(const ScopeInfoRef& scope_info,
1098                                        int slot_count, ScopeType scope_type);
1099  const Operator* CreateCatchContext(const ScopeInfoRef& scope_info);
1100  const Operator* CreateWithContext(const ScopeInfoRef& scope_info);
1101  const Operator* CreateBlockContext(const ScopeInfoRef& scpope_info);
1102
1103  const Operator* ObjectIsArray();
1104  const Operator* ParseInt();
1105  const Operator* RegExpTest();
1106
1107  const Operator* GetIterator(FeedbackSource const& load_feedback,
1108                              FeedbackSource const& call_feedback);
1109
1110 private:
1111  Zone* zone() const { return zone_; }
1112
1113  const JSOperatorGlobalCache& cache_;
1114  Zone* const zone_;
1115};
1116
1117// Node wrappers.
1118
1119class JSNodeWrapperBase : public NodeWrapper {
1120 public:
1121  explicit constexpr JSNodeWrapperBase(Node* node) : NodeWrapper(node) {}
1122
1123  // Valid iff this node has a context input.
1124  TNode<Object> context() const {
1125    // Could be a Context or NoContextConstant.
1126    return TNode<Object>::UncheckedCast(
1127        NodeProperties::GetContextInput(node()));
1128  }
1129
1130  // Valid iff this node has exactly one effect input.
1131  Effect effect() const {
1132    DCHECK_EQ(node()->op()->EffectInputCount(), 1);
1133    return Effect{NodeProperties::GetEffectInput(node())};
1134  }
1135
1136  // Valid iff this node has exactly one control input.
1137  Control control() const {
1138    DCHECK_EQ(node()->op()->ControlInputCount(), 1);
1139    return Control{NodeProperties::GetControlInput(node())};
1140  }
1141
1142  // Valid iff this node has a frame state input.
1143  FrameState frame_state() const {
1144    return FrameState{NodeProperties::GetFrameStateInput(node())};
1145  }
1146};
1147
1148#define DEFINE_INPUT_ACCESSORS(Name, name, TheIndex, Type) \
1149  static constexpr int Name##Index() { return TheIndex; }  \
1150  TNode<Type> name() const {                               \
1151    return TNode<Type>::UncheckedCast(                     \
1152        NodeProperties::GetValueInput(node(), TheIndex));  \
1153  }
1154
1155class JSUnaryOpNode final : public JSNodeWrapperBase {
1156 public:
1157  explicit constexpr JSUnaryOpNode(Node* node) : JSNodeWrapperBase(node) {
1158    DCHECK(JSOperator::IsUnaryWithFeedback(node->opcode()));
1159  }
1160
1161#define INPUTS(V)            \
1162  V(Value, value, 0, Object) \
1163  V(FeedbackVector, feedback_vector, 1, HeapObject)
1164  INPUTS(DEFINE_INPUT_ACCESSORS)
1165#undef INPUTS
1166};
1167
1168#define V(JSName, ...) using JSName##Node = JSUnaryOpNode;
1169JS_UNOP_WITH_FEEDBACK(V)
1170#undef V
1171
1172class JSBinaryOpNode final : public JSNodeWrapperBase {
1173 public:
1174  explicit constexpr JSBinaryOpNode(Node* node) : JSNodeWrapperBase(node) {
1175    DCHECK(JSOperator::IsBinaryWithFeedback(node->opcode()));
1176  }
1177
1178  const FeedbackParameter& Parameters() const {
1179    return FeedbackParameterOf(node()->op());
1180  }
1181
1182#define INPUTS(V)            \
1183  V(Left, left, 0, Object)   \
1184  V(Right, right, 1, Object) \
1185  V(FeedbackVector, feedback_vector, 2, HeapObject)
1186  INPUTS(DEFINE_INPUT_ACCESSORS)
1187#undef INPUTS
1188};
1189
1190#define V(JSName, ...) using JSName##Node = JSBinaryOpNode;
1191JS_BINOP_WITH_FEEDBACK(V)
1192#undef V
1193
1194class JSGetIteratorNode final : public JSNodeWrapperBase {
1195 public:
1196  explicit constexpr JSGetIteratorNode(Node* node) : JSNodeWrapperBase(node) {
1197    DCHECK_EQ(IrOpcode::kJSGetIterator, node->opcode());
1198  }
1199
1200  const GetIteratorParameters& Parameters() const {
1201    return GetIteratorParametersOf(node()->op());
1202  }
1203
1204#define INPUTS(V)                  \
1205  V(Receiver, receiver, 0, Object) \
1206  V(FeedbackVector, feedback_vector, 1, HeapObject)
1207  INPUTS(DEFINE_INPUT_ACCESSORS)
1208#undef INPUTS
1209};
1210
1211class JSCloneObjectNode final : public JSNodeWrapperBase {
1212 public:
1213  explicit constexpr JSCloneObjectNode(Node* node) : JSNodeWrapperBase(node) {
1214    DCHECK_EQ(IrOpcode::kJSCloneObject, node->opcode());
1215  }
1216
1217  const CloneObjectParameters& Parameters() const {
1218    return CloneObjectParametersOf(node()->op());
1219  }
1220
1221#define INPUTS(V)              \
1222  V(Source, source, 0, Object) \
1223  V(FeedbackVector, feedback_vector, 1, HeapObject)
1224  INPUTS(DEFINE_INPUT_ACCESSORS)
1225#undef INPUTS
1226};
1227
1228class JSGetTemplateObjectNode final : public JSNodeWrapperBase {
1229 public:
1230  explicit constexpr JSGetTemplateObjectNode(Node* node)
1231      : JSNodeWrapperBase(node) {
1232    DCHECK_EQ(IrOpcode::kJSGetTemplateObject, node->opcode());
1233  }
1234
1235  const GetTemplateObjectParameters& Parameters() const {
1236    return GetTemplateObjectParametersOf(node()->op());
1237  }
1238
1239#define INPUTS(V) V(FeedbackVector, feedback_vector, 0, HeapObject)
1240  INPUTS(DEFINE_INPUT_ACCESSORS)
1241#undef INPUTS
1242};
1243
1244class JSCreateLiteralOpNode final : public JSNodeWrapperBase {
1245 public:
1246  explicit constexpr JSCreateLiteralOpNode(Node* node)
1247      : JSNodeWrapperBase(node) {
1248    DCHECK(node->opcode() == IrOpcode::kJSCreateLiteralArray ||
1249           node->opcode() == IrOpcode::kJSCreateLiteralObject ||
1250           node->opcode() == IrOpcode::kJSCreateLiteralRegExp);
1251  }
1252
1253  const CreateLiteralParameters& Parameters() const {
1254    return CreateLiteralParametersOf(node()->op());
1255  }
1256
1257#define INPUTS(V) V(FeedbackVector, feedback_vector, 0, HeapObject)
1258  INPUTS(DEFINE_INPUT_ACCESSORS)
1259#undef INPUTS
1260};
1261
1262using JSCreateLiteralArrayNode = JSCreateLiteralOpNode;
1263using JSCreateLiteralObjectNode = JSCreateLiteralOpNode;
1264using JSCreateLiteralRegExpNode = JSCreateLiteralOpNode;
1265
1266class JSHasPropertyNode final : public JSNodeWrapperBase {
1267 public:
1268  explicit constexpr JSHasPropertyNode(Node* node) : JSNodeWrapperBase(node) {
1269    DCHECK_EQ(IrOpcode::kJSHasProperty, node->opcode());
1270  }
1271
1272  const PropertyAccess& Parameters() const {
1273    return PropertyAccessOf(node()->op());
1274  }
1275
1276#define INPUTS(V)              \
1277  V(Object, object, 0, Object) \
1278  V(Key, key, 1, Object)       \
1279  V(FeedbackVector, feedback_vector, 2, HeapObject)
1280  INPUTS(DEFINE_INPUT_ACCESSORS)
1281#undef INPUTS
1282};
1283
1284class JSLoadPropertyNode final : public JSNodeWrapperBase {
1285 public:
1286  explicit constexpr JSLoadPropertyNode(Node* node) : JSNodeWrapperBase(node) {
1287    DCHECK_EQ(IrOpcode::kJSLoadProperty, node->opcode());
1288  }
1289
1290  const PropertyAccess& Parameters() const {
1291    return PropertyAccessOf(node()->op());
1292  }
1293
1294#define INPUTS(V)              \
1295  V(Object, object, 0, Object) \
1296  V(Key, key, 1, Object)       \
1297  V(FeedbackVector, feedback_vector, 2, HeapObject)
1298  INPUTS(DEFINE_INPUT_ACCESSORS)
1299#undef INPUTS
1300};
1301
1302class JSSetKeyedPropertyNode final : public JSNodeWrapperBase {
1303 public:
1304  explicit constexpr JSSetKeyedPropertyNode(Node* node)
1305      : JSNodeWrapperBase(node) {
1306    DCHECK_EQ(IrOpcode::kJSSetKeyedProperty, node->opcode());
1307  }
1308
1309  const PropertyAccess& Parameters() const {
1310    return PropertyAccessOf(node()->op());
1311  }
1312
1313#define INPUTS(V)              \
1314  V(Object, object, 0, Object) \
1315  V(Key, key, 1, Object)       \
1316  V(Value, value, 2, Object)   \
1317  V(FeedbackVector, feedback_vector, 3, HeapObject)
1318  INPUTS(DEFINE_INPUT_ACCESSORS)
1319#undef INPUTS
1320};
1321
1322class JSDefineKeyedOwnPropertyNode final : public JSNodeWrapperBase {
1323 public:
1324  explicit constexpr JSDefineKeyedOwnPropertyNode(Node* node)
1325      : JSNodeWrapperBase(node) {
1326    DCHECK_EQ(IrOpcode::kJSDefineKeyedOwnProperty, node->opcode());
1327  }
1328
1329  const PropertyAccess& Parameters() const {
1330    return PropertyAccessOf(node()->op());
1331  }
1332
1333#define INPUTS(V)              \
1334  V(Object, object, 0, Object) \
1335  V(Key, key, 1, Object)       \
1336  V(Value, value, 2, Object)   \
1337  V(FeedbackVector, feedback_vector, 3, HeapObject)
1338  INPUTS(DEFINE_INPUT_ACCESSORS)
1339#undef INPUTS
1340};
1341
1342namespace js_node_wrapper_utils {
1343// Avoids template definitions in the .cc file.
1344TNode<Oddball> UndefinedConstant(JSGraph* jsgraph);
1345}  // namespace js_node_wrapper_utils
1346
1347class JSCallOrConstructNode : public JSNodeWrapperBase {
1348 public:
1349  explicit constexpr JSCallOrConstructNode(Node* node)
1350      : JSNodeWrapperBase(node) {
1351    DCHECK(IsValidNode(node));
1352  }
1353
1354#define INPUTS(V)              \
1355  V(Target, target, 0, Object) \
1356  V(ReceiverOrNewTarget, receiver_or_new_target, 1, Object)
1357  INPUTS(DEFINE_INPUT_ACCESSORS)
1358#undef INPUTS
1359
1360  // Besides actual arguments, JSCall nodes (and variants) also take the
1361  // following. Note that we rely on the fact that all variants (JSCall,
1362  // JSCallWithArrayLike, JSCallWithSpread, JSConstruct,
1363  // JSConstructWithArrayLike, JSConstructWithSpread, JSWasmCall) have the same
1364  // underlying node layout.
1365  static constexpr int kTargetInputCount = 1;
1366  static constexpr int kReceiverOrNewTargetInputCount = 1;
1367  static constexpr int kFeedbackVectorInputCount = 1;
1368  static constexpr int kExtraInputCount = kTargetInputCount +
1369                                          kReceiverOrNewTargetInputCount +
1370                                          kFeedbackVectorInputCount;
1371  STATIC_ASSERT(kExtraInputCount == CallParameters::kExtraCallInputCount);
1372  STATIC_ASSERT(kExtraInputCount ==
1373                ConstructParameters::kExtraConstructInputCount);
1374
1375  // Just for static asserts for spots that rely on node layout.
1376  static constexpr bool kFeedbackVectorIsLastInput = true;
1377
1378  // Some spots rely on the fact that call and construct variants have the same
1379  // layout.
1380  static constexpr bool kHaveIdenticalLayouts = true;
1381
1382  // This is the arity fed into Call/ConstructArguments.
1383  static constexpr int ArityForArgc(int parameters) {
1384    return parameters + kExtraInputCount;
1385  }
1386
1387  static constexpr int FirstArgumentIndex() {
1388    return ReceiverOrNewTargetIndex() + 1;
1389  }
1390  static constexpr int ArgumentIndex(int i) { return FirstArgumentIndex() + i; }
1391
1392  TNode<Object> Argument(int i) const {
1393    DCHECK_LT(i, ArgumentCount());
1394    return TNode<Object>::UncheckedCast(
1395        NodeProperties::GetValueInput(node(), ArgumentIndex(i)));
1396  }
1397  int LastArgumentIndex() const {
1398    DCHECK_GT(ArgumentCount(), 0);
1399    return ArgumentIndex(ArgumentCount() - 1);
1400  }
1401  TNode<Object> LastArgument() const {
1402    DCHECK_GT(ArgumentCount(), 0);
1403    return Argument(ArgumentCount() - 1);
1404  }
1405  TNode<Object> ArgumentOr(int i, Node* default_value) const {
1406    return i < ArgumentCount() ? Argument(i)
1407                               : TNode<Object>::UncheckedCast(default_value);
1408  }
1409  TNode<Object> ArgumentOrUndefined(int i, JSGraph* jsgraph) const {
1410    return ArgumentOr(i, js_node_wrapper_utils::UndefinedConstant(jsgraph));
1411  }
1412  virtual int ArgumentCount() const = 0;
1413
1414  static constexpr int FeedbackVectorIndexForArgc(int argc) {
1415    STATIC_ASSERT(kFeedbackVectorIsLastInput);
1416    return ArgumentIndex(argc - 1) + 1;
1417  }
1418  int FeedbackVectorIndex() const {
1419    return FeedbackVectorIndexForArgc(ArgumentCount());
1420  }
1421  TNode<HeapObject> feedback_vector() const {
1422    return TNode<HeapObject>::UncheckedCast(
1423        NodeProperties::GetValueInput(node(), FeedbackVectorIndex()));
1424  }
1425
1426 private:
1427  static constexpr bool IsValidNode(Node* node) {
1428    return node->opcode() == IrOpcode::kJSCall ||
1429           node->opcode() == IrOpcode::kJSCallWithArrayLike ||
1430           node->opcode() == IrOpcode::kJSCallWithSpread ||
1431           node->opcode() == IrOpcode::kJSConstruct ||
1432           node->opcode() == IrOpcode::kJSConstructWithArrayLike ||
1433           node->opcode() == IrOpcode::kJSConstructWithSpread
1434#if V8_ENABLE_WEBASSEMBLY
1435           || node->opcode() == IrOpcode::kJSWasmCall
1436#endif     // V8_ENABLE_WEBASSEMBLY
1437        ;  // NOLINT(whitespace/semicolon)
1438  }
1439};
1440
1441template <int kOpcode>
1442bool IsExpectedOpcode(int opcode) {
1443  return opcode == kOpcode;
1444}
1445
1446template <int kOpcode1, int kOpcode2, int... kOpcodes>
1447bool IsExpectedOpcode(int opcode) {
1448  return opcode == kOpcode1 || IsExpectedOpcode<kOpcode2, kOpcodes...>(opcode);
1449}
1450
1451template <int... kOpcodes>
1452class JSCallNodeBase final : public JSCallOrConstructNode {
1453 public:
1454  explicit constexpr JSCallNodeBase(Node* node) : JSCallOrConstructNode(node) {
1455    DCHECK(IsExpectedOpcode<kOpcodes...>(node->opcode()));
1456  }
1457
1458  const CallParameters& Parameters() const {
1459    return CallParametersOf(node()->op());
1460  }
1461
1462#define INPUTS(V)              \
1463  V(Target, target, 0, Object) \
1464  V(Receiver, receiver, 1, Object)
1465  INPUTS(DEFINE_INPUT_ACCESSORS)
1466#undef INPUTS
1467
1468  static constexpr int kReceiverInputCount = 1;
1469  STATIC_ASSERT(kReceiverInputCount ==
1470                JSCallOrConstructNode::kReceiverOrNewTargetInputCount);
1471
1472  int ArgumentCount() const override {
1473    // Note: The count reported by this function depends only on the parameter,
1474    // thus adding/removing inputs will not affect it.
1475    return Parameters().arity_without_implicit_args();
1476  }
1477};
1478
1479using JSCallNode = JSCallNodeBase<IrOpcode::kJSCall>;
1480using JSCallWithSpreadNode = JSCallNodeBase<IrOpcode::kJSCallWithSpread>;
1481using JSCallWithArrayLikeNode = JSCallNodeBase<IrOpcode::kJSCallWithArrayLike>;
1482using JSCallWithArrayLikeOrSpreadNode =
1483    JSCallNodeBase<IrOpcode::kJSCallWithArrayLike, IrOpcode::kJSCallWithSpread>;
1484
1485#if V8_ENABLE_WEBASSEMBLY
1486class JSWasmCallNode final : public JSCallOrConstructNode {
1487 public:
1488  explicit constexpr JSWasmCallNode(Node* node) : JSCallOrConstructNode(node) {
1489    DCHECK_EQ(IrOpcode::kJSWasmCall, node->opcode());
1490  }
1491
1492  const JSWasmCallParameters& Parameters() const {
1493    return OpParameter<JSWasmCallParameters>(node()->op());
1494  }
1495
1496#define INPUTS(V)              \
1497  V(Target, target, 0, Object) \
1498  V(Receiver, receiver, 1, Object)
1499  INPUTS(DEFINE_INPUT_ACCESSORS)
1500#undef INPUTS
1501
1502  static constexpr int kReceiverInputCount = 1;
1503  STATIC_ASSERT(kReceiverInputCount ==
1504                JSCallOrConstructNode::kReceiverOrNewTargetInputCount);
1505
1506  int ArgumentCount() const override {
1507    // Note: The count reported by this function depends only on the parameter
1508    // count, thus adding/removing inputs will not affect it.
1509    return Parameters().arity_without_implicit_args();
1510  }
1511
1512  static Type TypeForWasmReturnType(const wasm::ValueType& type);
1513};
1514#endif  // V8_ENABLE_WEBASSEMBLY
1515
1516template <int kOpcode>
1517class JSConstructNodeBase final : public JSCallOrConstructNode {
1518 public:
1519  explicit constexpr JSConstructNodeBase(Node* node)
1520      : JSCallOrConstructNode(node) {
1521    DCHECK_EQ(kOpcode, node->opcode());
1522  }
1523
1524  const ConstructParameters& Parameters() const {
1525    return ConstructParametersOf(node()->op());
1526  }
1527
1528#define INPUTS(V)              \
1529  V(Target, target, 0, Object) \
1530  V(NewTarget, new_target, 1, Object)
1531  INPUTS(DEFINE_INPUT_ACCESSORS)
1532#undef INPUTS
1533
1534  static constexpr int kNewTargetInputCount = 1;
1535  STATIC_ASSERT(kNewTargetInputCount ==
1536                JSCallOrConstructNode::kReceiverOrNewTargetInputCount);
1537
1538  int ArgumentCount() const {
1539    // Note: The count reported by this function depends only on the parameter,
1540    // thus adding/removing inputs will not affect it.
1541    return Parameters().arity_without_implicit_args();
1542  }
1543};
1544
1545using JSConstructNode = JSConstructNodeBase<IrOpcode::kJSConstruct>;
1546using JSConstructWithSpreadNode =
1547    JSConstructNodeBase<IrOpcode::kJSConstructWithSpread>;
1548using JSConstructWithArrayLikeNode =
1549    JSConstructNodeBase<IrOpcode::kJSConstructWithArrayLike>;
1550
1551class JSLoadNamedNode final : public JSNodeWrapperBase {
1552 public:
1553  explicit constexpr JSLoadNamedNode(Node* node) : JSNodeWrapperBase(node) {
1554    DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode());
1555  }
1556
1557  const NamedAccess& Parameters() const { return NamedAccessOf(node()->op()); }
1558
1559#define INPUTS(V)              \
1560  V(Object, object, 0, Object) \
1561  V(FeedbackVector, feedback_vector, 1, HeapObject)
1562  INPUTS(DEFINE_INPUT_ACCESSORS)
1563#undef INPUTS
1564};
1565
1566class JSLoadNamedFromSuperNode final : public JSNodeWrapperBase {
1567 public:
1568  explicit constexpr JSLoadNamedFromSuperNode(Node* node)
1569      : JSNodeWrapperBase(node) {
1570    DCHECK_EQ(IrOpcode::kJSLoadNamedFromSuper, node->opcode());
1571  }
1572
1573  const NamedAccess& Parameters() const { return NamedAccessOf(node()->op()); }
1574
1575#define INPUTS(V)                       \
1576  V(Receiver, receiver, 0, Object)      \
1577  V(HomeObject, home_object, 1, Object) \
1578  V(FeedbackVector, feedback_vector, 2, HeapObject)
1579  INPUTS(DEFINE_INPUT_ACCESSORS)
1580#undef INPUTS
1581};
1582
1583class JSSetNamedPropertyNode final : public JSNodeWrapperBase {
1584 public:
1585  explicit constexpr JSSetNamedPropertyNode(Node* node)
1586      : JSNodeWrapperBase(node) {
1587    DCHECK_EQ(IrOpcode::kJSSetNamedProperty, node->opcode());
1588  }
1589
1590  const NamedAccess& Parameters() const { return NamedAccessOf(node()->op()); }
1591
1592#define INPUTS(V)              \
1593  V(Object, object, 0, Object) \
1594  V(Value, value, 1, Object)   \
1595  V(FeedbackVector, feedback_vector, 2, HeapObject)
1596  INPUTS(DEFINE_INPUT_ACCESSORS)
1597#undef INPUTS
1598};
1599
1600class JSDefineNamedOwnPropertyNode final : public JSNodeWrapperBase {
1601 public:
1602  explicit constexpr JSDefineNamedOwnPropertyNode(Node* node)
1603      : JSNodeWrapperBase(node) {
1604    DCHECK_EQ(IrOpcode::kJSDefineNamedOwnProperty, node->opcode());
1605  }
1606
1607  const DefineNamedOwnPropertyParameters& Parameters() const {
1608    return DefineNamedOwnPropertyParametersOf(node()->op());
1609  }
1610
1611#define INPUTS(V)              \
1612  V(Object, object, 0, Object) \
1613  V(Value, value, 1, Object)   \
1614  V(FeedbackVector, feedback_vector, 2, HeapObject)
1615  INPUTS(DEFINE_INPUT_ACCESSORS)
1616#undef INPUTS
1617};
1618
1619class JSStoreGlobalNode final : public JSNodeWrapperBase {
1620 public:
1621  explicit constexpr JSStoreGlobalNode(Node* node) : JSNodeWrapperBase(node) {
1622    DCHECK_EQ(IrOpcode::kJSStoreGlobal, node->opcode());
1623  }
1624
1625  const StoreGlobalParameters& Parameters() const {
1626    return StoreGlobalParametersOf(node()->op());
1627  }
1628
1629#define INPUTS(V)            \
1630  V(Value, value, 0, Object) \
1631  V(FeedbackVector, feedback_vector, 1, HeapObject)
1632  INPUTS(DEFINE_INPUT_ACCESSORS)
1633#undef INPUTS
1634};
1635
1636class JSLoadGlobalNode final : public JSNodeWrapperBase {
1637 public:
1638  explicit constexpr JSLoadGlobalNode(Node* node) : JSNodeWrapperBase(node) {
1639    DCHECK_EQ(IrOpcode::kJSLoadGlobal, node->opcode());
1640  }
1641
1642  const LoadGlobalParameters& Parameters() const {
1643    return LoadGlobalParametersOf(node()->op());
1644  }
1645
1646#define INPUTS(V) V(FeedbackVector, feedback_vector, 0, HeapObject)
1647  INPUTS(DEFINE_INPUT_ACCESSORS)
1648#undef INPUTS
1649};
1650
1651class JSCreateEmptyLiteralArrayNode final : public JSNodeWrapperBase {
1652 public:
1653  explicit constexpr JSCreateEmptyLiteralArrayNode(Node* node)
1654      : JSNodeWrapperBase(node) {
1655    DCHECK_EQ(IrOpcode::kJSCreateEmptyLiteralArray, node->opcode());
1656  }
1657
1658  const FeedbackParameter& Parameters() const {
1659    return FeedbackParameterOf(node()->op());
1660  }
1661
1662#define INPUTS(V) V(FeedbackVector, feedback_vector, 0, HeapObject)
1663  INPUTS(DEFINE_INPUT_ACCESSORS)
1664#undef INPUTS
1665};
1666
1667class JSDefineKeyedOwnPropertyInLiteralNode final : public JSNodeWrapperBase {
1668 public:
1669  explicit constexpr JSDefineKeyedOwnPropertyInLiteralNode(Node* node)
1670      : JSNodeWrapperBase(node) {
1671    DCHECK_EQ(IrOpcode::kJSDefineKeyedOwnPropertyInLiteral, node->opcode());
1672  }
1673
1674  const FeedbackParameter& Parameters() const {
1675    return FeedbackParameterOf(node()->op());
1676  }
1677
1678#define INPUTS(V)              \
1679  V(Object, object, 0, Object) \
1680  V(Name, name, 1, Object)     \
1681  V(Value, value, 2, Object)   \
1682  V(Flags, flags, 3, Object)   \
1683  V(FeedbackVector, feedback_vector, 4, HeapObject)
1684  INPUTS(DEFINE_INPUT_ACCESSORS)
1685#undef INPUTS
1686};
1687
1688class JSStoreInArrayLiteralNode final : public JSNodeWrapperBase {
1689 public:
1690  explicit constexpr JSStoreInArrayLiteralNode(Node* node)
1691      : JSNodeWrapperBase(node) {
1692    DCHECK_EQ(IrOpcode::kJSStoreInArrayLiteral, node->opcode());
1693  }
1694
1695  const FeedbackParameter& Parameters() const {
1696    return FeedbackParameterOf(node()->op());
1697  }
1698
1699#define INPUTS(V)            \
1700  V(Array, array, 0, Object) \
1701  V(Index, index, 1, Object) \
1702  V(Value, value, 2, Object) \
1703  V(FeedbackVector, feedback_vector, 3, HeapObject)
1704  INPUTS(DEFINE_INPUT_ACCESSORS)
1705#undef INPUTS
1706};
1707
1708class JSCreateClosureNode final : public JSNodeWrapperBase {
1709 public:
1710  explicit constexpr JSCreateClosureNode(Node* node) : JSNodeWrapperBase(node) {
1711    DCHECK_EQ(IrOpcode::kJSCreateClosure, node->opcode());
1712  }
1713
1714  const CreateClosureParameters& Parameters() const {
1715    return CreateClosureParametersOf(node()->op());
1716  }
1717
1718#define INPUTS(V) V(FeedbackCell, feedback_cell, 0, FeedbackCell)
1719  INPUTS(DEFINE_INPUT_ACCESSORS)
1720#undef INPUTS
1721
1722  FeedbackCellRef GetFeedbackCellRefChecked(JSHeapBroker* broker) const;
1723};
1724
1725class JSForInPrepareNode final : public JSNodeWrapperBase {
1726 public:
1727  explicit constexpr JSForInPrepareNode(Node* node) : JSNodeWrapperBase(node) {
1728    DCHECK_EQ(IrOpcode::kJSForInPrepare, node->opcode());
1729  }
1730
1731  const ForInParameters& Parameters() const {
1732    return ForInParametersOf(node()->op());
1733  }
1734
1735#define INPUTS(V)                      \
1736  V(Enumerator, enumerator, 0, Object) \
1737  V(FeedbackVector, feedback_vector, 1, HeapObject)
1738  INPUTS(DEFINE_INPUT_ACCESSORS)
1739#undef INPUTS
1740};
1741
1742class JSForInNextNode final : public JSNodeWrapperBase {
1743 public:
1744  explicit constexpr JSForInNextNode(Node* node) : JSNodeWrapperBase(node) {
1745    DCHECK_EQ(IrOpcode::kJSForInNext, node->opcode());
1746  }
1747
1748  const ForInParameters& Parameters() const {
1749    return ForInParametersOf(node()->op());
1750  }
1751
1752#define INPUTS(V)                       \
1753  V(Receiver, receiver, 0, Object)      \
1754  V(CacheArray, cache_array, 1, Object) \
1755  V(CacheType, cache_type, 2, Object)   \
1756  V(Index, index, 3, Smi)               \
1757  V(FeedbackVector, feedback_vector, 4, HeapObject)
1758  INPUTS(DEFINE_INPUT_ACCESSORS)
1759#undef INPUTS
1760};
1761
1762#undef DEFINE_INPUT_ACCESSORS
1763
1764}  // namespace compiler
1765}  // namespace internal
1766}  // namespace v8
1767
1768#endif  // V8_COMPILER_JS_OPERATOR_H_
1769