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