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