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