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