1// Copyright 2014 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/compiler/common-operator.h" 6 7#include "src/base/lazy-instance.h" 8#include "src/compiler/linkage.h" 9#include "src/compiler/node.h" 10#include "src/compiler/opcodes.h" 11#include "src/compiler/operator.h" 12#include "src/handles/handles-inl.h" 13#include "src/zone/zone.h" 14 15namespace v8 { 16namespace internal { 17namespace compiler { 18 19std::ostream& operator<<(std::ostream& os, BranchHint hint) { 20 switch (hint) { 21 case BranchHint::kNone: 22 return os << "None"; 23 case BranchHint::kTrue: 24 return os << "True"; 25 case BranchHint::kFalse: 26 return os << "False"; 27 } 28 UNREACHABLE(); 29} 30 31std::ostream& operator<<(std::ostream& os, TrapId trap_id) { 32 switch (trap_id) { 33#define TRAP_CASE(Name) \ 34 case TrapId::k##Name: \ 35 return os << #Name; 36 FOREACH_WASM_TRAPREASON(TRAP_CASE) 37#undef TRAP_CASE 38 case TrapId::kInvalid: 39 return os << "Invalid"; 40 } 41 UNREACHABLE(); 42} 43 44TrapId TrapIdOf(const Operator* const op) { 45 DCHECK(op->opcode() == IrOpcode::kTrapIf || 46 op->opcode() == IrOpcode::kTrapUnless); 47 return OpParameter<TrapId>(op); 48} 49 50BranchHint BranchHintOf(const Operator* const op) { 51 switch (op->opcode()) { 52 case IrOpcode::kIfValue: 53 return IfValueParametersOf(op).hint(); 54 case IrOpcode::kIfDefault: 55 case IrOpcode::kBranch: 56 return OpParameter<BranchHint>(op); 57 default: 58 UNREACHABLE(); 59 } 60} 61 62int ValueInputCountOfReturn(Operator const* const op) { 63 DCHECK_EQ(IrOpcode::kReturn, op->opcode()); 64 // Return nodes have a hidden input at index 0 which we ignore in the value 65 // input count. 66 return op->ValueInputCount() - 1; 67} 68 69bool operator==(DeoptimizeParameters lhs, DeoptimizeParameters rhs) { 70 return lhs.reason() == rhs.reason() && lhs.feedback() == rhs.feedback(); 71} 72 73bool operator!=(DeoptimizeParameters lhs, DeoptimizeParameters rhs) { 74 return !(lhs == rhs); 75} 76 77size_t hash_value(DeoptimizeParameters p) { 78 FeedbackSource::Hash feebdack_hash; 79 return base::hash_combine(p.reason(), feebdack_hash(p.feedback())); 80} 81 82std::ostream& operator<<(std::ostream& os, DeoptimizeParameters p) { 83 return os << p.reason() << ", " << p.feedback(); 84} 85 86DeoptimizeParameters const& DeoptimizeParametersOf(Operator const* const op) { 87 DCHECK(op->opcode() == IrOpcode::kDeoptimize || 88 op->opcode() == IrOpcode::kDeoptimizeIf || 89 op->opcode() == IrOpcode::kDeoptimizeUnless); 90 return OpParameter<DeoptimizeParameters>(op); 91} 92 93const Operator* CommonOperatorBuilder::DelayedStringConstant( 94 const StringConstantBase* str) { 95 return zone()->New<Operator1<const StringConstantBase*>>( 96 IrOpcode::kDelayedStringConstant, Operator::kPure, 97 "DelayedStringConstant", 0, 0, 0, 1, 0, 0, str); 98} 99 100bool operator==(SelectParameters const& lhs, SelectParameters const& rhs) { 101 return lhs.representation() == rhs.representation() && 102 lhs.hint() == rhs.hint(); 103} 104 105 106bool operator!=(SelectParameters const& lhs, SelectParameters const& rhs) { 107 return !(lhs == rhs); 108} 109 110 111size_t hash_value(SelectParameters const& p) { 112 return base::hash_combine(p.representation(), p.hint()); 113} 114 115 116std::ostream& operator<<(std::ostream& os, SelectParameters const& p) { 117 return os << p.representation() << ", " << p.hint(); 118} 119 120 121SelectParameters const& SelectParametersOf(const Operator* const op) { 122 DCHECK_EQ(IrOpcode::kSelect, op->opcode()); 123 return OpParameter<SelectParameters>(op); 124} 125 126CallDescriptor const* CallDescriptorOf(const Operator* const op) { 127 DCHECK(op->opcode() == IrOpcode::kCall || 128 op->opcode() == IrOpcode::kTailCall); 129 return OpParameter<CallDescriptor const*>(op); 130} 131 132size_t ProjectionIndexOf(const Operator* const op) { 133 DCHECK_EQ(IrOpcode::kProjection, op->opcode()); 134 return OpParameter<size_t>(op); 135} 136 137 138MachineRepresentation PhiRepresentationOf(const Operator* const op) { 139 DCHECK_EQ(IrOpcode::kPhi, op->opcode()); 140 return OpParameter<MachineRepresentation>(op); 141} 142 143MachineRepresentation LoopExitValueRepresentationOf(const Operator* const op) { 144 DCHECK_EQ(IrOpcode::kLoopExitValue, op->opcode()); 145 return OpParameter<MachineRepresentation>(op); 146} 147 148int ParameterIndexOf(const Operator* const op) { 149 DCHECK_EQ(IrOpcode::kParameter, op->opcode()); 150 return OpParameter<ParameterInfo>(op).index(); 151} 152 153 154const ParameterInfo& ParameterInfoOf(const Operator* const op) { 155 DCHECK_EQ(IrOpcode::kParameter, op->opcode()); 156 return OpParameter<ParameterInfo>(op); 157} 158 159 160bool operator==(ParameterInfo const& lhs, ParameterInfo const& rhs) { 161 return lhs.index() == rhs.index(); 162} 163 164 165bool operator!=(ParameterInfo const& lhs, ParameterInfo const& rhs) { 166 return !(lhs == rhs); 167} 168 169 170size_t hash_value(ParameterInfo const& p) { return p.index(); } 171 172 173std::ostream& operator<<(std::ostream& os, ParameterInfo const& i) { 174 os << i.index(); 175 if (i.debug_name()) os << ", debug name: " << i.debug_name(); 176 return os; 177} 178 179std::ostream& operator<<(std::ostream& os, ObjectStateInfo const& i) { 180 return os << "id:" << i.object_id() << ", size:" << i.size(); 181} 182 183size_t hash_value(ObjectStateInfo const& p) { 184 return base::hash_combine(p.object_id(), p.size()); 185} 186 187std::ostream& operator<<(std::ostream& os, TypedObjectStateInfo const& i) { 188 return os << "id:" << i.object_id() << ", " << i.machine_types(); 189} 190 191size_t hash_value(TypedObjectStateInfo const& p) { 192 return base::hash_combine(p.object_id(), p.machine_types()); 193} 194 195bool operator==(RelocatablePtrConstantInfo const& lhs, 196 RelocatablePtrConstantInfo const& rhs) { 197 return lhs.rmode() == rhs.rmode() && lhs.value() == rhs.value() && 198 lhs.type() == rhs.type(); 199} 200 201bool operator!=(RelocatablePtrConstantInfo const& lhs, 202 RelocatablePtrConstantInfo const& rhs) { 203 return !(lhs == rhs); 204} 205 206size_t hash_value(RelocatablePtrConstantInfo const& p) { 207 return base::hash_combine(p.value(), int8_t{p.rmode()}, p.type()); 208} 209 210std::ostream& operator<<(std::ostream& os, 211 RelocatablePtrConstantInfo const& p) { 212 return os << p.value() << ", " << static_cast<int>(p.rmode()) << ", " 213 << p.type(); 214} 215 216SparseInputMask::InputIterator::InputIterator( 217 SparseInputMask::BitMaskType bit_mask, Node* parent) 218 : bit_mask_(bit_mask), parent_(parent), real_index_(0) { 219#if DEBUG 220 if (bit_mask_ != SparseInputMask::kDenseBitMask) { 221 DCHECK_EQ(base::bits::CountPopulation(bit_mask_) - 222 base::bits::CountPopulation(kEndMarker), 223 parent->InputCount()); 224 } 225#endif 226} 227 228void SparseInputMask::InputIterator::Advance() { 229 DCHECK(!IsEnd()); 230 231 if (IsReal()) { 232 ++real_index_; 233 } 234 bit_mask_ >>= 1; 235} 236 237size_t SparseInputMask::InputIterator::AdvanceToNextRealOrEnd() { 238 DCHECK_NE(bit_mask_, SparseInputMask::kDenseBitMask); 239 240 size_t count = base::bits::CountTrailingZeros(bit_mask_); 241 bit_mask_ >>= count; 242 DCHECK(IsReal() || IsEnd()); 243 return count; 244} 245 246Node* SparseInputMask::InputIterator::GetReal() const { 247 DCHECK(IsReal()); 248 return parent_->InputAt(real_index_); 249} 250 251bool SparseInputMask::InputIterator::IsReal() const { 252 return bit_mask_ == SparseInputMask::kDenseBitMask || 253 (bit_mask_ & kEntryMask); 254} 255 256bool SparseInputMask::InputIterator::IsEnd() const { 257 return (bit_mask_ == kEndMarker) || 258 (bit_mask_ == SparseInputMask::kDenseBitMask && 259 real_index_ >= parent_->InputCount()); 260} 261 262int SparseInputMask::CountReal() const { 263 DCHECK(!IsDense()); 264 return base::bits::CountPopulation(bit_mask_) - 265 base::bits::CountPopulation(kEndMarker); 266} 267 268SparseInputMask::InputIterator SparseInputMask::IterateOverInputs(Node* node) { 269 DCHECK(IsDense() || CountReal() == node->InputCount()); 270 return InputIterator(bit_mask_, node); 271} 272 273bool operator==(SparseInputMask const& lhs, SparseInputMask const& rhs) { 274 return lhs.mask() == rhs.mask(); 275} 276 277bool operator!=(SparseInputMask const& lhs, SparseInputMask const& rhs) { 278 return !(lhs == rhs); 279} 280 281size_t hash_value(SparseInputMask const& p) { 282 return base::hash_value(p.mask()); 283} 284 285std::ostream& operator<<(std::ostream& os, SparseInputMask const& p) { 286 if (p.IsDense()) { 287 return os << "dense"; 288 } else { 289 SparseInputMask::BitMaskType mask = p.mask(); 290 DCHECK_NE(mask, SparseInputMask::kDenseBitMask); 291 292 os << "sparse:"; 293 294 while (mask != SparseInputMask::kEndMarker) { 295 if (mask & SparseInputMask::kEntryMask) { 296 os << "^"; 297 } else { 298 os << "."; 299 } 300 mask >>= 1; 301 } 302 return os; 303 } 304} 305 306bool operator==(TypedStateValueInfo const& lhs, 307 TypedStateValueInfo const& rhs) { 308 return lhs.machine_types() == rhs.machine_types() && 309 lhs.sparse_input_mask() == rhs.sparse_input_mask(); 310} 311 312bool operator!=(TypedStateValueInfo const& lhs, 313 TypedStateValueInfo const& rhs) { 314 return !(lhs == rhs); 315} 316 317size_t hash_value(TypedStateValueInfo const& p) { 318 return base::hash_combine(p.machine_types(), p.sparse_input_mask()); 319} 320 321std::ostream& operator<<(std::ostream& os, TypedStateValueInfo const& p) { 322 return os << p.machine_types() << ", " << p.sparse_input_mask(); 323} 324 325size_t hash_value(RegionObservability observability) { 326 return static_cast<size_t>(observability); 327} 328 329std::ostream& operator<<(std::ostream& os, RegionObservability observability) { 330 switch (observability) { 331 case RegionObservability::kObservable: 332 return os << "observable"; 333 case RegionObservability::kNotObservable: 334 return os << "not-observable"; 335 } 336 UNREACHABLE(); 337} 338 339RegionObservability RegionObservabilityOf(Operator const* op) { 340 DCHECK_EQ(IrOpcode::kBeginRegion, op->opcode()); 341 return OpParameter<RegionObservability>(op); 342} 343 344Type TypeGuardTypeOf(Operator const* op) { 345 DCHECK_EQ(IrOpcode::kTypeGuard, op->opcode()); 346 return OpParameter<Type>(op); 347} 348 349std::ostream& operator<<(std::ostream& os, 350 const ZoneVector<MachineType>* types) { 351 // Print all the MachineTypes, separated by commas. 352 bool first = true; 353 for (MachineType elem : *types) { 354 if (!first) { 355 os << ", "; 356 } 357 first = false; 358 os << elem; 359 } 360 return os; 361} 362 363int OsrValueIndexOf(Operator const* op) { 364 DCHECK_EQ(IrOpcode::kOsrValue, op->opcode()); 365 return OpParameter<int>(op); 366} 367 368SparseInputMask SparseInputMaskOf(Operator const* op) { 369 DCHECK(op->opcode() == IrOpcode::kStateValues || 370 op->opcode() == IrOpcode::kTypedStateValues); 371 372 if (op->opcode() == IrOpcode::kTypedStateValues) { 373 return OpParameter<TypedStateValueInfo>(op).sparse_input_mask(); 374 } 375 return OpParameter<SparseInputMask>(op); 376} 377 378ZoneVector<MachineType> const* MachineTypesOf(Operator const* op) { 379 DCHECK(op->opcode() == IrOpcode::kTypedObjectState || 380 op->opcode() == IrOpcode::kTypedStateValues); 381 382 if (op->opcode() == IrOpcode::kTypedStateValues) { 383 return OpParameter<TypedStateValueInfo>(op).machine_types(); 384 } 385 return OpParameter<TypedObjectStateInfo>(op).machine_types(); 386} 387 388V8_EXPORT_PRIVATE bool operator==(IfValueParameters const& l, 389 IfValueParameters const& r) { 390 return l.value() == r.value() && 391 l.comparison_order() == r.comparison_order() && l.hint() == r.hint(); 392} 393 394size_t hash_value(IfValueParameters const& p) { 395 return base::hash_combine(p.value(), p.comparison_order(), p.hint()); 396} 397 398V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, 399 IfValueParameters const& p) { 400 out << p.value() << " (order " << p.comparison_order() << ", hint " 401 << p.hint() << ")"; 402 return out; 403} 404 405IfValueParameters const& IfValueParametersOf(const Operator* op) { 406 DCHECK(op->opcode() == IrOpcode::kIfValue); 407 return OpParameter<IfValueParameters>(op); 408} 409 410V8_EXPORT_PRIVATE bool operator==(const SLVerifierHintParameters& p1, 411 const SLVerifierHintParameters& p2) { 412 return p1.semantics() == p2.semantics() && 413 p1.override_output_type() == p2.override_output_type(); 414} 415 416size_t hash_value(const SLVerifierHintParameters& p) { 417 return base::hash_combine( 418 p.semantics(), 419 p.override_output_type() ? hash_value(*p.override_output_type()) : 0); 420} 421 422V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, 423 const SLVerifierHintParameters& p) { 424 if (p.semantics()) { 425 p.semantics()->PrintTo(out); 426 } else { 427 out << "nullptr"; 428 } 429 out << ", "; 430 if (const auto& t = p.override_output_type()) { 431 t->PrintTo(out); 432 } else { 433 out << ", nullopt"; 434 } 435 return out; 436} 437 438const SLVerifierHintParameters& SLVerifierHintParametersOf(const Operator* op) { 439 DCHECK_EQ(op->opcode(), IrOpcode::kSLVerifierHint); 440 return OpParameter<SLVerifierHintParameters>(op); 441} 442 443#define COMMON_CACHED_OP_LIST(V) \ 444 V(Plug, Operator::kNoProperties, 0, 0, 0, 1, 0, 0) \ 445 V(Dead, Operator::kFoldable, 0, 0, 0, 1, 1, 1) \ 446 V(Unreachable, Operator::kFoldable, 0, 1, 1, 1, 1, 0) \ 447 V(IfTrue, Operator::kKontrol, 0, 0, 1, 0, 0, 1) \ 448 V(IfFalse, Operator::kKontrol, 0, 0, 1, 0, 0, 1) \ 449 V(IfSuccess, Operator::kKontrol, 0, 0, 1, 0, 0, 1) \ 450 V(IfException, Operator::kKontrol, 0, 1, 1, 1, 1, 1) \ 451 V(Throw, Operator::kKontrol, 0, 1, 1, 0, 0, 1) \ 452 V(Terminate, Operator::kKontrol, 0, 1, 1, 0, 0, 1) \ 453 V(LoopExit, Operator::kKontrol, 0, 0, 2, 0, 0, 1) \ 454 V(LoopExitEffect, Operator::kNoThrow, 0, 1, 1, 0, 1, 0) \ 455 V(Checkpoint, Operator::kKontrol, 0, 1, 1, 0, 1, 0) \ 456 V(FinishRegion, Operator::kKontrol, 1, 1, 0, 1, 1, 0) \ 457 V(Retain, Operator::kKontrol, 1, 1, 0, 0, 1, 0) 458 459#define CACHED_LOOP_EXIT_VALUE_LIST(V) V(kTagged) 460 461#define CACHED_BRANCH_LIST(V) \ 462 V(None) \ 463 V(True) \ 464 V(False) 465 466#define CACHED_RETURN_LIST(V) \ 467 V(1) \ 468 V(2) \ 469 V(3) \ 470 V(4) 471 472#define CACHED_END_LIST(V) \ 473 V(1) \ 474 V(2) \ 475 V(3) \ 476 V(4) \ 477 V(5) \ 478 V(6) \ 479 V(7) \ 480 V(8) 481 482 483#define CACHED_EFFECT_PHI_LIST(V) \ 484 V(1) \ 485 V(2) \ 486 V(3) \ 487 V(4) \ 488 V(5) \ 489 V(6) 490 491#define CACHED_INDUCTION_VARIABLE_PHI_LIST(V) \ 492 V(4) \ 493 V(5) \ 494 V(6) \ 495 V(7) 496 497#define CACHED_LOOP_LIST(V) \ 498 V(1) \ 499 V(2) 500 501 502#define CACHED_MERGE_LIST(V) \ 503 V(1) \ 504 V(2) \ 505 V(3) \ 506 V(4) \ 507 V(5) \ 508 V(6) \ 509 V(7) \ 510 V(8) 511 512#define CACHED_DEOPTIMIZE_LIST(V) \ 513 V(MinusZero) \ 514 V(WrongMap) \ 515 V(InsufficientTypeFeedbackForGenericKeyedAccess) \ 516 V(InsufficientTypeFeedbackForGenericNamedAccess) 517 518#define CACHED_DEOPTIMIZE_IF_LIST(V) \ 519 V(DivisionByZero) \ 520 V(Hole) \ 521 V(MinusZero) \ 522 V(Overflow) \ 523 V(Smi) 524 525#define CACHED_DEOPTIMIZE_UNLESS_LIST(V) \ 526 V(LostPrecision) \ 527 V(LostPrecisionOrNaN) \ 528 V(NotAHeapNumber) \ 529 V(NotANumberOrOddball) \ 530 V(NotASmi) \ 531 V(OutOfBounds) \ 532 V(WrongInstanceType) \ 533 V(WrongMap) 534 535#define CACHED_TRAP_IF_LIST(V) \ 536 V(TrapDivUnrepresentable) \ 537 V(TrapFloatUnrepresentable) 538 539// The reason for a trap. 540#define CACHED_TRAP_UNLESS_LIST(V) \ 541 V(TrapUnreachable) \ 542 V(TrapMemOutOfBounds) \ 543 V(TrapDivByZero) \ 544 V(TrapDivUnrepresentable) \ 545 V(TrapRemByZero) \ 546 V(TrapFloatUnrepresentable) \ 547 V(TrapTableOutOfBounds) \ 548 V(TrapFuncSigMismatch) 549 550#define CACHED_PARAMETER_LIST(V) \ 551 V(0) \ 552 V(1) \ 553 V(2) \ 554 V(3) \ 555 V(4) \ 556 V(5) \ 557 V(6) 558 559 560#define CACHED_PHI_LIST(V) \ 561 V(kTagged, 1) \ 562 V(kTagged, 2) \ 563 V(kTagged, 3) \ 564 V(kTagged, 4) \ 565 V(kTagged, 5) \ 566 V(kTagged, 6) \ 567 V(kBit, 2) \ 568 V(kFloat64, 2) \ 569 V(kWord32, 2) 570 571 572#define CACHED_PROJECTION_LIST(V) \ 573 V(0) \ 574 V(1) 575 576 577#define CACHED_STATE_VALUES_LIST(V) \ 578 V(0) \ 579 V(1) \ 580 V(2) \ 581 V(3) \ 582 V(4) \ 583 V(5) \ 584 V(6) \ 585 V(7) \ 586 V(8) \ 587 V(10) \ 588 V(11) \ 589 V(12) \ 590 V(13) \ 591 V(14) 592 593 594struct CommonOperatorGlobalCache final { 595#define CACHED(Name, properties, value_input_count, effect_input_count, \ 596 control_input_count, value_output_count, effect_output_count, \ 597 control_output_count) \ 598 struct Name##Operator final : public Operator { \ 599 Name##Operator() \ 600 : Operator(IrOpcode::k##Name, properties, #Name, value_input_count, \ 601 effect_input_count, control_input_count, \ 602 value_output_count, effect_output_count, \ 603 control_output_count) {} \ 604 }; \ 605 Name##Operator k##Name##Operator; 606 COMMON_CACHED_OP_LIST(CACHED) 607#undef CACHED 608 609 template <size_t kInputCount> 610 struct EndOperator final : public Operator { 611 EndOperator() 612 : Operator( // -- 613 IrOpcode::kEnd, Operator::kKontrol, // opcode 614 "End", // name 615 0, 0, kInputCount, 0, 0, 0) {} // counts 616 }; 617#define CACHED_END(input_count) \ 618 EndOperator<input_count> kEnd##input_count##Operator; 619 CACHED_END_LIST(CACHED_END) 620#undef CACHED_END 621 622 template <size_t kValueInputCount> 623 struct ReturnOperator final : public Operator { 624 ReturnOperator() 625 : Operator( // -- 626 IrOpcode::kReturn, Operator::kNoThrow, // opcode 627 "Return", // name 628 kValueInputCount + 1, 1, 1, 0, 0, 1) {} // counts 629 }; 630#define CACHED_RETURN(value_input_count) \ 631 ReturnOperator<value_input_count> kReturn##value_input_count##Operator; 632 CACHED_RETURN_LIST(CACHED_RETURN) 633#undef CACHED_RETURN 634 635 template <BranchHint hint> 636 struct BranchOperator final : public Operator1<BranchHint> { 637 BranchOperator() 638 : Operator1<BranchHint>( // -- 639 IrOpcode::kBranch, Operator::kKontrol, // opcode 640 "Branch", // name 641 1, 0, 1, 0, 0, 2, // counts 642 hint) {} // parameter 643 }; 644#define CACHED_BRANCH(Hint) \ 645 BranchOperator<BranchHint::k##Hint> kBranch##Hint##Operator; 646 CACHED_BRANCH_LIST(CACHED_BRANCH) 647#undef CACHED_BRANCH 648 649 template <int kEffectInputCount> 650 struct EffectPhiOperator final : public Operator { 651 EffectPhiOperator() 652 : Operator( // -- 653 IrOpcode::kEffectPhi, Operator::kKontrol, // opcode 654 "EffectPhi", // name 655 0, kEffectInputCount, 1, 0, 1, 0) {} // counts 656 }; 657#define CACHED_EFFECT_PHI(input_count) \ 658 EffectPhiOperator<input_count> kEffectPhi##input_count##Operator; 659 CACHED_EFFECT_PHI_LIST(CACHED_EFFECT_PHI) 660#undef CACHED_EFFECT_PHI 661 662 template <RegionObservability kRegionObservability> 663 struct BeginRegionOperator final : public Operator1<RegionObservability> { 664 BeginRegionOperator() 665 : Operator1<RegionObservability>( // -- 666 IrOpcode::kBeginRegion, Operator::kKontrol, // opcode 667 "BeginRegion", // name 668 0, 1, 0, 0, 1, 0, // counts 669 kRegionObservability) {} // parameter 670 }; 671 BeginRegionOperator<RegionObservability::kObservable> 672 kBeginRegionObservableOperator; 673 BeginRegionOperator<RegionObservability::kNotObservable> 674 kBeginRegionNotObservableOperator; 675 676 template <size_t kInputCount> 677 struct LoopOperator final : public Operator { 678 LoopOperator() 679 : Operator( // -- 680 IrOpcode::kLoop, Operator::kKontrol, // opcode 681 "Loop", // name 682 0, 0, kInputCount, 0, 0, 1) {} // counts 683 }; 684#define CACHED_LOOP(input_count) \ 685 LoopOperator<input_count> kLoop##input_count##Operator; 686 CACHED_LOOP_LIST(CACHED_LOOP) 687#undef CACHED_LOOP 688 689 template <size_t kInputCount> 690 struct MergeOperator final : public Operator { 691 MergeOperator() 692 : Operator( // -- 693 IrOpcode::kMerge, Operator::kKontrol, // opcode 694 "Merge", // name 695 0, 0, kInputCount, 0, 0, 1) {} // counts 696 }; 697#define CACHED_MERGE(input_count) \ 698 MergeOperator<input_count> kMerge##input_count##Operator; 699 CACHED_MERGE_LIST(CACHED_MERGE) 700#undef CACHED_MERGE 701 702 template <MachineRepresentation kRep> 703 struct LoopExitValueOperator final : public Operator1<MachineRepresentation> { 704 LoopExitValueOperator() 705 : Operator1<MachineRepresentation>(IrOpcode::kLoopExitValue, 706 Operator::kPure, "LoopExitValue", 1, 707 0, 1, 1, 0, 0, kRep) {} 708 }; 709#define CACHED_LOOP_EXIT_VALUE(rep) \ 710 LoopExitValueOperator<MachineRepresentation::rep> \ 711 kLoopExitValue##rep##Operator; 712 CACHED_LOOP_EXIT_VALUE_LIST(CACHED_LOOP_EXIT_VALUE) 713#undef CACHED_LOOP_EXIT_VALUE 714 715 template <DeoptimizeReason kReason> 716 struct DeoptimizeOperator final : public Operator1<DeoptimizeParameters> { 717 DeoptimizeOperator() 718 : Operator1<DeoptimizeParameters>( // -- 719 IrOpcode::kDeoptimize, // opcode 720 Operator::kFoldable | Operator::kNoThrow, // properties 721 "Deoptimize", // name 722 1, 1, 1, 0, 0, 1, // counts 723 DeoptimizeParameters(kReason, FeedbackSource())) {} 724 }; 725#define CACHED_DEOPTIMIZE(Reason) \ 726 DeoptimizeOperator<DeoptimizeReason::k##Reason> kDeoptimize##Reason##Operator; 727 CACHED_DEOPTIMIZE_LIST(CACHED_DEOPTIMIZE) 728#undef CACHED_DEOPTIMIZE 729 730 template <DeoptimizeReason kReason> 731 struct DeoptimizeIfOperator final : public Operator1<DeoptimizeParameters> { 732 DeoptimizeIfOperator() 733 : Operator1<DeoptimizeParameters>( // -- 734 IrOpcode::kDeoptimizeIf, // opcode 735 Operator::kFoldable | Operator::kNoThrow, // properties 736 "DeoptimizeIf", // name 737 2, 1, 1, 0, 1, 1, // counts 738 DeoptimizeParameters(kReason, FeedbackSource())) {} 739 }; 740#define CACHED_DEOPTIMIZE_IF(Reason) \ 741 DeoptimizeIfOperator<DeoptimizeReason::k##Reason> \ 742 kDeoptimizeIf##Reason##Operator; 743 CACHED_DEOPTIMIZE_IF_LIST(CACHED_DEOPTIMIZE_IF) 744#undef CACHED_DEOPTIMIZE_IF 745 746 template <DeoptimizeReason kReason> 747 struct DeoptimizeUnlessOperator final 748 : public Operator1<DeoptimizeParameters> { 749 DeoptimizeUnlessOperator() 750 : Operator1<DeoptimizeParameters>( // -- 751 IrOpcode::kDeoptimizeUnless, // opcode 752 Operator::kFoldable | Operator::kNoThrow, // properties 753 "DeoptimizeUnless", // name 754 2, 1, 1, 0, 1, 1, // counts 755 DeoptimizeParameters(kReason, FeedbackSource())) {} 756 }; 757#define CACHED_DEOPTIMIZE_UNLESS(Reason) \ 758 DeoptimizeUnlessOperator<DeoptimizeReason::k##Reason> \ 759 kDeoptimizeUnless##Reason##Operator; 760 CACHED_DEOPTIMIZE_UNLESS_LIST(CACHED_DEOPTIMIZE_UNLESS) 761#undef CACHED_DEOPTIMIZE_UNLESS 762 763 template <TrapId trap_id> 764 struct TrapIfOperator final : public Operator1<TrapId> { 765 TrapIfOperator() 766 : Operator1<TrapId>( // -- 767 IrOpcode::kTrapIf, // opcode 768 Operator::kFoldable | Operator::kNoThrow, // properties 769 "TrapIf", // name 770 1, 1, 1, 0, 0, 1, // counts 771 trap_id) {} // parameter 772 }; 773#define CACHED_TRAP_IF(Trap) \ 774 TrapIfOperator<TrapId::k##Trap> kTrapIf##Trap##Operator; 775 CACHED_TRAP_IF_LIST(CACHED_TRAP_IF) 776#undef CACHED_TRAP_IF 777 778 template <TrapId trap_id> 779 struct TrapUnlessOperator final : public Operator1<TrapId> { 780 TrapUnlessOperator() 781 : Operator1<TrapId>( // -- 782 IrOpcode::kTrapUnless, // opcode 783 Operator::kFoldable | Operator::kNoThrow, // properties 784 "TrapUnless", // name 785 1, 1, 1, 0, 0, 1, // counts 786 trap_id) {} // parameter 787 }; 788#define CACHED_TRAP_UNLESS(Trap) \ 789 TrapUnlessOperator<TrapId::k##Trap> kTrapUnless##Trap##Operator; 790 CACHED_TRAP_UNLESS_LIST(CACHED_TRAP_UNLESS) 791#undef CACHED_TRAP_UNLESS 792 793 template <MachineRepresentation kRep, int kInputCount> 794 struct PhiOperator final : public Operator1<MachineRepresentation> { 795 PhiOperator() 796 : Operator1<MachineRepresentation>( //-- 797 IrOpcode::kPhi, Operator::kPure, // opcode 798 "Phi", // name 799 kInputCount, 0, 1, 1, 0, 0, // counts 800 kRep) {} // parameter 801 }; 802#define CACHED_PHI(rep, input_count) \ 803 PhiOperator<MachineRepresentation::rep, input_count> \ 804 kPhi##rep##input_count##Operator; 805 CACHED_PHI_LIST(CACHED_PHI) 806#undef CACHED_PHI 807 808 template <int kInputCount> 809 struct InductionVariablePhiOperator final : public Operator { 810 InductionVariablePhiOperator() 811 : Operator( //-- 812 IrOpcode::kInductionVariablePhi, Operator::kPure, // opcode 813 "InductionVariablePhi", // name 814 kInputCount, 0, 1, 1, 0, 0) {} // counts 815 }; 816#define CACHED_INDUCTION_VARIABLE_PHI(input_count) \ 817 InductionVariablePhiOperator<input_count> \ 818 kInductionVariablePhi##input_count##Operator; 819 CACHED_INDUCTION_VARIABLE_PHI_LIST(CACHED_INDUCTION_VARIABLE_PHI) 820#undef CACHED_INDUCTION_VARIABLE_PHI 821 822 template <int kIndex> 823 struct ParameterOperator final : public Operator1<ParameterInfo> { 824 ParameterOperator() 825 : Operator1<ParameterInfo>( // -- 826 IrOpcode::kParameter, Operator::kPure, // opcode 827 "Parameter", // name 828 1, 0, 0, 1, 0, 0, // counts, 829 ParameterInfo(kIndex, nullptr)) {} // parameter and name 830 }; 831#define CACHED_PARAMETER(index) \ 832 ParameterOperator<index> kParameter##index##Operator; 833 CACHED_PARAMETER_LIST(CACHED_PARAMETER) 834#undef CACHED_PARAMETER 835 836 template <size_t kIndex> 837 struct ProjectionOperator final : public Operator1<size_t> { 838 ProjectionOperator() 839 : Operator1<size_t>( // -- 840 IrOpcode::kProjection, // opcode 841 Operator::kPure, // flags 842 "Projection", // name 843 1, 0, 1, 1, 0, 0, // counts, 844 kIndex) {} // parameter 845 }; 846#define CACHED_PROJECTION(index) \ 847 ProjectionOperator<index> kProjection##index##Operator; 848 CACHED_PROJECTION_LIST(CACHED_PROJECTION) 849#undef CACHED_PROJECTION 850 851 template <int kInputCount> 852 struct StateValuesOperator final : public Operator1<SparseInputMask> { 853 StateValuesOperator() 854 : Operator1<SparseInputMask>( // -- 855 IrOpcode::kStateValues, // opcode 856 Operator::kPure, // flags 857 "StateValues", // name 858 kInputCount, 0, 0, 1, 0, 0, // counts 859 SparseInputMask::Dense()) {} // parameter 860 }; 861#define CACHED_STATE_VALUES(input_count) \ 862 StateValuesOperator<input_count> kStateValues##input_count##Operator; 863 CACHED_STATE_VALUES_LIST(CACHED_STATE_VALUES) 864#undef CACHED_STATE_VALUES 865}; 866 867namespace { 868DEFINE_LAZY_LEAKY_OBJECT_GETTER(CommonOperatorGlobalCache, 869 GetCommonOperatorGlobalCache) 870} // namespace 871 872CommonOperatorBuilder::CommonOperatorBuilder(Zone* zone) 873 : cache_(*GetCommonOperatorGlobalCache()), zone_(zone) {} 874 875#define CACHED(Name, properties, value_input_count, effect_input_count, \ 876 control_input_count, value_output_count, effect_output_count, \ 877 control_output_count) \ 878 const Operator* CommonOperatorBuilder::Name() { \ 879 return &cache_.k##Name##Operator; \ 880 } 881COMMON_CACHED_OP_LIST(CACHED) 882#undef CACHED 883 884 885const Operator* CommonOperatorBuilder::End(size_t control_input_count) { 886 switch (control_input_count) { 887#define CACHED_END(input_count) \ 888 case input_count: \ 889 return &cache_.kEnd##input_count##Operator; 890 CACHED_END_LIST(CACHED_END) 891#undef CACHED_END 892 default: 893 break; 894 } 895 // Uncached. 896 return zone()->New<Operator>( //-- 897 IrOpcode::kEnd, Operator::kKontrol, // opcode 898 "End", // name 899 0, 0, control_input_count, 0, 0, 0); // counts 900} 901 902const Operator* CommonOperatorBuilder::Return(int value_input_count) { 903 switch (value_input_count) { 904#define CACHED_RETURN(input_count) \ 905 case input_count: \ 906 return &cache_.kReturn##input_count##Operator; 907 CACHED_RETURN_LIST(CACHED_RETURN) 908#undef CACHED_RETURN 909 default: 910 break; 911 } 912 // Uncached. 913 return zone()->New<Operator>( //-- 914 IrOpcode::kReturn, Operator::kNoThrow, // opcode 915 "Return", // name 916 value_input_count + 1, 1, 1, 0, 0, 1); // counts 917} 918 919const Operator* CommonOperatorBuilder::StaticAssert(const char* source) { 920 return zone()->New<Operator1<const char*>>( 921 IrOpcode::kStaticAssert, Operator::kFoldable, "StaticAssert", 1, 1, 0, 0, 922 1, 0, source); 923} 924 925const Operator* CommonOperatorBuilder::SLVerifierHint( 926 const Operator* semantics, 927 const base::Optional<Type>& override_output_type) { 928 return zone()->New<Operator1<SLVerifierHintParameters>>( 929 IrOpcode::kSLVerifierHint, Operator::kNoProperties, "SLVerifierHint", 1, 930 0, 0, 1, 0, 0, SLVerifierHintParameters(semantics, override_output_type)); 931} 932 933const Operator* CommonOperatorBuilder::Branch(BranchHint hint) { 934#define CACHED_BRANCH(Hint) \ 935 if (hint == BranchHint::k##Hint) { \ 936 return &cache_.kBranch##Hint##Operator; \ 937 } 938 CACHED_BRANCH_LIST(CACHED_BRANCH) 939#undef CACHED_BRANCH 940 UNREACHABLE(); 941} 942 943const Operator* CommonOperatorBuilder::Deoptimize( 944 DeoptimizeReason reason, FeedbackSource const& feedback) { 945#define CACHED_DEOPTIMIZE(Reason) \ 946 if (reason == DeoptimizeReason::k##Reason && !feedback.IsValid()) { \ 947 return &cache_.kDeoptimize##Reason##Operator; \ 948 } 949 CACHED_DEOPTIMIZE_LIST(CACHED_DEOPTIMIZE) 950#undef CACHED_DEOPTIMIZE 951 // Uncached 952 DeoptimizeParameters parameter(reason, feedback); 953 return zone()->New<Operator1<DeoptimizeParameters>>( // -- 954 IrOpcode::kDeoptimize, // opcodes 955 Operator::kFoldable | Operator::kNoThrow, // properties 956 "Deoptimize", // name 957 1, 1, 1, 0, 0, 1, // counts 958 parameter); // parameter 959} 960 961const Operator* CommonOperatorBuilder::DeoptimizeIf( 962 DeoptimizeReason reason, FeedbackSource const& feedback) { 963#define CACHED_DEOPTIMIZE_IF(Reason) \ 964 if (reason == DeoptimizeReason::k##Reason && !feedback.IsValid()) { \ 965 return &cache_.kDeoptimizeIf##Reason##Operator; \ 966 } 967 CACHED_DEOPTIMIZE_IF_LIST(CACHED_DEOPTIMIZE_IF) 968#undef CACHED_DEOPTIMIZE_IF 969 // Uncached 970 DeoptimizeParameters parameter(reason, feedback); 971 return zone()->New<Operator1<DeoptimizeParameters>>( // -- 972 IrOpcode::kDeoptimizeIf, // opcode 973 Operator::kFoldable | Operator::kNoThrow, // properties 974 "DeoptimizeIf", // name 975 2, 1, 1, 0, 1, 1, // counts 976 parameter); // parameter 977} 978 979const Operator* CommonOperatorBuilder::DeoptimizeUnless( 980 DeoptimizeReason reason, FeedbackSource const& feedback) { 981#define CACHED_DEOPTIMIZE_UNLESS(Reason) \ 982 if (reason == DeoptimizeReason::k##Reason && !feedback.IsValid()) { \ 983 return &cache_.kDeoptimizeUnless##Reason##Operator; \ 984 } 985 CACHED_DEOPTIMIZE_UNLESS_LIST(CACHED_DEOPTIMIZE_UNLESS) 986#undef CACHED_DEOPTIMIZE_UNLESS 987 // Uncached 988 DeoptimizeParameters parameter(reason, feedback); 989 return zone()->New<Operator1<DeoptimizeParameters>>( // -- 990 IrOpcode::kDeoptimizeUnless, // opcode 991 Operator::kFoldable | Operator::kNoThrow, // properties 992 "DeoptimizeUnless", // name 993 2, 1, 1, 0, 1, 1, // counts 994 parameter); // parameter 995} 996 997const Operator* CommonOperatorBuilder::TrapIf(TrapId trap_id) { 998 switch (trap_id) { 999#define CACHED_TRAP_IF(Trap) \ 1000 case TrapId::k##Trap: \ 1001 return &cache_.kTrapIf##Trap##Operator; 1002 CACHED_TRAP_IF_LIST(CACHED_TRAP_IF) 1003#undef CACHED_TRAP_IF 1004 default: 1005 break; 1006 } 1007 // Uncached 1008 return zone()->New<Operator1<TrapId>>( // -- 1009 IrOpcode::kTrapIf, // opcode 1010 Operator::kFoldable | Operator::kNoThrow, // properties 1011 "TrapIf", // name 1012 1, 1, 1, 0, 0, 1, // counts 1013 trap_id); // parameter 1014} 1015 1016const Operator* CommonOperatorBuilder::TrapUnless(TrapId trap_id) { 1017 switch (trap_id) { 1018#define CACHED_TRAP_UNLESS(Trap) \ 1019 case TrapId::k##Trap: \ 1020 return &cache_.kTrapUnless##Trap##Operator; 1021 CACHED_TRAP_UNLESS_LIST(CACHED_TRAP_UNLESS) 1022#undef CACHED_TRAP_UNLESS 1023 default: 1024 break; 1025 } 1026 // Uncached 1027 return zone()->New<Operator1<TrapId>>( // -- 1028 IrOpcode::kTrapUnless, // opcode 1029 Operator::kFoldable | Operator::kNoThrow, // properties 1030 "TrapUnless", // name 1031 1, 1, 1, 0, 0, 1, // counts 1032 trap_id); // parameter 1033} 1034 1035const Operator* CommonOperatorBuilder::Switch(size_t control_output_count) { 1036 return zone()->New<Operator>( // -- 1037 IrOpcode::kSwitch, Operator::kKontrol, // opcode 1038 "Switch", // name 1039 1, 0, 1, 0, 0, control_output_count); // counts 1040} 1041 1042const Operator* CommonOperatorBuilder::IfValue(int32_t index, 1043 int32_t comparison_order, 1044 BranchHint hint) { 1045 return zone()->New<Operator1<IfValueParameters>>( // -- 1046 IrOpcode::kIfValue, Operator::kKontrol, // opcode 1047 "IfValue", // name 1048 0, 0, 1, 0, 0, 1, // counts 1049 IfValueParameters(index, comparison_order, hint)); // parameter 1050} 1051 1052const Operator* CommonOperatorBuilder::IfDefault(BranchHint hint) { 1053 return zone()->New<Operator1<BranchHint>>( // -- 1054 IrOpcode::kIfDefault, Operator::kKontrol, // opcode 1055 "IfDefault", // name 1056 0, 0, 1, 0, 0, 1, // counts 1057 hint); // parameter 1058} 1059 1060const Operator* CommonOperatorBuilder::Start(int value_output_count) { 1061 return zone()->New<Operator>( // -- 1062 IrOpcode::kStart, Operator::kFoldable | Operator::kNoThrow, // opcode 1063 "Start", // name 1064 0, 0, 0, value_output_count, 1, 1); // counts 1065} 1066 1067 1068const Operator* CommonOperatorBuilder::Loop(int control_input_count) { 1069 switch (control_input_count) { 1070#define CACHED_LOOP(input_count) \ 1071 case input_count: \ 1072 return &cache_.kLoop##input_count##Operator; 1073 CACHED_LOOP_LIST(CACHED_LOOP) 1074#undef CACHED_LOOP 1075 default: 1076 break; 1077 } 1078 // Uncached. 1079 return zone()->New<Operator>( // -- 1080 IrOpcode::kLoop, Operator::kKontrol, // opcode 1081 "Loop", // name 1082 0, 0, control_input_count, 0, 0, 1); // counts 1083} 1084 1085 1086const Operator* CommonOperatorBuilder::Merge(int control_input_count) { 1087 switch (control_input_count) { 1088#define CACHED_MERGE(input_count) \ 1089 case input_count: \ 1090 return &cache_.kMerge##input_count##Operator; 1091 CACHED_MERGE_LIST(CACHED_MERGE) 1092#undef CACHED_MERGE 1093 default: 1094 break; 1095 } 1096 // Uncached. 1097 return zone()->New<Operator>( // -- 1098 IrOpcode::kMerge, Operator::kKontrol, // opcode 1099 "Merge", // name 1100 0, 0, control_input_count, 0, 0, 1); // counts 1101} 1102 1103const Operator* CommonOperatorBuilder::LoopExitValue( 1104 MachineRepresentation rep) { 1105 switch (rep) { 1106#define CACHED_LOOP_EXIT_VALUE(kRep) \ 1107 case MachineRepresentation::kRep: \ 1108 return &cache_.kLoopExitValue##kRep##Operator; 1109 1110 CACHED_LOOP_EXIT_VALUE_LIST(CACHED_LOOP_EXIT_VALUE) 1111#undef CACHED_LOOP_EXIT_VALUE 1112 default: 1113 // Uncached. 1114 return zone()->New<Operator1<MachineRepresentation>>( // -- 1115 IrOpcode::kLoopExitValue, Operator::kPure, // opcode 1116 "LoopExitValue", // name 1117 1, 0, 1, 1, 0, 0, // counts 1118 rep); // parameter 1119 } 1120} 1121 1122const Operator* CommonOperatorBuilder::Parameter(int index, 1123 const char* debug_name) { 1124 if (!debug_name) { 1125 switch (index) { 1126#define CACHED_PARAMETER(index) \ 1127 case index: \ 1128 return &cache_.kParameter##index##Operator; 1129 CACHED_PARAMETER_LIST(CACHED_PARAMETER) 1130#undef CACHED_PARAMETER 1131 default: 1132 break; 1133 } 1134 } 1135 // Uncached. 1136 return zone()->New<Operator1<ParameterInfo>>( // -- 1137 IrOpcode::kParameter, Operator::kPure, // opcode 1138 "Parameter", // name 1139 1, 0, 0, 1, 0, 0, // counts 1140 ParameterInfo(index, debug_name)); // parameter info 1141} 1142 1143const Operator* CommonOperatorBuilder::OsrValue(int index) { 1144 return zone()->New<Operator1<int>>( // -- 1145 IrOpcode::kOsrValue, Operator::kNoProperties, // opcode 1146 "OsrValue", // name 1147 0, 0, 1, 1, 0, 0, // counts 1148 index); // parameter 1149} 1150 1151const Operator* CommonOperatorBuilder::Int32Constant(int32_t value) { 1152 return zone()->New<Operator1<int32_t>>( // -- 1153 IrOpcode::kInt32Constant, Operator::kPure, // opcode 1154 "Int32Constant", // name 1155 0, 0, 0, 1, 0, 0, // counts 1156 value); // parameter 1157} 1158 1159 1160const Operator* CommonOperatorBuilder::Int64Constant(int64_t value) { 1161 return zone()->New<Operator1<int64_t>>( // -- 1162 IrOpcode::kInt64Constant, Operator::kPure, // opcode 1163 "Int64Constant", // name 1164 0, 0, 0, 1, 0, 0, // counts 1165 value); // parameter 1166} 1167 1168const Operator* CommonOperatorBuilder::TaggedIndexConstant(int32_t value) { 1169 return zone()->New<Operator1<int32_t>>( // -- 1170 IrOpcode::kTaggedIndexConstant, Operator::kPure, // opcode 1171 "TaggedIndexConstant", // name 1172 0, 0, 0, 1, 0, 0, // counts 1173 value); // parameter 1174} 1175 1176const Operator* CommonOperatorBuilder::Float32Constant(volatile float value) { 1177 return zone()->New<Operator1<float>>( // -- 1178 IrOpcode::kFloat32Constant, Operator::kPure, // opcode 1179 "Float32Constant", // name 1180 0, 0, 0, 1, 0, 0, // counts 1181 value); // parameter 1182} 1183 1184 1185const Operator* CommonOperatorBuilder::Float64Constant(volatile double value) { 1186 return zone()->New<Operator1<double>>( // -- 1187 IrOpcode::kFloat64Constant, Operator::kPure, // opcode 1188 "Float64Constant", // name 1189 0, 0, 0, 1, 0, 0, // counts 1190 value); // parameter 1191} 1192 1193 1194const Operator* CommonOperatorBuilder::ExternalConstant( 1195 const ExternalReference& value) { 1196 return zone()->New<Operator1<ExternalReference>>( // -- 1197 IrOpcode::kExternalConstant, Operator::kPure, // opcode 1198 "ExternalConstant", // name 1199 0, 0, 0, 1, 0, 0, // counts 1200 value); // parameter 1201} 1202 1203 1204const Operator* CommonOperatorBuilder::NumberConstant(volatile double value) { 1205 return zone()->New<Operator1<double>>( // -- 1206 IrOpcode::kNumberConstant, Operator::kPure, // opcode 1207 "NumberConstant", // name 1208 0, 0, 0, 1, 0, 0, // counts 1209 value); // parameter 1210} 1211 1212const Operator* CommonOperatorBuilder::PointerConstant(intptr_t value) { 1213 return zone()->New<Operator1<intptr_t>>( // -- 1214 IrOpcode::kPointerConstant, Operator::kPure, // opcode 1215 "PointerConstant", // name 1216 0, 0, 0, 1, 0, 0, // counts 1217 value); // parameter 1218} 1219 1220const Operator* CommonOperatorBuilder::HeapConstant( 1221 const Handle<HeapObject>& value) { 1222 return zone()->New<Operator1<Handle<HeapObject>>>( // -- 1223 IrOpcode::kHeapConstant, Operator::kPure, // opcode 1224 "HeapConstant", // name 1225 0, 0, 0, 1, 0, 0, // counts 1226 value); // parameter 1227} 1228 1229const Operator* CommonOperatorBuilder::CompressedHeapConstant( 1230 const Handle<HeapObject>& value) { 1231 return zone()->New<Operator1<Handle<HeapObject>>>( // -- 1232 IrOpcode::kCompressedHeapConstant, Operator::kPure, // opcode 1233 "CompressedHeapConstant", // name 1234 0, 0, 0, 1, 0, 0, // counts 1235 value); // parameter 1236} 1237 1238Handle<HeapObject> HeapConstantOf(const Operator* op) { 1239 DCHECK(IrOpcode::kHeapConstant == op->opcode() || 1240 IrOpcode::kCompressedHeapConstant == op->opcode()); 1241 return OpParameter<Handle<HeapObject>>(op); 1242} 1243 1244const StringConstantBase* StringConstantBaseOf(const Operator* op) { 1245 DCHECK_EQ(IrOpcode::kDelayedStringConstant, op->opcode()); 1246 return OpParameter<const StringConstantBase*>(op); 1247} 1248 1249const char* StaticAssertSourceOf(const Operator* op) { 1250 DCHECK_EQ(IrOpcode::kStaticAssert, op->opcode()); 1251 return OpParameter<const char*>(op); 1252} 1253 1254const Operator* CommonOperatorBuilder::RelocatableInt32Constant( 1255 int32_t value, RelocInfo::Mode rmode) { 1256 return zone()->New<Operator1<RelocatablePtrConstantInfo>>( // -- 1257 IrOpcode::kRelocatableInt32Constant, Operator::kPure, // opcode 1258 "RelocatableInt32Constant", // name 1259 0, 0, 0, 1, 0, 0, // counts 1260 RelocatablePtrConstantInfo(value, rmode)); // parameter 1261} 1262 1263const Operator* CommonOperatorBuilder::RelocatableInt64Constant( 1264 int64_t value, RelocInfo::Mode rmode) { 1265 return zone()->New<Operator1<RelocatablePtrConstantInfo>>( // -- 1266 IrOpcode::kRelocatableInt64Constant, Operator::kPure, // opcode 1267 "RelocatableInt64Constant", // name 1268 0, 0, 0, 1, 0, 0, // counts 1269 RelocatablePtrConstantInfo(value, rmode)); // parameter 1270} 1271 1272const Operator* CommonOperatorBuilder::ObjectId(uint32_t object_id) { 1273 return zone()->New<Operator1<uint32_t>>( // -- 1274 IrOpcode::kObjectId, Operator::kPure, // opcode 1275 "ObjectId", // name 1276 0, 0, 0, 1, 0, 0, // counts 1277 object_id); // parameter 1278} 1279 1280const Operator* CommonOperatorBuilder::Select(MachineRepresentation rep, 1281 BranchHint hint) { 1282 return zone()->New<Operator1<SelectParameters>>( // -- 1283 IrOpcode::kSelect, Operator::kPure, // opcode 1284 "Select", // name 1285 3, 0, 0, 1, 0, 0, // counts 1286 SelectParameters(rep, hint)); // parameter 1287} 1288 1289 1290const Operator* CommonOperatorBuilder::Phi(MachineRepresentation rep, 1291 int value_input_count) { 1292 DCHECK_LT(0, value_input_count); // Disallow empty phis. 1293#define CACHED_PHI(kRep, kValueInputCount) \ 1294 if (MachineRepresentation::kRep == rep && \ 1295 kValueInputCount == value_input_count) { \ 1296 return &cache_.kPhi##kRep##kValueInputCount##Operator; \ 1297 } 1298 CACHED_PHI_LIST(CACHED_PHI) 1299#undef CACHED_PHI 1300 // Uncached. 1301 return zone()->New<Operator1<MachineRepresentation>>( // -- 1302 IrOpcode::kPhi, Operator::kPure, // opcode 1303 "Phi", // name 1304 value_input_count, 0, 1, 1, 0, 0, // counts 1305 rep); // parameter 1306} 1307 1308const Operator* CommonOperatorBuilder::TypeGuard(Type type) { 1309 return zone()->New<Operator1<Type>>( // -- 1310 IrOpcode::kTypeGuard, Operator::kPure, // opcode 1311 "TypeGuard", // name 1312 1, 1, 1, 1, 1, 0, // counts 1313 type); // parameter 1314} 1315 1316const Operator* CommonOperatorBuilder::FoldConstant() { 1317 return zone()->New<Operator>( // -- 1318 IrOpcode::kFoldConstant, Operator::kPure, // opcode 1319 "FoldConstant", // name 1320 2, 0, 0, 1, 0, 0); // counts 1321} 1322 1323const Operator* CommonOperatorBuilder::EffectPhi(int effect_input_count) { 1324 DCHECK_LT(0, effect_input_count); // Disallow empty effect phis. 1325 switch (effect_input_count) { 1326#define CACHED_EFFECT_PHI(input_count) \ 1327 case input_count: \ 1328 return &cache_.kEffectPhi##input_count##Operator; 1329 CACHED_EFFECT_PHI_LIST(CACHED_EFFECT_PHI) 1330#undef CACHED_EFFECT_PHI 1331 default: 1332 break; 1333 } 1334 // Uncached. 1335 return zone()->New<Operator>( // -- 1336 IrOpcode::kEffectPhi, Operator::kKontrol, // opcode 1337 "EffectPhi", // name 1338 0, effect_input_count, 1, 0, 1, 0); // counts 1339} 1340 1341const Operator* CommonOperatorBuilder::InductionVariablePhi(int input_count) { 1342 DCHECK_LE(4, input_count); // There must be always the entry, backedge, 1343 // increment and at least one bound. 1344 switch (input_count) { 1345#define CACHED_INDUCTION_VARIABLE_PHI(input_count) \ 1346 case input_count: \ 1347 return &cache_.kInductionVariablePhi##input_count##Operator; 1348 CACHED_INDUCTION_VARIABLE_PHI_LIST(CACHED_INDUCTION_VARIABLE_PHI) 1349#undef CACHED_INDUCTION_VARIABLE_PHI 1350 default: 1351 break; 1352 } 1353 // Uncached. 1354 return zone()->New<Operator>( // -- 1355 IrOpcode::kInductionVariablePhi, Operator::kPure, // opcode 1356 "InductionVariablePhi", // name 1357 input_count, 0, 1, 1, 0, 0); // counts 1358} 1359 1360const Operator* CommonOperatorBuilder::BeginRegion( 1361 RegionObservability region_observability) { 1362 switch (region_observability) { 1363 case RegionObservability::kObservable: 1364 return &cache_.kBeginRegionObservableOperator; 1365 case RegionObservability::kNotObservable: 1366 return &cache_.kBeginRegionNotObservableOperator; 1367 } 1368 UNREACHABLE(); 1369} 1370 1371const Operator* CommonOperatorBuilder::StateValues(int arguments, 1372 SparseInputMask bitmask) { 1373 if (bitmask.IsDense()) { 1374 switch (arguments) { 1375#define CACHED_STATE_VALUES(arguments) \ 1376 case arguments: \ 1377 return &cache_.kStateValues##arguments##Operator; 1378 CACHED_STATE_VALUES_LIST(CACHED_STATE_VALUES) 1379#undef CACHED_STATE_VALUES 1380 default: 1381 break; 1382 } 1383 } 1384 1385#if DEBUG 1386 DCHECK(bitmask.IsDense() || bitmask.CountReal() == arguments); 1387#endif 1388 1389 // Uncached. 1390 return zone()->New<Operator1<SparseInputMask>>( // -- 1391 IrOpcode::kStateValues, Operator::kPure, // opcode 1392 "StateValues", // name 1393 arguments, 0, 0, 1, 0, 0, // counts 1394 bitmask); // parameter 1395} 1396 1397const Operator* CommonOperatorBuilder::TypedStateValues( 1398 const ZoneVector<MachineType>* types, SparseInputMask bitmask) { 1399#if DEBUG 1400 DCHECK(bitmask.IsDense() || 1401 bitmask.CountReal() == static_cast<int>(types->size())); 1402#endif 1403 1404 return zone()->New<Operator1<TypedStateValueInfo>>( // -- 1405 IrOpcode::kTypedStateValues, Operator::kPure, // opcode 1406 "TypedStateValues", // name 1407 static_cast<int>(types->size()), 0, 0, 1, 0, 0, // counts 1408 TypedStateValueInfo(types, bitmask)); // parameters 1409} 1410 1411const Operator* CommonOperatorBuilder::ArgumentsElementsState( 1412 ArgumentsStateType type) { 1413 return zone()->New<Operator1<ArgumentsStateType>>( // -- 1414 IrOpcode::kArgumentsElementsState, Operator::kPure, // opcode 1415 "ArgumentsElementsState", // name 1416 0, 0, 0, 1, 0, 0, // counts 1417 type); // parameter 1418} 1419 1420const Operator* CommonOperatorBuilder::ArgumentsLengthState() { 1421 return zone()->New<Operator>( // -- 1422 IrOpcode::kArgumentsLengthState, Operator::kPure, // opcode 1423 "ArgumentsLengthState", // name 1424 0, 0, 0, 1, 0, 0); // counts 1425} 1426 1427ArgumentsStateType ArgumentsStateTypeOf(Operator const* op) { 1428 DCHECK(op->opcode() == IrOpcode::kArgumentsElementsState); 1429 return OpParameter<ArgumentsStateType>(op); 1430} 1431 1432const Operator* CommonOperatorBuilder::ObjectState(uint32_t object_id, 1433 int pointer_slots) { 1434 return zone()->New<Operator1<ObjectStateInfo>>( // -- 1435 IrOpcode::kObjectState, Operator::kPure, // opcode 1436 "ObjectState", // name 1437 pointer_slots, 0, 0, 1, 0, 0, // counts 1438 ObjectStateInfo{object_id, pointer_slots}); // parameter 1439} 1440 1441const Operator* CommonOperatorBuilder::TypedObjectState( 1442 uint32_t object_id, const ZoneVector<MachineType>* types) { 1443 return zone()->New<Operator1<TypedObjectStateInfo>>( // -- 1444 IrOpcode::kTypedObjectState, Operator::kPure, // opcode 1445 "TypedObjectState", // name 1446 static_cast<int>(types->size()), 0, 0, 1, 0, 0, // counts 1447 TypedObjectStateInfo(object_id, types)); // parameter 1448} 1449 1450uint32_t ObjectIdOf(Operator const* op) { 1451 switch (op->opcode()) { 1452 case IrOpcode::kObjectState: 1453 return OpParameter<ObjectStateInfo>(op).object_id(); 1454 case IrOpcode::kTypedObjectState: 1455 return OpParameter<TypedObjectStateInfo>(op).object_id(); 1456 case IrOpcode::kObjectId: 1457 return OpParameter<uint32_t>(op); 1458 default: 1459 UNREACHABLE(); 1460 } 1461} 1462 1463MachineRepresentation DeadValueRepresentationOf(Operator const* op) { 1464 DCHECK_EQ(IrOpcode::kDeadValue, op->opcode()); 1465 return OpParameter<MachineRepresentation>(op); 1466} 1467 1468const Operator* CommonOperatorBuilder::FrameState( 1469 BytecodeOffset bailout_id, OutputFrameStateCombine state_combine, 1470 const FrameStateFunctionInfo* function_info) { 1471 FrameStateInfo state_info(bailout_id, state_combine, function_info); 1472 return zone()->New<Operator1<FrameStateInfo>>( // -- 1473 IrOpcode::kFrameState, Operator::kPure, // opcode 1474 "FrameState", // name 1475 5, 0, 0, 1, 0, 0, // counts 1476 state_info); // parameter 1477} 1478 1479const Operator* CommonOperatorBuilder::Call( 1480 const CallDescriptor* call_descriptor) { 1481 class CallOperator final : public Operator1<const CallDescriptor*> { 1482 public: 1483 explicit CallOperator(const CallDescriptor* call_descriptor) 1484 : Operator1<const CallDescriptor*>( 1485 IrOpcode::kCall, call_descriptor->properties(), "Call", 1486 call_descriptor->InputCount() + 1487 call_descriptor->FrameStateCount(), 1488 Operator::ZeroIfPure(call_descriptor->properties()), 1489 Operator::ZeroIfEliminatable(call_descriptor->properties()), 1490 call_descriptor->ReturnCount(), 1491 Operator::ZeroIfPure(call_descriptor->properties()), 1492 Operator::ZeroIfNoThrow(call_descriptor->properties()), 1493 call_descriptor) {} 1494 1495 void PrintParameter(std::ostream& os, 1496 PrintVerbosity verbose) const override { 1497 os << "[" << *parameter() << "]"; 1498 } 1499 }; 1500 return zone()->New<CallOperator>(call_descriptor); 1501} 1502 1503const Operator* CommonOperatorBuilder::TailCall( 1504 const CallDescriptor* call_descriptor) { 1505 class TailCallOperator final : public Operator1<const CallDescriptor*> { 1506 public: 1507 explicit TailCallOperator(const CallDescriptor* call_descriptor) 1508 : Operator1<const CallDescriptor*>( 1509 IrOpcode::kTailCall, 1510 call_descriptor->properties() | Operator::kNoThrow, "TailCall", 1511 call_descriptor->InputCount() + 1512 call_descriptor->FrameStateCount(), 1513 1, 1, 0, 0, 1, call_descriptor) {} 1514 1515 void PrintParameter(std::ostream& os, 1516 PrintVerbosity verbose) const override { 1517 os << "[" << *parameter() << "]"; 1518 } 1519 }; 1520 return zone()->New<TailCallOperator>(call_descriptor); 1521} 1522 1523const Operator* CommonOperatorBuilder::Projection(size_t index) { 1524 switch (index) { 1525#define CACHED_PROJECTION(index) \ 1526 case index: \ 1527 return &cache_.kProjection##index##Operator; 1528 CACHED_PROJECTION_LIST(CACHED_PROJECTION) 1529#undef CACHED_PROJECTION 1530 default: 1531 break; 1532 } 1533 // Uncached. 1534 return zone()->New<Operator1<size_t>>( // -- 1535 IrOpcode::kProjection, // opcode 1536 Operator::kPure, // flags 1537 "Projection", // name 1538 1, 0, 1, 1, 0, 0, // counts 1539 index); // parameter 1540} 1541 1542 1543const Operator* CommonOperatorBuilder::ResizeMergeOrPhi(const Operator* op, 1544 int size) { 1545 if (op->opcode() == IrOpcode::kPhi) { 1546 return Phi(PhiRepresentationOf(op), size); 1547 } else if (op->opcode() == IrOpcode::kEffectPhi) { 1548 return EffectPhi(size); 1549 } else if (op->opcode() == IrOpcode::kMerge) { 1550 return Merge(size); 1551 } else if (op->opcode() == IrOpcode::kLoop) { 1552 return Loop(size); 1553 } else { 1554 UNREACHABLE(); 1555 } 1556} 1557 1558const FrameStateFunctionInfo* 1559CommonOperatorBuilder::CreateFrameStateFunctionInfo( 1560 FrameStateType type, int parameter_count, int local_count, 1561 Handle<SharedFunctionInfo> shared_info) { 1562 return zone()->New<FrameStateFunctionInfo>(type, parameter_count, local_count, 1563 shared_info); 1564} 1565 1566#if V8_ENABLE_WEBASSEMBLY 1567const FrameStateFunctionInfo* 1568CommonOperatorBuilder::CreateJSToWasmFrameStateFunctionInfo( 1569 FrameStateType type, int parameter_count, int local_count, 1570 Handle<SharedFunctionInfo> shared_info, 1571 const wasm::FunctionSig* signature) { 1572 DCHECK_EQ(type, FrameStateType::kJSToWasmBuiltinContinuation); 1573 DCHECK_NOT_NULL(signature); 1574 return zone()->New<JSToWasmFrameStateFunctionInfo>( 1575 type, parameter_count, local_count, shared_info, signature); 1576} 1577#endif // V8_ENABLE_WEBASSEMBLY 1578 1579const Operator* CommonOperatorBuilder::DeadValue(MachineRepresentation rep) { 1580 return zone()->New<Operator1<MachineRepresentation>>( // -- 1581 IrOpcode::kDeadValue, Operator::kPure, // opcode 1582 "DeadValue", // name 1583 1, 0, 0, 1, 0, 0, // counts 1584 rep); // parameter 1585} 1586 1587const FrameStateInfo& FrameStateInfoOf(const Operator* op) { 1588 DCHECK_EQ(IrOpcode::kFrameState, op->opcode()); 1589 return OpParameter<FrameStateInfo>(op); 1590} 1591 1592#undef COMMON_CACHED_OP_LIST 1593#undef CACHED_BRANCH_LIST 1594#undef CACHED_RETURN_LIST 1595#undef CACHED_END_LIST 1596#undef CACHED_EFFECT_PHI_LIST 1597#undef CACHED_INDUCTION_VARIABLE_PHI_LIST 1598#undef CACHED_LOOP_LIST 1599#undef CACHED_MERGE_LIST 1600#undef CACHED_DEOPTIMIZE_LIST 1601#undef CACHED_DEOPTIMIZE_IF_LIST 1602#undef CACHED_DEOPTIMIZE_UNLESS_LIST 1603#undef CACHED_TRAP_IF_LIST 1604#undef CACHED_TRAP_UNLESS_LIST 1605#undef CACHED_PARAMETER_LIST 1606#undef CACHED_PHI_LIST 1607#undef CACHED_PROJECTION_LIST 1608#undef CACHED_STATE_VALUES_LIST 1609 1610} // namespace compiler 1611} // namespace internal 1612} // namespace v8 1613