1 // Copyright 2014 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/compiler/js-operator.h" 6 7 #include <limits> 8 9 #include "src/base/lazy-instance.h" 10 #include "src/compiler/opcodes.h" 11 #include "src/compiler/operator.h" 12 #include "src/feedback-vector.h" 13 #include "src/handles-inl.h" 14 #include "src/objects-inl.h" 15 16 namespace v8 { 17 namespace internal { 18 namespace compiler { 19 20 VectorSlotPair::VectorSlotPair() {} 21 22 23 int VectorSlotPair::index() const { 24 return vector_.is_null() ? -1 : FeedbackVector::GetIndex(slot_); 25 } 26 27 28 bool operator==(VectorSlotPair const& lhs, VectorSlotPair const& rhs) { 29 return lhs.slot() == rhs.slot() && 30 lhs.vector().location() == rhs.vector().location(); 31 } 32 33 34 bool operator!=(VectorSlotPair const& lhs, VectorSlotPair const& rhs) { 35 return !(lhs == rhs); 36 } 37 38 39 size_t hash_value(VectorSlotPair const& p) { 40 return base::hash_combine(p.slot(), p.vector().location()); 41 } 42 43 44 ConvertReceiverMode ConvertReceiverModeOf(Operator const* op) { 45 DCHECK_EQ(IrOpcode::kJSConvertReceiver, op->opcode()); 46 return OpParameter<ConvertReceiverMode>(op); 47 } 48 49 50 ToBooleanHints ToBooleanHintsOf(Operator const* op) { 51 DCHECK_EQ(IrOpcode::kJSToBoolean, op->opcode()); 52 return OpParameter<ToBooleanHints>(op); 53 } 54 55 bool operator==(ConstructParameters const& lhs, 56 ConstructParameters const& rhs) { 57 return lhs.arity() == rhs.arity() && lhs.frequency() == rhs.frequency() && 58 lhs.feedback() == rhs.feedback(); 59 } 60 61 bool operator!=(ConstructParameters const& lhs, 62 ConstructParameters const& rhs) { 63 return !(lhs == rhs); 64 } 65 66 size_t hash_value(ConstructParameters const& p) { 67 return base::hash_combine(p.arity(), p.frequency(), p.feedback()); 68 } 69 70 std::ostream& operator<<(std::ostream& os, ConstructParameters const& p) { 71 return os << p.arity() << ", " << p.frequency(); 72 } 73 74 ConstructParameters const& ConstructParametersOf(Operator const* op) { 75 DCHECK_EQ(IrOpcode::kJSConstruct, op->opcode()); 76 return OpParameter<ConstructParameters>(op); 77 } 78 79 bool operator==(ConstructWithSpreadParameters const& lhs, 80 ConstructWithSpreadParameters const& rhs) { 81 return lhs.arity() == rhs.arity(); 82 } 83 84 bool operator!=(ConstructWithSpreadParameters const& lhs, 85 ConstructWithSpreadParameters const& rhs) { 86 return !(lhs == rhs); 87 } 88 89 size_t hash_value(ConstructWithSpreadParameters const& p) { 90 return base::hash_combine(p.arity()); 91 } 92 93 std::ostream& operator<<(std::ostream& os, 94 ConstructWithSpreadParameters const& p) { 95 return os << p.arity(); 96 } 97 98 ConstructWithSpreadParameters const& ConstructWithSpreadParametersOf( 99 Operator const* op) { 100 DCHECK_EQ(IrOpcode::kJSConstructWithSpread, op->opcode()); 101 return OpParameter<ConstructWithSpreadParameters>(op); 102 } 103 104 std::ostream& operator<<(std::ostream& os, CallParameters const& p) { 105 os << p.arity() << ", " << p.frequency() << ", " << p.convert_mode() << ", " 106 << p.tail_call_mode(); 107 return os; 108 } 109 110 const CallParameters& CallParametersOf(const Operator* op) { 111 DCHECK_EQ(IrOpcode::kJSCall, op->opcode()); 112 return OpParameter<CallParameters>(op); 113 } 114 115 std::ostream& operator<<(std::ostream& os, 116 CallForwardVarargsParameters const& p) { 117 return os << p.start_index() << ", " << p.tail_call_mode(); 118 } 119 120 CallForwardVarargsParameters const& CallForwardVarargsParametersOf( 121 Operator const* op) { 122 DCHECK_EQ(IrOpcode::kJSCallForwardVarargs, op->opcode()); 123 return OpParameter<CallForwardVarargsParameters>(op); 124 } 125 126 bool operator==(CallWithSpreadParameters const& lhs, 127 CallWithSpreadParameters const& rhs) { 128 return lhs.arity() == rhs.arity(); 129 } 130 131 bool operator!=(CallWithSpreadParameters const& lhs, 132 CallWithSpreadParameters const& rhs) { 133 return !(lhs == rhs); 134 } 135 136 size_t hash_value(CallWithSpreadParameters const& p) { 137 return base::hash_combine(p.arity()); 138 } 139 140 std::ostream& operator<<(std::ostream& os, CallWithSpreadParameters const& p) { 141 return os << p.arity(); 142 } 143 144 CallWithSpreadParameters const& CallWithSpreadParametersOf(Operator const* op) { 145 DCHECK_EQ(IrOpcode::kJSCallWithSpread, op->opcode()); 146 return OpParameter<CallWithSpreadParameters>(op); 147 } 148 149 bool operator==(CallRuntimeParameters const& lhs, 150 CallRuntimeParameters const& rhs) { 151 return lhs.id() == rhs.id() && lhs.arity() == rhs.arity(); 152 } 153 154 155 bool operator!=(CallRuntimeParameters const& lhs, 156 CallRuntimeParameters const& rhs) { 157 return !(lhs == rhs); 158 } 159 160 161 size_t hash_value(CallRuntimeParameters const& p) { 162 return base::hash_combine(p.id(), p.arity()); 163 } 164 165 166 std::ostream& operator<<(std::ostream& os, CallRuntimeParameters const& p) { 167 return os << p.id() << ", " << p.arity(); 168 } 169 170 171 const CallRuntimeParameters& CallRuntimeParametersOf(const Operator* op) { 172 DCHECK_EQ(IrOpcode::kJSCallRuntime, op->opcode()); 173 return OpParameter<CallRuntimeParameters>(op); 174 } 175 176 177 ContextAccess::ContextAccess(size_t depth, size_t index, bool immutable) 178 : immutable_(immutable), 179 depth_(static_cast<uint16_t>(depth)), 180 index_(static_cast<uint32_t>(index)) { 181 DCHECK(depth <= std::numeric_limits<uint16_t>::max()); 182 DCHECK(index <= std::numeric_limits<uint32_t>::max()); 183 } 184 185 186 bool operator==(ContextAccess const& lhs, ContextAccess const& rhs) { 187 return lhs.depth() == rhs.depth() && lhs.index() == rhs.index() && 188 lhs.immutable() == rhs.immutable(); 189 } 190 191 192 bool operator!=(ContextAccess const& lhs, ContextAccess const& rhs) { 193 return !(lhs == rhs); 194 } 195 196 197 size_t hash_value(ContextAccess const& access) { 198 return base::hash_combine(access.depth(), access.index(), access.immutable()); 199 } 200 201 202 std::ostream& operator<<(std::ostream& os, ContextAccess const& access) { 203 return os << access.depth() << ", " << access.index() << ", " 204 << access.immutable(); 205 } 206 207 208 ContextAccess const& ContextAccessOf(Operator const* op) { 209 DCHECK(op->opcode() == IrOpcode::kJSLoadContext || 210 op->opcode() == IrOpcode::kJSStoreContext); 211 return OpParameter<ContextAccess>(op); 212 } 213 214 CreateCatchContextParameters::CreateCatchContextParameters( 215 Handle<String> catch_name, Handle<ScopeInfo> scope_info) 216 : catch_name_(catch_name), scope_info_(scope_info) {} 217 218 bool operator==(CreateCatchContextParameters const& lhs, 219 CreateCatchContextParameters const& rhs) { 220 return lhs.catch_name().location() == rhs.catch_name().location() && 221 lhs.scope_info().location() == rhs.scope_info().location(); 222 } 223 224 bool operator!=(CreateCatchContextParameters const& lhs, 225 CreateCatchContextParameters const& rhs) { 226 return !(lhs == rhs); 227 } 228 229 size_t hash_value(CreateCatchContextParameters const& parameters) { 230 return base::hash_combine(parameters.catch_name().location(), 231 parameters.scope_info().location()); 232 } 233 234 std::ostream& operator<<(std::ostream& os, 235 CreateCatchContextParameters const& parameters) { 236 return os << Brief(*parameters.catch_name()) << ", " 237 << Brief(*parameters.scope_info()); 238 } 239 240 CreateCatchContextParameters const& CreateCatchContextParametersOf( 241 Operator const* op) { 242 DCHECK_EQ(IrOpcode::kJSCreateCatchContext, op->opcode()); 243 return OpParameter<CreateCatchContextParameters>(op); 244 } 245 246 CreateFunctionContextParameters::CreateFunctionContextParameters( 247 int slot_count, ScopeType scope_type) 248 : slot_count_(slot_count), scope_type_(scope_type) {} 249 250 bool operator==(CreateFunctionContextParameters const& lhs, 251 CreateFunctionContextParameters const& rhs) { 252 return lhs.slot_count() == rhs.slot_count() && 253 lhs.scope_type() == rhs.scope_type(); 254 } 255 256 bool operator!=(CreateFunctionContextParameters const& lhs, 257 CreateFunctionContextParameters const& rhs) { 258 return !(lhs == rhs); 259 } 260 261 size_t hash_value(CreateFunctionContextParameters const& parameters) { 262 return base::hash_combine(parameters.slot_count(), 263 static_cast<int>(parameters.scope_type())); 264 } 265 266 std::ostream& operator<<(std::ostream& os, 267 CreateFunctionContextParameters const& parameters) { 268 return os << parameters.slot_count() << ", " << parameters.scope_type(); 269 } 270 271 CreateFunctionContextParameters const& CreateFunctionContextParametersOf( 272 Operator const* op) { 273 DCHECK_EQ(IrOpcode::kJSCreateFunctionContext, op->opcode()); 274 return OpParameter<CreateFunctionContextParameters>(op); 275 } 276 277 bool operator==(StoreNamedOwnParameters const& lhs, 278 StoreNamedOwnParameters const& rhs) { 279 return lhs.name().location() == rhs.name().location() && 280 lhs.feedback() == rhs.feedback(); 281 } 282 283 bool operator!=(StoreNamedOwnParameters const& lhs, 284 StoreNamedOwnParameters const& rhs) { 285 return !(lhs == rhs); 286 } 287 288 size_t hash_value(StoreNamedOwnParameters const& p) { 289 return base::hash_combine(p.name().location(), p.feedback()); 290 } 291 292 std::ostream& operator<<(std::ostream& os, StoreNamedOwnParameters const& p) { 293 return os << Brief(*p.name()); 294 } 295 296 StoreNamedOwnParameters const& StoreNamedOwnParametersOf(const Operator* op) { 297 DCHECK_EQ(IrOpcode::kJSStoreNamedOwn, op->opcode()); 298 return OpParameter<StoreNamedOwnParameters>(op); 299 } 300 301 bool operator==(DataPropertyParameters const& lhs, 302 DataPropertyParameters const& rhs) { 303 return lhs.feedback() == rhs.feedback(); 304 } 305 306 bool operator!=(DataPropertyParameters const& lhs, 307 DataPropertyParameters const& rhs) { 308 return !(lhs == rhs); 309 } 310 311 size_t hash_value(DataPropertyParameters const& p) { 312 return base::hash_combine(p.feedback()); 313 } 314 315 std::ostream& operator<<(std::ostream& os, DataPropertyParameters const& p) { 316 return os; 317 } 318 319 DataPropertyParameters const& DataPropertyParametersOf(const Operator* op) { 320 DCHECK(op->opcode() == IrOpcode::kJSStoreDataPropertyInLiteral); 321 return OpParameter<DataPropertyParameters>(op); 322 } 323 324 bool operator==(NamedAccess const& lhs, NamedAccess const& rhs) { 325 return lhs.name().location() == rhs.name().location() && 326 lhs.language_mode() == rhs.language_mode() && 327 lhs.feedback() == rhs.feedback(); 328 } 329 330 331 bool operator!=(NamedAccess const& lhs, NamedAccess const& rhs) { 332 return !(lhs == rhs); 333 } 334 335 336 size_t hash_value(NamedAccess const& p) { 337 return base::hash_combine(p.name().location(), p.language_mode(), 338 p.feedback()); 339 } 340 341 342 std::ostream& operator<<(std::ostream& os, NamedAccess const& p) { 343 return os << Brief(*p.name()) << ", " << p.language_mode(); 344 } 345 346 347 NamedAccess const& NamedAccessOf(const Operator* op) { 348 DCHECK(op->opcode() == IrOpcode::kJSLoadNamed || 349 op->opcode() == IrOpcode::kJSStoreNamed); 350 return OpParameter<NamedAccess>(op); 351 } 352 353 354 std::ostream& operator<<(std::ostream& os, PropertyAccess const& p) { 355 return os << p.language_mode(); 356 } 357 358 359 bool operator==(PropertyAccess const& lhs, PropertyAccess const& rhs) { 360 return lhs.language_mode() == rhs.language_mode() && 361 lhs.feedback() == rhs.feedback(); 362 } 363 364 365 bool operator!=(PropertyAccess const& lhs, PropertyAccess const& rhs) { 366 return !(lhs == rhs); 367 } 368 369 370 PropertyAccess const& PropertyAccessOf(const Operator* op) { 371 DCHECK(op->opcode() == IrOpcode::kJSLoadProperty || 372 op->opcode() == IrOpcode::kJSStoreProperty); 373 return OpParameter<PropertyAccess>(op); 374 } 375 376 377 size_t hash_value(PropertyAccess const& p) { 378 return base::hash_combine(p.language_mode(), p.feedback()); 379 } 380 381 382 bool operator==(LoadGlobalParameters const& lhs, 383 LoadGlobalParameters const& rhs) { 384 return lhs.name().location() == rhs.name().location() && 385 lhs.feedback() == rhs.feedback() && 386 lhs.typeof_mode() == rhs.typeof_mode(); 387 } 388 389 390 bool operator!=(LoadGlobalParameters const& lhs, 391 LoadGlobalParameters const& rhs) { 392 return !(lhs == rhs); 393 } 394 395 396 size_t hash_value(LoadGlobalParameters const& p) { 397 return base::hash_combine(p.name().location(), p.typeof_mode()); 398 } 399 400 401 std::ostream& operator<<(std::ostream& os, LoadGlobalParameters const& p) { 402 return os << Brief(*p.name()) << ", " << p.typeof_mode(); 403 } 404 405 406 const LoadGlobalParameters& LoadGlobalParametersOf(const Operator* op) { 407 DCHECK_EQ(IrOpcode::kJSLoadGlobal, op->opcode()); 408 return OpParameter<LoadGlobalParameters>(op); 409 } 410 411 412 bool operator==(StoreGlobalParameters const& lhs, 413 StoreGlobalParameters const& rhs) { 414 return lhs.language_mode() == rhs.language_mode() && 415 lhs.name().location() == rhs.name().location() && 416 lhs.feedback() == rhs.feedback(); 417 } 418 419 420 bool operator!=(StoreGlobalParameters const& lhs, 421 StoreGlobalParameters const& rhs) { 422 return !(lhs == rhs); 423 } 424 425 426 size_t hash_value(StoreGlobalParameters const& p) { 427 return base::hash_combine(p.language_mode(), p.name().location(), 428 p.feedback()); 429 } 430 431 432 std::ostream& operator<<(std::ostream& os, StoreGlobalParameters const& p) { 433 return os << p.language_mode() << ", " << Brief(*p.name()); 434 } 435 436 437 const StoreGlobalParameters& StoreGlobalParametersOf(const Operator* op) { 438 DCHECK_EQ(IrOpcode::kJSStoreGlobal, op->opcode()); 439 return OpParameter<StoreGlobalParameters>(op); 440 } 441 442 443 CreateArgumentsType const& CreateArgumentsTypeOf(const Operator* op) { 444 DCHECK_EQ(IrOpcode::kJSCreateArguments, op->opcode()); 445 return OpParameter<CreateArgumentsType>(op); 446 } 447 448 449 bool operator==(CreateArrayParameters const& lhs, 450 CreateArrayParameters const& rhs) { 451 return lhs.arity() == rhs.arity() && 452 lhs.site().location() == rhs.site().location(); 453 } 454 455 456 bool operator!=(CreateArrayParameters const& lhs, 457 CreateArrayParameters const& rhs) { 458 return !(lhs == rhs); 459 } 460 461 462 size_t hash_value(CreateArrayParameters const& p) { 463 return base::hash_combine(p.arity(), p.site().location()); 464 } 465 466 467 std::ostream& operator<<(std::ostream& os, CreateArrayParameters const& p) { 468 os << p.arity(); 469 if (!p.site().is_null()) os << ", " << Brief(*p.site()); 470 return os; 471 } 472 473 474 const CreateArrayParameters& CreateArrayParametersOf(const Operator* op) { 475 DCHECK_EQ(IrOpcode::kJSCreateArray, op->opcode()); 476 return OpParameter<CreateArrayParameters>(op); 477 } 478 479 480 bool operator==(CreateClosureParameters const& lhs, 481 CreateClosureParameters const& rhs) { 482 return lhs.pretenure() == rhs.pretenure() && 483 lhs.feedback() == rhs.feedback() && 484 lhs.shared_info().location() == rhs.shared_info().location(); 485 } 486 487 488 bool operator!=(CreateClosureParameters const& lhs, 489 CreateClosureParameters const& rhs) { 490 return !(lhs == rhs); 491 } 492 493 494 size_t hash_value(CreateClosureParameters const& p) { 495 return base::hash_combine(p.pretenure(), p.shared_info().location(), 496 p.feedback()); 497 } 498 499 500 std::ostream& operator<<(std::ostream& os, CreateClosureParameters const& p) { 501 return os << p.pretenure() << ", " << Brief(*p.shared_info()); 502 } 503 504 505 const CreateClosureParameters& CreateClosureParametersOf(const Operator* op) { 506 DCHECK_EQ(IrOpcode::kJSCreateClosure, op->opcode()); 507 return OpParameter<CreateClosureParameters>(op); 508 } 509 510 511 bool operator==(CreateLiteralParameters const& lhs, 512 CreateLiteralParameters const& rhs) { 513 return lhs.constant().location() == rhs.constant().location() && 514 lhs.length() == rhs.length() && lhs.flags() == rhs.flags() && 515 lhs.index() == rhs.index(); 516 } 517 518 519 bool operator!=(CreateLiteralParameters const& lhs, 520 CreateLiteralParameters const& rhs) { 521 return !(lhs == rhs); 522 } 523 524 525 size_t hash_value(CreateLiteralParameters const& p) { 526 return base::hash_combine(p.constant().location(), p.length(), p.flags(), 527 p.index()); 528 } 529 530 531 std::ostream& operator<<(std::ostream& os, CreateLiteralParameters const& p) { 532 return os << Brief(*p.constant()) << ", " << p.length() << ", " << p.flags() 533 << ", " << p.index(); 534 } 535 536 537 const CreateLiteralParameters& CreateLiteralParametersOf(const Operator* op) { 538 DCHECK(op->opcode() == IrOpcode::kJSCreateLiteralArray || 539 op->opcode() == IrOpcode::kJSCreateLiteralObject || 540 op->opcode() == IrOpcode::kJSCreateLiteralRegExp); 541 return OpParameter<CreateLiteralParameters>(op); 542 } 543 544 BinaryOperationHint BinaryOperationHintOf(const Operator* op) { 545 DCHECK_EQ(IrOpcode::kJSAdd, op->opcode()); 546 return OpParameter<BinaryOperationHint>(op); 547 } 548 549 CompareOperationHint CompareOperationHintOf(const Operator* op) { 550 DCHECK(op->opcode() == IrOpcode::kJSEqual || 551 op->opcode() == IrOpcode::kJSNotEqual || 552 op->opcode() == IrOpcode::kJSStrictEqual || 553 op->opcode() == IrOpcode::kJSStrictNotEqual || 554 op->opcode() == IrOpcode::kJSLessThan || 555 op->opcode() == IrOpcode::kJSGreaterThan || 556 op->opcode() == IrOpcode::kJSLessThanOrEqual || 557 op->opcode() == IrOpcode::kJSGreaterThanOrEqual); 558 return OpParameter<CompareOperationHint>(op); 559 } 560 561 #define CACHED_OP_LIST(V) \ 562 V(BitwiseOr, Operator::kNoProperties, 2, 1) \ 563 V(BitwiseXor, Operator::kNoProperties, 2, 1) \ 564 V(BitwiseAnd, Operator::kNoProperties, 2, 1) \ 565 V(ShiftLeft, Operator::kNoProperties, 2, 1) \ 566 V(ShiftRight, Operator::kNoProperties, 2, 1) \ 567 V(ShiftRightLogical, Operator::kNoProperties, 2, 1) \ 568 V(Subtract, Operator::kNoProperties, 2, 1) \ 569 V(Multiply, Operator::kNoProperties, 2, 1) \ 570 V(Divide, Operator::kNoProperties, 2, 1) \ 571 V(Modulus, Operator::kNoProperties, 2, 1) \ 572 V(ToInteger, Operator::kNoProperties, 1, 1) \ 573 V(ToLength, Operator::kNoProperties, 1, 1) \ 574 V(ToName, Operator::kNoProperties, 1, 1) \ 575 V(ToNumber, Operator::kNoProperties, 1, 1) \ 576 V(ToObject, Operator::kFoldable, 1, 1) \ 577 V(ToString, Operator::kNoProperties, 1, 1) \ 578 V(Create, Operator::kNoProperties, 2, 1) \ 579 V(CreateIterResultObject, Operator::kEliminatable, 2, 1) \ 580 V(CreateKeyValueArray, Operator::kEliminatable, 2, 1) \ 581 V(HasProperty, Operator::kNoProperties, 2, 1) \ 582 V(ClassOf, Operator::kPure, 1, 1) \ 583 V(TypeOf, Operator::kPure, 1, 1) \ 584 V(InstanceOf, Operator::kNoProperties, 2, 1) \ 585 V(OrdinaryHasInstance, Operator::kNoProperties, 2, 1) \ 586 V(ForInNext, Operator::kNoProperties, 4, 1) \ 587 V(ForInPrepare, Operator::kNoProperties, 1, 3) \ 588 V(LoadMessage, Operator::kNoThrow | Operator::kNoWrite, 0, 1) \ 589 V(StoreMessage, Operator::kNoRead | Operator::kNoThrow, 1, 0) \ 590 V(GeneratorRestoreContinuation, Operator::kNoThrow, 1, 1) \ 591 V(StackCheck, Operator::kNoWrite, 0, 0) \ 592 V(Debugger, Operator::kNoProperties, 0, 0) \ 593 V(GetSuperConstructor, Operator::kNoWrite, 1, 1) 594 595 #define BINARY_OP_LIST(V) V(Add) 596 597 #define COMPARE_OP_LIST(V) \ 598 V(Equal, Operator::kNoProperties) \ 599 V(NotEqual, Operator::kNoProperties) \ 600 V(StrictEqual, Operator::kPure) \ 601 V(StrictNotEqual, Operator::kPure) \ 602 V(LessThan, Operator::kNoProperties) \ 603 V(GreaterThan, Operator::kNoProperties) \ 604 V(LessThanOrEqual, Operator::kNoProperties) \ 605 V(GreaterThanOrEqual, Operator::kNoProperties) 606 607 struct JSOperatorGlobalCache final { 608 #define CACHED_OP(Name, properties, value_input_count, value_output_count) \ 609 struct Name##Operator final : public Operator { \ 610 Name##Operator() \ 611 : Operator(IrOpcode::kJS##Name, properties, "JS" #Name, \ 612 value_input_count, Operator::ZeroIfPure(properties), \ 613 Operator::ZeroIfEliminatable(properties), \ 614 value_output_count, Operator::ZeroIfPure(properties), \ 615 Operator::ZeroIfNoThrow(properties)) {} \ 616 }; \ 617 Name##Operator k##Name##Operator; 618 CACHED_OP_LIST(CACHED_OP) 619 #undef CACHED_OP 620 621 #define BINARY_OP(Name) \ 622 template <BinaryOperationHint kHint> \ 623 struct Name##Operator final : public Operator1<BinaryOperationHint> { \ 624 Name##Operator() \ 625 : Operator1<BinaryOperationHint>(IrOpcode::kJS##Name, \ 626 Operator::kNoProperties, "JS" #Name, \ 627 2, 1, 1, 1, 1, 2, kHint) {} \ 628 }; \ 629 Name##Operator<BinaryOperationHint::kNone> k##Name##NoneOperator; \ 630 Name##Operator<BinaryOperationHint::kSignedSmall> \ 631 k##Name##SignedSmallOperator; \ 632 Name##Operator<BinaryOperationHint::kSigned32> k##Name##Signed32Operator; \ 633 Name##Operator<BinaryOperationHint::kNumberOrOddball> \ 634 k##Name##NumberOrOddballOperator; \ 635 Name##Operator<BinaryOperationHint::kString> k##Name##StringOperator; \ 636 Name##Operator<BinaryOperationHint::kAny> k##Name##AnyOperator; 637 BINARY_OP_LIST(BINARY_OP) 638 #undef BINARY_OP 639 640 #define COMPARE_OP(Name, properties) \ 641 template <CompareOperationHint kHint> \ 642 struct Name##Operator final : public Operator1<CompareOperationHint> { \ 643 Name##Operator() \ 644 : Operator1<CompareOperationHint>( \ 645 IrOpcode::kJS##Name, properties, "JS" #Name, 2, 1, 1, 1, 1, \ 646 Operator::ZeroIfNoThrow(properties), kHint) {} \ 647 }; \ 648 Name##Operator<CompareOperationHint::kNone> k##Name##NoneOperator; \ 649 Name##Operator<CompareOperationHint::kSignedSmall> \ 650 k##Name##SignedSmallOperator; \ 651 Name##Operator<CompareOperationHint::kNumber> k##Name##NumberOperator; \ 652 Name##Operator<CompareOperationHint::kNumberOrOddball> \ 653 k##Name##NumberOrOddballOperator; \ 654 Name##Operator<CompareOperationHint::kInternalizedString> \ 655 k##Name##InternalizedStringOperator; \ 656 Name##Operator<CompareOperationHint::kString> k##Name##StringOperator; \ 657 Name##Operator<CompareOperationHint::kReceiver> k##Name##ReceiverOperator; \ 658 Name##Operator<CompareOperationHint::kAny> k##Name##AnyOperator; 659 COMPARE_OP_LIST(COMPARE_OP) 660 #undef COMPARE_OP 661 }; 662 663 static base::LazyInstance<JSOperatorGlobalCache>::type kCache = 664 LAZY_INSTANCE_INITIALIZER; 665 666 JSOperatorBuilder::JSOperatorBuilder(Zone* zone) 667 : cache_(kCache.Get()), zone_(zone) {} 668 669 #define CACHED_OP(Name, properties, value_input_count, value_output_count) \ 670 const Operator* JSOperatorBuilder::Name() { \ 671 return &cache_.k##Name##Operator; \ 672 } 673 CACHED_OP_LIST(CACHED_OP) 674 #undef CACHED_OP 675 676 #define BINARY_OP(Name) \ 677 const Operator* JSOperatorBuilder::Name(BinaryOperationHint hint) { \ 678 switch (hint) { \ 679 case BinaryOperationHint::kNone: \ 680 return &cache_.k##Name##NoneOperator; \ 681 case BinaryOperationHint::kSignedSmall: \ 682 return &cache_.k##Name##SignedSmallOperator; \ 683 case BinaryOperationHint::kSigned32: \ 684 return &cache_.k##Name##Signed32Operator; \ 685 case BinaryOperationHint::kNumberOrOddball: \ 686 return &cache_.k##Name##NumberOrOddballOperator; \ 687 case BinaryOperationHint::kString: \ 688 return &cache_.k##Name##StringOperator; \ 689 case BinaryOperationHint::kAny: \ 690 return &cache_.k##Name##AnyOperator; \ 691 } \ 692 UNREACHABLE(); \ 693 return nullptr; \ 694 } 695 BINARY_OP_LIST(BINARY_OP) 696 #undef BINARY_OP 697 698 #define COMPARE_OP(Name, ...) \ 699 const Operator* JSOperatorBuilder::Name(CompareOperationHint hint) { \ 700 switch (hint) { \ 701 case CompareOperationHint::kNone: \ 702 return &cache_.k##Name##NoneOperator; \ 703 case CompareOperationHint::kSignedSmall: \ 704 return &cache_.k##Name##SignedSmallOperator; \ 705 case CompareOperationHint::kNumber: \ 706 return &cache_.k##Name##NumberOperator; \ 707 case CompareOperationHint::kNumberOrOddball: \ 708 return &cache_.k##Name##NumberOrOddballOperator; \ 709 case CompareOperationHint::kInternalizedString: \ 710 return &cache_.k##Name##InternalizedStringOperator; \ 711 case CompareOperationHint::kString: \ 712 return &cache_.k##Name##StringOperator; \ 713 case CompareOperationHint::kReceiver: \ 714 return &cache_.k##Name##ReceiverOperator; \ 715 case CompareOperationHint::kAny: \ 716 return &cache_.k##Name##AnyOperator; \ 717 } \ 718 UNREACHABLE(); \ 719 return nullptr; \ 720 } 721 COMPARE_OP_LIST(COMPARE_OP) 722 #undef COMPARE_OP 723 724 const Operator* JSOperatorBuilder::StoreDataPropertyInLiteral( 725 const VectorSlotPair& feedback) { 726 DataPropertyParameters parameters(feedback); 727 return new (zone()) Operator1<DataPropertyParameters>( // -- 728 IrOpcode::kJSStoreDataPropertyInLiteral, 729 Operator::kNoThrow, // opcode 730 "JSStoreDataPropertyInLiteral", // name 731 4, 1, 1, 0, 1, 0, // counts 732 parameters); // parameter 733 } 734 735 const Operator* JSOperatorBuilder::ToBoolean(ToBooleanHints hints) { 736 // TODO(turbofan): Cache most important versions of this operator. 737 return new (zone()) Operator1<ToBooleanHints>( //-- 738 IrOpcode::kJSToBoolean, Operator::kPure, // opcode 739 "JSToBoolean", // name 740 1, 0, 0, 1, 0, 0, // inputs/outputs 741 hints); // parameter 742 } 743 744 const Operator* JSOperatorBuilder::CallForwardVarargs( 745 uint32_t start_index, TailCallMode tail_call_mode) { 746 CallForwardVarargsParameters parameters(start_index, tail_call_mode); 747 return new (zone()) Operator1<CallForwardVarargsParameters>( // -- 748 IrOpcode::kJSCallForwardVarargs, Operator::kNoProperties, // opcode 749 "JSCallForwardVarargs", // name 750 2, 1, 1, 1, 1, 2, // counts 751 parameters); // parameter 752 } 753 754 const Operator* JSOperatorBuilder::Call(size_t arity, float frequency, 755 VectorSlotPair const& feedback, 756 ConvertReceiverMode convert_mode, 757 TailCallMode tail_call_mode) { 758 CallParameters parameters(arity, frequency, feedback, tail_call_mode, 759 convert_mode); 760 return new (zone()) Operator1<CallParameters>( // -- 761 IrOpcode::kJSCall, Operator::kNoProperties, // opcode 762 "JSCall", // name 763 parameters.arity(), 1, 1, 1, 1, 2, // inputs/outputs 764 parameters); // parameter 765 } 766 767 const Operator* JSOperatorBuilder::CallWithSpread(uint32_t arity) { 768 CallWithSpreadParameters parameters(arity); 769 return new (zone()) Operator1<CallWithSpreadParameters>( // -- 770 IrOpcode::kJSCallWithSpread, Operator::kNoProperties, // opcode 771 "JSCallWithSpread", // name 772 parameters.arity(), 1, 1, 1, 1, 2, // counts 773 parameters); // parameter 774 } 775 776 const Operator* JSOperatorBuilder::CallRuntime(Runtime::FunctionId id) { 777 const Runtime::Function* f = Runtime::FunctionForId(id); 778 return CallRuntime(f, f->nargs); 779 } 780 781 782 const Operator* JSOperatorBuilder::CallRuntime(Runtime::FunctionId id, 783 size_t arity) { 784 const Runtime::Function* f = Runtime::FunctionForId(id); 785 return CallRuntime(f, arity); 786 } 787 788 789 const Operator* JSOperatorBuilder::CallRuntime(const Runtime::Function* f, 790 size_t arity) { 791 CallRuntimeParameters parameters(f->function_id, arity); 792 DCHECK(f->nargs == -1 || f->nargs == static_cast<int>(parameters.arity())); 793 return new (zone()) Operator1<CallRuntimeParameters>( // -- 794 IrOpcode::kJSCallRuntime, Operator::kNoProperties, // opcode 795 "JSCallRuntime", // name 796 parameters.arity(), 1, 1, f->result_size, 1, 2, // inputs/outputs 797 parameters); // parameter 798 } 799 800 const Operator* JSOperatorBuilder::Construct(uint32_t arity, float frequency, 801 VectorSlotPair const& feedback) { 802 ConstructParameters parameters(arity, frequency, feedback); 803 return new (zone()) Operator1<ConstructParameters>( // -- 804 IrOpcode::kJSConstruct, Operator::kNoProperties, // opcode 805 "JSConstruct", // name 806 parameters.arity(), 1, 1, 1, 1, 2, // counts 807 parameters); // parameter 808 } 809 810 const Operator* JSOperatorBuilder::ConstructWithSpread(uint32_t arity) { 811 ConstructWithSpreadParameters parameters(arity); 812 return new (zone()) Operator1<ConstructWithSpreadParameters>( // -- 813 IrOpcode::kJSConstructWithSpread, Operator::kNoProperties, // opcode 814 "JSConstructWithSpread", // name 815 parameters.arity(), 1, 1, 1, 1, 2, // counts 816 parameters); // parameter 817 } 818 819 const Operator* JSOperatorBuilder::ConvertReceiver( 820 ConvertReceiverMode convert_mode) { 821 return new (zone()) Operator1<ConvertReceiverMode>( // -- 822 IrOpcode::kJSConvertReceiver, Operator::kEliminatable, // opcode 823 "JSConvertReceiver", // name 824 1, 1, 1, 1, 1, 0, // counts 825 convert_mode); // parameter 826 } 827 828 const Operator* JSOperatorBuilder::LoadNamed(Handle<Name> name, 829 const VectorSlotPair& feedback) { 830 NamedAccess access(SLOPPY, name, feedback); 831 return new (zone()) Operator1<NamedAccess>( // -- 832 IrOpcode::kJSLoadNamed, Operator::kNoProperties, // opcode 833 "JSLoadNamed", // name 834 1, 1, 1, 1, 1, 2, // counts 835 access); // parameter 836 } 837 838 const Operator* JSOperatorBuilder::LoadProperty( 839 VectorSlotPair const& feedback) { 840 PropertyAccess access(SLOPPY, feedback); 841 return new (zone()) Operator1<PropertyAccess>( // -- 842 IrOpcode::kJSLoadProperty, Operator::kNoProperties, // opcode 843 "JSLoadProperty", // name 844 2, 1, 1, 1, 1, 2, // counts 845 access); // parameter 846 } 847 848 const Operator* JSOperatorBuilder::GeneratorStore(int register_count) { 849 return new (zone()) Operator1<int>( // -- 850 IrOpcode::kJSGeneratorStore, Operator::kNoThrow, // opcode 851 "JSGeneratorStore", // name 852 3 + register_count, 1, 1, 0, 1, 0, // counts 853 register_count); // parameter 854 } 855 856 const Operator* JSOperatorBuilder::GeneratorRestoreRegister(int index) { 857 return new (zone()) Operator1<int>( // -- 858 IrOpcode::kJSGeneratorRestoreRegister, Operator::kNoThrow, // opcode 859 "JSGeneratorRestoreRegister", // name 860 1, 1, 1, 1, 1, 0, // counts 861 index); // parameter 862 } 863 864 const Operator* JSOperatorBuilder::StoreNamed(LanguageMode language_mode, 865 Handle<Name> name, 866 VectorSlotPair const& feedback) { 867 NamedAccess access(language_mode, name, feedback); 868 return new (zone()) Operator1<NamedAccess>( // -- 869 IrOpcode::kJSStoreNamed, Operator::kNoProperties, // opcode 870 "JSStoreNamed", // name 871 2, 1, 1, 0, 1, 2, // counts 872 access); // parameter 873 } 874 875 876 const Operator* JSOperatorBuilder::StoreProperty( 877 LanguageMode language_mode, VectorSlotPair const& feedback) { 878 PropertyAccess access(language_mode, feedback); 879 return new (zone()) Operator1<PropertyAccess>( // -- 880 IrOpcode::kJSStoreProperty, Operator::kNoProperties, // opcode 881 "JSStoreProperty", // name 882 3, 1, 1, 0, 1, 2, // counts 883 access); // parameter 884 } 885 886 const Operator* JSOperatorBuilder::StoreNamedOwn( 887 Handle<Name> name, VectorSlotPair const& feedback) { 888 StoreNamedOwnParameters parameters(name, feedback); 889 return new (zone()) Operator1<StoreNamedOwnParameters>( // -- 890 IrOpcode::kJSStoreNamedOwn, Operator::kNoProperties, // opcode 891 "JSStoreNamedOwn", // name 892 2, 1, 1, 0, 1, 2, // counts 893 parameters); // parameter 894 } 895 896 const Operator* JSOperatorBuilder::DeleteProperty(LanguageMode language_mode) { 897 return new (zone()) Operator1<LanguageMode>( // -- 898 IrOpcode::kJSDeleteProperty, Operator::kNoProperties, // opcode 899 "JSDeleteProperty", // name 900 2, 1, 1, 1, 1, 2, // counts 901 language_mode); // parameter 902 } 903 904 905 const Operator* JSOperatorBuilder::LoadGlobal(const Handle<Name>& name, 906 const VectorSlotPair& feedback, 907 TypeofMode typeof_mode) { 908 LoadGlobalParameters parameters(name, feedback, typeof_mode); 909 return new (zone()) Operator1<LoadGlobalParameters>( // -- 910 IrOpcode::kJSLoadGlobal, Operator::kNoProperties, // opcode 911 "JSLoadGlobal", // name 912 0, 1, 1, 1, 1, 2, // counts 913 parameters); // parameter 914 } 915 916 917 const Operator* JSOperatorBuilder::StoreGlobal(LanguageMode language_mode, 918 const Handle<Name>& name, 919 const VectorSlotPair& feedback) { 920 StoreGlobalParameters parameters(language_mode, feedback, name); 921 return new (zone()) Operator1<StoreGlobalParameters>( // -- 922 IrOpcode::kJSStoreGlobal, Operator::kNoProperties, // opcode 923 "JSStoreGlobal", // name 924 1, 1, 1, 0, 1, 2, // counts 925 parameters); // parameter 926 } 927 928 929 const Operator* JSOperatorBuilder::LoadContext(size_t depth, size_t index, 930 bool immutable) { 931 ContextAccess access(depth, index, immutable); 932 return new (zone()) Operator1<ContextAccess>( // -- 933 IrOpcode::kJSLoadContext, // opcode 934 Operator::kNoWrite | Operator::kNoThrow, // flags 935 "JSLoadContext", // name 936 0, 1, 0, 1, 1, 0, // counts 937 access); // parameter 938 } 939 940 941 const Operator* JSOperatorBuilder::StoreContext(size_t depth, size_t index) { 942 ContextAccess access(depth, index, false); 943 return new (zone()) Operator1<ContextAccess>( // -- 944 IrOpcode::kJSStoreContext, // opcode 945 Operator::kNoRead | Operator::kNoThrow, // flags 946 "JSStoreContext", // name 947 1, 1, 1, 0, 1, 0, // counts 948 access); // parameter 949 } 950 951 const Operator* JSOperatorBuilder::LoadModule(int32_t cell_index) { 952 return new (zone()) Operator1<int32_t>( // -- 953 IrOpcode::kJSLoadModule, // opcode 954 Operator::kNoWrite | Operator::kNoThrow, // flags 955 "JSLoadModule", // name 956 1, 1, 1, 1, 1, 0, // counts 957 cell_index); // parameter 958 } 959 960 const Operator* JSOperatorBuilder::StoreModule(int32_t cell_index) { 961 return new (zone()) Operator1<int32_t>( // -- 962 IrOpcode::kJSStoreModule, // opcode 963 Operator::kNoRead | Operator::kNoThrow, // flags 964 "JSStoreModule", // name 965 2, 1, 1, 0, 1, 0, // counts 966 cell_index); // parameter 967 } 968 969 const Operator* JSOperatorBuilder::CreateArguments(CreateArgumentsType type) { 970 return new (zone()) Operator1<CreateArgumentsType>( // -- 971 IrOpcode::kJSCreateArguments, Operator::kEliminatable, // opcode 972 "JSCreateArguments", // name 973 1, 1, 0, 1, 1, 0, // counts 974 type); // parameter 975 } 976 977 978 const Operator* JSOperatorBuilder::CreateArray(size_t arity, 979 Handle<AllocationSite> site) { 980 // constructor, new_target, arg1, ..., argN 981 int const value_input_count = static_cast<int>(arity) + 2; 982 CreateArrayParameters parameters(arity, site); 983 return new (zone()) Operator1<CreateArrayParameters>( // -- 984 IrOpcode::kJSCreateArray, Operator::kNoProperties, // opcode 985 "JSCreateArray", // name 986 value_input_count, 1, 1, 1, 1, 2, // counts 987 parameters); // parameter 988 } 989 990 const Operator* JSOperatorBuilder::CreateClosure( 991 Handle<SharedFunctionInfo> shared_info, VectorSlotPair const& feedback, 992 PretenureFlag pretenure) { 993 CreateClosureParameters parameters(shared_info, feedback, pretenure); 994 return new (zone()) Operator1<CreateClosureParameters>( // -- 995 IrOpcode::kJSCreateClosure, Operator::kNoThrow, // opcode 996 "JSCreateClosure", // name 997 0, 1, 1, 1, 1, 0, // counts 998 parameters); // parameter 999 } 1000 1001 const Operator* JSOperatorBuilder::CreateLiteralArray( 1002 Handle<ConstantElementsPair> constant_elements, int literal_flags, 1003 int literal_index, int number_of_elements) { 1004 CreateLiteralParameters parameters(constant_elements, number_of_elements, 1005 literal_flags, literal_index); 1006 return new (zone()) Operator1<CreateLiteralParameters>( // -- 1007 IrOpcode::kJSCreateLiteralArray, Operator::kNoProperties, // opcode 1008 "JSCreateLiteralArray", // name 1009 1, 1, 1, 1, 1, 2, // counts 1010 parameters); // parameter 1011 } 1012 1013 const Operator* JSOperatorBuilder::CreateLiteralObject( 1014 Handle<BoilerplateDescription> constant_properties, int literal_flags, 1015 int literal_index, int number_of_properties) { 1016 CreateLiteralParameters parameters(constant_properties, number_of_properties, 1017 literal_flags, literal_index); 1018 return new (zone()) Operator1<CreateLiteralParameters>( // -- 1019 IrOpcode::kJSCreateLiteralObject, Operator::kNoProperties, // opcode 1020 "JSCreateLiteralObject", // name 1021 1, 1, 1, 1, 1, 2, // counts 1022 parameters); // parameter 1023 } 1024 1025 1026 const Operator* JSOperatorBuilder::CreateLiteralRegExp( 1027 Handle<String> constant_pattern, int literal_flags, int literal_index) { 1028 CreateLiteralParameters parameters(constant_pattern, -1, literal_flags, 1029 literal_index); 1030 return new (zone()) Operator1<CreateLiteralParameters>( // -- 1031 IrOpcode::kJSCreateLiteralRegExp, Operator::kNoProperties, // opcode 1032 "JSCreateLiteralRegExp", // name 1033 1, 1, 1, 1, 1, 2, // counts 1034 parameters); // parameter 1035 } 1036 1037 const Operator* JSOperatorBuilder::CreateFunctionContext(int slot_count, 1038 ScopeType scope_type) { 1039 CreateFunctionContextParameters parameters(slot_count, scope_type); 1040 return new (zone()) Operator1<CreateFunctionContextParameters>( // -- 1041 IrOpcode::kJSCreateFunctionContext, Operator::kNoProperties, // opcode 1042 "JSCreateFunctionContext", // name 1043 1, 1, 1, 1, 1, 2, // counts 1044 parameters); // parameter 1045 } 1046 1047 const Operator* JSOperatorBuilder::CreateCatchContext( 1048 const Handle<String>& name, const Handle<ScopeInfo>& scope_info) { 1049 CreateCatchContextParameters parameters(name, scope_info); 1050 return new (zone()) Operator1<CreateCatchContextParameters>( 1051 IrOpcode::kJSCreateCatchContext, Operator::kNoProperties, // opcode 1052 "JSCreateCatchContext", // name 1053 2, 1, 1, 1, 1, 2, // counts 1054 parameters); // parameter 1055 } 1056 1057 const Operator* JSOperatorBuilder::CreateWithContext( 1058 const Handle<ScopeInfo>& scope_info) { 1059 return new (zone()) Operator1<Handle<ScopeInfo>>( 1060 IrOpcode::kJSCreateWithContext, Operator::kNoProperties, // opcode 1061 "JSCreateWithContext", // name 1062 2, 1, 1, 1, 1, 2, // counts 1063 scope_info); // parameter 1064 } 1065 1066 const Operator* JSOperatorBuilder::CreateBlockContext( 1067 const Handle<ScopeInfo>& scope_info) { 1068 return new (zone()) Operator1<Handle<ScopeInfo>>( // -- 1069 IrOpcode::kJSCreateBlockContext, Operator::kNoProperties, // opcode 1070 "JSCreateBlockContext", // name 1071 1, 1, 1, 1, 1, 2, // counts 1072 scope_info); // parameter 1073 } 1074 1075 const Operator* JSOperatorBuilder::CreateScriptContext( 1076 const Handle<ScopeInfo>& scope_info) { 1077 return new (zone()) Operator1<Handle<ScopeInfo>>( // -- 1078 IrOpcode::kJSCreateScriptContext, Operator::kNoProperties, // opcode 1079 "JSCreateScriptContext", // name 1080 1, 1, 1, 1, 1, 2, // counts 1081 scope_info); // parameter 1082 } 1083 1084 } // namespace compiler 1085 } // namespace internal 1086 } // namespace v8 1087