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