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/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.machine_type == rhs.machine_type; 96} 97 98 99bool operator!=(FieldAccess const& lhs, FieldAccess const& rhs) { 100 return !(lhs == rhs); 101} 102 103 104size_t hash_value(FieldAccess const& access) { 105 // On purpose we don't include the write barrier kind here, as this method is 106 // really only relevant for eliminating loads and they don't care about the 107 // write barrier mode. 108 return base::hash_combine(access.base_is_tagged, access.offset, 109 access.machine_type); 110} 111 112 113std::ostream& operator<<(std::ostream& os, FieldAccess const& access) { 114 os << "[" << access.base_is_tagged << ", " << access.offset << ", "; 115#ifdef OBJECT_PRINT 116 Handle<Name> name; 117 if (access.name.ToHandle(&name)) { 118 name->Print(os); 119 os << ", "; 120 } 121#endif 122 access.type->PrintTo(os); 123 os << ", " << access.machine_type << ", " << access.write_barrier_kind << "]"; 124 return os; 125} 126 127 128bool operator==(ElementAccess const& lhs, ElementAccess const& rhs) { 129 // On purpose we don't include the write barrier kind here, as this method is 130 // really only relevant for eliminating loads and they don't care about the 131 // write barrier mode. 132 return lhs.base_is_tagged == rhs.base_is_tagged && 133 lhs.header_size == rhs.header_size && 134 lhs.machine_type == rhs.machine_type; 135} 136 137 138bool operator!=(ElementAccess const& lhs, ElementAccess const& rhs) { 139 return !(lhs == rhs); 140} 141 142 143size_t hash_value(ElementAccess const& access) { 144 // On purpose we don't include the write barrier kind here, as this method is 145 // really only relevant for eliminating loads and they don't care about the 146 // write barrier mode. 147 return base::hash_combine(access.base_is_tagged, access.header_size, 148 access.machine_type); 149} 150 151 152std::ostream& operator<<(std::ostream& os, ElementAccess const& access) { 153 os << access.base_is_tagged << ", " << access.header_size << ", "; 154 access.type->PrintTo(os); 155 os << ", " << access.machine_type << ", " << access.write_barrier_kind; 156 return os; 157} 158 159 160const FieldAccess& FieldAccessOf(const Operator* op) { 161 DCHECK_NOT_NULL(op); 162 DCHECK(op->opcode() == IrOpcode::kLoadField || 163 op->opcode() == IrOpcode::kStoreField); 164 return OpParameter<FieldAccess>(op); 165} 166 167 168const ElementAccess& ElementAccessOf(const Operator* op) { 169 DCHECK_NOT_NULL(op); 170 DCHECK(op->opcode() == IrOpcode::kLoadElement || 171 op->opcode() == IrOpcode::kStoreElement); 172 return OpParameter<ElementAccess>(op); 173} 174 175size_t hash_value(CheckFloat64HoleMode mode) { 176 return static_cast<size_t>(mode); 177} 178 179std::ostream& operator<<(std::ostream& os, CheckFloat64HoleMode mode) { 180 switch (mode) { 181 case CheckFloat64HoleMode::kAllowReturnHole: 182 return os << "allow-return-hole"; 183 case CheckFloat64HoleMode::kNeverReturnHole: 184 return os << "never-return-hole"; 185 } 186 UNREACHABLE(); 187 return os; 188} 189 190CheckFloat64HoleMode CheckFloat64HoleModeOf(const Operator* op) { 191 DCHECK_EQ(IrOpcode::kCheckFloat64Hole, op->opcode()); 192 return OpParameter<CheckFloat64HoleMode>(op); 193} 194 195size_t hash_value(CheckTaggedHoleMode mode) { 196 return static_cast<size_t>(mode); 197} 198 199std::ostream& operator<<(std::ostream& os, CheckTaggedHoleMode mode) { 200 switch (mode) { 201 case CheckTaggedHoleMode::kConvertHoleToUndefined: 202 return os << "convert-hole-to-undefined"; 203 case CheckTaggedHoleMode::kNeverReturnHole: 204 return os << "never-return-hole"; 205 } 206 UNREACHABLE(); 207 return os; 208} 209 210CheckTaggedHoleMode CheckTaggedHoleModeOf(const Operator* op) { 211 DCHECK_EQ(IrOpcode::kCheckTaggedHole, op->opcode()); 212 return OpParameter<CheckTaggedHoleMode>(op); 213} 214 215Type* TypeOf(const Operator* op) { 216 DCHECK_EQ(IrOpcode::kTypeGuard, op->opcode()); 217 return OpParameter<Type*>(op); 218} 219 220BinaryOperationHints::Hint BinaryOperationHintOf(const Operator* op) { 221 DCHECK(op->opcode() == IrOpcode::kSpeculativeNumberAdd || 222 op->opcode() == IrOpcode::kSpeculativeNumberSubtract || 223 op->opcode() == IrOpcode::kSpeculativeNumberMultiply || 224 op->opcode() == IrOpcode::kSpeculativeNumberDivide || 225 op->opcode() == IrOpcode::kSpeculativeNumberModulus); 226 return OpParameter<BinaryOperationHints::Hint>(op); 227} 228 229CompareOperationHints::Hint CompareOperationHintOf(const Operator* op) { 230 DCHECK(op->opcode() == IrOpcode::kSpeculativeNumberEqual || 231 op->opcode() == IrOpcode::kSpeculativeNumberLessThan || 232 op->opcode() == IrOpcode::kSpeculativeNumberLessThanOrEqual); 233 return OpParameter<CompareOperationHints::Hint>(op); 234} 235 236#define PURE_OP_LIST(V) \ 237 V(BooleanNot, Operator::kNoProperties, 1) \ 238 V(BooleanToNumber, Operator::kNoProperties, 1) \ 239 V(NumberEqual, Operator::kCommutative, 2) \ 240 V(NumberLessThan, Operator::kNoProperties, 2) \ 241 V(NumberLessThanOrEqual, Operator::kNoProperties, 2) \ 242 V(NumberAdd, Operator::kCommutative, 2) \ 243 V(NumberSubtract, Operator::kNoProperties, 2) \ 244 V(NumberMultiply, Operator::kCommutative, 2) \ 245 V(NumberDivide, Operator::kNoProperties, 2) \ 246 V(NumberModulus, Operator::kNoProperties, 2) \ 247 V(NumberBitwiseOr, Operator::kCommutative, 2) \ 248 V(NumberBitwiseXor, Operator::kCommutative, 2) \ 249 V(NumberBitwiseAnd, Operator::kCommutative, 2) \ 250 V(NumberShiftLeft, Operator::kNoProperties, 2) \ 251 V(NumberShiftRight, Operator::kNoProperties, 2) \ 252 V(NumberShiftRightLogical, Operator::kNoProperties, 2) \ 253 V(NumberImul, Operator::kCommutative, 2) \ 254 V(NumberAbs, Operator::kNoProperties, 1) \ 255 V(NumberClz32, Operator::kNoProperties, 1) \ 256 V(NumberCeil, Operator::kNoProperties, 1) \ 257 V(NumberFloor, Operator::kNoProperties, 1) \ 258 V(NumberFround, Operator::kNoProperties, 1) \ 259 V(NumberAtan, Operator::kNoProperties, 1) \ 260 V(NumberAtan2, Operator::kNoProperties, 2) \ 261 V(NumberAtanh, Operator::kNoProperties, 1) \ 262 V(NumberCbrt, Operator::kNoProperties, 1) \ 263 V(NumberCos, Operator::kNoProperties, 1) \ 264 V(NumberExp, Operator::kNoProperties, 1) \ 265 V(NumberExpm1, Operator::kNoProperties, 1) \ 266 V(NumberLog, Operator::kNoProperties, 1) \ 267 V(NumberLog1p, Operator::kNoProperties, 1) \ 268 V(NumberLog10, Operator::kNoProperties, 1) \ 269 V(NumberLog2, Operator::kNoProperties, 1) \ 270 V(NumberRound, Operator::kNoProperties, 1) \ 271 V(NumberSin, Operator::kNoProperties, 1) \ 272 V(NumberSqrt, Operator::kNoProperties, 1) \ 273 V(NumberTan, Operator::kNoProperties, 1) \ 274 V(NumberTrunc, Operator::kNoProperties, 1) \ 275 V(NumberToInt32, Operator::kNoProperties, 1) \ 276 V(NumberToUint32, Operator::kNoProperties, 1) \ 277 V(NumberSilenceNaN, Operator::kNoProperties, 1) \ 278 V(StringFromCharCode, Operator::kNoProperties, 1) \ 279 V(StringToNumber, Operator::kNoProperties, 1) \ 280 V(PlainPrimitiveToNumber, Operator::kNoProperties, 1) \ 281 V(PlainPrimitiveToWord32, Operator::kNoProperties, 1) \ 282 V(PlainPrimitiveToFloat64, Operator::kNoProperties, 1) \ 283 V(ChangeTaggedSignedToInt32, Operator::kNoProperties, 1) \ 284 V(ChangeTaggedToInt32, Operator::kNoProperties, 1) \ 285 V(ChangeTaggedToUint32, Operator::kNoProperties, 1) \ 286 V(ChangeTaggedToFloat64, Operator::kNoProperties, 1) \ 287 V(ChangeInt31ToTaggedSigned, Operator::kNoProperties, 1) \ 288 V(ChangeInt32ToTagged, Operator::kNoProperties, 1) \ 289 V(ChangeUint32ToTagged, Operator::kNoProperties, 1) \ 290 V(ChangeFloat64ToTagged, Operator::kNoProperties, 1) \ 291 V(ChangeTaggedToBit, Operator::kNoProperties, 1) \ 292 V(ChangeBitToTagged, Operator::kNoProperties, 1) \ 293 V(TruncateTaggedToWord32, Operator::kNoProperties, 1) \ 294 V(TruncateTaggedToFloat64, Operator::kNoProperties, 1) \ 295 V(ObjectIsCallable, Operator::kNoProperties, 1) \ 296 V(ObjectIsNumber, Operator::kNoProperties, 1) \ 297 V(ObjectIsReceiver, Operator::kNoProperties, 1) \ 298 V(ObjectIsSmi, Operator::kNoProperties, 1) \ 299 V(ObjectIsString, Operator::kNoProperties, 1) \ 300 V(ObjectIsUndetectable, Operator::kNoProperties, 1) \ 301 V(StringEqual, Operator::kCommutative, 2) \ 302 V(StringLessThan, Operator::kNoProperties, 2) \ 303 V(StringLessThanOrEqual, Operator::kNoProperties, 2) 304 305#define SPECULATIVE_BINOP_LIST(V) \ 306 V(SpeculativeNumberAdd) \ 307 V(SpeculativeNumberSubtract) \ 308 V(SpeculativeNumberDivide) \ 309 V(SpeculativeNumberMultiply) \ 310 V(SpeculativeNumberModulus) 311 312#define CHECKED_OP_LIST(V) \ 313 V(CheckTaggedPointer, 1) \ 314 V(CheckTaggedSigned, 1) \ 315 V(CheckedInt32Add, 2) \ 316 V(CheckedInt32Sub, 2) \ 317 V(CheckedUint32ToInt32, 1) \ 318 V(CheckedFloat64ToInt32, 1) \ 319 V(CheckedTaggedToInt32, 1) \ 320 V(CheckedTaggedToFloat64, 1) 321 322struct SimplifiedOperatorGlobalCache final { 323#define PURE(Name, properties, input_count) \ 324 struct Name##Operator final : public Operator { \ 325 Name##Operator() \ 326 : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \ 327 input_count, 0, 0, 1, 0, 0) {} \ 328 }; \ 329 Name##Operator k##Name; 330 PURE_OP_LIST(PURE) 331#undef PURE 332 333#define CHECKED(Name, value_input_count) \ 334 struct Name##Operator final : public Operator { \ 335 Name##Operator() \ 336 : Operator(IrOpcode::k##Name, \ 337 Operator::kFoldable | Operator::kNoThrow, #Name, \ 338 value_input_count, 1, 1, 1, 1, 0) {} \ 339 }; \ 340 Name##Operator k##Name; 341 CHECKED_OP_LIST(CHECKED) 342#undef CHECKED 343 344 template <CheckFloat64HoleMode kMode> 345 struct CheckFloat64HoleNaNOperator final 346 : public Operator1<CheckFloat64HoleMode> { 347 CheckFloat64HoleNaNOperator() 348 : Operator1<CheckFloat64HoleMode>( 349 IrOpcode::kCheckFloat64Hole, 350 Operator::kFoldable | Operator::kNoThrow, "CheckFloat64Hole", 1, 351 1, 1, 1, 1, 0, kMode) {} 352 }; 353 CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kAllowReturnHole> 354 kCheckFloat64HoleAllowReturnHoleOperator; 355 CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kNeverReturnHole> 356 kCheckFloat64HoleNeverReturnHoleOperator; 357 358 template <CheckTaggedHoleMode kMode> 359 struct CheckTaggedHoleOperator final : public Operator1<CheckTaggedHoleMode> { 360 CheckTaggedHoleOperator() 361 : Operator1<CheckTaggedHoleMode>( 362 IrOpcode::kCheckTaggedHole, 363 Operator::kFoldable | Operator::kNoThrow, "CheckTaggedHole", 1, 1, 364 1, 1, 1, 0, kMode) {} 365 }; 366 CheckTaggedHoleOperator<CheckTaggedHoleMode::kConvertHoleToUndefined> 367 kCheckTaggedHoleConvertHoleToUndefinedOperator; 368 CheckTaggedHoleOperator<CheckTaggedHoleMode::kNeverReturnHole> 369 kCheckTaggedHoleNeverReturnHoleOperator; 370 371 template <PretenureFlag kPretenure> 372 struct AllocateOperator final : public Operator1<PretenureFlag> { 373 AllocateOperator() 374 : Operator1<PretenureFlag>( 375 IrOpcode::kAllocate, 376 Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite, 377 "Allocate", 1, 1, 1, 1, 1, 0, kPretenure) {} 378 }; 379 AllocateOperator<NOT_TENURED> kAllocateNotTenuredOperator; 380 AllocateOperator<TENURED> kAllocateTenuredOperator; 381 382#define BUFFER_ACCESS(Type, type, TYPE, ctype, size) \ 383 struct LoadBuffer##Type##Operator final : public Operator1<BufferAccess> { \ 384 LoadBuffer##Type##Operator() \ 385 : Operator1<BufferAccess>( \ 386 IrOpcode::kLoadBuffer, \ 387 Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite, \ 388 "LoadBuffer", 3, 1, 1, 1, 1, 0, \ 389 BufferAccess(kExternal##Type##Array)) {} \ 390 }; \ 391 struct StoreBuffer##Type##Operator final : public Operator1<BufferAccess> { \ 392 StoreBuffer##Type##Operator() \ 393 : Operator1<BufferAccess>( \ 394 IrOpcode::kStoreBuffer, \ 395 Operator::kNoDeopt | Operator::kNoRead | Operator::kNoThrow, \ 396 "StoreBuffer", 4, 1, 1, 0, 1, 0, \ 397 BufferAccess(kExternal##Type##Array)) {} \ 398 }; \ 399 LoadBuffer##Type##Operator kLoadBuffer##Type; \ 400 StoreBuffer##Type##Operator kStoreBuffer##Type; 401 TYPED_ARRAYS(BUFFER_ACCESS) 402#undef BUFFER_ACCESS 403}; 404 405 406static base::LazyInstance<SimplifiedOperatorGlobalCache>::type kCache = 407 LAZY_INSTANCE_INITIALIZER; 408 409 410SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone) 411 : cache_(kCache.Get()), zone_(zone) {} 412 413#define GET_FROM_CACHE(Name, properties, input_count) \ 414 const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; } 415PURE_OP_LIST(GET_FROM_CACHE) 416#undef GET_FROM_CACHE 417 418#define GET_FROM_CACHE(Name, value_input_count) \ 419 const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; } 420CHECKED_OP_LIST(GET_FROM_CACHE) 421#undef GET_FROM_CACHE 422 423const Operator* SimplifiedOperatorBuilder::CheckFloat64Hole( 424 CheckFloat64HoleMode mode) { 425 switch (mode) { 426 case CheckFloat64HoleMode::kAllowReturnHole: 427 return &cache_.kCheckFloat64HoleAllowReturnHoleOperator; 428 case CheckFloat64HoleMode::kNeverReturnHole: 429 return &cache_.kCheckFloat64HoleNeverReturnHoleOperator; 430 } 431 UNREACHABLE(); 432 return nullptr; 433} 434 435const Operator* SimplifiedOperatorBuilder::CheckTaggedHole( 436 CheckTaggedHoleMode mode) { 437 switch (mode) { 438 case CheckTaggedHoleMode::kConvertHoleToUndefined: 439 return &cache_.kCheckTaggedHoleConvertHoleToUndefinedOperator; 440 case CheckTaggedHoleMode::kNeverReturnHole: 441 return &cache_.kCheckTaggedHoleNeverReturnHoleOperator; 442 } 443 UNREACHABLE(); 444 return nullptr; 445} 446 447const Operator* SimplifiedOperatorBuilder::ReferenceEqual(Type* type) { 448 return new (zone()) Operator(IrOpcode::kReferenceEqual, 449 Operator::kCommutative | Operator::kPure, 450 "ReferenceEqual", 2, 0, 0, 1, 0, 0); 451} 452 453const Operator* SimplifiedOperatorBuilder::CheckBounds() { 454 // TODO(bmeurer): Cache this operator. Make it pure! 455 return new (zone()) 456 Operator(IrOpcode::kCheckBounds, Operator::kFoldable | Operator::kNoThrow, 457 "CheckBounds", 2, 1, 1, 1, 1, 0); 458} 459 460const Operator* SimplifiedOperatorBuilder::TypeGuard(Type* type) { 461 class TypeGuardOperator final : public Operator1<Type*> { 462 public: 463 explicit TypeGuardOperator(Type* type) 464 : Operator1<Type*>( // -- 465 IrOpcode::kTypeGuard, Operator::kPure, // opcode 466 "TypeGuard", // name 467 1, 0, 1, 1, 0, 0, // counts 468 type) {} // parameter 469 470 void PrintParameter(std::ostream& os) const final { 471 parameter()->PrintTo(os); 472 } 473 }; 474 return new (zone()) TypeGuardOperator(type); 475} 476 477const Operator* SimplifiedOperatorBuilder::Allocate(PretenureFlag pretenure) { 478 switch (pretenure) { 479 case NOT_TENURED: 480 return &cache_.kAllocateNotTenuredOperator; 481 case TENURED: 482 return &cache_.kAllocateTenuredOperator; 483 } 484 UNREACHABLE(); 485 return nullptr; 486} 487 488 489const Operator* SimplifiedOperatorBuilder::LoadBuffer(BufferAccess access) { 490 switch (access.external_array_type()) { 491#define LOAD_BUFFER(Type, type, TYPE, ctype, size) \ 492 case kExternal##Type##Array: \ 493 return &cache_.kLoadBuffer##Type; 494 TYPED_ARRAYS(LOAD_BUFFER) 495#undef LOAD_BUFFER 496 } 497 UNREACHABLE(); 498 return nullptr; 499} 500 501 502const Operator* SimplifiedOperatorBuilder::StoreBuffer(BufferAccess access) { 503 switch (access.external_array_type()) { 504#define STORE_BUFFER(Type, type, TYPE, ctype, size) \ 505 case kExternal##Type##Array: \ 506 return &cache_.kStoreBuffer##Type; 507 TYPED_ARRAYS(STORE_BUFFER) 508#undef STORE_BUFFER 509 } 510 UNREACHABLE(); 511 return nullptr; 512} 513 514#define SPECULATIVE_BINOP_DEF(Name) \ 515 const Operator* SimplifiedOperatorBuilder::Name( \ 516 BinaryOperationHints::Hint hint) { \ 517 return new (zone()) Operator1<BinaryOperationHints::Hint>( \ 518 IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, #Name, 2, \ 519 1, 1, 1, 1, 0, hint); \ 520 } 521SPECULATIVE_BINOP_LIST(SPECULATIVE_BINOP_DEF) 522#undef SPECULATIVE_BINOP_DEF 523 524const Operator* SimplifiedOperatorBuilder::SpeculativeNumberEqual( 525 CompareOperationHints::Hint hint) { 526 return new (zone()) Operator1<CompareOperationHints::Hint>( 527 IrOpcode::kSpeculativeNumberEqual, 528 Operator::kFoldable | Operator::kNoThrow, "SpeculativeNumberEqual", 2, 1, 529 1, 1, 1, 0, hint); 530} 531 532const Operator* SimplifiedOperatorBuilder::SpeculativeNumberLessThan( 533 CompareOperationHints::Hint hint) { 534 return new (zone()) Operator1<CompareOperationHints::Hint>( 535 IrOpcode::kSpeculativeNumberLessThan, 536 Operator::kFoldable | Operator::kNoThrow, "SpeculativeNumberLessThan", 2, 537 1, 1, 1, 1, 0, hint); 538} 539 540const Operator* SimplifiedOperatorBuilder::SpeculativeNumberLessThanOrEqual( 541 CompareOperationHints::Hint hint) { 542 return new (zone()) Operator1<CompareOperationHints::Hint>( 543 IrOpcode::kSpeculativeNumberLessThanOrEqual, 544 Operator::kFoldable | Operator::kNoThrow, 545 "SpeculativeNumberLessThanOrEqual", 2, 1, 1, 1, 1, 0, hint); 546} 547 548#define ACCESS_OP_LIST(V) \ 549 V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1) \ 550 V(StoreField, FieldAccess, Operator::kNoRead, 2, 1, 0) \ 551 V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1) \ 552 V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0) 553 554#define ACCESS(Name, Type, properties, value_input_count, control_input_count, \ 555 output_count) \ 556 const Operator* SimplifiedOperatorBuilder::Name(const Type& access) { \ 557 return new (zone()) \ 558 Operator1<Type>(IrOpcode::k##Name, \ 559 Operator::kNoDeopt | Operator::kNoThrow | properties, \ 560 #Name, value_input_count, 1, control_input_count, \ 561 output_count, 1, 0, access); \ 562 } 563ACCESS_OP_LIST(ACCESS) 564#undef ACCESS 565 566} // namespace compiler 567} // namespace internal 568} // namespace v8 569