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