1 // Copyright 2012 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/simplified-operator.h" 6 7 #include "src/base/lazy-instance.h" 8 #include "src/compiler/opcodes.h" 9 #include "src/compiler/operator.h" 10 #include "src/compiler/types.h" 11 #include "src/handles-inl.h" 12 #include "src/objects-inl.h" 13 #include "src/objects/map.h" 14 #include "src/objects/name.h" 15 16 namespace v8 { 17 namespace internal { 18 namespace compiler { 19 20 size_t hash_value(BaseTaggedness base_taggedness) { 21 return static_cast<uint8_t>(base_taggedness); 22 } 23 24 std::ostream& operator<<(std::ostream& os, BaseTaggedness base_taggedness) { 25 switch (base_taggedness) { 26 case kUntaggedBase: 27 return os << "untagged base"; 28 case kTaggedBase: 29 return os << "tagged base"; 30 } 31 UNREACHABLE(); 32 } 33 34 bool operator==(FieldAccess const& lhs, FieldAccess const& rhs) { 35 // On purpose we don't include the write barrier kind here, as this method is 36 // really only relevant for eliminating loads and they don't care about the 37 // write barrier mode. 38 return lhs.base_is_tagged == rhs.base_is_tagged && lhs.offset == rhs.offset && 39 lhs.map.address() == rhs.map.address() && 40 lhs.machine_type == rhs.machine_type; 41 } 42 43 size_t hash_value(FieldAccess const& access) { 44 // On purpose we don't include the write barrier kind here, as this method is 45 // really only relevant for eliminating loads and they don't care about the 46 // write barrier mode. 47 return base::hash_combine(access.base_is_tagged, access.offset, 48 access.machine_type); 49 } 50 51 size_t hash_value(LoadSensitivity load_sensitivity) { 52 return static_cast<size_t>(load_sensitivity); 53 } 54 55 std::ostream& operator<<(std::ostream& os, LoadSensitivity load_sensitivity) { 56 switch (load_sensitivity) { 57 case LoadSensitivity::kCritical: 58 return os << "Critical"; 59 case LoadSensitivity::kSafe: 60 return os << "Safe"; 61 case LoadSensitivity::kUnsafe: 62 return os << "Unsafe"; 63 } 64 UNREACHABLE(); 65 } 66 67 std::ostream& operator<<(std::ostream& os, FieldAccess const& access) { 68 os << "[" << access.base_is_tagged << ", " << access.offset << ", "; 69 #ifdef OBJECT_PRINT 70 Handle<Name> name; 71 if (access.name.ToHandle(&name)) { 72 name->NamePrint(os); 73 os << ", "; 74 } 75 Handle<Map> map; 76 if (access.map.ToHandle(&map)) { 77 os << Brief(*map) << ", "; 78 } 79 #endif 80 os << access.type << ", " << access.machine_type << ", " 81 << access.write_barrier_kind; 82 if (FLAG_untrusted_code_mitigations || FLAG_branch_load_poisoning) { 83 os << ", " << access.load_sensitivity; 84 } 85 os << "]"; 86 return os; 87 } 88 89 template <> 90 void Operator1<FieldAccess>::PrintParameter(std::ostream& os, 91 PrintVerbosity verbose) const { 92 if (verbose == PrintVerbosity::kVerbose) { 93 os << parameter(); 94 } else { 95 os << "[+" << parameter().offset << "]"; 96 } 97 } 98 99 bool operator==(ElementAccess const& lhs, ElementAccess const& rhs) { 100 // On purpose we don't include the write barrier kind here, as this method is 101 // really only relevant for eliminating loads and they don't care about the 102 // write barrier mode. 103 return lhs.base_is_tagged == rhs.base_is_tagged && 104 lhs.header_size == rhs.header_size && 105 lhs.machine_type == rhs.machine_type; 106 } 107 108 size_t hash_value(ElementAccess const& access) { 109 // On purpose we don't include the write barrier kind here, as this method is 110 // really only relevant for eliminating loads and they don't care about the 111 // write barrier mode. 112 return base::hash_combine(access.base_is_tagged, access.header_size, 113 access.machine_type); 114 } 115 116 117 std::ostream& operator<<(std::ostream& os, ElementAccess const& access) { 118 os << access.base_is_tagged << ", " << access.header_size << ", " 119 << access.type << ", " << access.machine_type << ", " 120 << access.write_barrier_kind; 121 if (FLAG_untrusted_code_mitigations || FLAG_branch_load_poisoning) { 122 os << ", " << access.load_sensitivity; 123 } 124 return os; 125 } 126 127 const FieldAccess& FieldAccessOf(const Operator* op) { 128 DCHECK_NOT_NULL(op); 129 DCHECK(op->opcode() == IrOpcode::kLoadField || 130 op->opcode() == IrOpcode::kStoreField); 131 return OpParameter<FieldAccess>(op); 132 } 133 134 135 const ElementAccess& ElementAccessOf(const Operator* op) { 136 DCHECK_NOT_NULL(op); 137 DCHECK(op->opcode() == IrOpcode::kLoadElement || 138 op->opcode() == IrOpcode::kStoreElement); 139 return OpParameter<ElementAccess>(op); 140 } 141 142 ExternalArrayType ExternalArrayTypeOf(const Operator* op) { 143 DCHECK(op->opcode() == IrOpcode::kLoadTypedElement || 144 op->opcode() == IrOpcode::kLoadDataViewElement || 145 op->opcode() == IrOpcode::kStoreTypedElement || 146 op->opcode() == IrOpcode::kStoreDataViewElement); 147 return OpParameter<ExternalArrayType>(op); 148 } 149 150 ConvertReceiverMode ConvertReceiverModeOf(Operator const* op) { 151 DCHECK_EQ(IrOpcode::kConvertReceiver, op->opcode()); 152 return OpParameter<ConvertReceiverMode>(op); 153 } 154 155 size_t hash_value(CheckFloat64HoleMode mode) { 156 return static_cast<size_t>(mode); 157 } 158 159 std::ostream& operator<<(std::ostream& os, CheckFloat64HoleMode mode) { 160 switch (mode) { 161 case CheckFloat64HoleMode::kAllowReturnHole: 162 return os << "allow-return-hole"; 163 case CheckFloat64HoleMode::kNeverReturnHole: 164 return os << "never-return-hole"; 165 } 166 UNREACHABLE(); 167 } 168 169 CheckFloat64HoleParameters const& CheckFloat64HoleParametersOf( 170 Operator const* op) { 171 DCHECK_EQ(IrOpcode::kCheckFloat64Hole, op->opcode()); 172 return OpParameter<CheckFloat64HoleParameters>(op); 173 } 174 175 std::ostream& operator<<(std::ostream& os, 176 CheckFloat64HoleParameters const& params) { 177 os << params.mode(); 178 if (params.feedback().IsValid()) os << "; " << params.feedback(); 179 return os; 180 } 181 182 size_t hash_value(const CheckFloat64HoleParameters& params) { 183 return base::hash_combine(params.mode(), params.feedback()); 184 } 185 186 bool operator==(CheckFloat64HoleParameters const& lhs, 187 CheckFloat64HoleParameters const& rhs) { 188 return lhs.mode() == rhs.mode() && lhs.feedback() == rhs.feedback(); 189 } 190 191 bool operator!=(CheckFloat64HoleParameters const& lhs, 192 CheckFloat64HoleParameters const& rhs) { 193 return !(lhs == rhs); 194 } 195 196 CheckForMinusZeroMode CheckMinusZeroModeOf(const Operator* op) { 197 DCHECK(op->opcode() == IrOpcode::kChangeFloat64ToTagged || 198 op->opcode() == IrOpcode::kCheckedInt32Mul); 199 return OpParameter<CheckForMinusZeroMode>(op); 200 } 201 202 size_t hash_value(CheckForMinusZeroMode mode) { 203 return static_cast<size_t>(mode); 204 } 205 206 std::ostream& operator<<(std::ostream& os, CheckForMinusZeroMode mode) { 207 switch (mode) { 208 case CheckForMinusZeroMode::kCheckForMinusZero: 209 return os << "check-for-minus-zero"; 210 case CheckForMinusZeroMode::kDontCheckForMinusZero: 211 return os << "dont-check-for-minus-zero"; 212 } 213 UNREACHABLE(); 214 } 215 216 std::ostream& operator<<(std::ostream& os, CheckMapsFlags flags) { 217 bool empty = true; 218 if (flags & CheckMapsFlag::kTryMigrateInstance) { 219 os << "TryMigrateInstance"; 220 empty = false; 221 } 222 if (empty) os << "None"; 223 return os; 224 } 225 226 MapsParameterInfo::MapsParameterInfo(ZoneHandleSet<Map> const& maps) 227 : maps_(maps), instance_type_(Nothing<InstanceType>()) { 228 DCHECK_LT(0, maps.size()); 229 instance_type_ = Just(maps.at(0)->instance_type()); 230 for (size_t i = 1; i < maps.size(); ++i) { 231 if (instance_type_.FromJust() != maps.at(i)->instance_type()) { 232 instance_type_ = Nothing<InstanceType>(); 233 break; 234 } 235 } 236 } 237 238 std::ostream& operator<<(std::ostream& os, MapsParameterInfo const& p) { 239 ZoneHandleSet<Map> const& maps = p.maps(); 240 InstanceType instance_type; 241 if (p.instance_type().To(&instance_type)) { 242 os << ", " << instance_type; 243 } 244 for (size_t i = 0; i < maps.size(); ++i) { 245 os << ", " << Brief(*maps[i]); 246 } 247 return os; 248 } 249 250 bool operator==(MapsParameterInfo const& lhs, MapsParameterInfo const& rhs) { 251 return lhs.maps() == rhs.maps(); 252 } 253 254 bool operator!=(MapsParameterInfo const& lhs, MapsParameterInfo const& rhs) { 255 return !(lhs == rhs); 256 } 257 258 size_t hash_value(MapsParameterInfo const& p) { return hash_value(p.maps()); } 259 260 bool operator==(CheckMapsParameters const& lhs, 261 CheckMapsParameters const& rhs) { 262 return lhs.flags() == rhs.flags() && lhs.maps() == rhs.maps() && 263 lhs.feedback() == rhs.feedback(); 264 } 265 266 size_t hash_value(CheckMapsParameters const& p) { 267 return base::hash_combine(p.flags(), p.maps(), p.feedback()); 268 } 269 270 std::ostream& operator<<(std::ostream& os, CheckMapsParameters const& p) { 271 os << p.flags() << p.maps_info(); 272 if (p.feedback().IsValid()) { 273 os << "; " << p.feedback(); 274 } 275 return os; 276 } 277 278 CheckMapsParameters const& CheckMapsParametersOf(Operator const* op) { 279 DCHECK_EQ(IrOpcode::kCheckMaps, op->opcode()); 280 return OpParameter<CheckMapsParameters>(op); 281 } 282 283 MapsParameterInfo const& CompareMapsParametersOf(Operator const* op) { 284 DCHECK_EQ(IrOpcode::kCompareMaps, op->opcode()); 285 return OpParameter<MapsParameterInfo>(op); 286 } 287 288 MapsParameterInfo const& MapGuardMapsOf(Operator const* op) { 289 DCHECK_EQ(IrOpcode::kMapGuard, op->opcode()); 290 return OpParameter<MapsParameterInfo>(op); 291 } 292 293 size_t hash_value(CheckTaggedInputMode mode) { 294 return static_cast<size_t>(mode); 295 } 296 297 std::ostream& operator<<(std::ostream& os, CheckTaggedInputMode mode) { 298 switch (mode) { 299 case CheckTaggedInputMode::kNumber: 300 return os << "Number"; 301 case CheckTaggedInputMode::kNumberOrOddball: 302 return os << "NumberOrOddball"; 303 } 304 UNREACHABLE(); 305 } 306 307 std::ostream& operator<<(std::ostream& os, GrowFastElementsMode mode) { 308 switch (mode) { 309 case GrowFastElementsMode::kDoubleElements: 310 return os << "DoubleElements"; 311 case GrowFastElementsMode::kSmiOrObjectElements: 312 return os << "SmiOrObjectElements"; 313 } 314 UNREACHABLE(); 315 } 316 317 bool operator==(const GrowFastElementsParameters& lhs, 318 const GrowFastElementsParameters& rhs) { 319 return lhs.mode() == rhs.mode() && lhs.feedback() == rhs.feedback(); 320 } 321 322 inline size_t hash_value(const GrowFastElementsParameters& params) { 323 return base::hash_combine(params.mode(), params.feedback()); 324 } 325 326 std::ostream& operator<<(std::ostream& os, 327 const GrowFastElementsParameters& params) { 328 os << params.mode(); 329 if (params.feedback().IsValid()) { 330 os << params.feedback(); 331 } 332 return os; 333 } 334 335 const GrowFastElementsParameters& GrowFastElementsParametersOf( 336 const Operator* op) { 337 DCHECK_EQ(IrOpcode::kMaybeGrowFastElements, op->opcode()); 338 return OpParameter<GrowFastElementsParameters>(op); 339 } 340 341 bool operator==(ElementsTransition const& lhs, ElementsTransition const& rhs) { 342 return lhs.mode() == rhs.mode() && 343 lhs.source().address() == rhs.source().address() && 344 lhs.target().address() == rhs.target().address(); 345 } 346 347 size_t hash_value(ElementsTransition transition) { 348 return base::hash_combine(static_cast<uint8_t>(transition.mode()), 349 transition.source().address(), 350 transition.target().address()); 351 } 352 353 std::ostream& operator<<(std::ostream& os, ElementsTransition transition) { 354 switch (transition.mode()) { 355 case ElementsTransition::kFastTransition: 356 return os << "fast-transition from " << Brief(*transition.source()) 357 << " to " << Brief(*transition.target()); 358 case ElementsTransition::kSlowTransition: 359 return os << "slow-transition from " << Brief(*transition.source()) 360 << " to " << Brief(*transition.target()); 361 } 362 UNREACHABLE(); 363 } 364 365 ElementsTransition const& ElementsTransitionOf(const Operator* op) { 366 DCHECK_EQ(IrOpcode::kTransitionElementsKind, op->opcode()); 367 return OpParameter<ElementsTransition>(op); 368 } 369 370 namespace { 371 372 // Parameters for the TransitionAndStoreElement opcode. 373 class TransitionAndStoreElementParameters final { 374 public: 375 TransitionAndStoreElementParameters(Handle<Map> double_map, 376 Handle<Map> fast_map); 377 378 Handle<Map> double_map() const { return double_map_; } 379 Handle<Map> fast_map() const { return fast_map_; } 380 381 private: 382 Handle<Map> const double_map_; 383 Handle<Map> const fast_map_; 384 }; 385 386 TransitionAndStoreElementParameters::TransitionAndStoreElementParameters( 387 Handle<Map> double_map, Handle<Map> fast_map) 388 : double_map_(double_map), fast_map_(fast_map) {} 389 390 bool operator==(TransitionAndStoreElementParameters const& lhs, 391 TransitionAndStoreElementParameters const& rhs) { 392 return lhs.fast_map().address() == rhs.fast_map().address() && 393 lhs.double_map().address() == rhs.double_map().address(); 394 } 395 396 size_t hash_value(TransitionAndStoreElementParameters parameters) { 397 return base::hash_combine(parameters.fast_map().address(), 398 parameters.double_map().address()); 399 } 400 401 std::ostream& operator<<(std::ostream& os, 402 TransitionAndStoreElementParameters parameters) { 403 return os << "fast-map" << Brief(*parameters.fast_map()) << " double-map" 404 << Brief(*parameters.double_map()); 405 } 406 407 } // namespace 408 409 namespace { 410 411 // Parameters for the TransitionAndStoreNonNumberElement opcode. 412 class TransitionAndStoreNonNumberElementParameters final { 413 public: 414 TransitionAndStoreNonNumberElementParameters(Handle<Map> fast_map, 415 Type value_type); 416 417 Handle<Map> fast_map() const { return fast_map_; } 418 Type value_type() const { return value_type_; } 419 420 private: 421 Handle<Map> const fast_map_; 422 Type value_type_; 423 }; 424 425 TransitionAndStoreNonNumberElementParameters:: 426 TransitionAndStoreNonNumberElementParameters(Handle<Map> fast_map, 427 Type value_type) 428 : fast_map_(fast_map), value_type_(value_type) {} 429 430 bool operator==(TransitionAndStoreNonNumberElementParameters const& lhs, 431 TransitionAndStoreNonNumberElementParameters const& rhs) { 432 return lhs.fast_map().address() == rhs.fast_map().address() && 433 lhs.value_type() == rhs.value_type(); 434 } 435 436 size_t hash_value(TransitionAndStoreNonNumberElementParameters parameters) { 437 return base::hash_combine(parameters.fast_map().address(), 438 parameters.value_type()); 439 } 440 441 std::ostream& operator<<( 442 std::ostream& os, TransitionAndStoreNonNumberElementParameters parameters) { 443 return os << parameters.value_type() << ", fast-map" 444 << Brief(*parameters.fast_map()); 445 } 446 447 } // namespace 448 449 namespace { 450 451 // Parameters for the TransitionAndStoreNumberElement opcode. 452 class TransitionAndStoreNumberElementParameters final { 453 public: 454 explicit TransitionAndStoreNumberElementParameters(Handle<Map> double_map); 455 456 Handle<Map> double_map() const { return double_map_; } 457 458 private: 459 Handle<Map> const double_map_; 460 }; 461 462 TransitionAndStoreNumberElementParameters:: 463 TransitionAndStoreNumberElementParameters(Handle<Map> double_map) 464 : double_map_(double_map) {} 465 466 bool operator==(TransitionAndStoreNumberElementParameters const& lhs, 467 TransitionAndStoreNumberElementParameters const& rhs) { 468 return lhs.double_map().address() == rhs.double_map().address(); 469 } 470 471 size_t hash_value(TransitionAndStoreNumberElementParameters parameters) { 472 return base::hash_combine(parameters.double_map().address()); 473 } 474 475 std::ostream& operator<<(std::ostream& os, 476 TransitionAndStoreNumberElementParameters parameters) { 477 return os << "double-map" << Brief(*parameters.double_map()); 478 } 479 480 } // namespace 481 482 Handle<Map> DoubleMapParameterOf(const Operator* op) { 483 if (op->opcode() == IrOpcode::kTransitionAndStoreElement) { 484 return OpParameter<TransitionAndStoreElementParameters>(op).double_map(); 485 } else if (op->opcode() == IrOpcode::kTransitionAndStoreNumberElement) { 486 return OpParameter<TransitionAndStoreNumberElementParameters>(op) 487 .double_map(); 488 } 489 UNREACHABLE(); 490 return Handle<Map>::null(); 491 } 492 493 Type ValueTypeParameterOf(const Operator* op) { 494 DCHECK_EQ(IrOpcode::kTransitionAndStoreNonNumberElement, op->opcode()); 495 return OpParameter<TransitionAndStoreNonNumberElementParameters>(op) 496 .value_type(); 497 } 498 499 Handle<Map> FastMapParameterOf(const Operator* op) { 500 if (op->opcode() == IrOpcode::kTransitionAndStoreElement) { 501 return OpParameter<TransitionAndStoreElementParameters>(op).fast_map(); 502 } else if (op->opcode() == IrOpcode::kTransitionAndStoreNonNumberElement) { 503 return OpParameter<TransitionAndStoreNonNumberElementParameters>(op) 504 .fast_map(); 505 } 506 UNREACHABLE(); 507 return Handle<Map>::null(); 508 } 509 510 std::ostream& operator<<(std::ostream& os, NumberOperationHint hint) { 511 switch (hint) { 512 case NumberOperationHint::kSignedSmall: 513 return os << "SignedSmall"; 514 case NumberOperationHint::kSignedSmallInputs: 515 return os << "SignedSmallInputs"; 516 case NumberOperationHint::kSigned32: 517 return os << "Signed32"; 518 case NumberOperationHint::kNumber: 519 return os << "Number"; 520 case NumberOperationHint::kNumberOrOddball: 521 return os << "NumberOrOddball"; 522 } 523 UNREACHABLE(); 524 } 525 526 size_t hash_value(NumberOperationHint hint) { 527 return static_cast<uint8_t>(hint); 528 } 529 530 NumberOperationHint NumberOperationHintOf(const Operator* op) { 531 DCHECK(op->opcode() == IrOpcode::kSpeculativeNumberAdd || 532 op->opcode() == IrOpcode::kSpeculativeNumberSubtract || 533 op->opcode() == IrOpcode::kSpeculativeNumberMultiply || 534 op->opcode() == IrOpcode::kSpeculativeNumberDivide || 535 op->opcode() == IrOpcode::kSpeculativeNumberModulus || 536 op->opcode() == IrOpcode::kSpeculativeNumberShiftLeft || 537 op->opcode() == IrOpcode::kSpeculativeNumberShiftRight || 538 op->opcode() == IrOpcode::kSpeculativeNumberShiftRightLogical || 539 op->opcode() == IrOpcode::kSpeculativeNumberBitwiseAnd || 540 op->opcode() == IrOpcode::kSpeculativeNumberBitwiseOr || 541 op->opcode() == IrOpcode::kSpeculativeNumberBitwiseXor || 542 op->opcode() == IrOpcode::kSpeculativeNumberEqual || 543 op->opcode() == IrOpcode::kSpeculativeNumberLessThan || 544 op->opcode() == IrOpcode::kSpeculativeNumberLessThanOrEqual || 545 op->opcode() == IrOpcode::kSpeculativeSafeIntegerAdd || 546 op->opcode() == IrOpcode::kSpeculativeSafeIntegerSubtract); 547 return OpParameter<NumberOperationHint>(op); 548 } 549 550 bool operator==(NumberOperationParameters const& lhs, 551 NumberOperationParameters const& rhs) { 552 return lhs.hint() == rhs.hint() && lhs.feedback() == rhs.feedback(); 553 } 554 555 size_t hash_value(NumberOperationParameters const& p) { 556 return base::hash_combine(p.hint(), p.feedback()); 557 } 558 559 std::ostream& operator<<(std::ostream& os, NumberOperationParameters const& p) { 560 return os << p.hint() << " " << p.feedback(); 561 } 562 563 NumberOperationParameters const& NumberOperationParametersOf( 564 Operator const* op) { 565 DCHECK_EQ(IrOpcode::kSpeculativeToNumber, op->opcode()); 566 return OpParameter<NumberOperationParameters>(op); 567 } 568 569 size_t hash_value(AllocateParameters info) { 570 return base::hash_combine(info.type(), info.pretenure()); 571 } 572 573 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, 574 AllocateParameters info) { 575 return os << info.type() << ", " << info.pretenure(); 576 } 577 578 bool operator==(AllocateParameters const& lhs, AllocateParameters const& rhs) { 579 return lhs.pretenure() == rhs.pretenure() && lhs.type() == rhs.type(); 580 } 581 582 PretenureFlag PretenureFlagOf(const Operator* op) { 583 if (op->opcode() == IrOpcode::kNewDoubleElements || 584 op->opcode() == IrOpcode::kNewSmiOrObjectElements) { 585 return OpParameter<PretenureFlag>(op); 586 } 587 DCHECK(op->opcode() == IrOpcode::kAllocate || 588 op->opcode() == IrOpcode::kAllocateRaw); 589 return OpParameter<AllocateParameters>(op).pretenure(); 590 } 591 592 Type AllocateTypeOf(const Operator* op) { 593 DCHECK_EQ(IrOpcode::kAllocate, op->opcode()); 594 return OpParameter<AllocateParameters>(op).type(); 595 } 596 597 UnicodeEncoding UnicodeEncodingOf(const Operator* op) { 598 DCHECK(op->opcode() == IrOpcode::kStringFromSingleCodePoint || 599 op->opcode() == IrOpcode::kStringCodePointAt); 600 return OpParameter<UnicodeEncoding>(op); 601 } 602 603 AbortReason AbortReasonOf(const Operator* op) { 604 DCHECK_EQ(IrOpcode::kRuntimeAbort, op->opcode()); 605 return static_cast<AbortReason>(OpParameter<int>(op)); 606 } 607 608 const CheckTaggedInputParameters& CheckTaggedInputParametersOf( 609 const Operator* op) { 610 DCHECK(op->opcode() == IrOpcode::kCheckedTruncateTaggedToWord32 || 611 op->opcode() == IrOpcode::kCheckedTaggedToFloat64); 612 return OpParameter<CheckTaggedInputParameters>(op); 613 } 614 615 std::ostream& operator<<(std::ostream& os, 616 const CheckTaggedInputParameters& params) { 617 os << params.mode(); 618 if (params.feedback().IsValid()) { 619 os << "; " << params.feedback(); 620 } 621 return os; 622 } 623 624 size_t hash_value(const CheckTaggedInputParameters& params) { 625 return base::hash_combine(params.mode(), params.feedback()); 626 } 627 628 bool operator==(CheckTaggedInputParameters const& lhs, 629 CheckTaggedInputParameters const& rhs) { 630 return lhs.mode() == rhs.mode() && lhs.feedback() == rhs.feedback(); 631 } 632 633 const CheckMinusZeroParameters& CheckMinusZeroParametersOf(const Operator* op) { 634 DCHECK(IrOpcode::kCheckedTaggedToInt32 == op->opcode() || 635 IrOpcode::kCheckedFloat64ToInt32 == op->opcode()); 636 return OpParameter<CheckMinusZeroParameters>(op); 637 } 638 639 std::ostream& operator<<(std::ostream& os, 640 const CheckMinusZeroParameters& params) { 641 os << params.mode(); 642 if (params.feedback().IsValid()) { 643 os << "; " << params.feedback(); 644 } 645 return os; 646 } 647 648 size_t hash_value(const CheckMinusZeroParameters& params) { 649 return base::hash_combine(params.mode(), params.feedback()); 650 } 651 652 bool operator==(CheckMinusZeroParameters const& lhs, 653 CheckMinusZeroParameters const& rhs) { 654 return lhs.mode() == rhs.mode() && lhs.feedback() == rhs.feedback(); 655 } 656 657 #define PURE_OP_LIST(V) \ 658 V(BooleanNot, Operator::kNoProperties, 1, 0) \ 659 V(NumberEqual, Operator::kCommutative, 2, 0) \ 660 V(NumberLessThan, Operator::kNoProperties, 2, 0) \ 661 V(NumberLessThanOrEqual, Operator::kNoProperties, 2, 0) \ 662 V(NumberAdd, Operator::kCommutative, 2, 0) \ 663 V(NumberSubtract, Operator::kNoProperties, 2, 0) \ 664 V(NumberMultiply, Operator::kCommutative, 2, 0) \ 665 V(NumberDivide, Operator::kNoProperties, 2, 0) \ 666 V(NumberModulus, Operator::kNoProperties, 2, 0) \ 667 V(NumberBitwiseOr, Operator::kCommutative, 2, 0) \ 668 V(NumberBitwiseXor, Operator::kCommutative, 2, 0) \ 669 V(NumberBitwiseAnd, Operator::kCommutative, 2, 0) \ 670 V(NumberShiftLeft, Operator::kNoProperties, 2, 0) \ 671 V(NumberShiftRight, Operator::kNoProperties, 2, 0) \ 672 V(NumberShiftRightLogical, Operator::kNoProperties, 2, 0) \ 673 V(NumberImul, Operator::kCommutative, 2, 0) \ 674 V(NumberAbs, Operator::kNoProperties, 1, 0) \ 675 V(NumberClz32, Operator::kNoProperties, 1, 0) \ 676 V(NumberCeil, Operator::kNoProperties, 1, 0) \ 677 V(NumberFloor, Operator::kNoProperties, 1, 0) \ 678 V(NumberFround, Operator::kNoProperties, 1, 0) \ 679 V(NumberAcos, Operator::kNoProperties, 1, 0) \ 680 V(NumberAcosh, Operator::kNoProperties, 1, 0) \ 681 V(NumberAsin, Operator::kNoProperties, 1, 0) \ 682 V(NumberAsinh, Operator::kNoProperties, 1, 0) \ 683 V(NumberAtan, Operator::kNoProperties, 1, 0) \ 684 V(NumberAtan2, Operator::kNoProperties, 2, 0) \ 685 V(NumberAtanh, Operator::kNoProperties, 1, 0) \ 686 V(NumberCbrt, Operator::kNoProperties, 1, 0) \ 687 V(NumberCos, Operator::kNoProperties, 1, 0) \ 688 V(NumberCosh, Operator::kNoProperties, 1, 0) \ 689 V(NumberExp, Operator::kNoProperties, 1, 0) \ 690 V(NumberExpm1, Operator::kNoProperties, 1, 0) \ 691 V(NumberLog, Operator::kNoProperties, 1, 0) \ 692 V(NumberLog1p, Operator::kNoProperties, 1, 0) \ 693 V(NumberLog10, Operator::kNoProperties, 1, 0) \ 694 V(NumberLog2, Operator::kNoProperties, 1, 0) \ 695 V(NumberMax, Operator::kNoProperties, 2, 0) \ 696 V(NumberMin, Operator::kNoProperties, 2, 0) \ 697 V(NumberPow, Operator::kNoProperties, 2, 0) \ 698 V(NumberRound, Operator::kNoProperties, 1, 0) \ 699 V(NumberSign, Operator::kNoProperties, 1, 0) \ 700 V(NumberSin, Operator::kNoProperties, 1, 0) \ 701 V(NumberSinh, Operator::kNoProperties, 1, 0) \ 702 V(NumberSqrt, Operator::kNoProperties, 1, 0) \ 703 V(NumberTan, Operator::kNoProperties, 1, 0) \ 704 V(NumberTanh, Operator::kNoProperties, 1, 0) \ 705 V(NumberTrunc, Operator::kNoProperties, 1, 0) \ 706 V(NumberToBoolean, Operator::kNoProperties, 1, 0) \ 707 V(NumberToInt32, Operator::kNoProperties, 1, 0) \ 708 V(NumberToString, Operator::kNoProperties, 1, 0) \ 709 V(NumberToUint32, Operator::kNoProperties, 1, 0) \ 710 V(NumberToUint8Clamped, Operator::kNoProperties, 1, 0) \ 711 V(NumberSilenceNaN, Operator::kNoProperties, 1, 0) \ 712 V(StringToNumber, Operator::kNoProperties, 1, 0) \ 713 V(StringFromSingleCharCode, Operator::kNoProperties, 1, 0) \ 714 V(StringIndexOf, Operator::kNoProperties, 3, 0) \ 715 V(StringLength, Operator::kNoProperties, 1, 0) \ 716 V(StringToLowerCaseIntl, Operator::kNoProperties, 1, 0) \ 717 V(StringToUpperCaseIntl, Operator::kNoProperties, 1, 0) \ 718 V(TypeOf, Operator::kNoProperties, 1, 1) \ 719 V(PlainPrimitiveToNumber, Operator::kNoProperties, 1, 0) \ 720 V(PlainPrimitiveToWord32, Operator::kNoProperties, 1, 0) \ 721 V(PlainPrimitiveToFloat64, Operator::kNoProperties, 1, 0) \ 722 V(ChangeTaggedSignedToInt32, Operator::kNoProperties, 1, 0) \ 723 V(ChangeTaggedToInt32, Operator::kNoProperties, 1, 0) \ 724 V(ChangeTaggedToUint32, Operator::kNoProperties, 1, 0) \ 725 V(ChangeTaggedToFloat64, Operator::kNoProperties, 1, 0) \ 726 V(ChangeTaggedToTaggedSigned, Operator::kNoProperties, 1, 0) \ 727 V(ChangeFloat64ToTaggedPointer, Operator::kNoProperties, 1, 0) \ 728 V(ChangeInt31ToTaggedSigned, Operator::kNoProperties, 1, 0) \ 729 V(ChangeInt32ToTagged, Operator::kNoProperties, 1, 0) \ 730 V(ChangeUint32ToTagged, Operator::kNoProperties, 1, 0) \ 731 V(ChangeTaggedToBit, Operator::kNoProperties, 1, 0) \ 732 V(ChangeBitToTagged, Operator::kNoProperties, 1, 0) \ 733 V(TruncateTaggedToBit, Operator::kNoProperties, 1, 0) \ 734 V(TruncateTaggedPointerToBit, Operator::kNoProperties, 1, 0) \ 735 V(TruncateTaggedToWord32, Operator::kNoProperties, 1, 0) \ 736 V(TruncateTaggedToFloat64, Operator::kNoProperties, 1, 0) \ 737 V(ObjectIsArrayBufferView, Operator::kNoProperties, 1, 0) \ 738 V(ObjectIsBigInt, Operator::kNoProperties, 1, 0) \ 739 V(ObjectIsCallable, Operator::kNoProperties, 1, 0) \ 740 V(ObjectIsConstructor, Operator::kNoProperties, 1, 0) \ 741 V(ObjectIsDetectableCallable, Operator::kNoProperties, 1, 0) \ 742 V(ObjectIsMinusZero, Operator::kNoProperties, 1, 0) \ 743 V(ObjectIsNaN, Operator::kNoProperties, 1, 0) \ 744 V(NumberIsNaN, Operator::kNoProperties, 1, 0) \ 745 V(ObjectIsNonCallable, Operator::kNoProperties, 1, 0) \ 746 V(ObjectIsNumber, Operator::kNoProperties, 1, 0) \ 747 V(ObjectIsReceiver, Operator::kNoProperties, 1, 0) \ 748 V(ObjectIsSmi, Operator::kNoProperties, 1, 0) \ 749 V(ObjectIsString, Operator::kNoProperties, 1, 0) \ 750 V(ObjectIsSymbol, Operator::kNoProperties, 1, 0) \ 751 V(ObjectIsUndetectable, Operator::kNoProperties, 1, 0) \ 752 V(NumberIsFloat64Hole, Operator::kNoProperties, 1, 0) \ 753 V(NumberIsFinite, Operator::kNoProperties, 1, 0) \ 754 V(ObjectIsFiniteNumber, Operator::kNoProperties, 1, 0) \ 755 V(NumberIsInteger, Operator::kNoProperties, 1, 0) \ 756 V(ObjectIsSafeInteger, Operator::kNoProperties, 1, 0) \ 757 V(NumberIsSafeInteger, Operator::kNoProperties, 1, 0) \ 758 V(ObjectIsInteger, Operator::kNoProperties, 1, 0) \ 759 V(ConvertTaggedHoleToUndefined, Operator::kNoProperties, 1, 0) \ 760 V(SameValue, Operator::kCommutative, 2, 0) \ 761 V(ReferenceEqual, Operator::kCommutative, 2, 0) \ 762 V(StringEqual, Operator::kCommutative, 2, 0) \ 763 V(StringLessThan, Operator::kNoProperties, 2, 0) \ 764 V(StringLessThanOrEqual, Operator::kNoProperties, 2, 0) \ 765 V(ToBoolean, Operator::kNoProperties, 1, 0) \ 766 V(NewConsString, Operator::kNoProperties, 3, 0) \ 767 V(PoisonIndex, Operator::kNoProperties, 1, 0) 768 769 #define EFFECT_DEPENDENT_OP_LIST(V) \ 770 V(StringCharCodeAt, Operator::kNoProperties, 2, 1) \ 771 V(StringSubstring, Operator::kNoProperties, 3, 1) \ 772 V(DateNow, Operator::kNoProperties, 0, 1) 773 774 #define SPECULATIVE_NUMBER_BINOP_LIST(V) \ 775 SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(V) \ 776 V(SpeculativeNumberEqual) \ 777 V(SpeculativeNumberLessThan) \ 778 V(SpeculativeNumberLessThanOrEqual) 779 780 #define CHECKED_OP_LIST(V) \ 781 V(CheckEqualsInternalizedString, 2, 0) \ 782 V(CheckEqualsSymbol, 2, 0) \ 783 V(CheckHeapObject, 1, 1) \ 784 V(CheckInternalizedString, 1, 1) \ 785 V(CheckNotTaggedHole, 1, 1) \ 786 V(CheckReceiver, 1, 1) \ 787 V(CheckSymbol, 1, 1) \ 788 V(CheckedInt32Add, 2, 1) \ 789 V(CheckedInt32Div, 2, 1) \ 790 V(CheckedInt32Mod, 2, 1) \ 791 V(CheckedInt32Sub, 2, 1) \ 792 V(CheckedUint32Div, 2, 1) \ 793 V(CheckedUint32Mod, 2, 1) 794 795 #define CHECKED_WITH_FEEDBACK_OP_LIST(V) \ 796 V(CheckBounds, 2, 1) \ 797 V(CheckNumber, 1, 1) \ 798 V(CheckSmi, 1, 1) \ 799 V(CheckString, 1, 1) \ 800 V(CheckedInt32ToTaggedSigned, 1, 1) \ 801 V(CheckedTaggedSignedToInt32, 1, 1) \ 802 V(CheckedTaggedToTaggedPointer, 1, 1) \ 803 V(CheckedTaggedToTaggedSigned, 1, 1) \ 804 V(CheckedUint32ToInt32, 1, 1) \ 805 V(CheckedUint32ToTaggedSigned, 1, 1) 806 807 struct SimplifiedOperatorGlobalCache final { 808 #define PURE(Name, properties, value_input_count, control_input_count) \ 809 struct Name##Operator final : public Operator { \ 810 Name##Operator() \ 811 : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \ 812 value_input_count, 0, control_input_count, 1, 0, 0) {} \ 813 }; \ 814 Name##Operator k##Name; 815 PURE_OP_LIST(PURE) 816 #undef PURE 817 818 #define EFFECT_DEPENDENT(Name, properties, value_input_count, \ 819 control_input_count) \ 820 struct Name##Operator final : public Operator { \ 821 Name##Operator() \ 822 : Operator(IrOpcode::k##Name, \ 823 Operator::kNoDeopt | Operator::kNoWrite | \ 824 Operator::kNoThrow | properties, \ 825 #Name, value_input_count, 1, control_input_count, 1, 1, \ 826 0) {} \ 827 }; \ 828 Name##Operator k##Name; 829 EFFECT_DEPENDENT_OP_LIST(EFFECT_DEPENDENT) 830 #undef EFFECT_DEPENDENT 831 832 #define CHECKED(Name, value_input_count, value_output_count) \ 833 struct Name##Operator final : public Operator { \ 834 Name##Operator() \ 835 : Operator(IrOpcode::k##Name, \ 836 Operator::kFoldable | Operator::kNoThrow, #Name, \ 837 value_input_count, 1, 1, value_output_count, 1, 0) {} \ 838 }; \ 839 Name##Operator k##Name; 840 CHECKED_OP_LIST(CHECKED) 841 #undef CHECKED 842 843 #define CHECKED_WITH_FEEDBACK(Name, value_input_count, value_output_count) \ 844 struct Name##Operator final : public Operator1<CheckParameters> { \ 845 Name##Operator() \ 846 : Operator1<CheckParameters>( \ 847 IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, \ 848 #Name, value_input_count, 1, 1, value_output_count, 1, 0, \ 849 CheckParameters(VectorSlotPair())) {} \ 850 }; \ 851 Name##Operator k##Name; 852 CHECKED_WITH_FEEDBACK_OP_LIST(CHECKED_WITH_FEEDBACK) 853 #undef CHECKED_WITH_FEEDBACK 854 855 template <DeoptimizeReason kDeoptimizeReason> 856 struct CheckIfOperator final : public Operator1<CheckIfParameters> { 857 CheckIfOperator() 858 : Operator1<CheckIfParameters>( 859 IrOpcode::kCheckIf, Operator::kFoldable | Operator::kNoThrow, 860 "CheckIf", 1, 1, 1, 0, 1, 0, 861 CheckIfParameters(kDeoptimizeReason, VectorSlotPair())) {} 862 }; 863 #define CHECK_IF(Name, message) \ 864 CheckIfOperator<DeoptimizeReason::k##Name> kCheckIf##Name; 865 DEOPTIMIZE_REASON_LIST(CHECK_IF) 866 #undef CHECK_IF 867 868 template <UnicodeEncoding kEncoding> 869 struct StringCodePointAtOperator final : public Operator1<UnicodeEncoding> { 870 StringCodePointAtOperator() 871 : Operator1<UnicodeEncoding>(IrOpcode::kStringCodePointAt, 872 Operator::kFoldable | Operator::kNoThrow, 873 "StringCodePointAt", 2, 1, 1, 1, 1, 0, 874 kEncoding) {} 875 }; 876 StringCodePointAtOperator<UnicodeEncoding::UTF16> 877 kStringCodePointAtOperatorUTF16; 878 StringCodePointAtOperator<UnicodeEncoding::UTF32> 879 kStringCodePointAtOperatorUTF32; 880 881 template <UnicodeEncoding kEncoding> 882 struct StringFromSingleCodePointOperator final 883 : public Operator1<UnicodeEncoding> { 884 StringFromSingleCodePointOperator() 885 : Operator1<UnicodeEncoding>( 886 IrOpcode::kStringFromSingleCodePoint, Operator::kPure, 887 "StringFromSingleCodePoint", 1, 0, 0, 1, 0, 0, kEncoding) {} 888 }; 889 StringFromSingleCodePointOperator<UnicodeEncoding::UTF16> 890 kStringFromSingleCodePointOperatorUTF16; 891 StringFromSingleCodePointOperator<UnicodeEncoding::UTF32> 892 kStringFromSingleCodePointOperatorUTF32; 893 894 struct ArrayBufferWasNeuteredOperator final : public Operator { 895 ArrayBufferWasNeuteredOperator() 896 : Operator(IrOpcode::kArrayBufferWasNeutered, Operator::kEliminatable, 897 "ArrayBufferWasNeutered", 1, 1, 1, 1, 1, 0) {} 898 }; 899 ArrayBufferWasNeuteredOperator kArrayBufferWasNeutered; 900 901 struct FindOrderedHashMapEntryOperator final : public Operator { 902 FindOrderedHashMapEntryOperator() 903 : Operator(IrOpcode::kFindOrderedHashMapEntry, Operator::kEliminatable, 904 "FindOrderedHashMapEntry", 2, 1, 1, 1, 1, 0) {} 905 }; 906 FindOrderedHashMapEntryOperator kFindOrderedHashMapEntry; 907 908 struct FindOrderedHashMapEntryForInt32KeyOperator final : public Operator { 909 FindOrderedHashMapEntryForInt32KeyOperator() 910 : Operator(IrOpcode::kFindOrderedHashMapEntryForInt32Key, 911 Operator::kEliminatable, 912 "FindOrderedHashMapEntryForInt32Key", 2, 1, 1, 1, 1, 0) {} 913 }; 914 FindOrderedHashMapEntryForInt32KeyOperator 915 kFindOrderedHashMapEntryForInt32Key; 916 917 struct ArgumentsFrameOperator final : public Operator { 918 ArgumentsFrameOperator() 919 : Operator(IrOpcode::kArgumentsFrame, Operator::kPure, "ArgumentsFrame", 920 0, 0, 0, 1, 0, 0) {} 921 }; 922 ArgumentsFrameOperator kArgumentsFrame; 923 924 template <CheckForMinusZeroMode kMode> 925 struct ChangeFloat64ToTaggedOperator final 926 : public Operator1<CheckForMinusZeroMode> { 927 ChangeFloat64ToTaggedOperator() 928 : Operator1<CheckForMinusZeroMode>( 929 IrOpcode::kChangeFloat64ToTagged, Operator::kPure, 930 "ChangeFloat64ToTagged", 1, 0, 0, 1, 0, 0, kMode) {} 931 }; 932 ChangeFloat64ToTaggedOperator<CheckForMinusZeroMode::kCheckForMinusZero> 933 kChangeFloat64ToTaggedCheckForMinusZeroOperator; 934 ChangeFloat64ToTaggedOperator<CheckForMinusZeroMode::kDontCheckForMinusZero> 935 kChangeFloat64ToTaggedDontCheckForMinusZeroOperator; 936 937 template <CheckForMinusZeroMode kMode> 938 struct CheckedInt32MulOperator final 939 : public Operator1<CheckForMinusZeroMode> { 940 CheckedInt32MulOperator() 941 : Operator1<CheckForMinusZeroMode>( 942 IrOpcode::kCheckedInt32Mul, 943 Operator::kFoldable | Operator::kNoThrow, "CheckedInt32Mul", 2, 1, 944 1, 1, 1, 0, kMode) {} 945 }; 946 CheckedInt32MulOperator<CheckForMinusZeroMode::kCheckForMinusZero> 947 kCheckedInt32MulCheckForMinusZeroOperator; 948 CheckedInt32MulOperator<CheckForMinusZeroMode::kDontCheckForMinusZero> 949 kCheckedInt32MulDontCheckForMinusZeroOperator; 950 951 template <CheckForMinusZeroMode kMode> 952 struct CheckedFloat64ToInt32Operator final 953 : public Operator1<CheckMinusZeroParameters> { 954 CheckedFloat64ToInt32Operator() 955 : Operator1<CheckMinusZeroParameters>( 956 IrOpcode::kCheckedFloat64ToInt32, 957 Operator::kFoldable | Operator::kNoThrow, "CheckedFloat64ToInt32", 958 1, 1, 1, 1, 1, 0, 959 CheckMinusZeroParameters(kMode, VectorSlotPair())) {} 960 }; 961 CheckedFloat64ToInt32Operator<CheckForMinusZeroMode::kCheckForMinusZero> 962 kCheckedFloat64ToInt32CheckForMinusZeroOperator; 963 CheckedFloat64ToInt32Operator<CheckForMinusZeroMode::kDontCheckForMinusZero> 964 kCheckedFloat64ToInt32DontCheckForMinusZeroOperator; 965 966 template <CheckForMinusZeroMode kMode> 967 struct CheckedTaggedToInt32Operator final 968 : public Operator1<CheckMinusZeroParameters> { 969 CheckedTaggedToInt32Operator() 970 : Operator1<CheckMinusZeroParameters>( 971 IrOpcode::kCheckedTaggedToInt32, 972 Operator::kFoldable | Operator::kNoThrow, "CheckedTaggedToInt32", 973 1, 1, 1, 1, 1, 0, 974 CheckMinusZeroParameters(kMode, VectorSlotPair())) {} 975 }; 976 CheckedTaggedToInt32Operator<CheckForMinusZeroMode::kCheckForMinusZero> 977 kCheckedTaggedToInt32CheckForMinusZeroOperator; 978 CheckedTaggedToInt32Operator<CheckForMinusZeroMode::kDontCheckForMinusZero> 979 kCheckedTaggedToInt32DontCheckForMinusZeroOperator; 980 981 template <CheckTaggedInputMode kMode> 982 struct CheckedTaggedToFloat64Operator final 983 : public Operator1<CheckTaggedInputParameters> { 984 CheckedTaggedToFloat64Operator() 985 : Operator1<CheckTaggedInputParameters>( 986 IrOpcode::kCheckedTaggedToFloat64, 987 Operator::kFoldable | Operator::kNoThrow, 988 "CheckedTaggedToFloat64", 1, 1, 1, 1, 1, 0, 989 CheckTaggedInputParameters(kMode, VectorSlotPair())) {} 990 }; 991 CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumber> 992 kCheckedTaggedToFloat64NumberOperator; 993 CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumberOrOddball> 994 kCheckedTaggedToFloat64NumberOrOddballOperator; 995 996 template <CheckTaggedInputMode kMode> 997 struct CheckedTruncateTaggedToWord32Operator final 998 : public Operator1<CheckTaggedInputParameters> { 999 CheckedTruncateTaggedToWord32Operator() 1000 : Operator1<CheckTaggedInputParameters>( 1001 IrOpcode::kCheckedTruncateTaggedToWord32, 1002 Operator::kFoldable | Operator::kNoThrow, 1003 "CheckedTruncateTaggedToWord32", 1, 1, 1, 1, 1, 0, 1004 CheckTaggedInputParameters(kMode, VectorSlotPair())) {} 1005 }; 1006 CheckedTruncateTaggedToWord32Operator<CheckTaggedInputMode::kNumber> 1007 kCheckedTruncateTaggedToWord32NumberOperator; 1008 CheckedTruncateTaggedToWord32Operator<CheckTaggedInputMode::kNumberOrOddball> 1009 kCheckedTruncateTaggedToWord32NumberOrOddballOperator; 1010 1011 template <ConvertReceiverMode kMode> 1012 struct ConvertReceiverOperator final : public Operator1<ConvertReceiverMode> { 1013 ConvertReceiverOperator() 1014 : Operator1<ConvertReceiverMode>( // -- 1015 IrOpcode::kConvertReceiver, // opcode 1016 Operator::kEliminatable, // flags 1017 "ConvertReceiver", // name 1018 2, 1, 1, 1, 1, 0, // counts 1019 kMode) {} // param 1020 }; 1021 ConvertReceiverOperator<ConvertReceiverMode::kAny> 1022 kConvertReceiverAnyOperator; 1023 ConvertReceiverOperator<ConvertReceiverMode::kNullOrUndefined> 1024 kConvertReceiverNullOrUndefinedOperator; 1025 ConvertReceiverOperator<ConvertReceiverMode::kNotNullOrUndefined> 1026 kConvertReceiverNotNullOrUndefinedOperator; 1027 1028 template <CheckFloat64HoleMode kMode> 1029 struct CheckFloat64HoleNaNOperator final 1030 : public Operator1<CheckFloat64HoleParameters> { 1031 CheckFloat64HoleNaNOperator() 1032 : Operator1<CheckFloat64HoleParameters>( 1033 IrOpcode::kCheckFloat64Hole, 1034 Operator::kFoldable | Operator::kNoThrow, "CheckFloat64Hole", 1, 1035 1, 1, 1, 1, 0, 1036 CheckFloat64HoleParameters(kMode, VectorSlotPair())) {} 1037 }; 1038 CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kAllowReturnHole> 1039 kCheckFloat64HoleAllowReturnHoleOperator; 1040 CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kNeverReturnHole> 1041 kCheckFloat64HoleNeverReturnHoleOperator; 1042 1043 struct EnsureWritableFastElementsOperator final : public Operator { 1044 EnsureWritableFastElementsOperator() 1045 : Operator( // -- 1046 IrOpcode::kEnsureWritableFastElements, // opcode 1047 Operator::kNoDeopt | Operator::kNoThrow, // flags 1048 "EnsureWritableFastElements", // name 1049 2, 1, 1, 1, 1, 0) {} // counts 1050 }; 1051 EnsureWritableFastElementsOperator kEnsureWritableFastElements; 1052 1053 template <GrowFastElementsMode kMode> 1054 struct GrowFastElementsOperator final 1055 : public Operator1<GrowFastElementsParameters> { 1056 GrowFastElementsOperator() 1057 : Operator1(IrOpcode::kMaybeGrowFastElements, Operator::kNoThrow, 1058 "MaybeGrowFastElements", 4, 1, 1, 1, 1, 0, 1059 GrowFastElementsParameters(kMode, VectorSlotPair())) {} 1060 }; 1061 1062 GrowFastElementsOperator<GrowFastElementsMode::kDoubleElements> 1063 kGrowFastElementsOperatorDoubleElements; 1064 GrowFastElementsOperator<GrowFastElementsMode::kSmiOrObjectElements> 1065 kGrowFastElementsOperatorSmiOrObjectElements; 1066 1067 struct LoadFieldByIndexOperator final : public Operator { 1068 LoadFieldByIndexOperator() 1069 : Operator( // -- 1070 IrOpcode::kLoadFieldByIndex, // opcode 1071 Operator::kEliminatable, // flags, 1072 "LoadFieldByIndex", // name 1073 2, 1, 1, 1, 1, 0) {} // counts; 1074 }; 1075 LoadFieldByIndexOperator kLoadFieldByIndex; 1076 1077 #define SPECULATIVE_NUMBER_BINOP(Name) \ 1078 template <NumberOperationHint kHint> \ 1079 struct Name##Operator final : public Operator1<NumberOperationHint> { \ 1080 Name##Operator() \ 1081 : Operator1<NumberOperationHint>( \ 1082 IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, \ 1083 #Name, 2, 1, 1, 1, 1, 0, kHint) {} \ 1084 }; \ 1085 Name##Operator<NumberOperationHint::kSignedSmall> \ 1086 k##Name##SignedSmallOperator; \ 1087 Name##Operator<NumberOperationHint::kSignedSmallInputs> \ 1088 k##Name##SignedSmallInputsOperator; \ 1089 Name##Operator<NumberOperationHint::kSigned32> k##Name##Signed32Operator; \ 1090 Name##Operator<NumberOperationHint::kNumber> k##Name##NumberOperator; \ 1091 Name##Operator<NumberOperationHint::kNumberOrOddball> \ 1092 k##Name##NumberOrOddballOperator; 1093 SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP) 1094 #undef SPECULATIVE_NUMBER_BINOP 1095 1096 template <NumberOperationHint kHint> 1097 struct SpeculativeToNumberOperator final 1098 : public Operator1<NumberOperationParameters> { 1099 SpeculativeToNumberOperator() 1100 : Operator1<NumberOperationParameters>( 1101 IrOpcode::kSpeculativeToNumber, 1102 Operator::kFoldable | Operator::kNoThrow, "SpeculativeToNumber", 1103 1, 1, 1, 1, 1, 0, 1104 NumberOperationParameters(kHint, VectorSlotPair())) {} 1105 }; 1106 SpeculativeToNumberOperator<NumberOperationHint::kSignedSmall> 1107 kSpeculativeToNumberSignedSmallOperator; 1108 SpeculativeToNumberOperator<NumberOperationHint::kSigned32> 1109 kSpeculativeToNumberSigned32Operator; 1110 SpeculativeToNumberOperator<NumberOperationHint::kNumber> 1111 kSpeculativeToNumberNumberOperator; 1112 SpeculativeToNumberOperator<NumberOperationHint::kNumberOrOddball> 1113 kSpeculativeToNumberNumberOrOddballOperator; 1114 }; 1115 1116 static base::LazyInstance<SimplifiedOperatorGlobalCache>::type 1117 kSimplifiedOperatorGlobalCache = LAZY_INSTANCE_INITIALIZER; 1118 1119 SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone) 1120 : cache_(kSimplifiedOperatorGlobalCache.Get()), zone_(zone) {} 1121 1122 #define GET_FROM_CACHE(Name, ...) \ 1123 const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; } 1124 PURE_OP_LIST(GET_FROM_CACHE) 1125 EFFECT_DEPENDENT_OP_LIST(GET_FROM_CACHE) 1126 CHECKED_OP_LIST(GET_FROM_CACHE) 1127 GET_FROM_CACHE(ArrayBufferWasNeutered) 1128 GET_FROM_CACHE(ArgumentsFrame) 1129 GET_FROM_CACHE(FindOrderedHashMapEntry) 1130 GET_FROM_CACHE(FindOrderedHashMapEntryForInt32Key) 1131 GET_FROM_CACHE(LoadFieldByIndex) 1132 #undef GET_FROM_CACHE 1133 1134 #define GET_FROM_CACHE_WITH_FEEDBACK(Name, value_input_count, \ 1135 value_output_count) \ 1136 const Operator* SimplifiedOperatorBuilder::Name( \ 1137 const VectorSlotPair& feedback) { \ 1138 if (!feedback.IsValid()) { \ 1139 return &cache_.k##Name; \ 1140 } \ 1141 return new (zone()) Operator1<CheckParameters>( \ 1142 IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, #Name, \ 1143 value_input_count, 1, 1, value_output_count, 1, 0, \ 1144 CheckParameters(feedback)); \ 1145 } 1146 CHECKED_WITH_FEEDBACK_OP_LIST(GET_FROM_CACHE_WITH_FEEDBACK) 1147 #undef GET_FROM_CACHE_WITH_FEEDBACK 1148 1149 bool IsCheckedWithFeedback(const Operator* op) { 1150 #define CASE(Name, ...) case IrOpcode::k##Name: 1151 switch (op->opcode()) { 1152 CHECKED_WITH_FEEDBACK_OP_LIST(CASE) return true; 1153 default: 1154 return false; 1155 } 1156 #undef CASE 1157 } 1158 1159 const Operator* SimplifiedOperatorBuilder::RuntimeAbort(AbortReason reason) { 1160 return new (zone()) Operator1<int>( // -- 1161 IrOpcode::kRuntimeAbort, // opcode 1162 Operator::kNoThrow | Operator::kNoDeopt, // flags 1163 "RuntimeAbort", // name 1164 0, 1, 1, 0, 1, 0, // counts 1165 static_cast<int>(reason)); // parameter 1166 } 1167 1168 const Operator* SimplifiedOperatorBuilder::CheckIf( 1169 DeoptimizeReason reason, const VectorSlotPair& feedback) { 1170 if (!feedback.IsValid()) { 1171 switch (reason) { 1172 #define CHECK_IF(Name, message) \ 1173 case DeoptimizeReason::k##Name: \ 1174 return &cache_.kCheckIf##Name; 1175 DEOPTIMIZE_REASON_LIST(CHECK_IF) 1176 #undef CHECK_IF 1177 } 1178 } 1179 return new (zone()) Operator1<CheckIfParameters>( 1180 IrOpcode::kCheckIf, Operator::kFoldable | Operator::kNoThrow, "CheckIf", 1181 1, 1, 1, 0, 1, 0, CheckIfParameters(reason, feedback)); 1182 } 1183 1184 const Operator* SimplifiedOperatorBuilder::ChangeFloat64ToTagged( 1185 CheckForMinusZeroMode mode) { 1186 switch (mode) { 1187 case CheckForMinusZeroMode::kCheckForMinusZero: 1188 return &cache_.kChangeFloat64ToTaggedCheckForMinusZeroOperator; 1189 case CheckForMinusZeroMode::kDontCheckForMinusZero: 1190 return &cache_.kChangeFloat64ToTaggedDontCheckForMinusZeroOperator; 1191 } 1192 UNREACHABLE(); 1193 } 1194 1195 const Operator* SimplifiedOperatorBuilder::CheckedInt32Mul( 1196 CheckForMinusZeroMode mode) { 1197 switch (mode) { 1198 case CheckForMinusZeroMode::kCheckForMinusZero: 1199 return &cache_.kCheckedInt32MulCheckForMinusZeroOperator; 1200 case CheckForMinusZeroMode::kDontCheckForMinusZero: 1201 return &cache_.kCheckedInt32MulDontCheckForMinusZeroOperator; 1202 } 1203 UNREACHABLE(); 1204 } 1205 1206 const Operator* SimplifiedOperatorBuilder::CheckedFloat64ToInt32( 1207 CheckForMinusZeroMode mode, const VectorSlotPair& feedback) { 1208 if (!feedback.IsValid()) { 1209 switch (mode) { 1210 case CheckForMinusZeroMode::kCheckForMinusZero: 1211 return &cache_.kCheckedFloat64ToInt32CheckForMinusZeroOperator; 1212 case CheckForMinusZeroMode::kDontCheckForMinusZero: 1213 return &cache_.kCheckedFloat64ToInt32DontCheckForMinusZeroOperator; 1214 } 1215 } 1216 return new (zone()) Operator1<CheckMinusZeroParameters>( 1217 IrOpcode::kCheckedFloat64ToInt32, 1218 Operator::kFoldable | Operator::kNoThrow, "CheckedFloat64ToInt32", 1, 1, 1219 1, 1, 1, 0, CheckMinusZeroParameters(mode, feedback)); 1220 } 1221 1222 const Operator* SimplifiedOperatorBuilder::CheckedTaggedToInt32( 1223 CheckForMinusZeroMode mode, const VectorSlotPair& feedback) { 1224 if (!feedback.IsValid()) { 1225 switch (mode) { 1226 case CheckForMinusZeroMode::kCheckForMinusZero: 1227 return &cache_.kCheckedTaggedToInt32CheckForMinusZeroOperator; 1228 case CheckForMinusZeroMode::kDontCheckForMinusZero: 1229 return &cache_.kCheckedTaggedToInt32DontCheckForMinusZeroOperator; 1230 } 1231 } 1232 return new (zone()) Operator1<CheckMinusZeroParameters>( 1233 IrOpcode::kCheckedTaggedToInt32, Operator::kFoldable | Operator::kNoThrow, 1234 "CheckedTaggedToInt32", 1, 1, 1, 1, 1, 0, 1235 CheckMinusZeroParameters(mode, feedback)); 1236 } 1237 1238 const Operator* SimplifiedOperatorBuilder::CheckedTaggedToFloat64( 1239 CheckTaggedInputMode mode, const VectorSlotPair& feedback) { 1240 if (!feedback.IsValid()) { 1241 switch (mode) { 1242 case CheckTaggedInputMode::kNumber: 1243 return &cache_.kCheckedTaggedToFloat64NumberOperator; 1244 case CheckTaggedInputMode::kNumberOrOddball: 1245 return &cache_.kCheckedTaggedToFloat64NumberOrOddballOperator; 1246 } 1247 } 1248 return new (zone()) Operator1<CheckTaggedInputParameters>( 1249 IrOpcode::kCheckedTaggedToFloat64, 1250 Operator::kFoldable | Operator::kNoThrow, "CheckedTaggedToFloat64", 1, 1, 1251 1, 1, 1, 0, CheckTaggedInputParameters(mode, feedback)); 1252 } 1253 1254 const Operator* SimplifiedOperatorBuilder::CheckedTruncateTaggedToWord32( 1255 CheckTaggedInputMode mode, const VectorSlotPair& feedback) { 1256 if (!feedback.IsValid()) { 1257 switch (mode) { 1258 case CheckTaggedInputMode::kNumber: 1259 return &cache_.kCheckedTruncateTaggedToWord32NumberOperator; 1260 case CheckTaggedInputMode::kNumberOrOddball: 1261 return &cache_.kCheckedTruncateTaggedToWord32NumberOrOddballOperator; 1262 } 1263 } 1264 return new (zone()) Operator1<CheckTaggedInputParameters>( 1265 IrOpcode::kCheckedTruncateTaggedToWord32, 1266 Operator::kFoldable | Operator::kNoThrow, "CheckedTruncateTaggedToWord32", 1267 1, 1, 1, 1, 1, 0, CheckTaggedInputParameters(mode, feedback)); 1268 } 1269 1270 const Operator* SimplifiedOperatorBuilder::CheckMaps( 1271 CheckMapsFlags flags, ZoneHandleSet<Map> maps, 1272 const VectorSlotPair& feedback) { 1273 CheckMapsParameters const parameters(flags, maps, feedback); 1274 return new (zone()) Operator1<CheckMapsParameters>( // -- 1275 IrOpcode::kCheckMaps, // opcode 1276 Operator::kNoThrow | Operator::kNoWrite, // flags 1277 "CheckMaps", // name 1278 1, 1, 1, 0, 1, 0, // counts 1279 parameters); // parameter 1280 } 1281 1282 const Operator* SimplifiedOperatorBuilder::MapGuard(ZoneHandleSet<Map> maps) { 1283 return new (zone()) Operator1<MapsParameterInfo>( // -- 1284 IrOpcode::kMapGuard, Operator::kEliminatable, // opcode 1285 "MapGuard", // name 1286 1, 1, 1, 0, 1, 0, // counts 1287 MapsParameterInfo(maps)); // parameter 1288 } 1289 1290 const Operator* SimplifiedOperatorBuilder::CompareMaps( 1291 ZoneHandleSet<Map> maps) { 1292 return new (zone()) Operator1<MapsParameterInfo>( // -- 1293 IrOpcode::kCompareMaps, // opcode 1294 Operator::kEliminatable, // flags 1295 "CompareMaps", // name 1296 1, 1, 1, 1, 1, 0, // counts 1297 MapsParameterInfo(maps)); // parameter 1298 } 1299 1300 const Operator* SimplifiedOperatorBuilder::ConvertReceiver( 1301 ConvertReceiverMode mode) { 1302 switch (mode) { 1303 case ConvertReceiverMode::kAny: 1304 return &cache_.kConvertReceiverAnyOperator; 1305 case ConvertReceiverMode::kNullOrUndefined: 1306 return &cache_.kConvertReceiverNullOrUndefinedOperator; 1307 case ConvertReceiverMode::kNotNullOrUndefined: 1308 return &cache_.kConvertReceiverNotNullOrUndefinedOperator; 1309 } 1310 UNREACHABLE(); 1311 return nullptr; 1312 } 1313 1314 const Operator* SimplifiedOperatorBuilder::CheckFloat64Hole( 1315 CheckFloat64HoleMode mode, VectorSlotPair const& feedback) { 1316 if (!feedback.IsValid()) { 1317 switch (mode) { 1318 case CheckFloat64HoleMode::kAllowReturnHole: 1319 return &cache_.kCheckFloat64HoleAllowReturnHoleOperator; 1320 case CheckFloat64HoleMode::kNeverReturnHole: 1321 return &cache_.kCheckFloat64HoleNeverReturnHoleOperator; 1322 } 1323 UNREACHABLE(); 1324 } 1325 return new (zone()) Operator1<CheckFloat64HoleParameters>( 1326 IrOpcode::kCheckFloat64Hole, Operator::kFoldable | Operator::kNoThrow, 1327 "CheckFloat64Hole", 1, 1, 1, 1, 1, 0, 1328 CheckFloat64HoleParameters(mode, feedback)); 1329 } 1330 1331 const Operator* SimplifiedOperatorBuilder::SpeculativeToNumber( 1332 NumberOperationHint hint, const VectorSlotPair& feedback) { 1333 if (!feedback.IsValid()) { 1334 switch (hint) { 1335 case NumberOperationHint::kSignedSmall: 1336 return &cache_.kSpeculativeToNumberSignedSmallOperator; 1337 case NumberOperationHint::kSignedSmallInputs: 1338 break; 1339 case NumberOperationHint::kSigned32: 1340 return &cache_.kSpeculativeToNumberSigned32Operator; 1341 case NumberOperationHint::kNumber: 1342 return &cache_.kSpeculativeToNumberNumberOperator; 1343 case NumberOperationHint::kNumberOrOddball: 1344 return &cache_.kSpeculativeToNumberNumberOrOddballOperator; 1345 } 1346 } 1347 return new (zone()) Operator1<NumberOperationParameters>( 1348 IrOpcode::kSpeculativeToNumber, Operator::kFoldable | Operator::kNoThrow, 1349 "SpeculativeToNumber", 1, 1, 1, 1, 1, 0, 1350 NumberOperationParameters(hint, feedback)); 1351 } 1352 1353 const Operator* SimplifiedOperatorBuilder::EnsureWritableFastElements() { 1354 return &cache_.kEnsureWritableFastElements; 1355 } 1356 1357 const Operator* SimplifiedOperatorBuilder::MaybeGrowFastElements( 1358 GrowFastElementsMode mode, const VectorSlotPair& feedback) { 1359 if (!feedback.IsValid()) { 1360 switch (mode) { 1361 case GrowFastElementsMode::kDoubleElements: 1362 return &cache_.kGrowFastElementsOperatorDoubleElements; 1363 case GrowFastElementsMode::kSmiOrObjectElements: 1364 return &cache_.kGrowFastElementsOperatorSmiOrObjectElements; 1365 } 1366 } 1367 return new (zone()) Operator1<GrowFastElementsParameters>( // -- 1368 IrOpcode::kMaybeGrowFastElements, // opcode 1369 Operator::kNoThrow, // flags 1370 "MaybeGrowFastElements", // name 1371 4, 1, 1, 1, 1, 0, // counts 1372 GrowFastElementsParameters(mode, feedback)); // parameter 1373 } 1374 1375 const Operator* SimplifiedOperatorBuilder::TransitionElementsKind( 1376 ElementsTransition transition) { 1377 return new (zone()) Operator1<ElementsTransition>( // -- 1378 IrOpcode::kTransitionElementsKind, // opcode 1379 Operator::kNoDeopt | Operator::kNoThrow, // flags 1380 "TransitionElementsKind", // name 1381 1, 1, 1, 0, 1, 0, // counts 1382 transition); // parameter 1383 } 1384 1385 namespace { 1386 1387 struct ArgumentsLengthParameters { 1388 int formal_parameter_count; 1389 bool is_rest_length; 1390 }; 1391 1392 bool operator==(ArgumentsLengthParameters first, 1393 ArgumentsLengthParameters second) { 1394 return first.formal_parameter_count == second.formal_parameter_count && 1395 first.is_rest_length == second.is_rest_length; 1396 } 1397 1398 size_t hash_value(ArgumentsLengthParameters param) { 1399 return base::hash_combine(param.formal_parameter_count, param.is_rest_length); 1400 } 1401 1402 std::ostream& operator<<(std::ostream& os, ArgumentsLengthParameters param) { 1403 return os << param.formal_parameter_count << ", " 1404 << (param.is_rest_length ? "rest length" : "not rest length"); 1405 } 1406 1407 } // namespace 1408 1409 const Operator* SimplifiedOperatorBuilder::ArgumentsLength( 1410 int formal_parameter_count, bool is_rest_length) { 1411 return new (zone()) Operator1<ArgumentsLengthParameters>( // -- 1412 IrOpcode::kArgumentsLength, // opcode 1413 Operator::kPure, // flags 1414 "ArgumentsLength", // name 1415 1, 0, 0, 1, 0, 0, // counts 1416 ArgumentsLengthParameters{formal_parameter_count, 1417 is_rest_length}); // parameter 1418 } 1419 1420 int FormalParameterCountOf(const Operator* op) { 1421 DCHECK_EQ(IrOpcode::kArgumentsLength, op->opcode()); 1422 return OpParameter<ArgumentsLengthParameters>(op).formal_parameter_count; 1423 } 1424 1425 bool IsRestLengthOf(const Operator* op) { 1426 DCHECK_EQ(IrOpcode::kArgumentsLength, op->opcode()); 1427 return OpParameter<ArgumentsLengthParameters>(op).is_rest_length; 1428 } 1429 1430 bool operator==(CheckParameters const& lhs, CheckParameters const& rhs) { 1431 return lhs.feedback() == rhs.feedback(); 1432 } 1433 1434 size_t hash_value(CheckParameters const& p) { return hash_value(p.feedback()); } 1435 1436 std::ostream& operator<<(std::ostream& os, CheckParameters const& p) { 1437 return os << p.feedback(); 1438 } 1439 1440 CheckParameters const& CheckParametersOf(Operator const* op) { 1441 #define MAKE_OR(name, arg2, arg3) op->opcode() == IrOpcode::k##name || 1442 CHECK((CHECKED_WITH_FEEDBACK_OP_LIST(MAKE_OR) false)); 1443 #undef MAKE_OR 1444 return OpParameter<CheckParameters>(op); 1445 } 1446 1447 bool operator==(CheckIfParameters const& lhs, CheckIfParameters const& rhs) { 1448 return lhs.reason() == rhs.reason() && lhs.feedback() == rhs.feedback(); 1449 } 1450 1451 size_t hash_value(CheckIfParameters const& p) { 1452 return base::hash_combine(p.reason(), p.feedback()); 1453 } 1454 1455 std::ostream& operator<<(std::ostream& os, CheckIfParameters const& p) { 1456 return os << p.reason() << p.feedback(); 1457 } 1458 1459 CheckIfParameters const& CheckIfParametersOf(Operator const* op) { 1460 CHECK(op->opcode() == IrOpcode::kCheckIf); 1461 return OpParameter<CheckIfParameters>(op); 1462 } 1463 1464 const Operator* SimplifiedOperatorBuilder::NewDoubleElements( 1465 PretenureFlag pretenure) { 1466 return new (zone()) Operator1<PretenureFlag>( // -- 1467 IrOpcode::kNewDoubleElements, // opcode 1468 Operator::kEliminatable, // flags 1469 "NewDoubleElements", // name 1470 1, 1, 1, 1, 1, 0, // counts 1471 pretenure); // parameter 1472 } 1473 1474 const Operator* SimplifiedOperatorBuilder::NewSmiOrObjectElements( 1475 PretenureFlag pretenure) { 1476 return new (zone()) Operator1<PretenureFlag>( // -- 1477 IrOpcode::kNewSmiOrObjectElements, // opcode 1478 Operator::kEliminatable, // flags 1479 "NewSmiOrObjectElements", // name 1480 1, 1, 1, 1, 1, 0, // counts 1481 pretenure); // parameter 1482 } 1483 1484 const Operator* SimplifiedOperatorBuilder::NewArgumentsElements( 1485 int mapped_count) { 1486 return new (zone()) Operator1<int>( // -- 1487 IrOpcode::kNewArgumentsElements, // opcode 1488 Operator::kEliminatable, // flags 1489 "NewArgumentsElements", // name 1490 2, 1, 0, 1, 1, 0, // counts 1491 mapped_count); // parameter 1492 } 1493 1494 int NewArgumentsElementsMappedCountOf(const Operator* op) { 1495 DCHECK_EQ(IrOpcode::kNewArgumentsElements, op->opcode()); 1496 return OpParameter<int>(op); 1497 } 1498 1499 const Operator* SimplifiedOperatorBuilder::Allocate(Type type, 1500 PretenureFlag pretenure) { 1501 return new (zone()) Operator1<AllocateParameters>( 1502 IrOpcode::kAllocate, 1503 Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite, "Allocate", 1504 1, 1, 1, 1, 1, 0, AllocateParameters(type, pretenure)); 1505 } 1506 1507 const Operator* SimplifiedOperatorBuilder::AllocateRaw( 1508 Type type, PretenureFlag pretenure) { 1509 return new (zone()) Operator1<AllocateParameters>( 1510 IrOpcode::kAllocateRaw, 1511 Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite, 1512 "AllocateRaw", 1, 1, 1, 1, 1, 1, AllocateParameters(type, pretenure)); 1513 } 1514 1515 const Operator* SimplifiedOperatorBuilder::StringCodePointAt( 1516 UnicodeEncoding encoding) { 1517 switch (encoding) { 1518 case UnicodeEncoding::UTF16: 1519 return &cache_.kStringCodePointAtOperatorUTF16; 1520 case UnicodeEncoding::UTF32: 1521 return &cache_.kStringCodePointAtOperatorUTF32; 1522 } 1523 UNREACHABLE(); 1524 } 1525 1526 const Operator* SimplifiedOperatorBuilder::StringFromSingleCodePoint( 1527 UnicodeEncoding encoding) { 1528 switch (encoding) { 1529 case UnicodeEncoding::UTF16: 1530 return &cache_.kStringFromSingleCodePointOperatorUTF16; 1531 case UnicodeEncoding::UTF32: 1532 return &cache_.kStringFromSingleCodePointOperatorUTF32; 1533 } 1534 UNREACHABLE(); 1535 } 1536 1537 #define SPECULATIVE_NUMBER_BINOP(Name) \ 1538 const Operator* SimplifiedOperatorBuilder::Name(NumberOperationHint hint) { \ 1539 switch (hint) { \ 1540 case NumberOperationHint::kSignedSmall: \ 1541 return &cache_.k##Name##SignedSmallOperator; \ 1542 case NumberOperationHint::kSignedSmallInputs: \ 1543 return &cache_.k##Name##SignedSmallInputsOperator; \ 1544 case NumberOperationHint::kSigned32: \ 1545 return &cache_.k##Name##Signed32Operator; \ 1546 case NumberOperationHint::kNumber: \ 1547 return &cache_.k##Name##NumberOperator; \ 1548 case NumberOperationHint::kNumberOrOddball: \ 1549 return &cache_.k##Name##NumberOrOddballOperator; \ 1550 } \ 1551 UNREACHABLE(); \ 1552 return nullptr; \ 1553 } 1554 SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP) 1555 #undef SPECULATIVE_NUMBER_BINOP 1556 1557 #define ACCESS_OP_LIST(V) \ 1558 V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1) \ 1559 V(StoreField, FieldAccess, Operator::kNoRead, 2, 1, 0) \ 1560 V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1) \ 1561 V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0) \ 1562 V(LoadTypedElement, ExternalArrayType, Operator::kNoWrite, 4, 1, 1) \ 1563 V(StoreTypedElement, ExternalArrayType, Operator::kNoRead, 5, 1, 0) \ 1564 V(LoadDataViewElement, ExternalArrayType, Operator::kNoWrite, 4, 1, 1) \ 1565 V(StoreDataViewElement, ExternalArrayType, Operator::kNoRead, 5, 1, 0) 1566 1567 #define ACCESS(Name, Type, properties, value_input_count, control_input_count, \ 1568 output_count) \ 1569 const Operator* SimplifiedOperatorBuilder::Name(const Type& access) { \ 1570 return new (zone()) \ 1571 Operator1<Type>(IrOpcode::k##Name, \ 1572 Operator::kNoDeopt | Operator::kNoThrow | properties, \ 1573 #Name, value_input_count, 1, control_input_count, \ 1574 output_count, 1, 0, access); \ 1575 } 1576 ACCESS_OP_LIST(ACCESS) 1577 #undef ACCESS 1578 1579 const Operator* SimplifiedOperatorBuilder::TransitionAndStoreElement( 1580 Handle<Map> double_map, Handle<Map> fast_map) { 1581 TransitionAndStoreElementParameters parameters(double_map, fast_map); 1582 return new (zone()) Operator1<TransitionAndStoreElementParameters>( 1583 IrOpcode::kTransitionAndStoreElement, 1584 Operator::kNoDeopt | Operator::kNoThrow, "TransitionAndStoreElement", 3, 1585 1, 1, 0, 1, 0, parameters); 1586 } 1587 1588 const Operator* SimplifiedOperatorBuilder::StoreSignedSmallElement() { 1589 return new (zone()) Operator(IrOpcode::kStoreSignedSmallElement, 1590 Operator::kNoDeopt | Operator::kNoThrow, 1591 "StoreSignedSmallElement", 3, 1, 1, 0, 1, 0); 1592 } 1593 1594 const Operator* SimplifiedOperatorBuilder::TransitionAndStoreNumberElement( 1595 Handle<Map> double_map) { 1596 TransitionAndStoreNumberElementParameters parameters(double_map); 1597 return new (zone()) Operator1<TransitionAndStoreNumberElementParameters>( 1598 IrOpcode::kTransitionAndStoreNumberElement, 1599 Operator::kNoDeopt | Operator::kNoThrow, 1600 "TransitionAndStoreNumberElement", 3, 1, 1, 0, 1, 0, parameters); 1601 } 1602 1603 const Operator* SimplifiedOperatorBuilder::TransitionAndStoreNonNumberElement( 1604 Handle<Map> fast_map, Type value_type) { 1605 TransitionAndStoreNonNumberElementParameters parameters(fast_map, value_type); 1606 return new (zone()) Operator1<TransitionAndStoreNonNumberElementParameters>( 1607 IrOpcode::kTransitionAndStoreNonNumberElement, 1608 Operator::kNoDeopt | Operator::kNoThrow, 1609 "TransitionAndStoreNonNumberElement", 3, 1, 1, 0, 1, 0, parameters); 1610 } 1611 1612 #undef PURE_OP_LIST 1613 #undef EFFECT_DEPENDENT_OP_LIST 1614 #undef SPECULATIVE_NUMBER_BINOP_LIST 1615 #undef CHECKED_WITH_FEEDBACK_OP_LIST 1616 #undef CHECKED_OP_LIST 1617 #undef ACCESS_OP_LIST 1618 1619 } // namespace compiler 1620 } // namespace internal 1621 } // namespace v8 1622