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 #ifndef V8_CODE_STUBS_H_ 6 #define V8_CODE_STUBS_H_ 7 8 #include "src/allocation.h" 9 #include "src/assembler.h" 10 #include "src/code-stub-assembler.h" 11 #include "src/codegen.h" 12 #include "src/globals.h" 13 #include "src/ic/ic-state.h" 14 #include "src/interface-descriptors.h" 15 #include "src/macro-assembler.h" 16 #include "src/ostreams.h" 17 #include "src/type-hints.h" 18 19 namespace v8 { 20 namespace internal { 21 22 class ObjectLiteral; 23 24 // List of code stubs used on all platforms. 25 #define CODE_STUB_LIST_ALL_PLATFORMS(V) \ 26 /* --- PlatformCodeStubs --- */ \ 27 V(ArrayConstructor) \ 28 V(BinaryOpICWithAllocationSite) \ 29 V(CallApiCallback) \ 30 V(CallApiGetter) \ 31 V(CallConstruct) \ 32 V(CallIC) \ 33 V(CEntry) \ 34 V(CompareIC) \ 35 V(DoubleToI) \ 36 V(FunctionPrototype) \ 37 V(InternalArrayConstructor) \ 38 V(JSEntry) \ 39 V(LoadIndexedString) \ 40 V(MathPow) \ 41 V(ProfileEntryHook) \ 42 V(RecordWrite) \ 43 V(RegExpExec) \ 44 V(StoreBufferOverflow) \ 45 V(StoreElement) \ 46 V(SubString) \ 47 V(KeyedStoreIC) \ 48 V(LoadGlobalIC) \ 49 V(FastNewObject) \ 50 V(FastNewRestParameter) \ 51 V(FastNewSloppyArguments) \ 52 V(FastNewStrictArguments) \ 53 V(NameDictionaryLookup) \ 54 /* This can be removed once there are no */ \ 55 /* more deopting Hydrogen stubs. */ \ 56 V(StubFailureTrampoline) \ 57 /* These are only called from FCG */ \ 58 /* They can be removed when only the TF */ \ 59 /* version of the corresponding stub is */ \ 60 /* used universally */ \ 61 V(CallICTrampoline) \ 62 V(KeyedStoreICTrampoline) \ 63 /* --- HydrogenCodeStubs --- */ \ 64 /* These builtins w/ JS linkage are */ \ 65 /* just fast-cases of C++ builtins. They */ \ 66 /* require varg support from TF */ \ 67 V(FastArrayPush) \ 68 V(FastFunctionBind) \ 69 /* These will be ported/eliminated */ \ 70 /* as part of the new IC system, ask */ \ 71 /* ishell before doing anything */ \ 72 V(LoadConstant) \ 73 V(LoadDictionaryElement) \ 74 V(LoadFastElement) \ 75 V(LoadField) \ 76 /* These should never be ported to TF */ \ 77 /* because they are either used only by */ \ 78 /* FCG/Crankshaft or are deprecated */ \ 79 V(BinaryOpIC) \ 80 V(BinaryOpWithAllocationSite) \ 81 V(ToBooleanIC) \ 82 V(TransitionElementsKind) \ 83 /* --- TurboFanCodeStubs --- */ \ 84 V(AllocateHeapNumber) \ 85 V(AllocateFloat32x4) \ 86 V(AllocateInt32x4) \ 87 V(AllocateUint32x4) \ 88 V(AllocateBool32x4) \ 89 V(AllocateInt16x8) \ 90 V(AllocateUint16x8) \ 91 V(AllocateBool16x8) \ 92 V(AllocateInt8x16) \ 93 V(AllocateUint8x16) \ 94 V(AllocateBool8x16) \ 95 V(ArrayNoArgumentConstructor) \ 96 V(ArraySingleArgumentConstructor) \ 97 V(ArrayNArgumentsConstructor) \ 98 V(CreateAllocationSite) \ 99 V(CreateWeakCell) \ 100 V(StringLength) \ 101 V(AddWithFeedback) \ 102 V(SubtractWithFeedback) \ 103 V(MultiplyWithFeedback) \ 104 V(DivideWithFeedback) \ 105 V(ModulusWithFeedback) \ 106 V(Inc) \ 107 V(InternalArrayNoArgumentConstructor) \ 108 V(InternalArraySingleArgumentConstructor) \ 109 V(Dec) \ 110 V(ElementsTransitionAndStore) \ 111 V(FastCloneRegExp) \ 112 V(FastCloneShallowArray) \ 113 V(FastCloneShallowObject) \ 114 V(FastNewClosure) \ 115 V(FastNewFunctionContext) \ 116 V(KeyedLoadSloppyArguments) \ 117 V(KeyedStoreSloppyArguments) \ 118 V(LoadScriptContextField) \ 119 V(StoreScriptContextField) \ 120 V(NumberToString) \ 121 V(StringAdd) \ 122 V(GetProperty) \ 123 V(LoadIC) \ 124 V(LoadICProtoArray) \ 125 V(KeyedLoadICTF) \ 126 V(StoreFastElement) \ 127 V(StoreField) \ 128 V(StoreGlobal) \ 129 V(StoreIC) \ 130 V(KeyedStoreICTF) \ 131 V(StoreInterceptor) \ 132 V(StoreMap) \ 133 V(StoreTransition) \ 134 V(LoadApiGetter) \ 135 V(LoadIndexedInterceptor) \ 136 V(GrowArrayElements) \ 137 /* These are only called from FGC and */ \ 138 /* can be removed when we use ignition */ \ 139 /* only */ \ 140 V(LoadICTrampoline) \ 141 V(LoadGlobalICTrampoline) \ 142 V(KeyedLoadICTrampolineTF) \ 143 V(StoreICTrampoline) \ 144 V(KeyedStoreICTrampolineTF) 145 146 // List of code stubs only used on ARM 32 bits platforms. 147 #if V8_TARGET_ARCH_ARM 148 #define CODE_STUB_LIST_ARM(V) V(DirectCEntry) 149 150 #else 151 #define CODE_STUB_LIST_ARM(V) 152 #endif 153 154 // List of code stubs only used on ARM 64 bits platforms. 155 #if V8_TARGET_ARCH_ARM64 156 #define CODE_STUB_LIST_ARM64(V) \ 157 V(DirectCEntry) \ 158 V(RestoreRegistersState) \ 159 V(StoreRegistersState) 160 161 #else 162 #define CODE_STUB_LIST_ARM64(V) 163 #endif 164 165 // List of code stubs only used on PPC platforms. 166 #ifdef V8_TARGET_ARCH_PPC 167 #define CODE_STUB_LIST_PPC(V) \ 168 V(DirectCEntry) \ 169 V(StoreRegistersState) \ 170 V(RestoreRegistersState) 171 #else 172 #define CODE_STUB_LIST_PPC(V) 173 #endif 174 175 // List of code stubs only used on MIPS platforms. 176 #if V8_TARGET_ARCH_MIPS 177 #define CODE_STUB_LIST_MIPS(V) \ 178 V(DirectCEntry) \ 179 V(RestoreRegistersState) \ 180 V(StoreRegistersState) 181 #elif V8_TARGET_ARCH_MIPS64 182 #define CODE_STUB_LIST_MIPS(V) \ 183 V(DirectCEntry) \ 184 V(RestoreRegistersState) \ 185 V(StoreRegistersState) 186 #else 187 #define CODE_STUB_LIST_MIPS(V) 188 #endif 189 190 // List of code stubs only used on S390 platforms. 191 #ifdef V8_TARGET_ARCH_S390 192 #define CODE_STUB_LIST_S390(V) \ 193 V(DirectCEntry) \ 194 V(StoreRegistersState) \ 195 V(RestoreRegistersState) 196 #else 197 #define CODE_STUB_LIST_S390(V) 198 #endif 199 200 // Combined list of code stubs. 201 #define CODE_STUB_LIST(V) \ 202 CODE_STUB_LIST_ALL_PLATFORMS(V) \ 203 CODE_STUB_LIST_ARM(V) \ 204 CODE_STUB_LIST_ARM64(V) \ 205 CODE_STUB_LIST_PPC(V) \ 206 CODE_STUB_LIST_MIPS(V) \ 207 CODE_STUB_LIST_S390(V) 208 209 static const int kHasReturnedMinusZeroSentinel = 1; 210 211 // Stub is base classes of all stubs. 212 class CodeStub BASE_EMBEDDED { 213 public: 214 enum Major { 215 // TODO(mvstanton): eliminate the NoCache key by getting rid 216 // of the non-monomorphic-cache. 217 NoCache = 0, // marker for stubs that do custom caching] 218 #define DEF_ENUM(name) name, 219 CODE_STUB_LIST(DEF_ENUM) 220 #undef DEF_ENUM 221 NUMBER_OF_IDS 222 }; 223 224 // Retrieve the code for the stub. Generate the code if needed. 225 Handle<Code> GetCode(); 226 227 // Retrieve the code for the stub, make and return a copy of the code. 228 Handle<Code> GetCodeCopy(const Code::FindAndReplacePattern& pattern); 229 230 static Major MajorKeyFromKey(uint32_t key) { 231 return static_cast<Major>(MajorKeyBits::decode(key)); 232 } 233 static uint32_t MinorKeyFromKey(uint32_t key) { 234 return MinorKeyBits::decode(key); 235 } 236 237 // Gets the major key from a code object that is a code stub or binary op IC. 238 static Major GetMajorKey(Code* code_stub) { 239 return MajorKeyFromKey(code_stub->stub_key()); 240 } 241 242 static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); } 243 244 static const char* MajorName(Major major_key); 245 246 explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {} 247 virtual ~CodeStub() {} 248 249 static void GenerateStubsAheadOfTime(Isolate* isolate); 250 static void GenerateFPStubs(Isolate* isolate); 251 252 // Some stubs put untagged junk on the stack that cannot be scanned by the 253 // GC. This means that we must be statically sure that no GC can occur while 254 // they are running. If that is the case they should override this to return 255 // true, which will cause an assertion if we try to call something that can 256 // GC or if we try to put a stack frame on top of the junk, which would not 257 // result in a traversable stack. 258 virtual bool SometimesSetsUpAFrame() { return true; } 259 260 // Lookup the code in the (possibly custom) cache. 261 bool FindCodeInCache(Code** code_out); 262 263 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() const = 0; 264 265 virtual int GetStackParameterCount() const { 266 return GetCallInterfaceDescriptor().GetStackParameterCount(); 267 } 268 269 virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {} 270 271 static void InitializeDescriptor(Isolate* isolate, uint32_t key, 272 CodeStubDescriptor* desc); 273 274 static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key); 275 276 // Returns information for computing the number key. 277 virtual Major MajorKey() const = 0; 278 uint32_t MinorKey() const { return minor_key_; } 279 280 // BinaryOpStub needs to override this. 281 virtual Code::Kind GetCodeKind() const; 282 283 virtual ExtraICState GetExtraICState() const { return kNoExtraICState; } 284 285 Code::Flags GetCodeFlags() const; 286 287 friend std::ostream& operator<<(std::ostream& os, const CodeStub& s) { 288 s.PrintName(os); 289 return os; 290 } 291 292 Isolate* isolate() const { return isolate_; } 293 294 protected: 295 CodeStub(uint32_t key, Isolate* isolate) 296 : minor_key_(MinorKeyFromKey(key)), isolate_(isolate) {} 297 298 // Generates the assembler code for the stub. 299 virtual Handle<Code> GenerateCode() = 0; 300 301 // Returns whether the code generated for this stub needs to be allocated as 302 // a fixed (non-moveable) code object. 303 virtual bool NeedsImmovableCode() { return false; } 304 305 virtual void PrintName(std::ostream& os) const; // NOLINT 306 virtual void PrintBaseName(std::ostream& os) const; // NOLINT 307 virtual void PrintState(std::ostream& os) const { ; } // NOLINT 308 309 // Computes the key based on major and minor. 310 uint32_t GetKey() { 311 DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS); 312 return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey()); 313 } 314 315 uint32_t minor_key_; 316 317 private: 318 // Perform bookkeeping required after code generation when stub code is 319 // initially generated. 320 void RecordCodeGeneration(Handle<Code> code); 321 322 // Finish the code object after it has been generated. 323 virtual void FinishCode(Handle<Code> code) { } 324 325 // Activate newly generated stub. Is called after 326 // registering stub in the stub cache. 327 virtual void Activate(Code* code) { } 328 329 // Add the code to a specialized cache, specific to an individual 330 // stub type. Please note, this method must add the code object to a 331 // roots object, otherwise we will remove the code during GC. 332 virtual void AddToSpecialCache(Handle<Code> new_object) { } 333 334 // Find code in a specialized cache, work is delegated to the specific stub. 335 virtual bool FindCodeInSpecialCache(Code** code_out) { 336 return false; 337 } 338 339 // If a stub uses a special cache override this. 340 virtual bool UseSpecialCache() { return false; } 341 342 // We use this dispatch to statically instantiate the correct code stub for 343 // the given stub key and call the passed function with that code stub. 344 typedef void (*DispatchedCall)(CodeStub* stub, void** value_out); 345 static void Dispatch(Isolate* isolate, uint32_t key, void** value_out, 346 DispatchedCall call); 347 348 static void GetCodeDispatchCall(CodeStub* stub, void** value_out); 349 350 STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits)); 351 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {}; 352 class MinorKeyBits: public BitField<uint32_t, 353 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT 354 355 friend class BreakPointIterator; 356 357 Isolate* isolate_; 358 }; 359 360 361 #define DEFINE_CODE_STUB_BASE(NAME, SUPER) \ 362 public: \ 363 NAME(uint32_t key, Isolate* isolate) : SUPER(key, isolate) {} \ 364 \ 365 private: \ 366 DISALLOW_COPY_AND_ASSIGN(NAME) 367 368 369 #define DEFINE_CODE_STUB(NAME, SUPER) \ 370 public: \ 371 inline Major MajorKey() const override { return NAME; }; \ 372 \ 373 protected: \ 374 DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER) 375 376 377 #define DEFINE_PLATFORM_CODE_STUB(NAME, SUPER) \ 378 private: \ 379 void Generate(MacroAssembler* masm) override; \ 380 DEFINE_CODE_STUB(NAME, SUPER) 381 382 383 #define DEFINE_HYDROGEN_CODE_STUB(NAME, SUPER) \ 384 public: \ 385 void InitializeDescriptor(CodeStubDescriptor* descriptor) override; \ 386 Handle<Code> GenerateCode() override; \ 387 DEFINE_CODE_STUB(NAME, SUPER) 388 389 #define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER) \ 390 public: \ 391 void GenerateAssembly(CodeStubAssembler* assembler) const override; \ 392 DEFINE_CODE_STUB(NAME, SUPER) 393 394 #define DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(NAME, SUPER) \ 395 public: \ 396 static compiler::Node* Generate(CodeStubAssembler* assembler, \ 397 compiler::Node* left, compiler::Node* right, \ 398 compiler::Node* context); \ 399 void GenerateAssembly(CodeStubAssembler* assembler) const override { \ 400 assembler->Return(Generate(assembler, assembler->Parameter(0), \ 401 assembler->Parameter(1), \ 402 assembler->Parameter(2))); \ 403 } \ 404 DEFINE_CODE_STUB(NAME, SUPER) 405 406 #define DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(NAME, SUPER) \ 407 public: \ 408 static compiler::Node* Generate( \ 409 CodeStubAssembler* assembler, compiler::Node* left, \ 410 compiler::Node* right, compiler::Node* slot_id, \ 411 compiler::Node* type_feedback_vector, compiler::Node* context); \ 412 void GenerateAssembly(CodeStubAssembler* assembler) const override { \ 413 assembler->Return( \ 414 Generate(assembler, assembler->Parameter(0), assembler->Parameter(1), \ 415 assembler->Parameter(2), assembler->Parameter(3), \ 416 assembler->Parameter(4))); \ 417 } \ 418 DEFINE_CODE_STUB(NAME, SUPER) 419 420 #define DEFINE_TURBOFAN_UNARY_OP_CODE_STUB(NAME, SUPER) \ 421 public: \ 422 static compiler::Node* Generate(CodeStubAssembler* assembler, \ 423 compiler::Node* value, \ 424 compiler::Node* context); \ 425 void GenerateAssembly(CodeStubAssembler* assembler) const override { \ 426 assembler->Return(Generate(assembler, assembler->Parameter(0), \ 427 assembler->Parameter(1))); \ 428 } \ 429 DEFINE_CODE_STUB(NAME, SUPER) 430 431 #define DEFINE_TURBOFAN_UNARY_OP_CODE_STUB_WITH_FEEDBACK(NAME, SUPER) \ 432 public: \ 433 static compiler::Node* Generate( \ 434 CodeStubAssembler* assembler, compiler::Node* value, \ 435 compiler::Node* context, compiler::Node* type_feedback_vector, \ 436 compiler::Node* slot_id); \ 437 void GenerateAssembly(CodeStubAssembler* assembler) const override { \ 438 assembler->Return( \ 439 Generate(assembler, assembler->Parameter(0), assembler->Parameter(1), \ 440 assembler->Parameter(2), assembler->Parameter(3))); \ 441 } \ 442 DEFINE_CODE_STUB(NAME, SUPER) 443 444 #define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \ 445 public: \ 446 Handle<Code> GenerateCode() override; \ 447 DEFINE_CODE_STUB(NAME, SUPER) 448 449 #define DEFINE_CALL_INTERFACE_DESCRIPTOR(NAME) \ 450 public: \ 451 typedef NAME##Descriptor Descriptor; \ 452 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \ 453 return Descriptor(isolate()); \ 454 } 455 456 // There are some code stubs we just can't describe right now with a 457 // CallInterfaceDescriptor. Isolate behavior for those cases with this macro. 458 // An attempt to retrieve a descriptor will fail. 459 #define DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR() \ 460 public: \ 461 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \ 462 UNREACHABLE(); \ 463 return CallInterfaceDescriptor(); \ 464 } 465 466 467 class PlatformCodeStub : public CodeStub { 468 public: 469 // Retrieve the code for the stub. Generate the code if needed. 470 Handle<Code> GenerateCode() override; 471 472 protected: 473 explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {} 474 475 // Generates the assembler code for the stub. 476 virtual void Generate(MacroAssembler* masm) = 0; 477 478 DEFINE_CODE_STUB_BASE(PlatformCodeStub, CodeStub); 479 }; 480 481 482 enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE }; 483 484 485 class CodeStubDescriptor { 486 public: 487 explicit CodeStubDescriptor(CodeStub* stub); 488 489 CodeStubDescriptor(Isolate* isolate, uint32_t stub_key); 490 491 void Initialize(Address deoptimization_handler = NULL, 492 int hint_stack_parameter_count = -1, 493 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE); 494 void Initialize(Register stack_parameter_count, 495 Address deoptimization_handler = NULL, 496 int hint_stack_parameter_count = -1, 497 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE); 498 499 void SetMissHandler(Runtime::FunctionId id) { 500 miss_handler_id_ = id; 501 miss_handler_ = ExternalReference(Runtime::FunctionForId(id), isolate_); 502 has_miss_handler_ = true; 503 // Our miss handler infrastructure doesn't currently support 504 // variable stack parameter counts. 505 DCHECK(!stack_parameter_count_.is_valid()); 506 } 507 508 void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; } 509 CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; } 510 511 int GetRegisterParameterCount() const { 512 return call_descriptor().GetRegisterParameterCount(); 513 } 514 515 int GetStackParameterCount() const { 516 return call_descriptor().GetStackParameterCount(); 517 } 518 519 int GetParameterCount() const { 520 return call_descriptor().GetParameterCount(); 521 } 522 523 Register GetRegisterParameter(int index) const { 524 return call_descriptor().GetRegisterParameter(index); 525 } 526 527 MachineType GetParameterType(int index) const { 528 return call_descriptor().GetParameterType(index); 529 } 530 531 ExternalReference miss_handler() const { 532 DCHECK(has_miss_handler_); 533 return miss_handler_; 534 } 535 536 Runtime::FunctionId miss_handler_id() const { 537 DCHECK(has_miss_handler_); 538 return miss_handler_id_; 539 } 540 541 bool has_miss_handler() const { 542 return has_miss_handler_; 543 } 544 545 int GetHandlerParameterCount() const { 546 int params = GetParameterCount(); 547 if (PassesArgumentsToDeoptimizationHandler()) { 548 params += 1; 549 } 550 return params; 551 } 552 553 int hint_stack_parameter_count() const { return hint_stack_parameter_count_; } 554 Register stack_parameter_count() const { return stack_parameter_count_; } 555 StubFunctionMode function_mode() const { return function_mode_; } 556 Address deoptimization_handler() const { return deoptimization_handler_; } 557 558 private: 559 bool PassesArgumentsToDeoptimizationHandler() const { 560 return stack_parameter_count_.is_valid(); 561 } 562 563 Isolate* isolate_; 564 CallInterfaceDescriptor call_descriptor_; 565 Register stack_parameter_count_; 566 // If hint_stack_parameter_count_ > 0, the code stub can optimize the 567 // return sequence. Default value is -1, which means it is ignored. 568 int hint_stack_parameter_count_; 569 StubFunctionMode function_mode_; 570 571 Address deoptimization_handler_; 572 573 ExternalReference miss_handler_; 574 Runtime::FunctionId miss_handler_id_; 575 bool has_miss_handler_; 576 }; 577 578 579 class HydrogenCodeStub : public CodeStub { 580 public: 581 enum InitializationState { 582 UNINITIALIZED, 583 INITIALIZED 584 }; 585 586 template<class SubClass> 587 static Handle<Code> GetUninitialized(Isolate* isolate) { 588 SubClass::GenerateAheadOfTime(isolate); 589 return SubClass().GetCode(isolate); 590 } 591 592 // Retrieve the code for the stub. Generate the code if needed. 593 Handle<Code> GenerateCode() override = 0; 594 595 bool IsUninitialized() const { return IsMissBits::decode(minor_key_); } 596 597 Handle<Code> GenerateLightweightMissCode(ExternalReference miss); 598 599 Handle<Code> GenerateRuntimeTailCall(CodeStubDescriptor* descriptor); 600 601 template<class StateType> 602 void TraceTransition(StateType from, StateType to); 603 604 protected: 605 explicit HydrogenCodeStub(Isolate* isolate, 606 InitializationState state = INITIALIZED) 607 : CodeStub(isolate) { 608 minor_key_ = IsMissBits::encode(state == UNINITIALIZED); 609 } 610 611 void set_sub_minor_key(uint32_t key) { 612 minor_key_ = SubMinorKeyBits::update(minor_key_, key); 613 } 614 615 uint32_t sub_minor_key() const { return SubMinorKeyBits::decode(minor_key_); } 616 617 static const int kSubMinorKeyBits = kStubMinorKeyBits - 1; 618 619 private: 620 class IsMissBits : public BitField<bool, kSubMinorKeyBits, 1> {}; 621 class SubMinorKeyBits : public BitField<int, 0, kSubMinorKeyBits> {}; 622 623 void GenerateLightweightMiss(MacroAssembler* masm, ExternalReference miss); 624 625 DEFINE_CODE_STUB_BASE(HydrogenCodeStub, CodeStub); 626 }; 627 628 629 class TurboFanCodeStub : public CodeStub { 630 public: 631 // Retrieve the code for the stub. Generate the code if needed. 632 Handle<Code> GenerateCode() override; 633 634 int GetStackParameterCount() const override { 635 return GetCallInterfaceDescriptor().GetStackParameterCount(); 636 } 637 638 protected: 639 explicit TurboFanCodeStub(Isolate* isolate) : CodeStub(isolate) {} 640 641 virtual void GenerateAssembly(CodeStubAssembler* assembler) const = 0; 642 643 private: 644 DEFINE_CODE_STUB_BASE(TurboFanCodeStub, CodeStub); 645 }; 646 647 648 // Helper interface to prepare to/restore after making runtime calls. 649 class RuntimeCallHelper { 650 public: 651 virtual ~RuntimeCallHelper() {} 652 653 virtual void BeforeCall(MacroAssembler* masm) const = 0; 654 655 virtual void AfterCall(MacroAssembler* masm) const = 0; 656 657 protected: 658 RuntimeCallHelper() {} 659 660 private: 661 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper); 662 }; 663 664 665 } // namespace internal 666 } // namespace v8 667 668 #if V8_TARGET_ARCH_IA32 669 #include "src/ia32/code-stubs-ia32.h" 670 #elif V8_TARGET_ARCH_X64 671 #include "src/x64/code-stubs-x64.h" 672 #elif V8_TARGET_ARCH_ARM64 673 #include "src/arm64/code-stubs-arm64.h" 674 #elif V8_TARGET_ARCH_ARM 675 #include "src/arm/code-stubs-arm.h" 676 #elif V8_TARGET_ARCH_PPC 677 #include "src/ppc/code-stubs-ppc.h" 678 #elif V8_TARGET_ARCH_MIPS 679 #include "src/mips/code-stubs-mips.h" 680 #elif V8_TARGET_ARCH_MIPS64 681 #include "src/mips64/code-stubs-mips64.h" 682 #elif V8_TARGET_ARCH_S390 683 #include "src/s390/code-stubs-s390.h" 684 #elif V8_TARGET_ARCH_X87 685 #include "src/x87/code-stubs-x87.h" 686 #else 687 #error Unsupported target architecture. 688 #endif 689 690 namespace v8 { 691 namespace internal { 692 693 694 // RuntimeCallHelper implementation used in stubs: enters/leaves a 695 // newly created internal frame before/after the runtime call. 696 class StubRuntimeCallHelper : public RuntimeCallHelper { 697 public: 698 StubRuntimeCallHelper() {} 699 700 void BeforeCall(MacroAssembler* masm) const override; 701 702 void AfterCall(MacroAssembler* masm) const override; 703 }; 704 705 706 // Trivial RuntimeCallHelper implementation. 707 class NopRuntimeCallHelper : public RuntimeCallHelper { 708 public: 709 NopRuntimeCallHelper() {} 710 711 void BeforeCall(MacroAssembler* masm) const override {} 712 713 void AfterCall(MacroAssembler* masm) const override {} 714 }; 715 716 717 class StringLengthStub : public TurboFanCodeStub { 718 public: 719 explicit StringLengthStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 720 721 Code::Kind GetCodeKind() const override { return Code::HANDLER; } 722 ExtraICState GetExtraICState() const override { return Code::LOAD_IC; } 723 724 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector); 725 DEFINE_TURBOFAN_CODE_STUB(StringLength, TurboFanCodeStub); 726 }; 727 728 class AddWithFeedbackStub final : public TurboFanCodeStub { 729 public: 730 explicit AddWithFeedbackStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 731 732 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector); 733 DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(AddWithFeedback, 734 TurboFanCodeStub); 735 }; 736 737 class SubtractWithFeedbackStub final : public TurboFanCodeStub { 738 public: 739 explicit SubtractWithFeedbackStub(Isolate* isolate) 740 : TurboFanCodeStub(isolate) {} 741 742 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector); 743 DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(SubtractWithFeedback, 744 TurboFanCodeStub); 745 }; 746 747 class MultiplyWithFeedbackStub final : public TurboFanCodeStub { 748 public: 749 explicit MultiplyWithFeedbackStub(Isolate* isolate) 750 : TurboFanCodeStub(isolate) {} 751 752 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector); 753 DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(MultiplyWithFeedback, 754 TurboFanCodeStub); 755 }; 756 757 class DivideWithFeedbackStub final : public TurboFanCodeStub { 758 public: 759 explicit DivideWithFeedbackStub(Isolate* isolate) 760 : TurboFanCodeStub(isolate) {} 761 762 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector); 763 DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(DivideWithFeedback, 764 TurboFanCodeStub); 765 }; 766 767 class ModulusWithFeedbackStub final : public TurboFanCodeStub { 768 public: 769 explicit ModulusWithFeedbackStub(Isolate* isolate) 770 : TurboFanCodeStub(isolate) {} 771 772 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector); 773 DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(ModulusWithFeedback, 774 TurboFanCodeStub); 775 }; 776 777 class IncStub final : public TurboFanCodeStub { 778 public: 779 explicit IncStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 780 781 DEFINE_CALL_INTERFACE_DESCRIPTOR(CountOp); 782 DEFINE_TURBOFAN_UNARY_OP_CODE_STUB_WITH_FEEDBACK(Inc, TurboFanCodeStub); 783 }; 784 785 class DecStub final : public TurboFanCodeStub { 786 public: 787 explicit DecStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 788 789 DEFINE_CALL_INTERFACE_DESCRIPTOR(CountOp); 790 DEFINE_TURBOFAN_UNARY_OP_CODE_STUB_WITH_FEEDBACK(Dec, TurboFanCodeStub); 791 }; 792 793 class StoreInterceptorStub : public TurboFanCodeStub { 794 public: 795 explicit StoreInterceptorStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 796 797 void GenerateAssembly(CodeStubAssembler* assember) const override; 798 799 Code::Kind GetCodeKind() const override { return Code::HANDLER; } 800 ExtraICState GetExtraICState() const override { return Code::STORE_IC; } 801 802 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); 803 DEFINE_CODE_STUB(StoreInterceptor, TurboFanCodeStub); 804 }; 805 806 class LoadIndexedInterceptorStub : public TurboFanCodeStub { 807 public: 808 explicit LoadIndexedInterceptorStub(Isolate* isolate) 809 : TurboFanCodeStub(isolate) {} 810 811 Code::Kind GetCodeKind() const override { return Code::HANDLER; } 812 ExtraICState GetExtraICState() const override { return Code::KEYED_LOAD_IC; } 813 814 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector); 815 DEFINE_TURBOFAN_CODE_STUB(LoadIndexedInterceptor, TurboFanCodeStub); 816 }; 817 818 // ES6 [[Get]] operation. 819 class GetPropertyStub : public TurboFanCodeStub { 820 public: 821 explicit GetPropertyStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 822 823 DEFINE_CALL_INTERFACE_DESCRIPTOR(GetProperty); 824 DEFINE_TURBOFAN_CODE_STUB(GetProperty, TurboFanCodeStub); 825 }; 826 827 class NumberToStringStub final : public TurboFanCodeStub { 828 public: 829 explicit NumberToStringStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 830 831 DEFINE_CALL_INTERFACE_DESCRIPTOR(TypeConversion); 832 DEFINE_TURBOFAN_CODE_STUB(NumberToString, TurboFanCodeStub); 833 }; 834 835 class FastNewClosureStub : public TurboFanCodeStub { 836 public: 837 explicit FastNewClosureStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 838 839 static compiler::Node* Generate(CodeStubAssembler* assembler, 840 compiler::Node* shared_info, 841 compiler::Node* context); 842 843 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure); 844 DEFINE_TURBOFAN_CODE_STUB(FastNewClosure, TurboFanCodeStub); 845 }; 846 847 class FastNewFunctionContextStub final : public TurboFanCodeStub { 848 public: 849 static const int kMaximumSlots = 0x8000; 850 851 explicit FastNewFunctionContextStub(Isolate* isolate) 852 : TurboFanCodeStub(isolate) {} 853 854 static compiler::Node* Generate(CodeStubAssembler* assembler, 855 compiler::Node* function, 856 compiler::Node* slots, 857 compiler::Node* context); 858 859 private: 860 // FastNewFunctionContextStub can only allocate closures which fit in the 861 // new space. 862 STATIC_ASSERT(((kMaximumSlots + Context::MIN_CONTEXT_SLOTS) * kPointerSize + 863 FixedArray::kHeaderSize) < kMaxRegularHeapObjectSize); 864 865 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewFunctionContext); 866 DEFINE_TURBOFAN_CODE_STUB(FastNewFunctionContext, TurboFanCodeStub); 867 }; 868 869 870 class FastNewObjectStub final : public PlatformCodeStub { 871 public: 872 explicit FastNewObjectStub(Isolate* isolate) : PlatformCodeStub(isolate) {} 873 874 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewObject); 875 DEFINE_PLATFORM_CODE_STUB(FastNewObject, PlatformCodeStub); 876 }; 877 878 879 // TODO(turbofan): This stub should be possible to write in TurboFan 880 // using the CodeStubAssembler very soon in a way that is as efficient 881 // and easy as the current handwritten version, which is partly a copy 882 // of the strict arguments object materialization code. 883 class FastNewRestParameterStub final : public PlatformCodeStub { 884 public: 885 explicit FastNewRestParameterStub(Isolate* isolate, 886 bool skip_stub_frame = false) 887 : PlatformCodeStub(isolate) { 888 minor_key_ = SkipStubFrameBits::encode(skip_stub_frame); 889 } 890 891 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewRestParameter); 892 DEFINE_PLATFORM_CODE_STUB(FastNewRestParameter, PlatformCodeStub); 893 894 int skip_stub_frame() const { return SkipStubFrameBits::decode(minor_key_); } 895 896 private: 897 class SkipStubFrameBits : public BitField<bool, 0, 1> {}; 898 }; 899 900 901 // TODO(turbofan): This stub should be possible to write in TurboFan 902 // using the CodeStubAssembler very soon in a way that is as efficient 903 // and easy as the current handwritten version. 904 class FastNewSloppyArgumentsStub final : public PlatformCodeStub { 905 public: 906 explicit FastNewSloppyArgumentsStub(Isolate* isolate, 907 bool skip_stub_frame = false) 908 : PlatformCodeStub(isolate) { 909 minor_key_ = SkipStubFrameBits::encode(skip_stub_frame); 910 } 911 912 int skip_stub_frame() const { return SkipStubFrameBits::decode(minor_key_); } 913 914 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewSloppyArguments); 915 DEFINE_PLATFORM_CODE_STUB(FastNewSloppyArguments, PlatformCodeStub); 916 917 private: 918 class SkipStubFrameBits : public BitField<bool, 0, 1> {}; 919 }; 920 921 922 // TODO(turbofan): This stub should be possible to write in TurboFan 923 // using the CodeStubAssembler very soon in a way that is as efficient 924 // and easy as the current handwritten version. 925 class FastNewStrictArgumentsStub final : public PlatformCodeStub { 926 public: 927 explicit FastNewStrictArgumentsStub(Isolate* isolate, 928 bool skip_stub_frame = false) 929 : PlatformCodeStub(isolate) { 930 minor_key_ = SkipStubFrameBits::encode(skip_stub_frame); 931 } 932 933 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewStrictArguments); 934 DEFINE_PLATFORM_CODE_STUB(FastNewStrictArguments, PlatformCodeStub); 935 936 int skip_stub_frame() const { return SkipStubFrameBits::decode(minor_key_); } 937 938 private: 939 class SkipStubFrameBits : public BitField<bool, 0, 1> {}; 940 }; 941 942 class FastCloneRegExpStub final : public TurboFanCodeStub { 943 public: 944 explicit FastCloneRegExpStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 945 946 static compiler::Node* Generate(CodeStubAssembler* assembler, 947 compiler::Node* closure, 948 compiler::Node* literal_index, 949 compiler::Node* pattern, 950 compiler::Node* flags, 951 compiler::Node* context); 952 953 private: 954 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneRegExp); 955 DEFINE_TURBOFAN_CODE_STUB(FastCloneRegExp, TurboFanCodeStub); 956 }; 957 958 class FastCloneShallowArrayStub : public TurboFanCodeStub { 959 public: 960 FastCloneShallowArrayStub(Isolate* isolate, 961 AllocationSiteMode allocation_site_mode) 962 : TurboFanCodeStub(isolate) { 963 minor_key_ = AllocationSiteModeBits::encode(allocation_site_mode); 964 } 965 966 static compiler::Node* Generate(CodeStubAssembler* assembler, 967 compiler::Node* closure, 968 compiler::Node* literal_index, 969 compiler::Node* context, 970 CodeStubAssembler::Label* call_runtime, 971 AllocationSiteMode allocation_site_mode); 972 973 AllocationSiteMode allocation_site_mode() const { 974 return AllocationSiteModeBits::decode(minor_key_); 975 } 976 977 private: 978 class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {}; 979 980 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowArray); 981 DEFINE_TURBOFAN_CODE_STUB(FastCloneShallowArray, TurboFanCodeStub); 982 }; 983 984 class FastCloneShallowObjectStub : public TurboFanCodeStub { 985 public: 986 // Maximum number of properties in copied object. 987 static const int kMaximumClonedProperties = 6; 988 989 FastCloneShallowObjectStub(Isolate* isolate, int length) 990 : TurboFanCodeStub(isolate) { 991 DCHECK_GE(length, 0); 992 DCHECK_LE(length, kMaximumClonedProperties); 993 minor_key_ = LengthBits::encode(LengthBits::encode(length)); 994 } 995 996 static compiler::Node* GenerateFastPath( 997 CodeStubAssembler* assembler, 998 compiler::CodeAssembler::Label* call_runtime, compiler::Node* closure, 999 compiler::Node* literals_index, compiler::Node* properties_count); 1000 1001 static bool IsSupported(ObjectLiteral* expr); 1002 static int PropertiesCount(int literal_length); 1003 1004 int length() const { return LengthBits::decode(minor_key_); } 1005 1006 private: 1007 class LengthBits : public BitField<int, 0, 4> {}; 1008 1009 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowObject); 1010 DEFINE_TURBOFAN_CODE_STUB(FastCloneShallowObject, TurboFanCodeStub); 1011 }; 1012 1013 class CreateAllocationSiteStub : public TurboFanCodeStub { 1014 public: 1015 explicit CreateAllocationSiteStub(Isolate* isolate) 1016 : TurboFanCodeStub(isolate) {} 1017 static void GenerateAheadOfTime(Isolate* isolate); 1018 1019 DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateAllocationSite); 1020 DEFINE_TURBOFAN_CODE_STUB(CreateAllocationSite, TurboFanCodeStub); 1021 }; 1022 1023 class CreateWeakCellStub : public TurboFanCodeStub { 1024 public: 1025 explicit CreateWeakCellStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 1026 1027 static void GenerateAheadOfTime(Isolate* isolate); 1028 1029 DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateWeakCell); 1030 DEFINE_TURBOFAN_CODE_STUB(CreateWeakCell, TurboFanCodeStub); 1031 }; 1032 1033 class GrowArrayElementsStub : public TurboFanCodeStub { 1034 public: 1035 GrowArrayElementsStub(Isolate* isolate, ElementsKind kind) 1036 : TurboFanCodeStub(isolate) { 1037 minor_key_ = ElementsKindBits::encode(GetHoleyElementsKind(kind)); 1038 } 1039 1040 ElementsKind elements_kind() const { 1041 return ElementsKindBits::decode(minor_key_); 1042 } 1043 1044 private: 1045 class ElementsKindBits : public BitField<ElementsKind, 0, 8> {}; 1046 1047 DEFINE_CALL_INTERFACE_DESCRIPTOR(GrowArrayElements); 1048 DEFINE_TURBOFAN_CODE_STUB(GrowArrayElements, TurboFanCodeStub); 1049 }; 1050 1051 class FastArrayPushStub : public HydrogenCodeStub { 1052 public: 1053 explicit FastArrayPushStub(Isolate* isolate) : HydrogenCodeStub(isolate) {} 1054 1055 private: 1056 DEFINE_CALL_INTERFACE_DESCRIPTOR(VarArgFunction); 1057 DEFINE_HYDROGEN_CODE_STUB(FastArrayPush, HydrogenCodeStub); 1058 }; 1059 1060 class FastFunctionBindStub : public HydrogenCodeStub { 1061 public: 1062 explicit FastFunctionBindStub(Isolate* isolate) : HydrogenCodeStub(isolate) {} 1063 1064 private: 1065 DEFINE_CALL_INTERFACE_DESCRIPTOR(VarArgFunction); 1066 DEFINE_HYDROGEN_CODE_STUB(FastFunctionBind, HydrogenCodeStub); 1067 }; 1068 1069 enum AllocationSiteOverrideMode { 1070 DONT_OVERRIDE, 1071 DISABLE_ALLOCATION_SITES, 1072 LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES 1073 }; 1074 1075 1076 class ArrayConstructorStub: public PlatformCodeStub { 1077 public: 1078 explicit ArrayConstructorStub(Isolate* isolate); 1079 1080 private: 1081 void GenerateDispatchToArrayStub(MacroAssembler* masm, 1082 AllocationSiteOverrideMode mode); 1083 1084 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNArgumentsConstructor); 1085 DEFINE_PLATFORM_CODE_STUB(ArrayConstructor, PlatformCodeStub); 1086 }; 1087 1088 1089 class InternalArrayConstructorStub: public PlatformCodeStub { 1090 public: 1091 explicit InternalArrayConstructorStub(Isolate* isolate); 1092 1093 private: 1094 void GenerateCase(MacroAssembler* masm, ElementsKind kind); 1095 1096 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNArgumentsConstructor); 1097 DEFINE_PLATFORM_CODE_STUB(InternalArrayConstructor, PlatformCodeStub); 1098 }; 1099 1100 1101 class MathPowStub: public PlatformCodeStub { 1102 public: 1103 enum ExponentType { INTEGER, DOUBLE, TAGGED }; 1104 1105 MathPowStub(Isolate* isolate, ExponentType exponent_type) 1106 : PlatformCodeStub(isolate) { 1107 minor_key_ = ExponentTypeBits::encode(exponent_type); 1108 } 1109 1110 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { 1111 if (exponent_type() == TAGGED) { 1112 return MathPowTaggedDescriptor(isolate()); 1113 } else if (exponent_type() == INTEGER) { 1114 return MathPowIntegerDescriptor(isolate()); 1115 } else { 1116 // A CallInterfaceDescriptor doesn't specify double registers (yet). 1117 DCHECK_EQ(DOUBLE, exponent_type()); 1118 return ContextOnlyDescriptor(isolate()); 1119 } 1120 } 1121 1122 private: 1123 ExponentType exponent_type() const { 1124 return ExponentTypeBits::decode(minor_key_); 1125 } 1126 1127 class ExponentTypeBits : public BitField<ExponentType, 0, 2> {}; 1128 1129 DEFINE_PLATFORM_CODE_STUB(MathPow, PlatformCodeStub); 1130 }; 1131 1132 1133 class CallICStub: public PlatformCodeStub { 1134 public: 1135 CallICStub(Isolate* isolate, const CallICState& state) 1136 : PlatformCodeStub(isolate) { 1137 minor_key_ = state.GetExtraICState(); 1138 } 1139 1140 Code::Kind GetCodeKind() const override { return Code::CALL_IC; } 1141 1142 ExtraICState GetExtraICState() const final { 1143 return static_cast<ExtraICState>(minor_key_); 1144 } 1145 1146 protected: 1147 ConvertReceiverMode convert_mode() const { return state().convert_mode(); } 1148 TailCallMode tail_call_mode() const { return state().tail_call_mode(); } 1149 1150 CallICState state() const { return CallICState(GetExtraICState()); } 1151 1152 // Code generation helpers. 1153 void GenerateMiss(MacroAssembler* masm); 1154 void HandleArrayCase(MacroAssembler* masm, Label* miss); 1155 1156 private: 1157 void PrintState(std::ostream& os) const override; // NOLINT 1158 1159 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedbackAndVector); 1160 DEFINE_PLATFORM_CODE_STUB(CallIC, PlatformCodeStub); 1161 }; 1162 1163 1164 // TODO(verwaest): Translate to hydrogen code stub. 1165 class FunctionPrototypeStub : public PlatformCodeStub { 1166 public: 1167 explicit FunctionPrototypeStub(Isolate* isolate) 1168 : PlatformCodeStub(isolate) {} 1169 1170 Code::Kind GetCodeKind() const override { return Code::HANDLER; } 1171 ExtraICState GetExtraICState() const override { return Code::LOAD_IC; } 1172 1173 // TODO(mvstanton): only the receiver register is accessed. When this is 1174 // translated to a hydrogen code stub, a new CallInterfaceDescriptor 1175 // should be created that just uses that register for more efficient code. 1176 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { 1177 return LoadWithVectorDescriptor(isolate()); 1178 } 1179 1180 DEFINE_PLATFORM_CODE_STUB(FunctionPrototype, PlatformCodeStub); 1181 }; 1182 1183 1184 class LoadIndexedStringStub : public PlatformCodeStub { 1185 public: 1186 explicit LoadIndexedStringStub(Isolate* isolate) 1187 : PlatformCodeStub(isolate) {} 1188 1189 Code::Kind GetCodeKind() const override { return Code::HANDLER; } 1190 ExtraICState GetExtraICState() const override { return Code::KEYED_LOAD_IC; } 1191 1192 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load); 1193 DEFINE_PLATFORM_CODE_STUB(LoadIndexedString, PlatformCodeStub); 1194 }; 1195 1196 1197 class HandlerStub : public HydrogenCodeStub { 1198 public: 1199 Code::Kind GetCodeKind() const override { return Code::HANDLER; } 1200 ExtraICState GetExtraICState() const override { return kind(); } 1201 1202 void InitializeDescriptor(CodeStubDescriptor* descriptor) override; 1203 1204 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override; 1205 1206 protected: 1207 explicit HandlerStub(Isolate* isolate) : HydrogenCodeStub(isolate) {} 1208 1209 virtual Code::Kind kind() const = 0; 1210 1211 DEFINE_CODE_STUB_BASE(HandlerStub, HydrogenCodeStub); 1212 }; 1213 1214 1215 class LoadFieldStub: public HandlerStub { 1216 public: 1217 LoadFieldStub(Isolate* isolate, FieldIndex index) : HandlerStub(isolate) { 1218 int property_index_key = index.GetFieldAccessStubKey(); 1219 set_sub_minor_key(LoadFieldByIndexBits::encode(property_index_key)); 1220 } 1221 1222 FieldIndex index() const { 1223 int property_index_key = LoadFieldByIndexBits::decode(sub_minor_key()); 1224 return FieldIndex::FromFieldAccessStubKey(property_index_key); 1225 } 1226 1227 protected: 1228 Code::Kind kind() const override { return Code::LOAD_IC; } 1229 1230 private: 1231 class LoadFieldByIndexBits : public BitField<int, 0, 13> {}; 1232 1233 // TODO(ishell): The stub uses only kReceiver parameter. 1234 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector); 1235 DEFINE_HANDLER_CODE_STUB(LoadField, HandlerStub); 1236 }; 1237 1238 class KeyedLoadSloppyArgumentsStub : public TurboFanCodeStub { 1239 public: 1240 explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate) 1241 : TurboFanCodeStub(isolate) {} 1242 1243 Code::Kind GetCodeKind() const override { return Code::HANDLER; } 1244 ExtraICState GetExtraICState() const override { return Code::LOAD_IC; } 1245 1246 protected: 1247 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector); 1248 DEFINE_TURBOFAN_CODE_STUB(KeyedLoadSloppyArguments, TurboFanCodeStub); 1249 }; 1250 1251 1252 class CommonStoreModeBits : public BitField<KeyedAccessStoreMode, 0, 3> {}; 1253 1254 class KeyedStoreSloppyArgumentsStub : public TurboFanCodeStub { 1255 public: 1256 explicit KeyedStoreSloppyArgumentsStub(Isolate* isolate, 1257 KeyedAccessStoreMode mode) 1258 : TurboFanCodeStub(isolate) { 1259 minor_key_ = CommonStoreModeBits::encode(mode); 1260 } 1261 1262 Code::Kind GetCodeKind() const override { return Code::HANDLER; } 1263 ExtraICState GetExtraICState() const override { return Code::STORE_IC; } 1264 1265 protected: 1266 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); 1267 DEFINE_TURBOFAN_CODE_STUB(KeyedStoreSloppyArguments, TurboFanCodeStub); 1268 }; 1269 1270 1271 class LoadConstantStub : public HandlerStub { 1272 public: 1273 LoadConstantStub(Isolate* isolate, int constant_index) 1274 : HandlerStub(isolate) { 1275 set_sub_minor_key(ConstantIndexBits::encode(constant_index)); 1276 } 1277 1278 int constant_index() const { 1279 return ConstantIndexBits::decode(sub_minor_key()); 1280 } 1281 1282 protected: 1283 Code::Kind kind() const override { return Code::LOAD_IC; } 1284 1285 private: 1286 class ConstantIndexBits : public BitField<int, 0, kSubMinorKeyBits> {}; 1287 1288 // TODO(ishell): The stub uses only kReceiver parameter. 1289 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector); 1290 DEFINE_HANDLER_CODE_STUB(LoadConstant, HandlerStub); 1291 }; 1292 1293 class LoadApiGetterStub : public TurboFanCodeStub { 1294 public: 1295 LoadApiGetterStub(Isolate* isolate, bool receiver_is_holder, int index) 1296 : TurboFanCodeStub(isolate) { 1297 // If that's not true, we need to ensure that the receiver is actually a 1298 // JSReceiver. http://crbug.com/609134 1299 DCHECK(receiver_is_holder); 1300 minor_key_ = IndexBits::encode(index) | 1301 ReceiverIsHolderBits::encode(receiver_is_holder); 1302 } 1303 1304 Code::Kind GetCodeKind() const override { return Code::HANDLER; } 1305 ExtraICState GetExtraICState() const override { return Code::LOAD_IC; } 1306 1307 int index() const { return IndexBits::decode(minor_key_); } 1308 bool receiver_is_holder() const { 1309 return ReceiverIsHolderBits::decode(minor_key_); 1310 } 1311 1312 private: 1313 class ReceiverIsHolderBits : public BitField<bool, 0, 1> {}; 1314 class IndexBits : public BitField<int, 1, kDescriptorIndexBitCount> {}; 1315 1316 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load); 1317 DEFINE_TURBOFAN_CODE_STUB(LoadApiGetter, TurboFanCodeStub); 1318 }; 1319 1320 class StoreFieldStub : public TurboFanCodeStub { 1321 public: 1322 StoreFieldStub(Isolate* isolate, FieldIndex index, 1323 Representation representation) 1324 : TurboFanCodeStub(isolate) { 1325 int property_index_key = index.GetFieldAccessStubKey(); 1326 minor_key_ = StoreFieldByIndexBits::encode(property_index_key) | 1327 RepresentationBits::encode(representation.kind()); 1328 } 1329 1330 Code::Kind GetCodeKind() const override { return Code::HANDLER; } 1331 ExtraICState GetExtraICState() const override { return Code::STORE_IC; } 1332 1333 FieldIndex index() const { 1334 int property_index_key = StoreFieldByIndexBits::decode(minor_key_); 1335 return FieldIndex::FromFieldAccessStubKey(property_index_key); 1336 } 1337 1338 Representation representation() const { 1339 return Representation::FromKind(RepresentationBits::decode(minor_key_)); 1340 } 1341 1342 private: 1343 class StoreFieldByIndexBits : public BitField<int, 0, 13> {}; 1344 class RepresentationBits 1345 : public BitField<Representation::Kind, StoreFieldByIndexBits::kNext, 4> { 1346 }; 1347 STATIC_ASSERT(Representation::kNumRepresentations - 1 < 1348 RepresentationBits::kMax); 1349 1350 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); 1351 DEFINE_TURBOFAN_CODE_STUB(StoreField, TurboFanCodeStub); 1352 }; 1353 1354 class StoreMapStub : public TurboFanCodeStub { 1355 public: 1356 explicit StoreMapStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 1357 1358 Code::Kind GetCodeKind() const override { return Code::HANDLER; } 1359 ExtraICState GetExtraICState() const override { return Code::STORE_IC; } 1360 1361 private: 1362 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreTransition); 1363 DEFINE_TURBOFAN_CODE_STUB(StoreMap, TurboFanCodeStub); 1364 }; 1365 1366 class StoreTransitionStub : public TurboFanCodeStub { 1367 public: 1368 enum StoreMode { 1369 StoreMapAndValue, 1370 ExtendStorageAndStoreMapAndValue 1371 }; 1372 1373 StoreTransitionStub(Isolate* isolate, bool is_inobject, 1374 Representation representation, StoreMode store_mode) 1375 : TurboFanCodeStub(isolate) { 1376 minor_key_ = IsInobjectBits::encode(is_inobject) | 1377 RepresentationBits::encode(representation.kind()) | 1378 StoreModeBits::encode(store_mode); 1379 } 1380 1381 Code::Kind GetCodeKind() const override { return Code::HANDLER; } 1382 ExtraICState GetExtraICState() const override { return Code::STORE_IC; } 1383 1384 bool is_inobject() const { return IsInobjectBits::decode(minor_key_); } 1385 1386 Representation representation() const { 1387 return Representation::FromKind(RepresentationBits::decode(minor_key_)); 1388 } 1389 1390 StoreMode store_mode() const { return StoreModeBits::decode(minor_key_); } 1391 1392 private: 1393 class IsInobjectBits : public BitField<bool, 0, 1> {}; 1394 class RepresentationBits 1395 : public BitField<Representation::Kind, IsInobjectBits::kNext, 4> {}; 1396 STATIC_ASSERT(Representation::kNumRepresentations - 1 < 1397 RepresentationBits::kMax); 1398 class StoreModeBits 1399 : public BitField<StoreMode, RepresentationBits::kNext, 1> {}; 1400 1401 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreNamedTransition); 1402 DEFINE_TURBOFAN_CODE_STUB(StoreTransition, TurboFanCodeStub); 1403 }; 1404 1405 class StoreGlobalStub : public TurboFanCodeStub { 1406 public: 1407 StoreGlobalStub(Isolate* isolate, PropertyCellType type, 1408 Maybe<PropertyCellConstantType> constant_type, 1409 bool check_global) 1410 : TurboFanCodeStub(isolate) { 1411 PropertyCellConstantType encoded_constant_type = 1412 constant_type.FromMaybe(PropertyCellConstantType::kSmi); 1413 minor_key_ = CellTypeBits::encode(type) | 1414 ConstantTypeBits::encode(encoded_constant_type) | 1415 CheckGlobalBits::encode(check_global); 1416 } 1417 1418 Code::Kind GetCodeKind() const override { return Code::HANDLER; } 1419 ExtraICState GetExtraICState() const override { return Code::STORE_IC; } 1420 1421 static Handle<HeapObject> property_cell_placeholder(Isolate* isolate) { 1422 return isolate->factory()->uninitialized_value(); 1423 } 1424 1425 static Handle<HeapObject> global_map_placeholder(Isolate* isolate) { 1426 return isolate->factory()->termination_exception(); 1427 } 1428 1429 Handle<Code> GetCodeCopyFromTemplate(Handle<JSGlobalObject> global, 1430 Handle<PropertyCell> cell) { 1431 Code::FindAndReplacePattern pattern; 1432 if (check_global()) { 1433 pattern.Add(handle(global_map_placeholder(isolate())->map()), 1434 Map::WeakCellForMap(Handle<Map>(global->map()))); 1435 } 1436 pattern.Add(handle(property_cell_placeholder(isolate())->map()), 1437 isolate()->factory()->NewWeakCell(cell)); 1438 return CodeStub::GetCodeCopy(pattern); 1439 } 1440 1441 PropertyCellType cell_type() const { 1442 return CellTypeBits::decode(minor_key_); 1443 } 1444 1445 PropertyCellConstantType constant_type() const { 1446 DCHECK(PropertyCellType::kConstantType == cell_type()); 1447 return ConstantTypeBits::decode(minor_key_); 1448 } 1449 1450 bool check_global() const { return CheckGlobalBits::decode(minor_key_); } 1451 1452 private: 1453 class CellTypeBits : public BitField<PropertyCellType, 0, 2> {}; 1454 class ConstantTypeBits 1455 : public BitField<PropertyCellConstantType, CellTypeBits::kNext, 2> {}; 1456 class CheckGlobalBits : public BitField<bool, ConstantTypeBits::kNext, 1> {}; 1457 1458 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); 1459 DEFINE_TURBOFAN_CODE_STUB(StoreGlobal, TurboFanCodeStub); 1460 }; 1461 1462 class CallApiCallbackStub : public PlatformCodeStub { 1463 public: 1464 static const int kArgBits = 3; 1465 static const int kArgMax = (1 << kArgBits) - 1; 1466 1467 // CallApiCallbackStub for regular setters and getters. 1468 CallApiCallbackStub(Isolate* isolate, bool is_store, bool call_data_undefined, 1469 bool is_lazy) 1470 : CallApiCallbackStub(isolate, is_store ? 1 : 0, is_store, 1471 call_data_undefined, is_lazy) {} 1472 1473 // CallApiCallbackStub for callback functions. 1474 CallApiCallbackStub(Isolate* isolate, int argc, bool call_data_undefined, 1475 bool is_lazy) 1476 : CallApiCallbackStub(isolate, argc, false, call_data_undefined, 1477 is_lazy) {} 1478 1479 private: 1480 CallApiCallbackStub(Isolate* isolate, int argc, bool is_store, 1481 bool call_data_undefined, bool is_lazy) 1482 : PlatformCodeStub(isolate) { 1483 CHECK(0 <= argc && argc <= kArgMax); 1484 minor_key_ = IsStoreBits::encode(is_store) | 1485 CallDataUndefinedBits::encode(call_data_undefined) | 1486 ArgumentBits::encode(argc) | 1487 IsLazyAccessorBits::encode(is_lazy); 1488 } 1489 1490 bool is_store() const { return IsStoreBits::decode(minor_key_); } 1491 bool is_lazy() const { return IsLazyAccessorBits::decode(minor_key_); } 1492 bool call_data_undefined() const { 1493 return CallDataUndefinedBits::decode(minor_key_); 1494 } 1495 int argc() const { return ArgumentBits::decode(minor_key_); } 1496 1497 class IsStoreBits: public BitField<bool, 0, 1> {}; 1498 class CallDataUndefinedBits: public BitField<bool, 1, 1> {}; 1499 class ArgumentBits : public BitField<int, 2, kArgBits> {}; 1500 class IsLazyAccessorBits : public BitField<bool, 3 + kArgBits, 1> {}; 1501 1502 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiCallback); 1503 DEFINE_PLATFORM_CODE_STUB(CallApiCallback, PlatformCodeStub); 1504 }; 1505 1506 1507 class CallApiGetterStub : public PlatformCodeStub { 1508 public: 1509 explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {} 1510 1511 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiGetter); 1512 DEFINE_PLATFORM_CODE_STUB(CallApiGetter, PlatformCodeStub); 1513 }; 1514 1515 1516 class BinaryOpICStub : public HydrogenCodeStub { 1517 public: 1518 BinaryOpICStub(Isolate* isolate, Token::Value op) 1519 : HydrogenCodeStub(isolate, UNINITIALIZED) { 1520 BinaryOpICState state(isolate, op); 1521 set_sub_minor_key(state.GetExtraICState()); 1522 } 1523 1524 BinaryOpICStub(Isolate* isolate, const BinaryOpICState& state) 1525 : HydrogenCodeStub(isolate) { 1526 set_sub_minor_key(state.GetExtraICState()); 1527 } 1528 1529 static void GenerateAheadOfTime(Isolate* isolate); 1530 1531 Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; } 1532 1533 ExtraICState GetExtraICState() const final { 1534 return static_cast<ExtraICState>(sub_minor_key()); 1535 } 1536 1537 BinaryOpICState state() const { 1538 return BinaryOpICState(isolate(), GetExtraICState()); 1539 } 1540 1541 void PrintState(std::ostream& os) const final; // NOLINT 1542 1543 private: 1544 static void GenerateAheadOfTime(Isolate* isolate, 1545 const BinaryOpICState& state); 1546 1547 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp); 1548 DEFINE_HYDROGEN_CODE_STUB(BinaryOpIC, HydrogenCodeStub); 1549 }; 1550 1551 1552 // TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail 1553 // call support for stubs in Hydrogen. 1554 class BinaryOpICWithAllocationSiteStub final : public PlatformCodeStub { 1555 public: 1556 BinaryOpICWithAllocationSiteStub(Isolate* isolate, 1557 const BinaryOpICState& state) 1558 : PlatformCodeStub(isolate) { 1559 minor_key_ = state.GetExtraICState(); 1560 } 1561 1562 static void GenerateAheadOfTime(Isolate* isolate); 1563 1564 Handle<Code> GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site) { 1565 Code::FindAndReplacePattern pattern; 1566 pattern.Add(isolate()->factory()->undefined_map(), allocation_site); 1567 return CodeStub::GetCodeCopy(pattern); 1568 } 1569 1570 Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; } 1571 1572 ExtraICState GetExtraICState() const override { 1573 return static_cast<ExtraICState>(minor_key_); 1574 } 1575 1576 void PrintState(std::ostream& os) const override; // NOLINT 1577 1578 private: 1579 BinaryOpICState state() const { 1580 return BinaryOpICState(isolate(), GetExtraICState()); 1581 } 1582 1583 static void GenerateAheadOfTime(Isolate* isolate, 1584 const BinaryOpICState& state); 1585 1586 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite); 1587 DEFINE_PLATFORM_CODE_STUB(BinaryOpICWithAllocationSite, PlatformCodeStub); 1588 }; 1589 1590 1591 class BinaryOpWithAllocationSiteStub final : public BinaryOpICStub { 1592 public: 1593 BinaryOpWithAllocationSiteStub(Isolate* isolate, Token::Value op) 1594 : BinaryOpICStub(isolate, op) {} 1595 1596 BinaryOpWithAllocationSiteStub(Isolate* isolate, const BinaryOpICState& state) 1597 : BinaryOpICStub(isolate, state) {} 1598 1599 Code::Kind GetCodeKind() const final { return Code::STUB; } 1600 1601 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite); 1602 DEFINE_HYDROGEN_CODE_STUB(BinaryOpWithAllocationSite, BinaryOpICStub); 1603 }; 1604 1605 class StringAddStub final : public TurboFanCodeStub { 1606 public: 1607 StringAddStub(Isolate* isolate, StringAddFlags flags, 1608 PretenureFlag pretenure_flag) 1609 : TurboFanCodeStub(isolate) { 1610 minor_key_ = (StringAddFlagsBits::encode(flags) | 1611 PretenureFlagBits::encode(pretenure_flag)); 1612 } 1613 1614 StringAddFlags flags() const { 1615 return StringAddFlagsBits::decode(minor_key_); 1616 } 1617 1618 PretenureFlag pretenure_flag() const { 1619 return PretenureFlagBits::decode(minor_key_); 1620 } 1621 1622 private: 1623 class StringAddFlagsBits : public BitField<StringAddFlags, 0, 3> {}; 1624 class PretenureFlagBits : public BitField<PretenureFlag, 3, 1> {}; 1625 1626 void PrintBaseName(std::ostream& os) const override; // NOLINT 1627 1628 DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd); 1629 DEFINE_TURBOFAN_CODE_STUB(StringAdd, TurboFanCodeStub); 1630 }; 1631 1632 1633 class CompareICStub : public PlatformCodeStub { 1634 public: 1635 CompareICStub(Isolate* isolate, Token::Value op, CompareICState::State left, 1636 CompareICState::State right, CompareICState::State state) 1637 : PlatformCodeStub(isolate) { 1638 DCHECK(Token::IsCompareOp(op)); 1639 DCHECK(OpBits::is_valid(op - Token::EQ)); 1640 minor_key_ = OpBits::encode(op - Token::EQ) | 1641 LeftStateBits::encode(left) | RightStateBits::encode(right) | 1642 StateBits::encode(state); 1643 } 1644 // Creates uninitialized compare stub. 1645 CompareICStub(Isolate* isolate, Token::Value op) 1646 : CompareICStub(isolate, op, CompareICState::UNINITIALIZED, 1647 CompareICState::UNINITIALIZED, 1648 CompareICState::UNINITIALIZED) {} 1649 1650 CompareICStub(Isolate* isolate, ExtraICState extra_ic_state) 1651 : PlatformCodeStub(isolate) { 1652 minor_key_ = extra_ic_state; 1653 } 1654 1655 ExtraICState GetExtraICState() const final { 1656 return static_cast<ExtraICState>(minor_key_); 1657 } 1658 1659 void set_known_map(Handle<Map> map) { known_map_ = map; } 1660 1661 InlineCacheState GetICState() const; 1662 1663 Token::Value op() const { 1664 return static_cast<Token::Value>(Token::EQ + OpBits::decode(minor_key_)); 1665 } 1666 1667 CompareICState::State left() const { 1668 return LeftStateBits::decode(minor_key_); 1669 } 1670 CompareICState::State right() const { 1671 return RightStateBits::decode(minor_key_); 1672 } 1673 CompareICState::State state() const { return StateBits::decode(minor_key_); } 1674 1675 private: 1676 Code::Kind GetCodeKind() const override { return Code::COMPARE_IC; } 1677 1678 void GenerateBooleans(MacroAssembler* masm); 1679 void GenerateSmis(MacroAssembler* masm); 1680 void GenerateNumbers(MacroAssembler* masm); 1681 void GenerateInternalizedStrings(MacroAssembler* masm); 1682 void GenerateStrings(MacroAssembler* masm); 1683 void GenerateUniqueNames(MacroAssembler* masm); 1684 void GenerateReceivers(MacroAssembler* masm); 1685 void GenerateMiss(MacroAssembler* masm); 1686 void GenerateKnownReceivers(MacroAssembler* masm); 1687 void GenerateGeneric(MacroAssembler* masm); 1688 1689 bool strict() const { return op() == Token::EQ_STRICT; } 1690 Condition GetCondition() const; 1691 1692 // Although we don't cache anything in the special cache we have to define 1693 // this predicate to avoid appearance of code stubs with embedded maps in 1694 // the global stub cache. 1695 bool UseSpecialCache() override { 1696 return state() == CompareICState::KNOWN_RECEIVER; 1697 } 1698 1699 class OpBits : public BitField<int, 0, 3> {}; 1700 class LeftStateBits : public BitField<CompareICState::State, 3, 4> {}; 1701 class RightStateBits : public BitField<CompareICState::State, 7, 4> {}; 1702 class StateBits : public BitField<CompareICState::State, 11, 4> {}; 1703 1704 Handle<Map> known_map_; 1705 1706 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp); 1707 DEFINE_PLATFORM_CODE_STUB(CompareIC, PlatformCodeStub); 1708 }; 1709 1710 1711 class CEntryStub : public PlatformCodeStub { 1712 public: 1713 CEntryStub(Isolate* isolate, int result_size, 1714 SaveFPRegsMode save_doubles = kDontSaveFPRegs, 1715 ArgvMode argv_mode = kArgvOnStack, bool builtin_exit_frame = false) 1716 : PlatformCodeStub(isolate) { 1717 minor_key_ = SaveDoublesBits::encode(save_doubles == kSaveFPRegs) | 1718 FrameTypeBits::encode(builtin_exit_frame) | 1719 ArgvMode::encode(argv_mode == kArgvInRegister); 1720 DCHECK(result_size == 1 || result_size == 2 || result_size == 3); 1721 minor_key_ = ResultSizeBits::update(minor_key_, result_size); 1722 } 1723 1724 // The version of this stub that doesn't save doubles is generated ahead of 1725 // time, so it's OK to call it from other stubs that can't cope with GC during 1726 // their code generation. On machines that always have gp registers (x64) we 1727 // can generate both variants ahead of time. 1728 static void GenerateAheadOfTime(Isolate* isolate); 1729 1730 private: 1731 bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); } 1732 bool argv_in_register() const { return ArgvMode::decode(minor_key_); } 1733 bool is_builtin_exit() const { return FrameTypeBits::decode(minor_key_); } 1734 int result_size() const { return ResultSizeBits::decode(minor_key_); } 1735 1736 bool NeedsImmovableCode() override; 1737 1738 class SaveDoublesBits : public BitField<bool, 0, 1> {}; 1739 class ArgvMode : public BitField<bool, 1, 1> {}; 1740 class FrameTypeBits : public BitField<bool, 2, 1> {}; 1741 class ResultSizeBits : public BitField<int, 3, 3> {}; 1742 1743 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); 1744 DEFINE_PLATFORM_CODE_STUB(CEntry, PlatformCodeStub); 1745 }; 1746 1747 1748 class JSEntryStub : public PlatformCodeStub { 1749 public: 1750 JSEntryStub(Isolate* isolate, StackFrame::Type type) 1751 : PlatformCodeStub(isolate) { 1752 DCHECK(type == StackFrame::ENTRY || type == StackFrame::ENTRY_CONSTRUCT); 1753 minor_key_ = StackFrameTypeBits::encode(type); 1754 } 1755 1756 private: 1757 void FinishCode(Handle<Code> code) override; 1758 1759 void PrintName(std::ostream& os) const override { // NOLINT 1760 os << (type() == StackFrame::ENTRY ? "JSEntryStub" 1761 : "JSConstructEntryStub"); 1762 } 1763 1764 StackFrame::Type type() const { 1765 return StackFrameTypeBits::decode(minor_key_); 1766 } 1767 1768 class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {}; 1769 1770 int handler_offset_; 1771 1772 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); 1773 DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub); 1774 }; 1775 1776 1777 class RegExpExecStub: public PlatformCodeStub { 1778 public: 1779 explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { } 1780 1781 DEFINE_CALL_INTERFACE_DESCRIPTOR(RegExpExec); 1782 DEFINE_PLATFORM_CODE_STUB(RegExpExec, PlatformCodeStub); 1783 }; 1784 1785 // TODO(bmeurer/mvstanton): Turn CallConstructStub into ConstructICStub. 1786 class CallConstructStub final : public PlatformCodeStub { 1787 public: 1788 explicit CallConstructStub(Isolate* isolate) : PlatformCodeStub(isolate) {} 1789 1790 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallConstruct); 1791 DEFINE_PLATFORM_CODE_STUB(CallConstruct, PlatformCodeStub); 1792 }; 1793 1794 1795 enum ReceiverCheckMode { 1796 // We don't know anything about the receiver. 1797 RECEIVER_IS_UNKNOWN, 1798 1799 // We know the receiver is a string. 1800 RECEIVER_IS_STRING 1801 }; 1802 1803 1804 enum EmbedMode { 1805 // The code being generated is part of an IC handler, which may MISS 1806 // to an IC in failure cases. 1807 PART_OF_IC_HANDLER, 1808 1809 NOT_PART_OF_IC_HANDLER 1810 }; 1811 1812 1813 // Generates code implementing String.prototype.charCodeAt. 1814 // 1815 // Only supports the case when the receiver is a string and the index 1816 // is a number (smi or heap number) that is a valid index into the 1817 // string. Additional index constraints are specified by the 1818 // flags. Otherwise, bails out to the provided labels. 1819 // 1820 // Register usage: |object| may be changed to another string in a way 1821 // that doesn't affect charCodeAt/charAt semantics, |index| is 1822 // preserved, |scratch| and |result| are clobbered. 1823 class StringCharCodeAtGenerator { 1824 public: 1825 StringCharCodeAtGenerator(Register object, Register index, Register result, 1826 Label* receiver_not_string, Label* index_not_number, 1827 Label* index_out_of_range, 1828 ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN) 1829 : object_(object), 1830 index_(index), 1831 result_(result), 1832 receiver_not_string_(receiver_not_string), 1833 index_not_number_(index_not_number), 1834 index_out_of_range_(index_out_of_range), 1835 check_mode_(check_mode) { 1836 DCHECK(!result_.is(object_)); 1837 DCHECK(!result_.is(index_)); 1838 } 1839 1840 // Generates the fast case code. On the fallthrough path |result| 1841 // register contains the result. 1842 void GenerateFast(MacroAssembler* masm); 1843 1844 // Generates the slow case code. Must not be naturally 1845 // reachable. Expected to be put after a ret instruction (e.g., in 1846 // deferred code). Always jumps back to the fast case. 1847 void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode, 1848 const RuntimeCallHelper& call_helper); 1849 1850 // Skip handling slow case and directly jump to bailout. 1851 void SkipSlow(MacroAssembler* masm, Label* bailout) { 1852 masm->bind(&index_not_smi_); 1853 masm->bind(&call_runtime_); 1854 masm->jmp(bailout); 1855 } 1856 1857 private: 1858 Register object_; 1859 Register index_; 1860 Register result_; 1861 1862 Label* receiver_not_string_; 1863 Label* index_not_number_; 1864 Label* index_out_of_range_; 1865 1866 ReceiverCheckMode check_mode_; 1867 1868 Label call_runtime_; 1869 Label index_not_smi_; 1870 Label got_smi_index_; 1871 Label exit_; 1872 1873 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator); 1874 }; 1875 1876 1877 // Generates code for creating a one-char string from a char code. 1878 class StringCharFromCodeGenerator { 1879 public: 1880 StringCharFromCodeGenerator(Register code, 1881 Register result) 1882 : code_(code), 1883 result_(result) { 1884 DCHECK(!code_.is(result_)); 1885 } 1886 1887 // Generates the fast case code. On the fallthrough path |result| 1888 // register contains the result. 1889 void GenerateFast(MacroAssembler* masm); 1890 1891 // Generates the slow case code. Must not be naturally 1892 // reachable. Expected to be put after a ret instruction (e.g., in 1893 // deferred code). Always jumps back to the fast case. 1894 void GenerateSlow(MacroAssembler* masm, 1895 const RuntimeCallHelper& call_helper); 1896 1897 // Skip handling slow case and directly jump to bailout. 1898 void SkipSlow(MacroAssembler* masm, Label* bailout) { 1899 masm->bind(&slow_case_); 1900 masm->jmp(bailout); 1901 } 1902 1903 private: 1904 Register code_; 1905 Register result_; 1906 1907 Label slow_case_; 1908 Label exit_; 1909 1910 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator); 1911 }; 1912 1913 1914 // Generates code implementing String.prototype.charAt. 1915 // 1916 // Only supports the case when the receiver is a string and the index 1917 // is a number (smi or heap number) that is a valid index into the 1918 // string. Additional index constraints are specified by the 1919 // flags. Otherwise, bails out to the provided labels. 1920 // 1921 // Register usage: |object| may be changed to another string in a way 1922 // that doesn't affect charCodeAt/charAt semantics, |index| is 1923 // preserved, |scratch1|, |scratch2|, and |result| are clobbered. 1924 class StringCharAtGenerator { 1925 public: 1926 StringCharAtGenerator(Register object, Register index, Register scratch, 1927 Register result, Label* receiver_not_string, 1928 Label* index_not_number, Label* index_out_of_range, 1929 ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN) 1930 : char_code_at_generator_(object, index, scratch, receiver_not_string, 1931 index_not_number, index_out_of_range, 1932 check_mode), 1933 char_from_code_generator_(scratch, result) {} 1934 1935 // Generates the fast case code. On the fallthrough path |result| 1936 // register contains the result. 1937 void GenerateFast(MacroAssembler* masm) { 1938 char_code_at_generator_.GenerateFast(masm); 1939 char_from_code_generator_.GenerateFast(masm); 1940 } 1941 1942 // Generates the slow case code. Must not be naturally 1943 // reachable. Expected to be put after a ret instruction (e.g., in 1944 // deferred code). Always jumps back to the fast case. 1945 void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode, 1946 const RuntimeCallHelper& call_helper) { 1947 char_code_at_generator_.GenerateSlow(masm, embed_mode, call_helper); 1948 char_from_code_generator_.GenerateSlow(masm, call_helper); 1949 } 1950 1951 // Skip handling slow case and directly jump to bailout. 1952 void SkipSlow(MacroAssembler* masm, Label* bailout) { 1953 char_code_at_generator_.SkipSlow(masm, bailout); 1954 char_from_code_generator_.SkipSlow(masm, bailout); 1955 } 1956 1957 private: 1958 StringCharCodeAtGenerator char_code_at_generator_; 1959 StringCharFromCodeGenerator char_from_code_generator_; 1960 1961 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator); 1962 }; 1963 1964 1965 class LoadDictionaryElementStub : public HydrogenCodeStub { 1966 public: 1967 explicit LoadDictionaryElementStub(Isolate* isolate) 1968 : HydrogenCodeStub(isolate) {} 1969 1970 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector); 1971 DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub); 1972 }; 1973 1974 class LoadICTrampolineStub : public TurboFanCodeStub { 1975 public: 1976 explicit LoadICTrampolineStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 1977 1978 void GenerateAssembly(CodeStubAssembler* assembler) const override; 1979 1980 Code::Kind GetCodeKind() const override { return Code::LOAD_IC; } 1981 1982 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load); 1983 DEFINE_CODE_STUB(LoadICTrampoline, TurboFanCodeStub); 1984 }; 1985 1986 class LoadGlobalICTrampolineStub : public TurboFanCodeStub { 1987 public: 1988 explicit LoadGlobalICTrampolineStub(Isolate* isolate, 1989 const LoadGlobalICState& state) 1990 : TurboFanCodeStub(isolate) { 1991 minor_key_ = state.GetExtraICState(); 1992 } 1993 1994 void GenerateAssembly(CodeStubAssembler* assembler) const override; 1995 1996 Code::Kind GetCodeKind() const override { return Code::LOAD_GLOBAL_IC; } 1997 1998 ExtraICState GetExtraICState() const final { 1999 return static_cast<ExtraICState>(minor_key_); 2000 } 2001 2002 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadGlobal); 2003 DEFINE_CODE_STUB(LoadGlobalICTrampoline, TurboFanCodeStub); 2004 }; 2005 2006 class KeyedLoadICTrampolineTFStub : public LoadICTrampolineStub { 2007 public: 2008 explicit KeyedLoadICTrampolineTFStub(Isolate* isolate) 2009 : LoadICTrampolineStub(isolate) {} 2010 2011 void GenerateAssembly(CodeStubAssembler* assembler) const override; 2012 2013 Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; } 2014 2015 DEFINE_CODE_STUB(KeyedLoadICTrampolineTF, LoadICTrampolineStub); 2016 }; 2017 2018 class StoreICTrampolineStub : public TurboFanCodeStub { 2019 public: 2020 StoreICTrampolineStub(Isolate* isolate, const StoreICState& state) 2021 : TurboFanCodeStub(isolate) { 2022 minor_key_ = state.GetExtraICState(); 2023 } 2024 2025 void GenerateAssembly(CodeStubAssembler* assembler) const override; 2026 2027 Code::Kind GetCodeKind() const override { return Code::STORE_IC; } 2028 2029 ExtraICState GetExtraICState() const final { 2030 return static_cast<ExtraICState>(minor_key_); 2031 } 2032 2033 protected: 2034 StoreICState state() const { return StoreICState(GetExtraICState()); } 2035 2036 DEFINE_CALL_INTERFACE_DESCRIPTOR(Store); 2037 DEFINE_CODE_STUB(StoreICTrampoline, TurboFanCodeStub); 2038 }; 2039 2040 class KeyedStoreICTrampolineStub : public PlatformCodeStub { 2041 public: 2042 KeyedStoreICTrampolineStub(Isolate* isolate, const StoreICState& state) 2043 : PlatformCodeStub(isolate) { 2044 minor_key_ = state.GetExtraICState(); 2045 } 2046 2047 Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; } 2048 2049 ExtraICState GetExtraICState() const final { 2050 return static_cast<ExtraICState>(minor_key_); 2051 } 2052 2053 protected: 2054 StoreICState state() const { return StoreICState(GetExtraICState()); } 2055 2056 private: 2057 DEFINE_CALL_INTERFACE_DESCRIPTOR(Store); 2058 DEFINE_PLATFORM_CODE_STUB(KeyedStoreICTrampoline, PlatformCodeStub); 2059 }; 2060 2061 class KeyedStoreICTrampolineTFStub : public StoreICTrampolineStub { 2062 public: 2063 KeyedStoreICTrampolineTFStub(Isolate* isolate, const StoreICState& state) 2064 : StoreICTrampolineStub(isolate, state) {} 2065 2066 void GenerateAssembly(CodeStubAssembler* assembler) const override; 2067 2068 Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; } 2069 2070 DEFINE_CODE_STUB(KeyedStoreICTrampolineTF, StoreICTrampolineStub); 2071 }; 2072 2073 class CallICTrampolineStub : public PlatformCodeStub { 2074 public: 2075 CallICTrampolineStub(Isolate* isolate, const CallICState& state) 2076 : PlatformCodeStub(isolate) { 2077 minor_key_ = state.GetExtraICState(); 2078 } 2079 2080 Code::Kind GetCodeKind() const override { return Code::CALL_IC; } 2081 2082 ExtraICState GetExtraICState() const final { 2083 return static_cast<ExtraICState>(minor_key_); 2084 } 2085 2086 protected: 2087 CallICState state() const { 2088 return CallICState(static_cast<ExtraICState>(minor_key_)); 2089 } 2090 2091 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedback); 2092 DEFINE_PLATFORM_CODE_STUB(CallICTrampoline, PlatformCodeStub); 2093 }; 2094 2095 class LoadICStub : public TurboFanCodeStub { 2096 public: 2097 explicit LoadICStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 2098 2099 void GenerateAssembly(CodeStubAssembler* assembler) const override; 2100 2101 Code::Kind GetCodeKind() const override { return Code::LOAD_IC; } 2102 2103 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector); 2104 DEFINE_CODE_STUB(LoadIC, TurboFanCodeStub); 2105 }; 2106 2107 class LoadICProtoArrayStub : public TurboFanCodeStub { 2108 public: 2109 explicit LoadICProtoArrayStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 2110 2111 void GenerateAssembly(CodeStubAssembler* assembler) const override; 2112 2113 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadICProtoArray); 2114 DEFINE_CODE_STUB(LoadICProtoArray, TurboFanCodeStub); 2115 }; 2116 2117 class LoadGlobalICStub : public TurboFanCodeStub { 2118 public: 2119 explicit LoadGlobalICStub(Isolate* isolate, const LoadGlobalICState& state) 2120 : TurboFanCodeStub(isolate) { 2121 minor_key_ = state.GetExtraICState(); 2122 } 2123 2124 void GenerateAssembly(CodeStubAssembler* assembler) const override; 2125 2126 Code::Kind GetCodeKind() const override { return Code::LOAD_GLOBAL_IC; } 2127 2128 ExtraICState GetExtraICState() const final { 2129 return static_cast<ExtraICState>(minor_key_); 2130 } 2131 2132 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadGlobalWithVector); 2133 DEFINE_CODE_STUB(LoadGlobalIC, TurboFanCodeStub); 2134 }; 2135 2136 class KeyedLoadICTFStub : public LoadICStub { 2137 public: 2138 explicit KeyedLoadICTFStub(Isolate* isolate) : LoadICStub(isolate) {} 2139 2140 void GenerateAssembly(CodeStubAssembler* assembler) const override; 2141 2142 Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; } 2143 2144 DEFINE_CODE_STUB(KeyedLoadICTF, LoadICStub); 2145 }; 2146 2147 class StoreICStub : public TurboFanCodeStub { 2148 public: 2149 StoreICStub(Isolate* isolate, const StoreICState& state) 2150 : TurboFanCodeStub(isolate) { 2151 minor_key_ = state.GetExtraICState(); 2152 } 2153 2154 void GenerateAssembly(CodeStubAssembler* assembler) const override; 2155 2156 Code::Kind GetCodeKind() const override { return Code::STORE_IC; } 2157 ExtraICState GetExtraICState() const final { 2158 return static_cast<ExtraICState>(minor_key_); 2159 } 2160 2161 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); 2162 DEFINE_CODE_STUB(StoreIC, TurboFanCodeStub); 2163 }; 2164 2165 class KeyedStoreICStub : public PlatformCodeStub { 2166 public: 2167 KeyedStoreICStub(Isolate* isolate, const StoreICState& state) 2168 : PlatformCodeStub(isolate) { 2169 minor_key_ = state.GetExtraICState(); 2170 } 2171 2172 void GenerateForTrampoline(MacroAssembler* masm); 2173 2174 Code::Kind GetCodeKind() const final { return Code::KEYED_STORE_IC; } 2175 2176 ExtraICState GetExtraICState() const final { 2177 return static_cast<ExtraICState>(minor_key_); 2178 } 2179 2180 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); 2181 DEFINE_PLATFORM_CODE_STUB(KeyedStoreIC, PlatformCodeStub); 2182 2183 protected: 2184 void GenerateImpl(MacroAssembler* masm, bool in_frame); 2185 }; 2186 2187 class KeyedStoreICTFStub : public StoreICStub { 2188 public: 2189 KeyedStoreICTFStub(Isolate* isolate, const StoreICState& state) 2190 : StoreICStub(isolate, state) {} 2191 2192 void GenerateAssembly(CodeStubAssembler* assembler) const override; 2193 2194 Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; } 2195 2196 DEFINE_CODE_STUB(KeyedStoreICTF, StoreICStub); 2197 }; 2198 2199 class DoubleToIStub : public PlatformCodeStub { 2200 public: 2201 DoubleToIStub(Isolate* isolate, Register source, Register destination, 2202 int offset, bool is_truncating, bool skip_fastpath = false) 2203 : PlatformCodeStub(isolate) { 2204 minor_key_ = SourceRegisterBits::encode(source.code()) | 2205 DestinationRegisterBits::encode(destination.code()) | 2206 OffsetBits::encode(offset) | 2207 IsTruncatingBits::encode(is_truncating) | 2208 SkipFastPathBits::encode(skip_fastpath) | 2209 SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0); 2210 } 2211 2212 bool SometimesSetsUpAFrame() override { return false; } 2213 2214 private: 2215 Register source() const { 2216 return Register::from_code(SourceRegisterBits::decode(minor_key_)); 2217 } 2218 Register destination() const { 2219 return Register::from_code(DestinationRegisterBits::decode(minor_key_)); 2220 } 2221 bool is_truncating() const { return IsTruncatingBits::decode(minor_key_); } 2222 bool skip_fastpath() const { return SkipFastPathBits::decode(minor_key_); } 2223 int offset() const { return OffsetBits::decode(minor_key_); } 2224 2225 static const int kBitsPerRegisterNumber = 6; 2226 STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters); 2227 class SourceRegisterBits: 2228 public BitField<int, 0, kBitsPerRegisterNumber> {}; // NOLINT 2229 class DestinationRegisterBits: 2230 public BitField<int, kBitsPerRegisterNumber, 2231 kBitsPerRegisterNumber> {}; // NOLINT 2232 class IsTruncatingBits: 2233 public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {}; // NOLINT 2234 class OffsetBits: 2235 public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {}; // NOLINT 2236 class SkipFastPathBits: 2237 public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {}; // NOLINT 2238 class SSE3Bits: 2239 public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {}; // NOLINT 2240 2241 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); 2242 DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub); 2243 }; 2244 2245 class ScriptContextFieldStub : public TurboFanCodeStub { 2246 public: 2247 ScriptContextFieldStub(Isolate* isolate, 2248 const ScriptContextTable::LookupResult* lookup_result) 2249 : TurboFanCodeStub(isolate) { 2250 DCHECK(Accepted(lookup_result)); 2251 minor_key_ = ContextIndexBits::encode(lookup_result->context_index) | 2252 SlotIndexBits::encode(lookup_result->slot_index); 2253 } 2254 2255 Code::Kind GetCodeKind() const override { return Code::HANDLER; } 2256 2257 int context_index() const { return ContextIndexBits::decode(minor_key_); } 2258 2259 int slot_index() const { return SlotIndexBits::decode(minor_key_); } 2260 2261 static bool Accepted(const ScriptContextTable::LookupResult* lookup_result) { 2262 return ContextIndexBits::is_valid(lookup_result->context_index) && 2263 SlotIndexBits::is_valid(lookup_result->slot_index); 2264 } 2265 2266 private: 2267 static const int kContextIndexBits = 9; 2268 static const int kSlotIndexBits = 12; 2269 class ContextIndexBits : public BitField<int, 0, kContextIndexBits> {}; 2270 class SlotIndexBits 2271 : public BitField<int, kContextIndexBits, kSlotIndexBits> {}; 2272 2273 DEFINE_CODE_STUB_BASE(ScriptContextFieldStub, TurboFanCodeStub); 2274 }; 2275 2276 2277 class LoadScriptContextFieldStub : public ScriptContextFieldStub { 2278 public: 2279 LoadScriptContextFieldStub( 2280 Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result) 2281 : ScriptContextFieldStub(isolate, lookup_result) {} 2282 2283 ExtraICState GetExtraICState() const override { return Code::LOAD_IC; } 2284 2285 private: 2286 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector); 2287 DEFINE_TURBOFAN_CODE_STUB(LoadScriptContextField, ScriptContextFieldStub); 2288 }; 2289 2290 2291 class StoreScriptContextFieldStub : public ScriptContextFieldStub { 2292 public: 2293 StoreScriptContextFieldStub( 2294 Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result) 2295 : ScriptContextFieldStub(isolate, lookup_result) {} 2296 2297 ExtraICState GetExtraICState() const override { return Code::STORE_IC; } 2298 2299 private: 2300 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); 2301 DEFINE_TURBOFAN_CODE_STUB(StoreScriptContextField, ScriptContextFieldStub); 2302 }; 2303 2304 2305 class LoadFastElementStub : public HandlerStub { 2306 public: 2307 LoadFastElementStub(Isolate* isolate, bool is_js_array, 2308 ElementsKind elements_kind, 2309 bool convert_hole_to_undefined = false) 2310 : HandlerStub(isolate) { 2311 set_sub_minor_key( 2312 ElementsKindBits::encode(elements_kind) | 2313 IsJSArrayBits::encode(is_js_array) | 2314 CanConvertHoleToUndefined::encode(convert_hole_to_undefined)); 2315 } 2316 2317 Code::Kind kind() const override { return Code::KEYED_LOAD_IC; } 2318 2319 bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); } 2320 bool convert_hole_to_undefined() const { 2321 return CanConvertHoleToUndefined::decode(sub_minor_key()); 2322 } 2323 2324 ElementsKind elements_kind() const { 2325 return ElementsKindBits::decode(sub_minor_key()); 2326 } 2327 2328 private: 2329 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {}; 2330 class IsJSArrayBits: public BitField<bool, 8, 1> {}; 2331 class CanConvertHoleToUndefined : public BitField<bool, 9, 1> {}; 2332 2333 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector); 2334 DEFINE_HANDLER_CODE_STUB(LoadFastElement, HandlerStub); 2335 }; 2336 2337 class StoreFastElementStub : public TurboFanCodeStub { 2338 public: 2339 StoreFastElementStub(Isolate* isolate, bool is_js_array, 2340 ElementsKind elements_kind, KeyedAccessStoreMode mode) 2341 : TurboFanCodeStub(isolate) { 2342 minor_key_ = CommonStoreModeBits::encode(mode) | 2343 ElementsKindBits::encode(elements_kind) | 2344 IsJSArrayBits::encode(is_js_array); 2345 } 2346 2347 static void GenerateAheadOfTime(Isolate* isolate); 2348 2349 bool is_js_array() const { return IsJSArrayBits::decode(minor_key_); } 2350 2351 ElementsKind elements_kind() const { 2352 return ElementsKindBits::decode(minor_key_); 2353 } 2354 2355 KeyedAccessStoreMode store_mode() const { 2356 return CommonStoreModeBits::decode(minor_key_); 2357 } 2358 2359 Code::Kind GetCodeKind() const override { return Code::HANDLER; } 2360 ExtraICState GetExtraICState() const override { return Code::KEYED_STORE_IC; } 2361 2362 private: 2363 class ElementsKindBits 2364 : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {}; 2365 class IsJSArrayBits : public BitField<bool, ElementsKindBits::kNext, 1> {}; 2366 2367 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); 2368 DEFINE_TURBOFAN_CODE_STUB(StoreFastElement, TurboFanCodeStub); 2369 }; 2370 2371 2372 class TransitionElementsKindStub : public HydrogenCodeStub { 2373 public: 2374 TransitionElementsKindStub(Isolate* isolate, ElementsKind from_kind, 2375 ElementsKind to_kind) 2376 : HydrogenCodeStub(isolate) { 2377 set_sub_minor_key(FromKindBits::encode(from_kind) | 2378 ToKindBits::encode(to_kind)); 2379 } 2380 2381 ElementsKind from_kind() const { 2382 return FromKindBits::decode(sub_minor_key()); 2383 } 2384 2385 ElementsKind to_kind() const { return ToKindBits::decode(sub_minor_key()); } 2386 2387 private: 2388 class FromKindBits: public BitField<ElementsKind, 8, 8> {}; 2389 class ToKindBits: public BitField<ElementsKind, 0, 8> {}; 2390 2391 DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind); 2392 DEFINE_HYDROGEN_CODE_STUB(TransitionElementsKind, HydrogenCodeStub); 2393 }; 2394 2395 class AllocateHeapNumberStub : public TurboFanCodeStub { 2396 public: 2397 explicit AllocateHeapNumberStub(Isolate* isolate) 2398 : TurboFanCodeStub(isolate) {} 2399 2400 void InitializeDescriptor(CodeStubDescriptor* descriptor) override; 2401 void GenerateAssembly(CodeStubAssembler* assembler) const override; 2402 2403 DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateHeapNumber); 2404 DEFINE_CODE_STUB(AllocateHeapNumber, TurboFanCodeStub); 2405 }; 2406 2407 #define SIMD128_ALLOC_STUB(TYPE, Type, type, lane_count, lane_type) \ 2408 class Allocate##Type##Stub : public TurboFanCodeStub { \ 2409 public: \ 2410 explicit Allocate##Type##Stub(Isolate* isolate) \ 2411 : TurboFanCodeStub(isolate) {} \ 2412 \ 2413 void InitializeDescriptor(CodeStubDescriptor* descriptor) override; \ 2414 void GenerateAssembly(CodeStubAssembler* assembler) const override; \ 2415 \ 2416 DEFINE_CALL_INTERFACE_DESCRIPTOR(Allocate##Type); \ 2417 DEFINE_CODE_STUB(Allocate##Type, TurboFanCodeStub); \ 2418 }; 2419 SIMD128_TYPES(SIMD128_ALLOC_STUB) 2420 #undef SIMD128_ALLOC_STUB 2421 2422 class CommonArrayConstructorStub : public TurboFanCodeStub { 2423 protected: 2424 CommonArrayConstructorStub(Isolate* isolate, ElementsKind kind, 2425 AllocationSiteOverrideMode override_mode) 2426 : TurboFanCodeStub(isolate) { 2427 // It only makes sense to override local allocation site behavior 2428 // if there is a difference between the global allocation site policy 2429 // for an ElementsKind and the desired usage of the stub. 2430 DCHECK(override_mode != DISABLE_ALLOCATION_SITES || 2431 AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE); 2432 set_sub_minor_key(ElementsKindBits::encode(kind) | 2433 AllocationSiteOverrideModeBits::encode(override_mode)); 2434 } 2435 2436 void set_sub_minor_key(uint32_t key) { minor_key_ = key; } 2437 2438 uint32_t sub_minor_key() const { return minor_key_; } 2439 2440 CommonArrayConstructorStub(uint32_t key, Isolate* isolate) 2441 : TurboFanCodeStub(key, isolate) {} 2442 2443 public: 2444 ElementsKind elements_kind() const { 2445 return ElementsKindBits::decode(sub_minor_key()); 2446 } 2447 2448 AllocationSiteOverrideMode override_mode() const { 2449 return AllocationSiteOverrideModeBits::decode(sub_minor_key()); 2450 } 2451 2452 static void GenerateStubsAheadOfTime(Isolate* isolate); 2453 2454 private: 2455 // Ensure data fits within available bits. 2456 STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1); 2457 2458 class ElementsKindBits : public BitField<ElementsKind, 0, 8> {}; 2459 class AllocationSiteOverrideModeBits 2460 : public BitField<AllocationSiteOverrideMode, 8, 1> {}; // NOLINT 2461 }; 2462 2463 class ArrayNoArgumentConstructorStub : public CommonArrayConstructorStub { 2464 public: 2465 ArrayNoArgumentConstructorStub( 2466 Isolate* isolate, ElementsKind kind, 2467 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE) 2468 : CommonArrayConstructorStub(isolate, kind, override_mode) {} 2469 2470 private: 2471 void PrintName(std::ostream& os) const override { // NOLINT 2472 os << "ArrayNoArgumentConstructorStub"; 2473 } 2474 2475 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNoArgumentConstructor); 2476 DEFINE_TURBOFAN_CODE_STUB(ArrayNoArgumentConstructor, 2477 CommonArrayConstructorStub); 2478 }; 2479 2480 class InternalArrayNoArgumentConstructorStub 2481 : public CommonArrayConstructorStub { 2482 public: 2483 InternalArrayNoArgumentConstructorStub(Isolate* isolate, ElementsKind kind) 2484 : CommonArrayConstructorStub(isolate, kind, DONT_OVERRIDE) {} 2485 2486 private: 2487 void PrintName(std::ostream& os) const override { // NOLINT 2488 os << "InternalArrayNoArgumentConstructorStub"; 2489 } 2490 2491 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNoArgumentConstructor); 2492 DEFINE_TURBOFAN_CODE_STUB(InternalArrayNoArgumentConstructor, 2493 CommonArrayConstructorStub); 2494 }; 2495 2496 class ArraySingleArgumentConstructorStub : public CommonArrayConstructorStub { 2497 public: 2498 ArraySingleArgumentConstructorStub( 2499 Isolate* isolate, ElementsKind kind, 2500 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE) 2501 : CommonArrayConstructorStub(isolate, kind, override_mode) {} 2502 2503 private: 2504 void PrintName(std::ostream& os) const override { // NOLINT 2505 os << "ArraySingleArgumentConstructorStub"; 2506 } 2507 2508 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArraySingleArgumentConstructor); 2509 DEFINE_TURBOFAN_CODE_STUB(ArraySingleArgumentConstructor, 2510 CommonArrayConstructorStub); 2511 }; 2512 2513 class InternalArraySingleArgumentConstructorStub 2514 : public CommonArrayConstructorStub { 2515 public: 2516 InternalArraySingleArgumentConstructorStub(Isolate* isolate, 2517 ElementsKind kind) 2518 : CommonArrayConstructorStub(isolate, kind, DONT_OVERRIDE) {} 2519 2520 private: 2521 void PrintName(std::ostream& os) const override { // NOLINT 2522 os << "InternalArraySingleArgumentConstructorStub"; 2523 } 2524 2525 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArraySingleArgumentConstructor); 2526 DEFINE_TURBOFAN_CODE_STUB(InternalArraySingleArgumentConstructor, 2527 CommonArrayConstructorStub); 2528 }; 2529 2530 class ArrayNArgumentsConstructorStub : public PlatformCodeStub { 2531 public: 2532 explicit ArrayNArgumentsConstructorStub(Isolate* isolate) 2533 : PlatformCodeStub(isolate) {} 2534 2535 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { 2536 return ArrayNArgumentsConstructorDescriptor(isolate()); 2537 } 2538 2539 private: 2540 DEFINE_PLATFORM_CODE_STUB(ArrayNArgumentsConstructor, PlatformCodeStub); 2541 }; 2542 2543 class StoreElementStub : public PlatformCodeStub { 2544 public: 2545 StoreElementStub(Isolate* isolate, ElementsKind elements_kind, 2546 KeyedAccessStoreMode mode) 2547 : PlatformCodeStub(isolate) { 2548 // TODO(jkummerow): Rename this stub to StoreSlowElementStub, 2549 // drop elements_kind parameter. 2550 DCHECK_EQ(DICTIONARY_ELEMENTS, elements_kind); 2551 minor_key_ = ElementsKindBits::encode(elements_kind) | 2552 CommonStoreModeBits::encode(mode); 2553 } 2554 2555 Code::Kind GetCodeKind() const override { return Code::HANDLER; } 2556 ExtraICState GetExtraICState() const override { return Code::KEYED_STORE_IC; } 2557 2558 private: 2559 ElementsKind elements_kind() const { 2560 return ElementsKindBits::decode(minor_key_); 2561 } 2562 2563 class ElementsKindBits 2564 : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {}; 2565 2566 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); 2567 DEFINE_PLATFORM_CODE_STUB(StoreElement, PlatformCodeStub); 2568 }; 2569 2570 class ToBooleanICStub : public HydrogenCodeStub { 2571 public: 2572 ToBooleanICStub(Isolate* isolate, ExtraICState state) 2573 : HydrogenCodeStub(isolate) { 2574 set_sub_minor_key(HintsBits::encode(static_cast<uint16_t>(state))); 2575 } 2576 2577 bool UpdateStatus(Handle<Object> object); 2578 ToBooleanHints hints() const { 2579 return ToBooleanHints(HintsBits::decode(sub_minor_key())); 2580 } 2581 2582 Code::Kind GetCodeKind() const override { return Code::TO_BOOLEAN_IC; } 2583 void PrintState(std::ostream& os) const override; // NOLINT 2584 2585 bool SometimesSetsUpAFrame() override { return false; } 2586 2587 static Handle<Code> GetUninitialized(Isolate* isolate) { 2588 return ToBooleanICStub(isolate, UNINITIALIZED).GetCode(); 2589 } 2590 2591 ExtraICState GetExtraICState() const override { return hints(); } 2592 2593 InlineCacheState GetICState() const { 2594 if (hints() == ToBooleanHint::kNone) { 2595 return ::v8::internal::UNINITIALIZED; 2596 } else { 2597 return MONOMORPHIC; 2598 } 2599 } 2600 2601 private: 2602 ToBooleanICStub(Isolate* isolate, InitializationState init_state) 2603 : HydrogenCodeStub(isolate, init_state) {} 2604 2605 static const int kNumHints = 9; 2606 STATIC_ASSERT(static_cast<int>(ToBooleanHint::kAny) == 2607 ((1 << kNumHints) - 1)); 2608 class HintsBits : public BitField<uint16_t, 0, kNumHints> {}; 2609 2610 DEFINE_CALL_INTERFACE_DESCRIPTOR(TypeConversion); 2611 DEFINE_HYDROGEN_CODE_STUB(ToBooleanIC, HydrogenCodeStub); 2612 }; 2613 2614 class ElementsTransitionAndStoreStub : public TurboFanCodeStub { 2615 public: 2616 ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind, 2617 ElementsKind to_kind, bool is_jsarray, 2618 KeyedAccessStoreMode store_mode) 2619 : TurboFanCodeStub(isolate) { 2620 minor_key_ = CommonStoreModeBits::encode(store_mode) | 2621 FromBits::encode(from_kind) | ToBits::encode(to_kind) | 2622 IsJSArrayBits::encode(is_jsarray); 2623 } 2624 2625 ElementsKind from_kind() const { return FromBits::decode(minor_key_); } 2626 ElementsKind to_kind() const { return ToBits::decode(minor_key_); } 2627 bool is_jsarray() const { return IsJSArrayBits::decode(minor_key_); } 2628 KeyedAccessStoreMode store_mode() const { 2629 return CommonStoreModeBits::decode(minor_key_); 2630 } 2631 2632 Code::Kind GetCodeKind() const override { return Code::HANDLER; } 2633 ExtraICState GetExtraICState() const override { return Code::KEYED_STORE_IC; } 2634 2635 private: 2636 class FromBits 2637 : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {}; 2638 class ToBits : public BitField<ElementsKind, 11, 8> {}; 2639 class IsJSArrayBits : public BitField<bool, 19, 1> {}; 2640 2641 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreTransition); 2642 DEFINE_TURBOFAN_CODE_STUB(ElementsTransitionAndStore, TurboFanCodeStub); 2643 }; 2644 2645 2646 class StubFailureTrampolineStub : public PlatformCodeStub { 2647 public: 2648 StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode) 2649 : PlatformCodeStub(isolate) { 2650 minor_key_ = FunctionModeField::encode(function_mode); 2651 } 2652 2653 static void GenerateAheadOfTime(Isolate* isolate); 2654 2655 private: 2656 StubFunctionMode function_mode() const { 2657 return FunctionModeField::decode(minor_key_); 2658 } 2659 2660 class FunctionModeField : public BitField<StubFunctionMode, 0, 1> {}; 2661 2662 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); 2663 DEFINE_PLATFORM_CODE_STUB(StubFailureTrampoline, PlatformCodeStub); 2664 }; 2665 2666 2667 class ProfileEntryHookStub : public PlatformCodeStub { 2668 public: 2669 explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {} 2670 2671 // The profile entry hook function is not allowed to cause a GC. 2672 bool SometimesSetsUpAFrame() override { return false; } 2673 2674 // Generates a call to the entry hook if it's enabled. 2675 static void MaybeCallEntryHook(MacroAssembler* masm); 2676 2677 private: 2678 static void EntryHookTrampoline(intptr_t function, 2679 intptr_t stack_pointer, 2680 Isolate* isolate); 2681 2682 // ProfileEntryHookStub is called at the start of a function, so it has the 2683 // same register set. 2684 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction) 2685 DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub); 2686 }; 2687 2688 2689 class StoreBufferOverflowStub : public PlatformCodeStub { 2690 public: 2691 StoreBufferOverflowStub(Isolate* isolate, SaveFPRegsMode save_fp) 2692 : PlatformCodeStub(isolate) { 2693 minor_key_ = SaveDoublesBits::encode(save_fp == kSaveFPRegs); 2694 } 2695 2696 static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate); 2697 bool SometimesSetsUpAFrame() override { return false; } 2698 2699 private: 2700 bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); } 2701 2702 class SaveDoublesBits : public BitField<bool, 0, 1> {}; 2703 2704 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); 2705 DEFINE_PLATFORM_CODE_STUB(StoreBufferOverflow, PlatformCodeStub); 2706 }; 2707 2708 class SubStringStub : public TurboFanCodeStub { 2709 public: 2710 explicit SubStringStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 2711 2712 static compiler::Node* Generate(CodeStubAssembler* assembler, 2713 compiler::Node* string, compiler::Node* from, 2714 compiler::Node* to, compiler::Node* context); 2715 2716 void GenerateAssembly(CodeStubAssembler* assembler) const override { 2717 assembler->Return(Generate(assembler, 2718 assembler->Parameter(Descriptor::kString), 2719 assembler->Parameter(Descriptor::kFrom), 2720 assembler->Parameter(Descriptor::kTo), 2721 assembler->Parameter(Descriptor::kContext))); 2722 } 2723 2724 DEFINE_CALL_INTERFACE_DESCRIPTOR(SubString); 2725 DEFINE_CODE_STUB(SubString, TurboFanCodeStub); 2726 }; 2727 2728 2729 #undef DEFINE_CALL_INTERFACE_DESCRIPTOR 2730 #undef DEFINE_PLATFORM_CODE_STUB 2731 #undef DEFINE_HANDLER_CODE_STUB 2732 #undef DEFINE_HYDROGEN_CODE_STUB 2733 #undef DEFINE_CODE_STUB 2734 #undef DEFINE_CODE_STUB_BASE 2735 2736 } // namespace internal 2737 } // namespace v8 2738 2739 #endif // V8_CODE_STUBS_H_ 2740