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 12namespace v8 { 13namespace internal { 14namespace compiler { 15 16size_t hash_value(BaseTaggedness base_taggedness) { 17 return static_cast<uint8_t>(base_taggedness); 18} 19 20std::ostream& operator<<(std::ostream& os, BaseTaggedness base_taggedness) { 21 switch (base_taggedness) { 22 case kUntaggedBase: 23 return os << "untagged base"; 24 case kTaggedBase: 25 return os << "tagged base"; 26 } 27 UNREACHABLE(); 28 return os; 29} 30 31 32MachineType BufferAccess::machine_type() const { 33 switch (external_array_type_) { 34 case kExternalUint8Array: 35 case kExternalUint8ClampedArray: 36 return MachineType::Uint8(); 37 case kExternalInt8Array: 38 return MachineType::Int8(); 39 case kExternalUint16Array: 40 return MachineType::Uint16(); 41 case kExternalInt16Array: 42 return MachineType::Int16(); 43 case kExternalUint32Array: 44 return MachineType::Uint32(); 45 case kExternalInt32Array: 46 return MachineType::Int32(); 47 case kExternalFloat32Array: 48 return MachineType::Float32(); 49 case kExternalFloat64Array: 50 return MachineType::Float64(); 51 } 52 UNREACHABLE(); 53 return MachineType::None(); 54} 55 56 57bool operator==(BufferAccess lhs, BufferAccess rhs) { 58 return lhs.external_array_type() == rhs.external_array_type(); 59} 60 61 62bool operator!=(BufferAccess lhs, BufferAccess rhs) { return !(lhs == rhs); } 63 64 65size_t hash_value(BufferAccess access) { 66 return base::hash<ExternalArrayType>()(access.external_array_type()); 67} 68 69 70std::ostream& operator<<(std::ostream& os, BufferAccess access) { 71 switch (access.external_array_type()) { 72#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ 73 case kExternal##Type##Array: \ 74 return os << #Type; 75 TYPED_ARRAYS(TYPED_ARRAY_CASE) 76#undef TYPED_ARRAY_CASE 77 } 78 UNREACHABLE(); 79 return os; 80} 81 82 83BufferAccess const BufferAccessOf(const Operator* op) { 84 DCHECK(op->opcode() == IrOpcode::kLoadBuffer || 85 op->opcode() == IrOpcode::kStoreBuffer); 86 return OpParameter<BufferAccess>(op); 87} 88 89 90bool operator==(FieldAccess const& lhs, FieldAccess const& rhs) { 91 // On purpose we don't include the write barrier kind here, as this method is 92 // really only relevant for eliminating loads and they don't care about the 93 // write barrier mode. 94 return lhs.base_is_tagged == rhs.base_is_tagged && lhs.offset == rhs.offset && 95 lhs.map.address() == rhs.map.address() && 96 lhs.machine_type == rhs.machine_type; 97} 98 99 100bool operator!=(FieldAccess const& lhs, FieldAccess const& rhs) { 101 return !(lhs == rhs); 102} 103 104 105size_t hash_value(FieldAccess const& access) { 106 // On purpose we don't include the write barrier kind here, as this method is 107 // really only relevant for eliminating loads and they don't care about the 108 // write barrier mode. 109 return base::hash_combine(access.base_is_tagged, access.offset, 110 access.machine_type); 111} 112 113 114std::ostream& operator<<(std::ostream& os, FieldAccess const& access) { 115 os << "[" << access.base_is_tagged << ", " << access.offset << ", "; 116#ifdef OBJECT_PRINT 117 Handle<Name> name; 118 if (access.name.ToHandle(&name)) { 119 name->Print(os); 120 os << ", "; 121 } 122 Handle<Map> map; 123 if (access.map.ToHandle(&map)) { 124 os << Brief(*map) << ", "; 125 } 126#endif 127 access.type->PrintTo(os); 128 os << ", " << access.machine_type << ", " << access.write_barrier_kind << "]"; 129 return os; 130} 131 132template <> 133void Operator1<FieldAccess>::PrintParameter(std::ostream& os, 134 PrintVerbosity verbose) const { 135 if (verbose == PrintVerbosity::kVerbose) { 136 os << parameter(); 137 } else { 138 os << "[+" << parameter().offset << "]"; 139 } 140} 141 142bool operator==(ElementAccess const& lhs, ElementAccess const& rhs) { 143 // On purpose we don't include the write barrier kind here, as this method is 144 // really only relevant for eliminating loads and they don't care about the 145 // write barrier mode. 146 return lhs.base_is_tagged == rhs.base_is_tagged && 147 lhs.header_size == rhs.header_size && 148 lhs.machine_type == rhs.machine_type; 149} 150 151 152bool operator!=(ElementAccess const& lhs, ElementAccess const& rhs) { 153 return !(lhs == rhs); 154} 155 156 157size_t hash_value(ElementAccess const& access) { 158 // On purpose we don't include the write barrier kind here, as this method is 159 // really only relevant for eliminating loads and they don't care about the 160 // write barrier mode. 161 return base::hash_combine(access.base_is_tagged, access.header_size, 162 access.machine_type); 163} 164 165 166std::ostream& operator<<(std::ostream& os, ElementAccess const& access) { 167 os << access.base_is_tagged << ", " << access.header_size << ", "; 168 access.type->PrintTo(os); 169 os << ", " << access.machine_type << ", " << access.write_barrier_kind; 170 return os; 171} 172 173 174const FieldAccess& FieldAccessOf(const Operator* op) { 175 DCHECK_NOT_NULL(op); 176 DCHECK(op->opcode() == IrOpcode::kLoadField || 177 op->opcode() == IrOpcode::kStoreField); 178 return OpParameter<FieldAccess>(op); 179} 180 181 182const ElementAccess& ElementAccessOf(const Operator* op) { 183 DCHECK_NOT_NULL(op); 184 DCHECK(op->opcode() == IrOpcode::kLoadElement || 185 op->opcode() == IrOpcode::kStoreElement); 186 return OpParameter<ElementAccess>(op); 187} 188 189ExternalArrayType ExternalArrayTypeOf(const Operator* op) { 190 DCHECK(op->opcode() == IrOpcode::kLoadTypedElement || 191 op->opcode() == IrOpcode::kStoreTypedElement); 192 return OpParameter<ExternalArrayType>(op); 193} 194 195size_t hash_value(CheckFloat64HoleMode mode) { 196 return static_cast<size_t>(mode); 197} 198 199std::ostream& operator<<(std::ostream& os, CheckFloat64HoleMode mode) { 200 switch (mode) { 201 case CheckFloat64HoleMode::kAllowReturnHole: 202 return os << "allow-return-hole"; 203 case CheckFloat64HoleMode::kNeverReturnHole: 204 return os << "never-return-hole"; 205 } 206 UNREACHABLE(); 207 return os; 208} 209 210CheckFloat64HoleMode CheckFloat64HoleModeOf(const Operator* op) { 211 DCHECK_EQ(IrOpcode::kCheckFloat64Hole, op->opcode()); 212 return OpParameter<CheckFloat64HoleMode>(op); 213} 214 215CheckForMinusZeroMode CheckMinusZeroModeOf(const Operator* op) { 216 DCHECK(op->opcode() == IrOpcode::kCheckedInt32Mul || 217 op->opcode() == IrOpcode::kCheckedFloat64ToInt32 || 218 op->opcode() == IrOpcode::kCheckedTaggedToInt32); 219 return OpParameter<CheckForMinusZeroMode>(op); 220} 221 222size_t hash_value(CheckForMinusZeroMode mode) { 223 return static_cast<size_t>(mode); 224} 225 226std::ostream& operator<<(std::ostream& os, CheckForMinusZeroMode mode) { 227 switch (mode) { 228 case CheckForMinusZeroMode::kCheckForMinusZero: 229 return os << "check-for-minus-zero"; 230 case CheckForMinusZeroMode::kDontCheckForMinusZero: 231 return os << "dont-check-for-minus-zero"; 232 } 233 UNREACHABLE(); 234 return os; 235} 236 237std::ostream& operator<<(std::ostream& os, CheckMapsFlags flags) { 238 bool empty = true; 239 if (flags & CheckMapsFlag::kTryMigrateInstance) { 240 os << "TryMigrateInstance"; 241 empty = false; 242 } 243 if (empty) os << "None"; 244 return os; 245} 246 247bool operator==(CheckMapsParameters const& lhs, 248 CheckMapsParameters const& rhs) { 249 return lhs.flags() == rhs.flags() && lhs.maps() == rhs.maps(); 250} 251 252bool operator!=(CheckMapsParameters const& lhs, 253 CheckMapsParameters const& rhs) { 254 return !(lhs == rhs); 255} 256 257size_t hash_value(CheckMapsParameters const& p) { 258 return base::hash_combine(p.flags(), p.maps()); 259} 260 261std::ostream& operator<<(std::ostream& os, CheckMapsParameters const& p) { 262 ZoneHandleSet<Map> const& maps = p.maps(); 263 os << p.flags(); 264 for (size_t i = 0; i < maps.size(); ++i) { 265 os << ", " << Brief(*maps[i]); 266 } 267 return os; 268} 269 270CheckMapsParameters const& CheckMapsParametersOf(Operator const* op) { 271 DCHECK_EQ(IrOpcode::kCheckMaps, op->opcode()); 272 return OpParameter<CheckMapsParameters>(op); 273} 274 275size_t hash_value(CheckTaggedInputMode mode) { 276 return static_cast<size_t>(mode); 277} 278 279std::ostream& operator<<(std::ostream& os, CheckTaggedInputMode mode) { 280 switch (mode) { 281 case CheckTaggedInputMode::kNumber: 282 return os << "Number"; 283 case CheckTaggedInputMode::kNumberOrOddball: 284 return os << "NumberOrOddball"; 285 } 286 UNREACHABLE(); 287 return os; 288} 289 290CheckTaggedInputMode CheckTaggedInputModeOf(const Operator* op) { 291 DCHECK_EQ(IrOpcode::kCheckedTaggedToFloat64, op->opcode()); 292 return OpParameter<CheckTaggedInputMode>(op); 293} 294 295std::ostream& operator<<(std::ostream& os, GrowFastElementsFlags flags) { 296 bool empty = true; 297 if (flags & GrowFastElementsFlag::kArrayObject) { 298 os << "ArrayObject"; 299 empty = false; 300 } 301 if (flags & GrowFastElementsFlag::kDoubleElements) { 302 if (!empty) os << "|"; 303 os << "DoubleElements"; 304 empty = false; 305 } 306 if (flags & GrowFastElementsFlag::kHoleyElements) { 307 if (!empty) os << "|"; 308 os << "HoleyElements"; 309 empty = false; 310 } 311 if (empty) os << "None"; 312 return os; 313} 314 315GrowFastElementsFlags GrowFastElementsFlagsOf(const Operator* op) { 316 DCHECK_EQ(IrOpcode::kMaybeGrowFastElements, op->opcode()); 317 return OpParameter<GrowFastElementsFlags>(op); 318} 319 320bool operator==(ElementsTransition const& lhs, ElementsTransition const& rhs) { 321 return lhs.mode() == rhs.mode() && 322 lhs.source().address() == rhs.source().address() && 323 lhs.target().address() == rhs.target().address(); 324} 325 326bool operator!=(ElementsTransition const& lhs, ElementsTransition const& rhs) { 327 return !(lhs == rhs); 328} 329 330size_t hash_value(ElementsTransition transition) { 331 return base::hash_combine(static_cast<uint8_t>(transition.mode()), 332 transition.source().address(), 333 transition.target().address()); 334} 335 336std::ostream& operator<<(std::ostream& os, ElementsTransition transition) { 337 switch (transition.mode()) { 338 case ElementsTransition::kFastTransition: 339 return os << "fast-transition from " << Brief(*transition.source()) 340 << " to " << Brief(*transition.target()); 341 case ElementsTransition::kSlowTransition: 342 return os << "slow-transition from " << Brief(*transition.source()) 343 << " to " << Brief(*transition.target()); 344 } 345 UNREACHABLE(); 346 return os; 347} 348 349ElementsTransition const& ElementsTransitionOf(const Operator* op) { 350 DCHECK_EQ(IrOpcode::kTransitionElementsKind, op->opcode()); 351 return OpParameter<ElementsTransition>(op); 352} 353 354std::ostream& operator<<(std::ostream& os, NumberOperationHint hint) { 355 switch (hint) { 356 case NumberOperationHint::kSignedSmall: 357 return os << "SignedSmall"; 358 case NumberOperationHint::kSigned32: 359 return os << "Signed32"; 360 case NumberOperationHint::kNumber: 361 return os << "Number"; 362 case NumberOperationHint::kNumberOrOddball: 363 return os << "NumberOrOddball"; 364 } 365 UNREACHABLE(); 366 return os; 367} 368 369size_t hash_value(NumberOperationHint hint) { 370 return static_cast<uint8_t>(hint); 371} 372 373NumberOperationHint NumberOperationHintOf(const Operator* op) { 374 DCHECK(op->opcode() == IrOpcode::kSpeculativeNumberAdd || 375 op->opcode() == IrOpcode::kSpeculativeNumberSubtract || 376 op->opcode() == IrOpcode::kSpeculativeNumberMultiply || 377 op->opcode() == IrOpcode::kSpeculativeNumberDivide || 378 op->opcode() == IrOpcode::kSpeculativeNumberModulus || 379 op->opcode() == IrOpcode::kSpeculativeNumberShiftLeft || 380 op->opcode() == IrOpcode::kSpeculativeNumberShiftRight || 381 op->opcode() == IrOpcode::kSpeculativeNumberShiftRightLogical || 382 op->opcode() == IrOpcode::kSpeculativeNumberBitwiseAnd || 383 op->opcode() == IrOpcode::kSpeculativeNumberBitwiseOr || 384 op->opcode() == IrOpcode::kSpeculativeNumberBitwiseXor || 385 op->opcode() == IrOpcode::kSpeculativeNumberEqual || 386 op->opcode() == IrOpcode::kSpeculativeNumberLessThan || 387 op->opcode() == IrOpcode::kSpeculativeNumberLessThanOrEqual); 388 return OpParameter<NumberOperationHint>(op); 389} 390 391int ParameterCountOf(const Operator* op) { 392 DCHECK(op->opcode() == IrOpcode::kNewUnmappedArgumentsElements || 393 op->opcode() == IrOpcode::kNewRestParameterElements); 394 return OpParameter<int>(op); 395} 396 397PretenureFlag PretenureFlagOf(const Operator* op) { 398 DCHECK_EQ(IrOpcode::kAllocate, op->opcode()); 399 return OpParameter<PretenureFlag>(op); 400} 401 402UnicodeEncoding UnicodeEncodingOf(const Operator* op) { 403 DCHECK(op->opcode() == IrOpcode::kStringFromCodePoint); 404 return OpParameter<UnicodeEncoding>(op); 405} 406 407#define PURE_OP_LIST(V) \ 408 V(BooleanNot, Operator::kNoProperties, 1, 0) \ 409 V(NumberEqual, Operator::kCommutative, 2, 0) \ 410 V(NumberLessThan, Operator::kNoProperties, 2, 0) \ 411 V(NumberLessThanOrEqual, Operator::kNoProperties, 2, 0) \ 412 V(NumberAdd, Operator::kCommutative, 2, 0) \ 413 V(NumberSubtract, Operator::kNoProperties, 2, 0) \ 414 V(NumberMultiply, Operator::kCommutative, 2, 0) \ 415 V(NumberDivide, Operator::kNoProperties, 2, 0) \ 416 V(NumberModulus, Operator::kNoProperties, 2, 0) \ 417 V(NumberBitwiseOr, Operator::kCommutative, 2, 0) \ 418 V(NumberBitwiseXor, Operator::kCommutative, 2, 0) \ 419 V(NumberBitwiseAnd, Operator::kCommutative, 2, 0) \ 420 V(NumberShiftLeft, Operator::kNoProperties, 2, 0) \ 421 V(NumberShiftRight, Operator::kNoProperties, 2, 0) \ 422 V(NumberShiftRightLogical, Operator::kNoProperties, 2, 0) \ 423 V(NumberImul, Operator::kCommutative, 2, 0) \ 424 V(NumberAbs, Operator::kNoProperties, 1, 0) \ 425 V(NumberClz32, Operator::kNoProperties, 1, 0) \ 426 V(NumberCeil, Operator::kNoProperties, 1, 0) \ 427 V(NumberFloor, Operator::kNoProperties, 1, 0) \ 428 V(NumberFround, Operator::kNoProperties, 1, 0) \ 429 V(NumberAcos, Operator::kNoProperties, 1, 0) \ 430 V(NumberAcosh, Operator::kNoProperties, 1, 0) \ 431 V(NumberAsin, Operator::kNoProperties, 1, 0) \ 432 V(NumberAsinh, Operator::kNoProperties, 1, 0) \ 433 V(NumberAtan, Operator::kNoProperties, 1, 0) \ 434 V(NumberAtan2, Operator::kNoProperties, 2, 0) \ 435 V(NumberAtanh, Operator::kNoProperties, 1, 0) \ 436 V(NumberCbrt, Operator::kNoProperties, 1, 0) \ 437 V(NumberCos, Operator::kNoProperties, 1, 0) \ 438 V(NumberCosh, Operator::kNoProperties, 1, 0) \ 439 V(NumberExp, Operator::kNoProperties, 1, 0) \ 440 V(NumberExpm1, Operator::kNoProperties, 1, 0) \ 441 V(NumberLog, Operator::kNoProperties, 1, 0) \ 442 V(NumberLog1p, Operator::kNoProperties, 1, 0) \ 443 V(NumberLog10, Operator::kNoProperties, 1, 0) \ 444 V(NumberLog2, Operator::kNoProperties, 1, 0) \ 445 V(NumberMax, Operator::kNoProperties, 2, 0) \ 446 V(NumberMin, Operator::kNoProperties, 2, 0) \ 447 V(NumberPow, Operator::kNoProperties, 2, 0) \ 448 V(NumberRound, Operator::kNoProperties, 1, 0) \ 449 V(NumberSign, Operator::kNoProperties, 1, 0) \ 450 V(NumberSin, Operator::kNoProperties, 1, 0) \ 451 V(NumberSinh, Operator::kNoProperties, 1, 0) \ 452 V(NumberSqrt, Operator::kNoProperties, 1, 0) \ 453 V(NumberTan, Operator::kNoProperties, 1, 0) \ 454 V(NumberTanh, Operator::kNoProperties, 1, 0) \ 455 V(NumberTrunc, Operator::kNoProperties, 1, 0) \ 456 V(NumberToBoolean, Operator::kNoProperties, 1, 0) \ 457 V(NumberToInt32, Operator::kNoProperties, 1, 0) \ 458 V(NumberToUint32, Operator::kNoProperties, 1, 0) \ 459 V(NumberToUint8Clamped, Operator::kNoProperties, 1, 0) \ 460 V(NumberSilenceNaN, Operator::kNoProperties, 1, 0) \ 461 V(StringCharAt, Operator::kNoProperties, 2, 1) \ 462 V(StringCharCodeAt, Operator::kNoProperties, 2, 1) \ 463 V(StringFromCharCode, Operator::kNoProperties, 1, 0) \ 464 V(StringIndexOf, Operator::kNoProperties, 3, 0) \ 465 V(PlainPrimitiveToNumber, Operator::kNoProperties, 1, 0) \ 466 V(PlainPrimitiveToWord32, Operator::kNoProperties, 1, 0) \ 467 V(PlainPrimitiveToFloat64, Operator::kNoProperties, 1, 0) \ 468 V(ChangeTaggedSignedToInt32, Operator::kNoProperties, 1, 0) \ 469 V(ChangeTaggedToInt32, Operator::kNoProperties, 1, 0) \ 470 V(ChangeTaggedToUint32, Operator::kNoProperties, 1, 0) \ 471 V(ChangeTaggedToFloat64, Operator::kNoProperties, 1, 0) \ 472 V(ChangeTaggedToTaggedSigned, Operator::kNoProperties, 1, 0) \ 473 V(ChangeFloat64ToTagged, Operator::kNoProperties, 1, 0) \ 474 V(ChangeFloat64ToTaggedPointer, Operator::kNoProperties, 1, 0) \ 475 V(ChangeInt31ToTaggedSigned, Operator::kNoProperties, 1, 0) \ 476 V(ChangeInt32ToTagged, Operator::kNoProperties, 1, 0) \ 477 V(ChangeUint32ToTagged, Operator::kNoProperties, 1, 0) \ 478 V(ChangeTaggedToBit, Operator::kNoProperties, 1, 0) \ 479 V(ChangeBitToTagged, Operator::kNoProperties, 1, 0) \ 480 V(TruncateTaggedToBit, Operator::kNoProperties, 1, 0) \ 481 V(TruncateTaggedToWord32, Operator::kNoProperties, 1, 0) \ 482 V(TruncateTaggedToFloat64, Operator::kNoProperties, 1, 0) \ 483 V(ObjectIsDetectableCallable, Operator::kNoProperties, 1, 0) \ 484 V(ObjectIsNonCallable, Operator::kNoProperties, 1, 0) \ 485 V(ObjectIsNumber, Operator::kNoProperties, 1, 0) \ 486 V(ObjectIsReceiver, Operator::kNoProperties, 1, 0) \ 487 V(ObjectIsSmi, Operator::kNoProperties, 1, 0) \ 488 V(ObjectIsString, Operator::kNoProperties, 1, 0) \ 489 V(ObjectIsUndetectable, Operator::kNoProperties, 1, 0) \ 490 V(ConvertTaggedHoleToUndefined, Operator::kNoProperties, 1, 0) \ 491 V(ReferenceEqual, Operator::kCommutative, 2, 0) \ 492 V(StringEqual, Operator::kCommutative, 2, 0) \ 493 V(StringLessThan, Operator::kNoProperties, 2, 0) \ 494 V(StringLessThanOrEqual, Operator::kNoProperties, 2, 0) 495 496#define SPECULATIVE_NUMBER_BINOP_LIST(V) \ 497 SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(V) \ 498 V(SpeculativeNumberEqual) \ 499 V(SpeculativeNumberLessThan) \ 500 V(SpeculativeNumberLessThanOrEqual) 501 502#define CHECKED_OP_LIST(V) \ 503 V(CheckBounds, 2, 1) \ 504 V(CheckHeapObject, 1, 1) \ 505 V(CheckIf, 1, 0) \ 506 V(CheckInternalizedString, 1, 1) \ 507 V(CheckNumber, 1, 1) \ 508 V(CheckReceiver, 1, 1) \ 509 V(CheckSmi, 1, 1) \ 510 V(CheckString, 1, 1) \ 511 V(CheckTaggedHole, 1, 1) \ 512 V(CheckedInt32Add, 2, 1) \ 513 V(CheckedInt32Sub, 2, 1) \ 514 V(CheckedInt32Div, 2, 1) \ 515 V(CheckedInt32Mod, 2, 1) \ 516 V(CheckedUint32Div, 2, 1) \ 517 V(CheckedUint32Mod, 2, 1) \ 518 V(CheckedUint32ToInt32, 1, 1) \ 519 V(CheckedUint32ToTaggedSigned, 1, 1) \ 520 V(CheckedInt32ToTaggedSigned, 1, 1) \ 521 V(CheckedTaggedSignedToInt32, 1, 1) \ 522 V(CheckedTaggedToTaggedSigned, 1, 1) \ 523 V(CheckedTaggedToTaggedPointer, 1, 1) \ 524 V(CheckedTruncateTaggedToWord32, 1, 1) 525 526struct SimplifiedOperatorGlobalCache final { 527#define PURE(Name, properties, value_input_count, control_input_count) \ 528 struct Name##Operator final : public Operator { \ 529 Name##Operator() \ 530 : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \ 531 value_input_count, 0, control_input_count, 1, 0, 0) {} \ 532 }; \ 533 Name##Operator k##Name; 534 PURE_OP_LIST(PURE) 535#undef PURE 536 537#define CHECKED(Name, value_input_count, value_output_count) \ 538 struct Name##Operator final : public Operator { \ 539 Name##Operator() \ 540 : Operator(IrOpcode::k##Name, \ 541 Operator::kFoldable | Operator::kNoThrow, #Name, \ 542 value_input_count, 1, 1, value_output_count, 1, 0) {} \ 543 }; \ 544 Name##Operator k##Name; 545 CHECKED_OP_LIST(CHECKED) 546#undef CHECKED 547 548 template <UnicodeEncoding kEncoding> 549 struct StringFromCodePointOperator final : public Operator1<UnicodeEncoding> { 550 StringFromCodePointOperator() 551 : Operator1<UnicodeEncoding>(IrOpcode::kStringFromCodePoint, 552 Operator::kPure, "StringFromCodePoint", 1, 553 0, 0, 1, 0, 0, kEncoding) {} 554 }; 555 StringFromCodePointOperator<UnicodeEncoding::UTF16> 556 kStringFromCodePointOperatorUTF16; 557 StringFromCodePointOperator<UnicodeEncoding::UTF32> 558 kStringFromCodePointOperatorUTF32; 559 560 struct ArrayBufferWasNeuteredOperator final : public Operator { 561 ArrayBufferWasNeuteredOperator() 562 : Operator(IrOpcode::kArrayBufferWasNeutered, Operator::kEliminatable, 563 "ArrayBufferWasNeutered", 1, 1, 1, 1, 1, 0) {} 564 }; 565 ArrayBufferWasNeuteredOperator kArrayBufferWasNeutered; 566 567 template <CheckForMinusZeroMode kMode> 568 struct CheckedInt32MulOperator final 569 : public Operator1<CheckForMinusZeroMode> { 570 CheckedInt32MulOperator() 571 : Operator1<CheckForMinusZeroMode>( 572 IrOpcode::kCheckedInt32Mul, 573 Operator::kFoldable | Operator::kNoThrow, "CheckedInt32Mul", 2, 1, 574 1, 1, 1, 0, kMode) {} 575 }; 576 CheckedInt32MulOperator<CheckForMinusZeroMode::kCheckForMinusZero> 577 kCheckedInt32MulCheckForMinusZeroOperator; 578 CheckedInt32MulOperator<CheckForMinusZeroMode::kDontCheckForMinusZero> 579 kCheckedInt32MulDontCheckForMinusZeroOperator; 580 581 template <CheckForMinusZeroMode kMode> 582 struct CheckedFloat64ToInt32Operator final 583 : public Operator1<CheckForMinusZeroMode> { 584 CheckedFloat64ToInt32Operator() 585 : Operator1<CheckForMinusZeroMode>( 586 IrOpcode::kCheckedFloat64ToInt32, 587 Operator::kFoldable | Operator::kNoThrow, "CheckedFloat64ToInt32", 588 1, 1, 1, 1, 1, 0, kMode) {} 589 }; 590 CheckedFloat64ToInt32Operator<CheckForMinusZeroMode::kCheckForMinusZero> 591 kCheckedFloat64ToInt32CheckForMinusZeroOperator; 592 CheckedFloat64ToInt32Operator<CheckForMinusZeroMode::kDontCheckForMinusZero> 593 kCheckedFloat64ToInt32DontCheckForMinusZeroOperator; 594 595 template <CheckForMinusZeroMode kMode> 596 struct CheckedTaggedToInt32Operator final 597 : public Operator1<CheckForMinusZeroMode> { 598 CheckedTaggedToInt32Operator() 599 : Operator1<CheckForMinusZeroMode>( 600 IrOpcode::kCheckedTaggedToInt32, 601 Operator::kFoldable | Operator::kNoThrow, "CheckedTaggedToInt32", 602 1, 1, 1, 1, 1, 0, kMode) {} 603 }; 604 CheckedTaggedToInt32Operator<CheckForMinusZeroMode::kCheckForMinusZero> 605 kCheckedTaggedToInt32CheckForMinusZeroOperator; 606 CheckedTaggedToInt32Operator<CheckForMinusZeroMode::kDontCheckForMinusZero> 607 kCheckedTaggedToInt32DontCheckForMinusZeroOperator; 608 609 template <CheckTaggedInputMode kMode> 610 struct CheckedTaggedToFloat64Operator final 611 : public Operator1<CheckTaggedInputMode> { 612 CheckedTaggedToFloat64Operator() 613 : Operator1<CheckTaggedInputMode>( 614 IrOpcode::kCheckedTaggedToFloat64, 615 Operator::kFoldable | Operator::kNoThrow, 616 "CheckedTaggedToFloat64", 1, 1, 1, 1, 1, 0, kMode) {} 617 }; 618 CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumber> 619 kCheckedTaggedToFloat64NumberOperator; 620 CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumberOrOddball> 621 kCheckedTaggedToFloat64NumberOrOddballOperator; 622 623 template <CheckFloat64HoleMode kMode> 624 struct CheckFloat64HoleNaNOperator final 625 : public Operator1<CheckFloat64HoleMode> { 626 CheckFloat64HoleNaNOperator() 627 : Operator1<CheckFloat64HoleMode>( 628 IrOpcode::kCheckFloat64Hole, 629 Operator::kFoldable | Operator::kNoThrow, "CheckFloat64Hole", 1, 630 1, 1, 1, 1, 0, kMode) {} 631 }; 632 CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kAllowReturnHole> 633 kCheckFloat64HoleAllowReturnHoleOperator; 634 CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kNeverReturnHole> 635 kCheckFloat64HoleNeverReturnHoleOperator; 636 637 template <PretenureFlag kPretenure> 638 struct AllocateOperator final : public Operator1<PretenureFlag> { 639 AllocateOperator() 640 : Operator1<PretenureFlag>( 641 IrOpcode::kAllocate, 642 Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite, 643 "Allocate", 1, 1, 1, 1, 1, 0, kPretenure) {} 644 }; 645 AllocateOperator<NOT_TENURED> kAllocateNotTenuredOperator; 646 AllocateOperator<TENURED> kAllocateTenuredOperator; 647 648 struct EnsureWritableFastElementsOperator final : public Operator { 649 EnsureWritableFastElementsOperator() 650 : Operator( // -- 651 IrOpcode::kEnsureWritableFastElements, // opcode 652 Operator::kNoDeopt | Operator::kNoThrow, // flags 653 "EnsureWritableFastElements", // name 654 2, 1, 1, 1, 1, 0) {} // counts 655 }; 656 EnsureWritableFastElementsOperator kEnsureWritableFastElements; 657 658#define SPECULATIVE_NUMBER_BINOP(Name) \ 659 template <NumberOperationHint kHint> \ 660 struct Name##Operator final : public Operator1<NumberOperationHint> { \ 661 Name##Operator() \ 662 : Operator1<NumberOperationHint>( \ 663 IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, \ 664 #Name, 2, 1, 1, 1, 1, 0, kHint) {} \ 665 }; \ 666 Name##Operator<NumberOperationHint::kSignedSmall> \ 667 k##Name##SignedSmallOperator; \ 668 Name##Operator<NumberOperationHint::kSigned32> k##Name##Signed32Operator; \ 669 Name##Operator<NumberOperationHint::kNumber> k##Name##NumberOperator; \ 670 Name##Operator<NumberOperationHint::kNumberOrOddball> \ 671 k##Name##NumberOrOddballOperator; 672 SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP) 673#undef SPECULATIVE_NUMBER_BINOP 674 675#define BUFFER_ACCESS(Type, type, TYPE, ctype, size) \ 676 struct LoadBuffer##Type##Operator final : public Operator1<BufferAccess> { \ 677 LoadBuffer##Type##Operator() \ 678 : Operator1<BufferAccess>( \ 679 IrOpcode::kLoadBuffer, \ 680 Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite, \ 681 "LoadBuffer", 3, 1, 1, 1, 1, 0, \ 682 BufferAccess(kExternal##Type##Array)) {} \ 683 }; \ 684 struct StoreBuffer##Type##Operator final : public Operator1<BufferAccess> { \ 685 StoreBuffer##Type##Operator() \ 686 : Operator1<BufferAccess>( \ 687 IrOpcode::kStoreBuffer, \ 688 Operator::kNoDeopt | Operator::kNoRead | Operator::kNoThrow, \ 689 "StoreBuffer", 4, 1, 1, 0, 1, 0, \ 690 BufferAccess(kExternal##Type##Array)) {} \ 691 }; \ 692 LoadBuffer##Type##Operator kLoadBuffer##Type; \ 693 StoreBuffer##Type##Operator kStoreBuffer##Type; 694 TYPED_ARRAYS(BUFFER_ACCESS) 695#undef BUFFER_ACCESS 696}; 697 698 699static base::LazyInstance<SimplifiedOperatorGlobalCache>::type kCache = 700 LAZY_INSTANCE_INITIALIZER; 701 702 703SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone) 704 : cache_(kCache.Get()), zone_(zone) {} 705 706#define GET_FROM_CACHE(Name, ...) \ 707 const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; } 708PURE_OP_LIST(GET_FROM_CACHE) 709CHECKED_OP_LIST(GET_FROM_CACHE) 710GET_FROM_CACHE(ArrayBufferWasNeutered) 711#undef GET_FROM_CACHE 712 713const Operator* SimplifiedOperatorBuilder::CheckedInt32Mul( 714 CheckForMinusZeroMode mode) { 715 switch (mode) { 716 case CheckForMinusZeroMode::kCheckForMinusZero: 717 return &cache_.kCheckedInt32MulCheckForMinusZeroOperator; 718 case CheckForMinusZeroMode::kDontCheckForMinusZero: 719 return &cache_.kCheckedInt32MulDontCheckForMinusZeroOperator; 720 } 721 UNREACHABLE(); 722 return nullptr; 723} 724 725const Operator* SimplifiedOperatorBuilder::CheckedFloat64ToInt32( 726 CheckForMinusZeroMode mode) { 727 switch (mode) { 728 case CheckForMinusZeroMode::kCheckForMinusZero: 729 return &cache_.kCheckedFloat64ToInt32CheckForMinusZeroOperator; 730 case CheckForMinusZeroMode::kDontCheckForMinusZero: 731 return &cache_.kCheckedFloat64ToInt32DontCheckForMinusZeroOperator; 732 } 733 UNREACHABLE(); 734 return nullptr; 735} 736 737const Operator* SimplifiedOperatorBuilder::CheckedTaggedToInt32( 738 CheckForMinusZeroMode mode) { 739 switch (mode) { 740 case CheckForMinusZeroMode::kCheckForMinusZero: 741 return &cache_.kCheckedTaggedToInt32CheckForMinusZeroOperator; 742 case CheckForMinusZeroMode::kDontCheckForMinusZero: 743 return &cache_.kCheckedTaggedToInt32DontCheckForMinusZeroOperator; 744 } 745 UNREACHABLE(); 746 return nullptr; 747} 748 749const Operator* SimplifiedOperatorBuilder::CheckedTaggedToFloat64( 750 CheckTaggedInputMode mode) { 751 switch (mode) { 752 case CheckTaggedInputMode::kNumber: 753 return &cache_.kCheckedTaggedToFloat64NumberOperator; 754 case CheckTaggedInputMode::kNumberOrOddball: 755 return &cache_.kCheckedTaggedToFloat64NumberOrOddballOperator; 756 } 757 UNREACHABLE(); 758 return nullptr; 759} 760 761const Operator* SimplifiedOperatorBuilder::CheckMaps(CheckMapsFlags flags, 762 ZoneHandleSet<Map> maps) { 763 CheckMapsParameters const parameters(flags, maps); 764 return new (zone()) Operator1<CheckMapsParameters>( // -- 765 IrOpcode::kCheckMaps, // opcode 766 Operator::kNoThrow | Operator::kNoWrite, // flags 767 "CheckMaps", // name 768 1, 1, 1, 0, 1, 0, // counts 769 parameters); // parameter 770} 771 772const Operator* SimplifiedOperatorBuilder::CheckFloat64Hole( 773 CheckFloat64HoleMode mode) { 774 switch (mode) { 775 case CheckFloat64HoleMode::kAllowReturnHole: 776 return &cache_.kCheckFloat64HoleAllowReturnHoleOperator; 777 case CheckFloat64HoleMode::kNeverReturnHole: 778 return &cache_.kCheckFloat64HoleNeverReturnHoleOperator; 779 } 780 UNREACHABLE(); 781 return nullptr; 782} 783 784const Operator* SimplifiedOperatorBuilder::EnsureWritableFastElements() { 785 return &cache_.kEnsureWritableFastElements; 786} 787 788const Operator* SimplifiedOperatorBuilder::MaybeGrowFastElements( 789 GrowFastElementsFlags flags) { 790 return new (zone()) Operator1<GrowFastElementsFlags>( // -- 791 IrOpcode::kMaybeGrowFastElements, // opcode 792 Operator::kNoThrow, // flags 793 "MaybeGrowFastElements", // name 794 4, 1, 1, 1, 1, 0, // counts 795 flags); // parameter 796} 797 798const Operator* SimplifiedOperatorBuilder::TransitionElementsKind( 799 ElementsTransition transition) { 800 return new (zone()) Operator1<ElementsTransition>( // -- 801 IrOpcode::kTransitionElementsKind, // opcode 802 Operator::kNoDeopt | Operator::kNoThrow, // flags 803 "TransitionElementsKind", // name 804 1, 1, 1, 0, 1, 0, // counts 805 transition); // parameter 806} 807 808const Operator* SimplifiedOperatorBuilder::NewUnmappedArgumentsElements( 809 int parameter_count) { 810 return new (zone()) Operator1<int>( // -- 811 IrOpcode::kNewUnmappedArgumentsElements, // opcode 812 Operator::kEliminatable, // flags 813 "NewUnmappedArgumentsElements", // name 814 0, 1, 0, 1, 1, 0, // counts 815 parameter_count); // parameter 816} 817 818const Operator* SimplifiedOperatorBuilder::NewRestParameterElements( 819 int parameter_count) { 820 return new (zone()) Operator1<int>( // -- 821 IrOpcode::kNewRestParameterElements, // opcode 822 Operator::kEliminatable, // flags 823 "NewRestParameterElements", // name 824 0, 1, 0, 1, 1, 0, // counts 825 parameter_count); // parameter 826} 827 828const Operator* SimplifiedOperatorBuilder::Allocate(PretenureFlag pretenure) { 829 switch (pretenure) { 830 case NOT_TENURED: 831 return &cache_.kAllocateNotTenuredOperator; 832 case TENURED: 833 return &cache_.kAllocateTenuredOperator; 834 } 835 UNREACHABLE(); 836 return nullptr; 837} 838 839 840const Operator* SimplifiedOperatorBuilder::LoadBuffer(BufferAccess access) { 841 switch (access.external_array_type()) { 842#define LOAD_BUFFER(Type, type, TYPE, ctype, size) \ 843 case kExternal##Type##Array: \ 844 return &cache_.kLoadBuffer##Type; 845 TYPED_ARRAYS(LOAD_BUFFER) 846#undef LOAD_BUFFER 847 } 848 UNREACHABLE(); 849 return nullptr; 850} 851 852 853const Operator* SimplifiedOperatorBuilder::StoreBuffer(BufferAccess access) { 854 switch (access.external_array_type()) { 855#define STORE_BUFFER(Type, type, TYPE, ctype, size) \ 856 case kExternal##Type##Array: \ 857 return &cache_.kStoreBuffer##Type; 858 TYPED_ARRAYS(STORE_BUFFER) 859#undef STORE_BUFFER 860 } 861 UNREACHABLE(); 862 return nullptr; 863} 864 865const Operator* SimplifiedOperatorBuilder::StringFromCodePoint( 866 UnicodeEncoding encoding) { 867 switch (encoding) { 868 case UnicodeEncoding::UTF16: 869 return &cache_.kStringFromCodePointOperatorUTF16; 870 case UnicodeEncoding::UTF32: 871 return &cache_.kStringFromCodePointOperatorUTF32; 872 } 873 UNREACHABLE(); 874 return nullptr; 875} 876 877#define SPECULATIVE_NUMBER_BINOP(Name) \ 878 const Operator* SimplifiedOperatorBuilder::Name(NumberOperationHint hint) { \ 879 switch (hint) { \ 880 case NumberOperationHint::kSignedSmall: \ 881 return &cache_.k##Name##SignedSmallOperator; \ 882 case NumberOperationHint::kSigned32: \ 883 return &cache_.k##Name##Signed32Operator; \ 884 case NumberOperationHint::kNumber: \ 885 return &cache_.k##Name##NumberOperator; \ 886 case NumberOperationHint::kNumberOrOddball: \ 887 return &cache_.k##Name##NumberOrOddballOperator; \ 888 } \ 889 UNREACHABLE(); \ 890 return nullptr; \ 891 } 892SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP) 893#undef SPECULATIVE_NUMBER_BINOP 894 895#define ACCESS_OP_LIST(V) \ 896 V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1) \ 897 V(StoreField, FieldAccess, Operator::kNoRead, 2, 1, 0) \ 898 V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1) \ 899 V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0) \ 900 V(LoadTypedElement, ExternalArrayType, Operator::kNoWrite, 4, 1, 1) \ 901 V(StoreTypedElement, ExternalArrayType, Operator::kNoRead, 5, 1, 0) 902 903#define ACCESS(Name, Type, properties, value_input_count, control_input_count, \ 904 output_count) \ 905 const Operator* SimplifiedOperatorBuilder::Name(const Type& access) { \ 906 return new (zone()) \ 907 Operator1<Type>(IrOpcode::k##Name, \ 908 Operator::kNoDeopt | Operator::kNoThrow | properties, \ 909 #Name, value_input_count, 1, control_input_count, \ 910 output_count, 1, 0, access); \ 911 } 912ACCESS_OP_LIST(ACCESS) 913#undef ACCESS 914 915} // namespace compiler 916} // namespace internal 917} // namespace v8 918