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/codegen.h" 11 #include "src/factory.h" 12 #include "src/find-and-replace-pattern.h" 13 #include "src/globals.h" 14 #include "src/ic/ic-state.h" 15 #include "src/interface-descriptors.h" 16 #include "src/macro-assembler.h" 17 #include "src/ostreams.h" 18 #include "src/type-hints.h" 19 20 namespace v8 { 21 namespace internal { 22 23 // Forward declarations. 24 class CodeStubAssembler; 25 namespace compiler { 26 class CodeAssemblerLabel; 27 class CodeAssemblerState; 28 class Node; 29 } 30 31 // List of code stubs used on all platforms. 32 #define CODE_STUB_LIST_ALL_PLATFORMS(V) \ 33 /* --- PlatformCodeStubs --- */ \ 34 V(ArrayConstructor) \ 35 V(BinaryOpICWithAllocationSite) \ 36 V(CallApiCallback) \ 37 V(CallApiGetter) \ 38 V(CallConstruct) \ 39 V(CallIC) \ 40 V(CEntry) \ 41 V(CompareIC) \ 42 V(DoubleToI) \ 43 V(InternalArrayConstructor) \ 44 V(JSEntry) \ 45 V(MathPow) \ 46 V(ProfileEntryHook) \ 47 V(RecordWrite) \ 48 V(RegExpExec) \ 49 V(StoreBufferOverflow) \ 50 V(StoreSlowElement) \ 51 V(SubString) \ 52 V(NameDictionaryLookup) \ 53 /* This can be removed once there are no */ \ 54 /* more deopting Hydrogen stubs. */ \ 55 V(StubFailureTrampoline) \ 56 /* These are only called from FCG */ \ 57 /* They can be removed when only the TF */ \ 58 /* version of the corresponding stub is */ \ 59 /* used universally */ \ 60 V(CallICTrampoline) \ 61 /* --- HydrogenCodeStubs --- */ \ 62 /* These should never be ported to TF */ \ 63 /* because they are either used only by */ \ 64 /* FCG/Crankshaft or are deprecated */ \ 65 V(BinaryOpIC) \ 66 V(BinaryOpWithAllocationSite) \ 67 V(ToBooleanIC) \ 68 V(TransitionElementsKind) \ 69 /* --- TurboFanCodeStubs --- */ \ 70 V(AllocateHeapNumber) \ 71 V(ArrayNoArgumentConstructor) \ 72 V(ArraySingleArgumentConstructor) \ 73 V(ArrayNArgumentsConstructor) \ 74 V(CreateAllocationSite) \ 75 V(CreateWeakCell) \ 76 V(StringLength) \ 77 V(AddWithFeedback) \ 78 V(SubtractWithFeedback) \ 79 V(MultiplyWithFeedback) \ 80 V(DivideWithFeedback) \ 81 V(ModulusWithFeedback) \ 82 V(InternalArrayNoArgumentConstructor) \ 83 V(InternalArraySingleArgumentConstructor) \ 84 V(ElementsTransitionAndStore) \ 85 V(KeyedLoadSloppyArguments) \ 86 V(KeyedStoreSloppyArguments) \ 87 V(LoadScriptContextField) \ 88 V(StoreScriptContextField) \ 89 V(NumberToString) \ 90 V(StringAdd) \ 91 V(GetProperty) \ 92 V(StoreFastElement) \ 93 V(StoreGlobal) \ 94 V(StoreInterceptor) \ 95 V(LoadIndexedInterceptor) \ 96 V(GrowArrayElements) 97 98 // List of code stubs only used on ARM 32 bits platforms. 99 #if V8_TARGET_ARCH_ARM 100 #define CODE_STUB_LIST_ARM(V) V(DirectCEntry) 101 102 #else 103 #define CODE_STUB_LIST_ARM(V) 104 #endif 105 106 // List of code stubs only used on ARM 64 bits platforms. 107 #if V8_TARGET_ARCH_ARM64 108 #define CODE_STUB_LIST_ARM64(V) \ 109 V(DirectCEntry) \ 110 V(RestoreRegistersState) \ 111 V(StoreRegistersState) 112 113 #else 114 #define CODE_STUB_LIST_ARM64(V) 115 #endif 116 117 // List of code stubs only used on PPC platforms. 118 #ifdef V8_TARGET_ARCH_PPC 119 #define CODE_STUB_LIST_PPC(V) \ 120 V(DirectCEntry) \ 121 V(StoreRegistersState) \ 122 V(RestoreRegistersState) 123 #else 124 #define CODE_STUB_LIST_PPC(V) 125 #endif 126 127 // List of code stubs only used on MIPS platforms. 128 #if V8_TARGET_ARCH_MIPS 129 #define CODE_STUB_LIST_MIPS(V) \ 130 V(DirectCEntry) \ 131 V(RestoreRegistersState) \ 132 V(StoreRegistersState) 133 #elif V8_TARGET_ARCH_MIPS64 134 #define CODE_STUB_LIST_MIPS(V) \ 135 V(DirectCEntry) \ 136 V(RestoreRegistersState) \ 137 V(StoreRegistersState) 138 #else 139 #define CODE_STUB_LIST_MIPS(V) 140 #endif 141 142 // List of code stubs only used on S390 platforms. 143 #ifdef V8_TARGET_ARCH_S390 144 #define CODE_STUB_LIST_S390(V) \ 145 V(DirectCEntry) \ 146 V(StoreRegistersState) \ 147 V(RestoreRegistersState) 148 #else 149 #define CODE_STUB_LIST_S390(V) 150 #endif 151 152 // Combined list of code stubs. 153 #define CODE_STUB_LIST(V) \ 154 CODE_STUB_LIST_ALL_PLATFORMS(V) \ 155 CODE_STUB_LIST_ARM(V) \ 156 CODE_STUB_LIST_ARM64(V) \ 157 CODE_STUB_LIST_PPC(V) \ 158 CODE_STUB_LIST_MIPS(V) \ 159 CODE_STUB_LIST_S390(V) 160 161 static const int kHasReturnedMinusZeroSentinel = 1; 162 163 // Stub is base classes of all stubs. 164 class CodeStub BASE_EMBEDDED { 165 public: 166 enum Major { 167 // TODO(mvstanton): eliminate the NoCache key by getting rid 168 // of the non-monomorphic-cache. 169 NoCache = 0, // marker for stubs that do custom caching] 170 #define DEF_ENUM(name) name, 171 CODE_STUB_LIST(DEF_ENUM) 172 #undef DEF_ENUM 173 NUMBER_OF_IDS 174 }; 175 176 // Retrieve the code for the stub. Generate the code if needed. 177 Handle<Code> GetCode(); 178 179 // Retrieve the code for the stub, make and return a copy of the code. 180 Handle<Code> GetCodeCopy(const FindAndReplacePattern& pattern); 181 MajorKeyFromKey(uint32_t key)182 static Major MajorKeyFromKey(uint32_t key) { 183 return static_cast<Major>(MajorKeyBits::decode(key)); 184 } MinorKeyFromKey(uint32_t key)185 static uint32_t MinorKeyFromKey(uint32_t key) { 186 return MinorKeyBits::decode(key); 187 } 188 189 // Gets the major key from a code object that is a code stub or binary op IC. GetMajorKey(Code * code_stub)190 static Major GetMajorKey(Code* code_stub) { 191 return MajorKeyFromKey(code_stub->stub_key()); 192 } 193 NoCacheKey()194 static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); } 195 196 static const char* MajorName(Major major_key); 197 CodeStub(Isolate * isolate)198 explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {} ~CodeStub()199 virtual ~CodeStub() {} 200 201 static void GenerateStubsAheadOfTime(Isolate* isolate); 202 static void GenerateFPStubs(Isolate* isolate); 203 204 // Some stubs put untagged junk on the stack that cannot be scanned by the 205 // GC. This means that we must be statically sure that no GC can occur while 206 // they are running. If that is the case they should override this to return 207 // true, which will cause an assertion if we try to call something that can 208 // GC or if we try to put a stack frame on top of the junk, which would not 209 // result in a traversable stack. SometimesSetsUpAFrame()210 virtual bool SometimesSetsUpAFrame() { return true; } 211 212 // Lookup the code in the (possibly custom) cache. 213 bool FindCodeInCache(Code** code_out); 214 215 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() const = 0; 216 GetStackParameterCount()217 virtual int GetStackParameterCount() const { 218 return GetCallInterfaceDescriptor().GetStackParameterCount(); 219 } 220 InitializeDescriptor(CodeStubDescriptor * descriptor)221 virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {} 222 223 static void InitializeDescriptor(Isolate* isolate, uint32_t key, 224 CodeStubDescriptor* desc); 225 226 static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key); 227 228 // Returns information for computing the number key. 229 virtual Major MajorKey() const = 0; MinorKey()230 uint32_t MinorKey() const { return minor_key_; } 231 232 // BinaryOpStub needs to override this. 233 virtual Code::Kind GetCodeKind() const; 234 GetExtraICState()235 virtual ExtraICState GetExtraICState() const { return kNoExtraICState; } 236 237 Code::Flags GetCodeFlags() const; 238 239 friend std::ostream& operator<<(std::ostream& os, const CodeStub& s) { 240 s.PrintName(os); 241 return os; 242 } 243 isolate()244 Isolate* isolate() const { return isolate_; } 245 246 void DeleteStubFromCacheForTesting(); 247 248 protected: CodeStub(uint32_t key,Isolate * isolate)249 CodeStub(uint32_t key, Isolate* isolate) 250 : minor_key_(MinorKeyFromKey(key)), isolate_(isolate) {} 251 252 // Generates the assembler code for the stub. 253 virtual Handle<Code> GenerateCode() = 0; 254 255 // Returns whether the code generated for this stub needs to be allocated as 256 // a fixed (non-moveable) code object. NeedsImmovableCode()257 virtual bool NeedsImmovableCode() { return false; } 258 259 virtual void PrintName(std::ostream& os) const; // NOLINT 260 virtual void PrintBaseName(std::ostream& os) const; // NOLINT PrintState(std::ostream & os)261 virtual void PrintState(std::ostream& os) const { ; } // NOLINT 262 263 // Computes the key based on major and minor. GetKey()264 uint32_t GetKey() { 265 DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS); 266 return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey()); 267 } 268 269 uint32_t minor_key_; 270 271 private: 272 // Perform bookkeeping required after code generation when stub code is 273 // initially generated. 274 void RecordCodeGeneration(Handle<Code> code); 275 276 // Finish the code object after it has been generated. FinishCode(Handle<Code> code)277 virtual void FinishCode(Handle<Code> code) { } 278 279 // Activate newly generated stub. Is called after 280 // registering stub in the stub cache. Activate(Code * code)281 virtual void Activate(Code* code) { } 282 283 // Add the code to a specialized cache, specific to an individual 284 // stub type. Please note, this method must add the code object to a 285 // roots object, otherwise we will remove the code during GC. AddToSpecialCache(Handle<Code> new_object)286 virtual void AddToSpecialCache(Handle<Code> new_object) { } 287 288 // Find code in a specialized cache, work is delegated to the specific stub. FindCodeInSpecialCache(Code ** code_out)289 virtual bool FindCodeInSpecialCache(Code** code_out) { 290 return false; 291 } 292 293 // If a stub uses a special cache override this. UseSpecialCache()294 virtual bool UseSpecialCache() { return false; } 295 296 // We use this dispatch to statically instantiate the correct code stub for 297 // the given stub key and call the passed function with that code stub. 298 typedef void (*DispatchedCall)(CodeStub* stub, void** value_out); 299 static void Dispatch(Isolate* isolate, uint32_t key, void** value_out, 300 DispatchedCall call); 301 302 static void GetCodeDispatchCall(CodeStub* stub, void** value_out); 303 304 STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits)); 305 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {}; 306 class MinorKeyBits: public BitField<uint32_t, 307 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT 308 309 friend class BreakPointIterator; 310 311 Isolate* isolate_; 312 }; 313 314 315 #define DEFINE_CODE_STUB_BASE(NAME, SUPER) \ 316 public: \ 317 NAME(uint32_t key, Isolate* isolate) : SUPER(key, isolate) {} \ 318 \ 319 private: \ 320 DISALLOW_COPY_AND_ASSIGN(NAME) 321 322 323 #define DEFINE_CODE_STUB(NAME, SUPER) \ 324 public: \ 325 inline Major MajorKey() const override { return NAME; }; \ 326 \ 327 DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER) 328 329 330 #define DEFINE_PLATFORM_CODE_STUB(NAME, SUPER) \ 331 private: \ 332 void Generate(MacroAssembler* masm) override; \ 333 DEFINE_CODE_STUB(NAME, SUPER) 334 335 336 #define DEFINE_HYDROGEN_CODE_STUB(NAME, SUPER) \ 337 public: \ 338 void InitializeDescriptor(CodeStubDescriptor* descriptor) override; \ 339 Handle<Code> GenerateCode() override; \ 340 DEFINE_CODE_STUB(NAME, SUPER) 341 342 #define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER) \ 343 public: \ 344 void GenerateAssembly(compiler::CodeAssemblerState* state) const override; \ 345 DEFINE_CODE_STUB(NAME, SUPER) 346 347 #define DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(NAME, SUPER) \ 348 public: \ 349 static compiler::Node* Generate( \ 350 CodeStubAssembler* assembler, compiler::Node* left, \ 351 compiler::Node* right, compiler::Node* slot_id, \ 352 compiler::Node* feedback_vector, compiler::Node* context); \ 353 void GenerateAssembly(compiler::CodeAssemblerState* state) const override; \ 354 DEFINE_CODE_STUB(NAME, SUPER) 355 356 #define DEFINE_TURBOFAN_UNARY_OP_CODE_STUB_WITH_FEEDBACK(NAME, SUPER) \ 357 public: \ 358 static compiler::Node* Generate( \ 359 CodeStubAssembler* assembler, compiler::Node* value, \ 360 compiler::Node* context, compiler::Node* feedback_vector, \ 361 compiler::Node* slot_id); \ 362 void GenerateAssembly(compiler::CodeAssemblerState* state) const override; \ 363 DEFINE_CODE_STUB(NAME, SUPER) 364 365 #define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \ 366 public: \ 367 Handle<Code> GenerateCode() override; \ 368 DEFINE_CODE_STUB(NAME, SUPER) 369 370 #define DEFINE_CALL_INTERFACE_DESCRIPTOR(NAME) \ 371 public: \ 372 typedef NAME##Descriptor Descriptor; \ 373 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \ 374 return Descriptor(isolate()); \ 375 } 376 377 // There are some code stubs we just can't describe right now with a 378 // CallInterfaceDescriptor. Isolate behavior for those cases with this macro. 379 // An attempt to retrieve a descriptor will fail. 380 #define DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR() \ 381 public: \ 382 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \ 383 UNREACHABLE(); \ 384 return CallInterfaceDescriptor(); \ 385 } 386 387 388 class PlatformCodeStub : public CodeStub { 389 public: 390 // Retrieve the code for the stub. Generate the code if needed. 391 Handle<Code> GenerateCode() override; 392 393 protected: PlatformCodeStub(Isolate * isolate)394 explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {} 395 396 // Generates the assembler code for the stub. 397 virtual void Generate(MacroAssembler* masm) = 0; 398 399 DEFINE_CODE_STUB_BASE(PlatformCodeStub, CodeStub); 400 }; 401 402 403 enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE }; 404 405 406 class CodeStubDescriptor { 407 public: 408 explicit CodeStubDescriptor(CodeStub* stub); 409 410 CodeStubDescriptor(Isolate* isolate, uint32_t stub_key); 411 412 void Initialize(Address deoptimization_handler = NULL, 413 int hint_stack_parameter_count = -1, 414 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE); 415 void Initialize(Register stack_parameter_count, 416 Address deoptimization_handler = NULL, 417 int hint_stack_parameter_count = -1, 418 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE); 419 SetMissHandler(Runtime::FunctionId id)420 void SetMissHandler(Runtime::FunctionId id) { 421 miss_handler_id_ = id; 422 miss_handler_ = ExternalReference(Runtime::FunctionForId(id), isolate_); 423 has_miss_handler_ = true; 424 // Our miss handler infrastructure doesn't currently support 425 // variable stack parameter counts. 426 DCHECK(!stack_parameter_count_.is_valid()); 427 } 428 set_call_descriptor(CallInterfaceDescriptor d)429 void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; } call_descriptor()430 CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; } 431 GetRegisterParameterCount()432 int GetRegisterParameterCount() const { 433 return call_descriptor().GetRegisterParameterCount(); 434 } 435 GetStackParameterCount()436 int GetStackParameterCount() const { 437 return call_descriptor().GetStackParameterCount(); 438 } 439 GetParameterCount()440 int GetParameterCount() const { 441 return call_descriptor().GetParameterCount(); 442 } 443 GetRegisterParameter(int index)444 Register GetRegisterParameter(int index) const { 445 return call_descriptor().GetRegisterParameter(index); 446 } 447 GetParameterType(int index)448 MachineType GetParameterType(int index) const { 449 return call_descriptor().GetParameterType(index); 450 } 451 miss_handler()452 ExternalReference miss_handler() const { 453 DCHECK(has_miss_handler_); 454 return miss_handler_; 455 } 456 miss_handler_id()457 Runtime::FunctionId miss_handler_id() const { 458 DCHECK(has_miss_handler_); 459 return miss_handler_id_; 460 } 461 has_miss_handler()462 bool has_miss_handler() const { 463 return has_miss_handler_; 464 } 465 GetHandlerParameterCount()466 int GetHandlerParameterCount() const { 467 int params = GetParameterCount(); 468 if (PassesArgumentsToDeoptimizationHandler()) { 469 params += 1; 470 } 471 return params; 472 } 473 hint_stack_parameter_count()474 int hint_stack_parameter_count() const { return hint_stack_parameter_count_; } stack_parameter_count()475 Register stack_parameter_count() const { return stack_parameter_count_; } function_mode()476 StubFunctionMode function_mode() const { return function_mode_; } deoptimization_handler()477 Address deoptimization_handler() const { return deoptimization_handler_; } 478 479 private: PassesArgumentsToDeoptimizationHandler()480 bool PassesArgumentsToDeoptimizationHandler() const { 481 return stack_parameter_count_.is_valid(); 482 } 483 484 Isolate* isolate_; 485 CallInterfaceDescriptor call_descriptor_; 486 Register stack_parameter_count_; 487 // If hint_stack_parameter_count_ > 0, the code stub can optimize the 488 // return sequence. Default value is -1, which means it is ignored. 489 int hint_stack_parameter_count_; 490 StubFunctionMode function_mode_; 491 492 Address deoptimization_handler_; 493 494 ExternalReference miss_handler_; 495 Runtime::FunctionId miss_handler_id_; 496 bool has_miss_handler_; 497 }; 498 499 500 class HydrogenCodeStub : public CodeStub { 501 public: 502 enum InitializationState { 503 UNINITIALIZED, 504 INITIALIZED 505 }; 506 507 template<class SubClass> GetUninitialized(Isolate * isolate)508 static Handle<Code> GetUninitialized(Isolate* isolate) { 509 SubClass::GenerateAheadOfTime(isolate); 510 return SubClass().GetCode(isolate); 511 } 512 513 // Retrieve the code for the stub. Generate the code if needed. 514 Handle<Code> GenerateCode() override = 0; 515 IsUninitialized()516 bool IsUninitialized() const { return IsMissBits::decode(minor_key_); } 517 518 Handle<Code> GenerateLightweightMissCode(ExternalReference miss); 519 520 Handle<Code> GenerateRuntimeTailCall(CodeStubDescriptor* descriptor); 521 522 template<class StateType> 523 void TraceTransition(StateType from, StateType to); 524 525 protected: 526 explicit HydrogenCodeStub(Isolate* isolate, 527 InitializationState state = INITIALIZED) CodeStub(isolate)528 : CodeStub(isolate) { 529 minor_key_ = IsMissBits::encode(state == UNINITIALIZED); 530 } 531 set_sub_minor_key(uint32_t key)532 void set_sub_minor_key(uint32_t key) { 533 minor_key_ = SubMinorKeyBits::update(minor_key_, key); 534 } 535 sub_minor_key()536 uint32_t sub_minor_key() const { return SubMinorKeyBits::decode(minor_key_); } 537 538 static const int kSubMinorKeyBits = kStubMinorKeyBits - 1; 539 540 private: 541 class IsMissBits : public BitField<bool, kSubMinorKeyBits, 1> {}; 542 class SubMinorKeyBits : public BitField<int, 0, kSubMinorKeyBits> {}; 543 544 void GenerateLightweightMiss(MacroAssembler* masm, ExternalReference miss); 545 546 DEFINE_CODE_STUB_BASE(HydrogenCodeStub, CodeStub); 547 }; 548 549 550 class TurboFanCodeStub : public CodeStub { 551 public: 552 // Retrieve the code for the stub. Generate the code if needed. 553 Handle<Code> GenerateCode() override; 554 GetStackParameterCount()555 int GetStackParameterCount() const override { 556 return GetCallInterfaceDescriptor().GetStackParameterCount(); 557 } 558 559 protected: TurboFanCodeStub(Isolate * isolate)560 explicit TurboFanCodeStub(Isolate* isolate) : CodeStub(isolate) {} 561 562 virtual void GenerateAssembly(compiler::CodeAssemblerState* state) const = 0; 563 564 private: 565 DEFINE_CODE_STUB_BASE(TurboFanCodeStub, CodeStub); 566 }; 567 568 569 // Helper interface to prepare to/restore after making runtime calls. 570 class RuntimeCallHelper { 571 public: ~RuntimeCallHelper()572 virtual ~RuntimeCallHelper() {} 573 574 virtual void BeforeCall(MacroAssembler* masm) const = 0; 575 576 virtual void AfterCall(MacroAssembler* masm) const = 0; 577 578 protected: RuntimeCallHelper()579 RuntimeCallHelper() {} 580 581 private: 582 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper); 583 }; 584 585 586 } // namespace internal 587 } // namespace v8 588 589 #if V8_TARGET_ARCH_IA32 590 #include "src/ia32/code-stubs-ia32.h" 591 #elif V8_TARGET_ARCH_X64 592 #include "src/x64/code-stubs-x64.h" 593 #elif V8_TARGET_ARCH_ARM64 594 #include "src/arm64/code-stubs-arm64.h" 595 #elif V8_TARGET_ARCH_ARM 596 #include "src/arm/code-stubs-arm.h" 597 #elif V8_TARGET_ARCH_PPC 598 #include "src/ppc/code-stubs-ppc.h" 599 #elif V8_TARGET_ARCH_MIPS 600 #include "src/mips/code-stubs-mips.h" 601 #elif V8_TARGET_ARCH_MIPS64 602 #include "src/mips64/code-stubs-mips64.h" 603 #elif V8_TARGET_ARCH_S390 604 #include "src/s390/code-stubs-s390.h" 605 #elif V8_TARGET_ARCH_X87 606 #include "src/x87/code-stubs-x87.h" 607 #else 608 #error Unsupported target architecture. 609 #endif 610 611 namespace v8 { 612 namespace internal { 613 614 615 // RuntimeCallHelper implementation used in stubs: enters/leaves a 616 // newly created internal frame before/after the runtime call. 617 class StubRuntimeCallHelper : public RuntimeCallHelper { 618 public: StubRuntimeCallHelper()619 StubRuntimeCallHelper() {} 620 621 void BeforeCall(MacroAssembler* masm) const override; 622 623 void AfterCall(MacroAssembler* masm) const override; 624 }; 625 626 627 // Trivial RuntimeCallHelper implementation. 628 class NopRuntimeCallHelper : public RuntimeCallHelper { 629 public: NopRuntimeCallHelper()630 NopRuntimeCallHelper() {} 631 BeforeCall(MacroAssembler * masm)632 void BeforeCall(MacroAssembler* masm) const override {} 633 AfterCall(MacroAssembler * masm)634 void AfterCall(MacroAssembler* masm) const override {} 635 }; 636 637 638 class StringLengthStub : public TurboFanCodeStub { 639 public: StringLengthStub(Isolate * isolate)640 explicit StringLengthStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 641 GetCodeKind()642 Code::Kind GetCodeKind() const override { return Code::HANDLER; } GetExtraICState()643 ExtraICState GetExtraICState() const override { return Code::LOAD_IC; } 644 645 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector); 646 DEFINE_TURBOFAN_CODE_STUB(StringLength, TurboFanCodeStub); 647 }; 648 649 class AddWithFeedbackStub final : public TurboFanCodeStub { 650 public: AddWithFeedbackStub(Isolate * isolate)651 explicit AddWithFeedbackStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 652 653 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector); 654 DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(AddWithFeedback, 655 TurboFanCodeStub); 656 }; 657 658 class SubtractWithFeedbackStub final : public TurboFanCodeStub { 659 public: SubtractWithFeedbackStub(Isolate * isolate)660 explicit SubtractWithFeedbackStub(Isolate* isolate) 661 : TurboFanCodeStub(isolate) {} 662 663 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector); 664 DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(SubtractWithFeedback, 665 TurboFanCodeStub); 666 }; 667 668 class MultiplyWithFeedbackStub final : public TurboFanCodeStub { 669 public: MultiplyWithFeedbackStub(Isolate * isolate)670 explicit MultiplyWithFeedbackStub(Isolate* isolate) 671 : TurboFanCodeStub(isolate) {} 672 673 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector); 674 DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(MultiplyWithFeedback, 675 TurboFanCodeStub); 676 }; 677 678 class DivideWithFeedbackStub final : public TurboFanCodeStub { 679 public: DivideWithFeedbackStub(Isolate * isolate)680 explicit DivideWithFeedbackStub(Isolate* isolate) 681 : TurboFanCodeStub(isolate) {} 682 683 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector); 684 DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(DivideWithFeedback, 685 TurboFanCodeStub); 686 }; 687 688 class ModulusWithFeedbackStub final : public TurboFanCodeStub { 689 public: ModulusWithFeedbackStub(Isolate * isolate)690 explicit ModulusWithFeedbackStub(Isolate* isolate) 691 : TurboFanCodeStub(isolate) {} 692 693 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector); 694 DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(ModulusWithFeedback, 695 TurboFanCodeStub); 696 }; 697 698 class StoreInterceptorStub : public TurboFanCodeStub { 699 public: StoreInterceptorStub(Isolate * isolate)700 explicit StoreInterceptorStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 701 GetCodeKind()702 Code::Kind GetCodeKind() const override { return Code::HANDLER; } GetExtraICState()703 ExtraICState GetExtraICState() const override { return Code::STORE_IC; } 704 705 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); 706 DEFINE_TURBOFAN_CODE_STUB(StoreInterceptor, TurboFanCodeStub); 707 }; 708 709 class LoadIndexedInterceptorStub : public TurboFanCodeStub { 710 public: LoadIndexedInterceptorStub(Isolate * isolate)711 explicit LoadIndexedInterceptorStub(Isolate* isolate) 712 : TurboFanCodeStub(isolate) {} 713 GetCodeKind()714 Code::Kind GetCodeKind() const override { return Code::HANDLER; } GetExtraICState()715 ExtraICState GetExtraICState() const override { return Code::KEYED_LOAD_IC; } 716 717 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector); 718 DEFINE_TURBOFAN_CODE_STUB(LoadIndexedInterceptor, TurboFanCodeStub); 719 }; 720 721 // ES6 [[Get]] operation. 722 class GetPropertyStub : public TurboFanCodeStub { 723 public: GetPropertyStub(Isolate * isolate)724 explicit GetPropertyStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 725 726 DEFINE_CALL_INTERFACE_DESCRIPTOR(GetProperty); 727 DEFINE_TURBOFAN_CODE_STUB(GetProperty, TurboFanCodeStub); 728 }; 729 730 class NumberToStringStub final : public TurboFanCodeStub { 731 public: NumberToStringStub(Isolate * isolate)732 explicit NumberToStringStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 733 734 DEFINE_CALL_INTERFACE_DESCRIPTOR(TypeConversion); 735 DEFINE_TURBOFAN_CODE_STUB(NumberToString, TurboFanCodeStub); 736 }; 737 738 class CreateAllocationSiteStub : public TurboFanCodeStub { 739 public: CreateAllocationSiteStub(Isolate * isolate)740 explicit CreateAllocationSiteStub(Isolate* isolate) 741 : TurboFanCodeStub(isolate) {} 742 static void GenerateAheadOfTime(Isolate* isolate); 743 744 DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateAllocationSite); 745 DEFINE_TURBOFAN_CODE_STUB(CreateAllocationSite, TurboFanCodeStub); 746 }; 747 748 class CreateWeakCellStub : public TurboFanCodeStub { 749 public: CreateWeakCellStub(Isolate * isolate)750 explicit CreateWeakCellStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 751 752 static void GenerateAheadOfTime(Isolate* isolate); 753 754 DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateWeakCell); 755 DEFINE_TURBOFAN_CODE_STUB(CreateWeakCell, TurboFanCodeStub); 756 }; 757 758 class GrowArrayElementsStub : public TurboFanCodeStub { 759 public: GrowArrayElementsStub(Isolate * isolate,ElementsKind kind)760 GrowArrayElementsStub(Isolate* isolate, ElementsKind kind) 761 : TurboFanCodeStub(isolate) { 762 minor_key_ = ElementsKindBits::encode(GetHoleyElementsKind(kind)); 763 } 764 elements_kind()765 ElementsKind elements_kind() const { 766 return ElementsKindBits::decode(minor_key_); 767 } 768 769 private: 770 class ElementsKindBits : public BitField<ElementsKind, 0, 8> {}; 771 772 DEFINE_CALL_INTERFACE_DESCRIPTOR(GrowArrayElements); 773 DEFINE_TURBOFAN_CODE_STUB(GrowArrayElements, TurboFanCodeStub); 774 }; 775 776 enum AllocationSiteOverrideMode { 777 DONT_OVERRIDE, 778 DISABLE_ALLOCATION_SITES, 779 LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES 780 }; 781 782 783 class ArrayConstructorStub: public PlatformCodeStub { 784 public: 785 explicit ArrayConstructorStub(Isolate* isolate); 786 787 private: 788 void GenerateDispatchToArrayStub(MacroAssembler* masm, 789 AllocationSiteOverrideMode mode); 790 791 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor); 792 DEFINE_PLATFORM_CODE_STUB(ArrayConstructor, PlatformCodeStub); 793 }; 794 795 796 class InternalArrayConstructorStub: public PlatformCodeStub { 797 public: 798 explicit InternalArrayConstructorStub(Isolate* isolate); 799 800 private: 801 void GenerateCase(MacroAssembler* masm, ElementsKind kind); 802 803 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNArgumentsConstructor); 804 DEFINE_PLATFORM_CODE_STUB(InternalArrayConstructor, PlatformCodeStub); 805 }; 806 807 808 class MathPowStub: public PlatformCodeStub { 809 public: 810 enum ExponentType { INTEGER, DOUBLE, TAGGED }; 811 MathPowStub(Isolate * isolate,ExponentType exponent_type)812 MathPowStub(Isolate* isolate, ExponentType exponent_type) 813 : PlatformCodeStub(isolate) { 814 minor_key_ = ExponentTypeBits::encode(exponent_type); 815 } 816 GetCallInterfaceDescriptor()817 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { 818 if (exponent_type() == TAGGED) { 819 return MathPowTaggedDescriptor(isolate()); 820 } else if (exponent_type() == INTEGER) { 821 return MathPowIntegerDescriptor(isolate()); 822 } else { 823 // A CallInterfaceDescriptor doesn't specify double registers (yet). 824 DCHECK_EQ(DOUBLE, exponent_type()); 825 return ContextOnlyDescriptor(isolate()); 826 } 827 } 828 829 private: exponent_type()830 ExponentType exponent_type() const { 831 return ExponentTypeBits::decode(minor_key_); 832 } 833 834 class ExponentTypeBits : public BitField<ExponentType, 0, 2> {}; 835 836 DEFINE_PLATFORM_CODE_STUB(MathPow, PlatformCodeStub); 837 }; 838 839 class CallICStub : public TurboFanCodeStub { 840 public: CallICStub(Isolate * isolate,ConvertReceiverMode convert_mode,TailCallMode tail_call_mode)841 CallICStub(Isolate* isolate, ConvertReceiverMode convert_mode, 842 TailCallMode tail_call_mode) 843 : TurboFanCodeStub(isolate) { 844 minor_key_ = ConvertModeBits::encode(convert_mode) | 845 TailCallModeBits::encode(tail_call_mode); 846 } 847 848 protected: 849 typedef BitField<ConvertReceiverMode, 0, 2> ConvertModeBits; 850 typedef BitField<TailCallMode, ConvertModeBits::kNext, 1> TailCallModeBits; 851 convert_mode()852 ConvertReceiverMode convert_mode() const { 853 return ConvertModeBits::decode(minor_key_); 854 } tail_call_mode()855 TailCallMode tail_call_mode() const { 856 return TailCallModeBits::decode(minor_key_); 857 } 858 859 private: 860 void PrintState(std::ostream& os) const final; // NOLINT 861 862 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallIC); 863 DEFINE_TURBOFAN_CODE_STUB(CallIC, TurboFanCodeStub); 864 }; 865 866 class KeyedLoadSloppyArgumentsStub : public TurboFanCodeStub { 867 public: KeyedLoadSloppyArgumentsStub(Isolate * isolate)868 explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate) 869 : TurboFanCodeStub(isolate) {} 870 GetCodeKind()871 Code::Kind GetCodeKind() const override { return Code::HANDLER; } GetExtraICState()872 ExtraICState GetExtraICState() const override { return Code::LOAD_IC; } 873 874 protected: 875 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector); 876 DEFINE_TURBOFAN_CODE_STUB(KeyedLoadSloppyArguments, TurboFanCodeStub); 877 }; 878 879 880 class CommonStoreModeBits : public BitField<KeyedAccessStoreMode, 0, 3> {}; 881 882 class KeyedStoreSloppyArgumentsStub : public TurboFanCodeStub { 883 public: KeyedStoreSloppyArgumentsStub(Isolate * isolate,KeyedAccessStoreMode mode)884 explicit KeyedStoreSloppyArgumentsStub(Isolate* isolate, 885 KeyedAccessStoreMode mode) 886 : TurboFanCodeStub(isolate) { 887 minor_key_ = CommonStoreModeBits::encode(mode); 888 } 889 GetCodeKind()890 Code::Kind GetCodeKind() const override { return Code::HANDLER; } GetExtraICState()891 ExtraICState GetExtraICState() const override { return Code::STORE_IC; } 892 893 protected: 894 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); 895 DEFINE_TURBOFAN_CODE_STUB(KeyedStoreSloppyArguments, TurboFanCodeStub); 896 }; 897 898 class StoreGlobalStub : public TurboFanCodeStub { 899 public: StoreGlobalStub(Isolate * isolate,PropertyCellType type,Maybe<PropertyCellConstantType> constant_type,bool check_global)900 StoreGlobalStub(Isolate* isolate, PropertyCellType type, 901 Maybe<PropertyCellConstantType> constant_type, 902 bool check_global) 903 : TurboFanCodeStub(isolate) { 904 PropertyCellConstantType encoded_constant_type = 905 constant_type.FromMaybe(PropertyCellConstantType::kSmi); 906 minor_key_ = CellTypeBits::encode(type) | 907 ConstantTypeBits::encode(encoded_constant_type) | 908 CheckGlobalBits::encode(check_global); 909 } 910 GetCodeKind()911 Code::Kind GetCodeKind() const override { return Code::HANDLER; } GetExtraICState()912 ExtraICState GetExtraICState() const override { return Code::STORE_IC; } 913 property_cell_placeholder(Isolate * isolate)914 static Handle<HeapObject> property_cell_placeholder(Isolate* isolate) { 915 return isolate->factory()->uninitialized_value(); 916 } 917 global_map_placeholder(Isolate * isolate)918 static Handle<HeapObject> global_map_placeholder(Isolate* isolate) { 919 return isolate->factory()->termination_exception(); 920 } 921 GetCodeCopyFromTemplate(Handle<JSGlobalObject> global,Handle<PropertyCell> cell)922 Handle<Code> GetCodeCopyFromTemplate(Handle<JSGlobalObject> global, 923 Handle<PropertyCell> cell) { 924 FindAndReplacePattern pattern; 925 if (check_global()) { 926 pattern.Add(handle(global_map_placeholder(isolate())->map()), 927 Map::WeakCellForMap(Handle<Map>(global->map()))); 928 } 929 pattern.Add(handle(property_cell_placeholder(isolate())->map()), 930 isolate()->factory()->NewWeakCell(cell)); 931 return CodeStub::GetCodeCopy(pattern); 932 } 933 cell_type()934 PropertyCellType cell_type() const { 935 return CellTypeBits::decode(minor_key_); 936 } 937 constant_type()938 PropertyCellConstantType constant_type() const { 939 DCHECK(PropertyCellType::kConstantType == cell_type()); 940 return ConstantTypeBits::decode(minor_key_); 941 } 942 check_global()943 bool check_global() const { return CheckGlobalBits::decode(minor_key_); } 944 945 private: 946 class CellTypeBits : public BitField<PropertyCellType, 0, 2> {}; 947 class ConstantTypeBits 948 : public BitField<PropertyCellConstantType, CellTypeBits::kNext, 2> {}; 949 class CheckGlobalBits : public BitField<bool, ConstantTypeBits::kNext, 1> {}; 950 951 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); 952 DEFINE_TURBOFAN_CODE_STUB(StoreGlobal, TurboFanCodeStub); 953 }; 954 955 class CallApiCallbackStub : public PlatformCodeStub { 956 public: 957 static const int kArgBits = 3; 958 static const int kArgMax = (1 << kArgBits) - 1; 959 960 // CallApiCallbackStub for regular setters and getters. CallApiCallbackStub(Isolate * isolate,bool is_store,bool call_data_undefined,bool is_lazy)961 CallApiCallbackStub(Isolate* isolate, bool is_store, bool call_data_undefined, 962 bool is_lazy) 963 : CallApiCallbackStub(isolate, is_store ? 1 : 0, is_store, 964 call_data_undefined, is_lazy) {} 965 966 // CallApiCallbackStub for callback functions. CallApiCallbackStub(Isolate * isolate,int argc,bool call_data_undefined,bool is_lazy)967 CallApiCallbackStub(Isolate* isolate, int argc, bool call_data_undefined, 968 bool is_lazy) 969 : CallApiCallbackStub(isolate, argc, false, call_data_undefined, 970 is_lazy) {} 971 972 private: CallApiCallbackStub(Isolate * isolate,int argc,bool is_store,bool call_data_undefined,bool is_lazy)973 CallApiCallbackStub(Isolate* isolate, int argc, bool is_store, 974 bool call_data_undefined, bool is_lazy) 975 : PlatformCodeStub(isolate) { 976 CHECK(0 <= argc && argc <= kArgMax); 977 minor_key_ = IsStoreBits::encode(is_store) | 978 CallDataUndefinedBits::encode(call_data_undefined) | 979 ArgumentBits::encode(argc) | 980 IsLazyAccessorBits::encode(is_lazy); 981 } 982 is_store()983 bool is_store() const { return IsStoreBits::decode(minor_key_); } is_lazy()984 bool is_lazy() const { return IsLazyAccessorBits::decode(minor_key_); } call_data_undefined()985 bool call_data_undefined() const { 986 return CallDataUndefinedBits::decode(minor_key_); 987 } argc()988 int argc() const { return ArgumentBits::decode(minor_key_); } 989 990 class IsStoreBits: public BitField<bool, 0, 1> {}; 991 class CallDataUndefinedBits: public BitField<bool, 1, 1> {}; 992 class ArgumentBits : public BitField<int, 2, kArgBits> {}; 993 class IsLazyAccessorBits : public BitField<bool, 3 + kArgBits, 1> {}; 994 995 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiCallback); 996 DEFINE_PLATFORM_CODE_STUB(CallApiCallback, PlatformCodeStub); 997 }; 998 999 1000 class CallApiGetterStub : public PlatformCodeStub { 1001 public: CallApiGetterStub(Isolate * isolate)1002 explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {} 1003 1004 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiGetter); 1005 DEFINE_PLATFORM_CODE_STUB(CallApiGetter, PlatformCodeStub); 1006 }; 1007 1008 1009 class BinaryOpICStub : public HydrogenCodeStub { 1010 public: BinaryOpICStub(Isolate * isolate,Token::Value op)1011 BinaryOpICStub(Isolate* isolate, Token::Value op) 1012 : HydrogenCodeStub(isolate, UNINITIALIZED) { 1013 BinaryOpICState state(isolate, op); 1014 set_sub_minor_key(state.GetExtraICState()); 1015 } 1016 BinaryOpICStub(Isolate * isolate,const BinaryOpICState & state)1017 BinaryOpICStub(Isolate* isolate, const BinaryOpICState& state) 1018 : HydrogenCodeStub(isolate) { 1019 set_sub_minor_key(state.GetExtraICState()); 1020 } 1021 1022 static void GenerateAheadOfTime(Isolate* isolate); 1023 GetCodeKind()1024 Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; } 1025 GetExtraICState()1026 ExtraICState GetExtraICState() const final { 1027 return static_cast<ExtraICState>(sub_minor_key()); 1028 } 1029 state()1030 BinaryOpICState state() const { 1031 return BinaryOpICState(isolate(), GetExtraICState()); 1032 } 1033 1034 void PrintState(std::ostream& os) const final; // NOLINT 1035 1036 private: 1037 static void GenerateAheadOfTime(Isolate* isolate, 1038 const BinaryOpICState& state); 1039 1040 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp); 1041 DEFINE_HYDROGEN_CODE_STUB(BinaryOpIC, HydrogenCodeStub); 1042 }; 1043 1044 1045 // TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail 1046 // call support for stubs in Hydrogen. 1047 class BinaryOpICWithAllocationSiteStub final : public PlatformCodeStub { 1048 public: BinaryOpICWithAllocationSiteStub(Isolate * isolate,const BinaryOpICState & state)1049 BinaryOpICWithAllocationSiteStub(Isolate* isolate, 1050 const BinaryOpICState& state) 1051 : PlatformCodeStub(isolate) { 1052 minor_key_ = state.GetExtraICState(); 1053 } 1054 1055 static void GenerateAheadOfTime(Isolate* isolate); 1056 GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site)1057 Handle<Code> GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site) { 1058 FindAndReplacePattern pattern; 1059 pattern.Add(isolate()->factory()->undefined_map(), allocation_site); 1060 return CodeStub::GetCodeCopy(pattern); 1061 } 1062 GetCodeKind()1063 Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; } 1064 GetExtraICState()1065 ExtraICState GetExtraICState() const override { 1066 return static_cast<ExtraICState>(minor_key_); 1067 } 1068 1069 void PrintState(std::ostream& os) const override; // NOLINT 1070 1071 private: state()1072 BinaryOpICState state() const { 1073 return BinaryOpICState(isolate(), GetExtraICState()); 1074 } 1075 1076 static void GenerateAheadOfTime(Isolate* isolate, 1077 const BinaryOpICState& state); 1078 1079 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite); 1080 DEFINE_PLATFORM_CODE_STUB(BinaryOpICWithAllocationSite, PlatformCodeStub); 1081 }; 1082 1083 1084 class BinaryOpWithAllocationSiteStub final : public BinaryOpICStub { 1085 public: BinaryOpWithAllocationSiteStub(Isolate * isolate,Token::Value op)1086 BinaryOpWithAllocationSiteStub(Isolate* isolate, Token::Value op) 1087 : BinaryOpICStub(isolate, op) {} 1088 BinaryOpWithAllocationSiteStub(Isolate * isolate,const BinaryOpICState & state)1089 BinaryOpWithAllocationSiteStub(Isolate* isolate, const BinaryOpICState& state) 1090 : BinaryOpICStub(isolate, state) {} 1091 GetCodeKind()1092 Code::Kind GetCodeKind() const final { return Code::STUB; } 1093 1094 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite); 1095 DEFINE_HYDROGEN_CODE_STUB(BinaryOpWithAllocationSite, BinaryOpICStub); 1096 }; 1097 1098 class StringAddStub final : public TurboFanCodeStub { 1099 public: StringAddStub(Isolate * isolate,StringAddFlags flags,PretenureFlag pretenure_flag)1100 StringAddStub(Isolate* isolate, StringAddFlags flags, 1101 PretenureFlag pretenure_flag) 1102 : TurboFanCodeStub(isolate) { 1103 minor_key_ = (StringAddFlagsBits::encode(flags) | 1104 PretenureFlagBits::encode(pretenure_flag)); 1105 } 1106 flags()1107 StringAddFlags flags() const { 1108 return StringAddFlagsBits::decode(minor_key_); 1109 } 1110 pretenure_flag()1111 PretenureFlag pretenure_flag() const { 1112 return PretenureFlagBits::decode(minor_key_); 1113 } 1114 1115 private: 1116 class StringAddFlagsBits : public BitField<StringAddFlags, 0, 3> {}; 1117 class PretenureFlagBits : public BitField<PretenureFlag, 3, 1> {}; 1118 1119 void PrintBaseName(std::ostream& os) const override; // NOLINT 1120 1121 DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd); 1122 DEFINE_TURBOFAN_CODE_STUB(StringAdd, TurboFanCodeStub); 1123 }; 1124 1125 1126 class CompareICStub : public PlatformCodeStub { 1127 public: CompareICStub(Isolate * isolate,Token::Value op,CompareICState::State left,CompareICState::State right,CompareICState::State state)1128 CompareICStub(Isolate* isolate, Token::Value op, CompareICState::State left, 1129 CompareICState::State right, CompareICState::State state) 1130 : PlatformCodeStub(isolate) { 1131 DCHECK(Token::IsCompareOp(op)); 1132 DCHECK(OpBits::is_valid(op - Token::EQ)); 1133 minor_key_ = OpBits::encode(op - Token::EQ) | 1134 LeftStateBits::encode(left) | RightStateBits::encode(right) | 1135 StateBits::encode(state); 1136 } 1137 // Creates uninitialized compare stub. CompareICStub(Isolate * isolate,Token::Value op)1138 CompareICStub(Isolate* isolate, Token::Value op) 1139 : CompareICStub(isolate, op, CompareICState::UNINITIALIZED, 1140 CompareICState::UNINITIALIZED, 1141 CompareICState::UNINITIALIZED) {} 1142 CompareICStub(Isolate * isolate,ExtraICState extra_ic_state)1143 CompareICStub(Isolate* isolate, ExtraICState extra_ic_state) 1144 : PlatformCodeStub(isolate) { 1145 minor_key_ = extra_ic_state; 1146 } 1147 GetExtraICState()1148 ExtraICState GetExtraICState() const final { 1149 return static_cast<ExtraICState>(minor_key_); 1150 } 1151 set_known_map(Handle<Map> map)1152 void set_known_map(Handle<Map> map) { known_map_ = map; } 1153 1154 InlineCacheState GetICState() const; 1155 op()1156 Token::Value op() const { 1157 return static_cast<Token::Value>(Token::EQ + OpBits::decode(minor_key_)); 1158 } 1159 left()1160 CompareICState::State left() const { 1161 return LeftStateBits::decode(minor_key_); 1162 } right()1163 CompareICState::State right() const { 1164 return RightStateBits::decode(minor_key_); 1165 } state()1166 CompareICState::State state() const { return StateBits::decode(minor_key_); } 1167 1168 private: GetCodeKind()1169 Code::Kind GetCodeKind() const override { return Code::COMPARE_IC; } 1170 1171 void GenerateBooleans(MacroAssembler* masm); 1172 void GenerateSmis(MacroAssembler* masm); 1173 void GenerateNumbers(MacroAssembler* masm); 1174 void GenerateInternalizedStrings(MacroAssembler* masm); 1175 void GenerateStrings(MacroAssembler* masm); 1176 void GenerateUniqueNames(MacroAssembler* masm); 1177 void GenerateReceivers(MacroAssembler* masm); 1178 void GenerateMiss(MacroAssembler* masm); 1179 void GenerateKnownReceivers(MacroAssembler* masm); 1180 void GenerateGeneric(MacroAssembler* masm); 1181 strict()1182 bool strict() const { return op() == Token::EQ_STRICT; } 1183 Condition GetCondition() const; 1184 1185 // Although we don't cache anything in the special cache we have to define 1186 // this predicate to avoid appearance of code stubs with embedded maps in 1187 // the global stub cache. UseSpecialCache()1188 bool UseSpecialCache() override { 1189 return state() == CompareICState::KNOWN_RECEIVER; 1190 } 1191 1192 class OpBits : public BitField<int, 0, 3> {}; 1193 class LeftStateBits : public BitField<CompareICState::State, 3, 4> {}; 1194 class RightStateBits : public BitField<CompareICState::State, 7, 4> {}; 1195 class StateBits : public BitField<CompareICState::State, 11, 4> {}; 1196 1197 Handle<Map> known_map_; 1198 1199 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp); 1200 DEFINE_PLATFORM_CODE_STUB(CompareIC, PlatformCodeStub); 1201 }; 1202 1203 1204 class CEntryStub : public PlatformCodeStub { 1205 public: 1206 CEntryStub(Isolate* isolate, int result_size, 1207 SaveFPRegsMode save_doubles = kDontSaveFPRegs, 1208 ArgvMode argv_mode = kArgvOnStack, bool builtin_exit_frame = false) PlatformCodeStub(isolate)1209 : PlatformCodeStub(isolate) { 1210 minor_key_ = SaveDoublesBits::encode(save_doubles == kSaveFPRegs) | 1211 FrameTypeBits::encode(builtin_exit_frame) | 1212 ArgvMode::encode(argv_mode == kArgvInRegister); 1213 DCHECK(result_size == 1 || result_size == 2 || result_size == 3); 1214 minor_key_ = ResultSizeBits::update(minor_key_, result_size); 1215 } 1216 1217 // The version of this stub that doesn't save doubles is generated ahead of 1218 // time, so it's OK to call it from other stubs that can't cope with GC during 1219 // their code generation. On machines that always have gp registers (x64) we 1220 // can generate both variants ahead of time. 1221 static void GenerateAheadOfTime(Isolate* isolate); 1222 1223 private: save_doubles()1224 bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); } argv_in_register()1225 bool argv_in_register() const { return ArgvMode::decode(minor_key_); } is_builtin_exit()1226 bool is_builtin_exit() const { return FrameTypeBits::decode(minor_key_); } result_size()1227 int result_size() const { return ResultSizeBits::decode(minor_key_); } 1228 1229 bool NeedsImmovableCode() override; 1230 1231 class SaveDoublesBits : public BitField<bool, 0, 1> {}; 1232 class ArgvMode : public BitField<bool, 1, 1> {}; 1233 class FrameTypeBits : public BitField<bool, 2, 1> {}; 1234 class ResultSizeBits : public BitField<int, 3, 3> {}; 1235 1236 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); 1237 DEFINE_PLATFORM_CODE_STUB(CEntry, PlatformCodeStub); 1238 }; 1239 1240 1241 class JSEntryStub : public PlatformCodeStub { 1242 public: JSEntryStub(Isolate * isolate,StackFrame::Type type)1243 JSEntryStub(Isolate* isolate, StackFrame::Type type) 1244 : PlatformCodeStub(isolate) { 1245 DCHECK(type == StackFrame::ENTRY || type == StackFrame::ENTRY_CONSTRUCT); 1246 minor_key_ = StackFrameTypeBits::encode(type); 1247 } 1248 1249 private: 1250 void FinishCode(Handle<Code> code) override; 1251 PrintName(std::ostream & os)1252 void PrintName(std::ostream& os) const override { // NOLINT 1253 os << (type() == StackFrame::ENTRY ? "JSEntryStub" 1254 : "JSConstructEntryStub"); 1255 } 1256 type()1257 StackFrame::Type type() const { 1258 return StackFrameTypeBits::decode(minor_key_); 1259 } 1260 1261 class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {}; 1262 1263 int handler_offset_; 1264 1265 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); 1266 DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub); 1267 }; 1268 1269 1270 class RegExpExecStub: public PlatformCodeStub { 1271 public: RegExpExecStub(Isolate * isolate)1272 explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { } 1273 1274 DEFINE_CALL_INTERFACE_DESCRIPTOR(RegExpExec); 1275 DEFINE_PLATFORM_CODE_STUB(RegExpExec, PlatformCodeStub); 1276 }; 1277 1278 // TODO(bmeurer/mvstanton): Turn CallConstructStub into ConstructICStub. 1279 class CallConstructStub final : public PlatformCodeStub { 1280 public: CallConstructStub(Isolate * isolate)1281 explicit CallConstructStub(Isolate* isolate) : PlatformCodeStub(isolate) {} 1282 1283 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallConstruct); 1284 DEFINE_PLATFORM_CODE_STUB(CallConstruct, PlatformCodeStub); 1285 }; 1286 1287 1288 enum ReceiverCheckMode { 1289 // We don't know anything about the receiver. 1290 RECEIVER_IS_UNKNOWN, 1291 1292 // We know the receiver is a string. 1293 RECEIVER_IS_STRING 1294 }; 1295 1296 1297 enum EmbedMode { 1298 // The code being generated is part of an IC handler, which may MISS 1299 // to an IC in failure cases. 1300 PART_OF_IC_HANDLER, 1301 1302 NOT_PART_OF_IC_HANDLER 1303 }; 1304 1305 1306 // Generates code implementing String.prototype.charCodeAt. 1307 // 1308 // Only supports the case when the receiver is a string and the index 1309 // is a number (smi or heap number) that is a valid index into the 1310 // string. Additional index constraints are specified by the 1311 // flags. Otherwise, bails out to the provided labels. 1312 // 1313 // Register usage: |object| may be changed to another string in a way 1314 // that doesn't affect charCodeAt/charAt semantics, |index| is 1315 // preserved, |scratch| and |result| are clobbered. 1316 class StringCharCodeAtGenerator { 1317 public: 1318 StringCharCodeAtGenerator(Register object, Register index, Register result, 1319 Label* receiver_not_string, Label* index_not_number, 1320 Label* index_out_of_range, 1321 ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN) object_(object)1322 : object_(object), 1323 index_(index), 1324 result_(result), 1325 receiver_not_string_(receiver_not_string), 1326 index_not_number_(index_not_number), 1327 index_out_of_range_(index_out_of_range), 1328 check_mode_(check_mode) { 1329 DCHECK(!result_.is(object_)); 1330 DCHECK(!result_.is(index_)); 1331 } 1332 1333 // Generates the fast case code. On the fallthrough path |result| 1334 // register contains the result. 1335 void GenerateFast(MacroAssembler* masm); 1336 1337 // Generates the slow case code. Must not be naturally 1338 // reachable. Expected to be put after a ret instruction (e.g., in 1339 // deferred code). Always jumps back to the fast case. 1340 void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode, 1341 const RuntimeCallHelper& call_helper); 1342 1343 private: 1344 Register object_; 1345 Register index_; 1346 Register result_; 1347 1348 Label* receiver_not_string_; 1349 Label* index_not_number_; 1350 Label* index_out_of_range_; 1351 1352 ReceiverCheckMode check_mode_; 1353 1354 Label call_runtime_; 1355 Label index_not_smi_; 1356 Label got_smi_index_; 1357 Label exit_; 1358 1359 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator); 1360 }; 1361 1362 class CallICTrampolineStub : public TurboFanCodeStub { 1363 public: CallICTrampolineStub(Isolate * isolate,ConvertReceiverMode convert_mode,TailCallMode tail_call_mode)1364 CallICTrampolineStub(Isolate* isolate, ConvertReceiverMode convert_mode, 1365 TailCallMode tail_call_mode) 1366 : TurboFanCodeStub(isolate) { 1367 minor_key_ = ConvertModeBits::encode(convert_mode) | 1368 TailCallModeBits::encode(tail_call_mode); 1369 } 1370 1371 protected: 1372 typedef BitField<ConvertReceiverMode, 0, 2> ConvertModeBits; 1373 typedef BitField<TailCallMode, ConvertModeBits::kNext, 1> TailCallModeBits; 1374 convert_mode()1375 ConvertReceiverMode convert_mode() const { 1376 return ConvertModeBits::decode(minor_key_); 1377 } tail_call_mode()1378 TailCallMode tail_call_mode() const { 1379 return TailCallModeBits::decode(minor_key_); 1380 } 1381 1382 private: 1383 void PrintState(std::ostream& os) const override; // NOLINT 1384 1385 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallICTrampoline); 1386 DEFINE_TURBOFAN_CODE_STUB(CallICTrampoline, TurboFanCodeStub); 1387 }; 1388 1389 class DoubleToIStub : public PlatformCodeStub { 1390 public: 1391 DoubleToIStub(Isolate* isolate, Register source, Register destination, 1392 int offset, bool is_truncating, bool skip_fastpath = false) PlatformCodeStub(isolate)1393 : PlatformCodeStub(isolate) { 1394 minor_key_ = SourceRegisterBits::encode(source.code()) | 1395 DestinationRegisterBits::encode(destination.code()) | 1396 OffsetBits::encode(offset) | 1397 IsTruncatingBits::encode(is_truncating) | 1398 SkipFastPathBits::encode(skip_fastpath) | 1399 SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0); 1400 } 1401 SometimesSetsUpAFrame()1402 bool SometimesSetsUpAFrame() override { return false; } 1403 1404 private: source()1405 Register source() const { 1406 return Register::from_code(SourceRegisterBits::decode(minor_key_)); 1407 } destination()1408 Register destination() const { 1409 return Register::from_code(DestinationRegisterBits::decode(minor_key_)); 1410 } is_truncating()1411 bool is_truncating() const { return IsTruncatingBits::decode(minor_key_); } skip_fastpath()1412 bool skip_fastpath() const { return SkipFastPathBits::decode(minor_key_); } offset()1413 int offset() const { return OffsetBits::decode(minor_key_); } 1414 1415 static const int kBitsPerRegisterNumber = 6; 1416 STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters); 1417 class SourceRegisterBits: 1418 public BitField<int, 0, kBitsPerRegisterNumber> {}; // NOLINT 1419 class DestinationRegisterBits: 1420 public BitField<int, kBitsPerRegisterNumber, 1421 kBitsPerRegisterNumber> {}; // NOLINT 1422 class IsTruncatingBits: 1423 public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {}; // NOLINT 1424 class OffsetBits: 1425 public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {}; // NOLINT 1426 class SkipFastPathBits: 1427 public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {}; // NOLINT 1428 class SSE3Bits: 1429 public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {}; // NOLINT 1430 1431 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); 1432 DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub); 1433 }; 1434 1435 class ScriptContextFieldStub : public TurboFanCodeStub { 1436 public: ScriptContextFieldStub(Isolate * isolate,const ScriptContextTable::LookupResult * lookup_result)1437 ScriptContextFieldStub(Isolate* isolate, 1438 const ScriptContextTable::LookupResult* lookup_result) 1439 : TurboFanCodeStub(isolate) { 1440 DCHECK(Accepted(lookup_result)); 1441 minor_key_ = ContextIndexBits::encode(lookup_result->context_index) | 1442 SlotIndexBits::encode(lookup_result->slot_index); 1443 } 1444 GetCodeKind()1445 Code::Kind GetCodeKind() const override { return Code::HANDLER; } 1446 context_index()1447 int context_index() const { return ContextIndexBits::decode(minor_key_); } 1448 slot_index()1449 int slot_index() const { return SlotIndexBits::decode(minor_key_); } 1450 Accepted(const ScriptContextTable::LookupResult * lookup_result)1451 static bool Accepted(const ScriptContextTable::LookupResult* lookup_result) { 1452 return ContextIndexBits::is_valid(lookup_result->context_index) && 1453 SlotIndexBits::is_valid(lookup_result->slot_index); 1454 } 1455 1456 private: 1457 static const int kContextIndexBits = 9; 1458 static const int kSlotIndexBits = 12; 1459 class ContextIndexBits : public BitField<int, 0, kContextIndexBits> {}; 1460 class SlotIndexBits 1461 : public BitField<int, kContextIndexBits, kSlotIndexBits> {}; 1462 1463 DEFINE_CODE_STUB_BASE(ScriptContextFieldStub, TurboFanCodeStub); 1464 }; 1465 1466 1467 class LoadScriptContextFieldStub : public ScriptContextFieldStub { 1468 public: LoadScriptContextFieldStub(Isolate * isolate,const ScriptContextTable::LookupResult * lookup_result)1469 LoadScriptContextFieldStub( 1470 Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result) 1471 : ScriptContextFieldStub(isolate, lookup_result) {} 1472 GetExtraICState()1473 ExtraICState GetExtraICState() const override { return Code::LOAD_IC; } 1474 1475 private: 1476 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector); 1477 DEFINE_TURBOFAN_CODE_STUB(LoadScriptContextField, ScriptContextFieldStub); 1478 }; 1479 1480 1481 class StoreScriptContextFieldStub : public ScriptContextFieldStub { 1482 public: StoreScriptContextFieldStub(Isolate * isolate,const ScriptContextTable::LookupResult * lookup_result)1483 StoreScriptContextFieldStub( 1484 Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result) 1485 : ScriptContextFieldStub(isolate, lookup_result) {} 1486 GetExtraICState()1487 ExtraICState GetExtraICState() const override { return Code::STORE_IC; } 1488 1489 private: 1490 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); 1491 DEFINE_TURBOFAN_CODE_STUB(StoreScriptContextField, ScriptContextFieldStub); 1492 }; 1493 1494 class StoreFastElementStub : public TurboFanCodeStub { 1495 public: StoreFastElementStub(Isolate * isolate,bool is_js_array,ElementsKind elements_kind,KeyedAccessStoreMode mode)1496 StoreFastElementStub(Isolate* isolate, bool is_js_array, 1497 ElementsKind elements_kind, KeyedAccessStoreMode mode) 1498 : TurboFanCodeStub(isolate) { 1499 minor_key_ = CommonStoreModeBits::encode(mode) | 1500 ElementsKindBits::encode(elements_kind) | 1501 IsJSArrayBits::encode(is_js_array); 1502 } 1503 1504 static void GenerateAheadOfTime(Isolate* isolate); 1505 is_js_array()1506 bool is_js_array() const { return IsJSArrayBits::decode(minor_key_); } 1507 elements_kind()1508 ElementsKind elements_kind() const { 1509 return ElementsKindBits::decode(minor_key_); 1510 } 1511 store_mode()1512 KeyedAccessStoreMode store_mode() const { 1513 return CommonStoreModeBits::decode(minor_key_); 1514 } 1515 GetCodeKind()1516 Code::Kind GetCodeKind() const override { return Code::HANDLER; } GetExtraICState()1517 ExtraICState GetExtraICState() const override { return Code::KEYED_STORE_IC; } 1518 1519 private: 1520 class ElementsKindBits 1521 : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {}; 1522 class IsJSArrayBits : public BitField<bool, ElementsKindBits::kNext, 1> {}; 1523 1524 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); 1525 DEFINE_TURBOFAN_CODE_STUB(StoreFastElement, TurboFanCodeStub); 1526 }; 1527 1528 1529 class TransitionElementsKindStub : public HydrogenCodeStub { 1530 public: TransitionElementsKindStub(Isolate * isolate,ElementsKind from_kind,ElementsKind to_kind)1531 TransitionElementsKindStub(Isolate* isolate, ElementsKind from_kind, 1532 ElementsKind to_kind) 1533 : HydrogenCodeStub(isolate) { 1534 set_sub_minor_key(FromKindBits::encode(from_kind) | 1535 ToKindBits::encode(to_kind)); 1536 } 1537 from_kind()1538 ElementsKind from_kind() const { 1539 return FromKindBits::decode(sub_minor_key()); 1540 } 1541 to_kind()1542 ElementsKind to_kind() const { return ToKindBits::decode(sub_minor_key()); } 1543 1544 private: 1545 class FromKindBits: public BitField<ElementsKind, 8, 8> {}; 1546 class ToKindBits: public BitField<ElementsKind, 0, 8> {}; 1547 1548 DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind); 1549 DEFINE_HYDROGEN_CODE_STUB(TransitionElementsKind, HydrogenCodeStub); 1550 }; 1551 1552 class AllocateHeapNumberStub : public TurboFanCodeStub { 1553 public: AllocateHeapNumberStub(Isolate * isolate)1554 explicit AllocateHeapNumberStub(Isolate* isolate) 1555 : TurboFanCodeStub(isolate) {} 1556 1557 void InitializeDescriptor(CodeStubDescriptor* descriptor) override; 1558 1559 DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateHeapNumber); 1560 DEFINE_TURBOFAN_CODE_STUB(AllocateHeapNumber, TurboFanCodeStub); 1561 }; 1562 1563 class CommonArrayConstructorStub : public TurboFanCodeStub { 1564 protected: CommonArrayConstructorStub(Isolate * isolate,ElementsKind kind,AllocationSiteOverrideMode override_mode)1565 CommonArrayConstructorStub(Isolate* isolate, ElementsKind kind, 1566 AllocationSiteOverrideMode override_mode) 1567 : TurboFanCodeStub(isolate) { 1568 // It only makes sense to override local allocation site behavior 1569 // if there is a difference between the global allocation site policy 1570 // for an ElementsKind and the desired usage of the stub. 1571 DCHECK(override_mode != DISABLE_ALLOCATION_SITES || 1572 AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE); 1573 set_sub_minor_key(ElementsKindBits::encode(kind) | 1574 AllocationSiteOverrideModeBits::encode(override_mode)); 1575 } 1576 set_sub_minor_key(uint32_t key)1577 void set_sub_minor_key(uint32_t key) { minor_key_ = key; } 1578 sub_minor_key()1579 uint32_t sub_minor_key() const { return minor_key_; } 1580 CommonArrayConstructorStub(uint32_t key,Isolate * isolate)1581 CommonArrayConstructorStub(uint32_t key, Isolate* isolate) 1582 : TurboFanCodeStub(key, isolate) {} 1583 1584 public: elements_kind()1585 ElementsKind elements_kind() const { 1586 return ElementsKindBits::decode(sub_minor_key()); 1587 } 1588 override_mode()1589 AllocationSiteOverrideMode override_mode() const { 1590 return AllocationSiteOverrideModeBits::decode(sub_minor_key()); 1591 } 1592 1593 static void GenerateStubsAheadOfTime(Isolate* isolate); 1594 1595 private: 1596 // Ensure data fits within available bits. 1597 STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1); 1598 1599 class ElementsKindBits : public BitField<ElementsKind, 0, 8> {}; 1600 class AllocationSiteOverrideModeBits 1601 : public BitField<AllocationSiteOverrideMode, 8, 1> {}; // NOLINT 1602 }; 1603 1604 class ArrayNoArgumentConstructorStub : public CommonArrayConstructorStub { 1605 public: 1606 ArrayNoArgumentConstructorStub( 1607 Isolate* isolate, ElementsKind kind, 1608 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE) CommonArrayConstructorStub(isolate,kind,override_mode)1609 : CommonArrayConstructorStub(isolate, kind, override_mode) {} 1610 1611 private: PrintName(std::ostream & os)1612 void PrintName(std::ostream& os) const override { // NOLINT 1613 os << "ArrayNoArgumentConstructorStub"; 1614 } 1615 1616 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNoArgumentConstructor); 1617 DEFINE_TURBOFAN_CODE_STUB(ArrayNoArgumentConstructor, 1618 CommonArrayConstructorStub); 1619 }; 1620 1621 class InternalArrayNoArgumentConstructorStub 1622 : public CommonArrayConstructorStub { 1623 public: InternalArrayNoArgumentConstructorStub(Isolate * isolate,ElementsKind kind)1624 InternalArrayNoArgumentConstructorStub(Isolate* isolate, ElementsKind kind) 1625 : CommonArrayConstructorStub(isolate, kind, DONT_OVERRIDE) {} 1626 1627 private: PrintName(std::ostream & os)1628 void PrintName(std::ostream& os) const override { // NOLINT 1629 os << "InternalArrayNoArgumentConstructorStub"; 1630 } 1631 1632 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNoArgumentConstructor); 1633 DEFINE_TURBOFAN_CODE_STUB(InternalArrayNoArgumentConstructor, 1634 CommonArrayConstructorStub); 1635 }; 1636 1637 class ArraySingleArgumentConstructorStub : public CommonArrayConstructorStub { 1638 public: 1639 ArraySingleArgumentConstructorStub( 1640 Isolate* isolate, ElementsKind kind, 1641 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE) CommonArrayConstructorStub(isolate,kind,override_mode)1642 : CommonArrayConstructorStub(isolate, kind, override_mode) {} 1643 1644 private: PrintName(std::ostream & os)1645 void PrintName(std::ostream& os) const override { // NOLINT 1646 os << "ArraySingleArgumentConstructorStub"; 1647 } 1648 1649 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArraySingleArgumentConstructor); 1650 DEFINE_TURBOFAN_CODE_STUB(ArraySingleArgumentConstructor, 1651 CommonArrayConstructorStub); 1652 }; 1653 1654 class InternalArraySingleArgumentConstructorStub 1655 : public CommonArrayConstructorStub { 1656 public: InternalArraySingleArgumentConstructorStub(Isolate * isolate,ElementsKind kind)1657 InternalArraySingleArgumentConstructorStub(Isolate* isolate, 1658 ElementsKind kind) 1659 : CommonArrayConstructorStub(isolate, kind, DONT_OVERRIDE) {} 1660 1661 private: PrintName(std::ostream & os)1662 void PrintName(std::ostream& os) const override { // NOLINT 1663 os << "InternalArraySingleArgumentConstructorStub"; 1664 } 1665 1666 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArraySingleArgumentConstructor); 1667 DEFINE_TURBOFAN_CODE_STUB(InternalArraySingleArgumentConstructor, 1668 CommonArrayConstructorStub); 1669 }; 1670 1671 class ArrayNArgumentsConstructorStub : public PlatformCodeStub { 1672 public: ArrayNArgumentsConstructorStub(Isolate * isolate)1673 explicit ArrayNArgumentsConstructorStub(Isolate* isolate) 1674 : PlatformCodeStub(isolate) {} 1675 GetCallInterfaceDescriptor()1676 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { 1677 return ArrayNArgumentsConstructorDescriptor(isolate()); 1678 } 1679 1680 private: 1681 DEFINE_PLATFORM_CODE_STUB(ArrayNArgumentsConstructor, PlatformCodeStub); 1682 }; 1683 1684 class StoreSlowElementStub : public TurboFanCodeStub { 1685 public: StoreSlowElementStub(Isolate * isolate,KeyedAccessStoreMode mode)1686 StoreSlowElementStub(Isolate* isolate, KeyedAccessStoreMode mode) 1687 : TurboFanCodeStub(isolate) { 1688 minor_key_ = CommonStoreModeBits::encode(mode); 1689 } 1690 GetCodeKind()1691 Code::Kind GetCodeKind() const override { return Code::HANDLER; } GetExtraICState()1692 ExtraICState GetExtraICState() const override { return Code::KEYED_STORE_IC; } 1693 1694 private: 1695 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); 1696 DEFINE_TURBOFAN_CODE_STUB(StoreSlowElement, TurboFanCodeStub); 1697 }; 1698 1699 class ToBooleanICStub : public HydrogenCodeStub { 1700 public: ToBooleanICStub(Isolate * isolate,ExtraICState state)1701 ToBooleanICStub(Isolate* isolate, ExtraICState state) 1702 : HydrogenCodeStub(isolate) { 1703 set_sub_minor_key(HintsBits::encode(static_cast<uint16_t>(state))); 1704 } 1705 1706 bool UpdateStatus(Handle<Object> object); hints()1707 ToBooleanHints hints() const { 1708 return ToBooleanHints(HintsBits::decode(sub_minor_key())); 1709 } 1710 GetCodeKind()1711 Code::Kind GetCodeKind() const override { return Code::TO_BOOLEAN_IC; } 1712 void PrintState(std::ostream& os) const override; // NOLINT 1713 SometimesSetsUpAFrame()1714 bool SometimesSetsUpAFrame() override { return false; } 1715 GetUninitialized(Isolate * isolate)1716 static Handle<Code> GetUninitialized(Isolate* isolate) { 1717 return ToBooleanICStub(isolate, UNINITIALIZED).GetCode(); 1718 } 1719 GetExtraICState()1720 ExtraICState GetExtraICState() const override { return hints(); } 1721 GetICState()1722 InlineCacheState GetICState() const { 1723 if (hints() == ToBooleanHint::kNone) { 1724 return ::v8::internal::UNINITIALIZED; 1725 } else { 1726 return MONOMORPHIC; 1727 } 1728 } 1729 1730 private: ToBooleanICStub(Isolate * isolate,InitializationState init_state)1731 ToBooleanICStub(Isolate* isolate, InitializationState init_state) 1732 : HydrogenCodeStub(isolate, init_state) {} 1733 1734 static const int kNumHints = 8; 1735 STATIC_ASSERT(static_cast<int>(ToBooleanHint::kAny) == 1736 ((1 << kNumHints) - 1)); 1737 class HintsBits : public BitField<uint16_t, 0, kNumHints> {}; 1738 1739 DEFINE_CALL_INTERFACE_DESCRIPTOR(TypeConversion); 1740 DEFINE_HYDROGEN_CODE_STUB(ToBooleanIC, HydrogenCodeStub); 1741 }; 1742 1743 class ElementsTransitionAndStoreStub : public TurboFanCodeStub { 1744 public: ElementsTransitionAndStoreStub(Isolate * isolate,ElementsKind from_kind,ElementsKind to_kind,bool is_jsarray,KeyedAccessStoreMode store_mode)1745 ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind, 1746 ElementsKind to_kind, bool is_jsarray, 1747 KeyedAccessStoreMode store_mode) 1748 : TurboFanCodeStub(isolate) { 1749 minor_key_ = CommonStoreModeBits::encode(store_mode) | 1750 FromBits::encode(from_kind) | ToBits::encode(to_kind) | 1751 IsJSArrayBits::encode(is_jsarray); 1752 } 1753 from_kind()1754 ElementsKind from_kind() const { return FromBits::decode(minor_key_); } to_kind()1755 ElementsKind to_kind() const { return ToBits::decode(minor_key_); } is_jsarray()1756 bool is_jsarray() const { return IsJSArrayBits::decode(minor_key_); } store_mode()1757 KeyedAccessStoreMode store_mode() const { 1758 return CommonStoreModeBits::decode(minor_key_); 1759 } 1760 GetCodeKind()1761 Code::Kind GetCodeKind() const override { return Code::HANDLER; } GetExtraICState()1762 ExtraICState GetExtraICState() const override { return Code::KEYED_STORE_IC; } 1763 1764 private: 1765 class FromBits 1766 : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {}; 1767 class ToBits : public BitField<ElementsKind, 11, 8> {}; 1768 class IsJSArrayBits : public BitField<bool, 19, 1> {}; 1769 1770 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreTransition); 1771 DEFINE_TURBOFAN_CODE_STUB(ElementsTransitionAndStore, TurboFanCodeStub); 1772 }; 1773 1774 1775 class StubFailureTrampolineStub : public PlatformCodeStub { 1776 public: StubFailureTrampolineStub(Isolate * isolate,StubFunctionMode function_mode)1777 StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode) 1778 : PlatformCodeStub(isolate) { 1779 minor_key_ = FunctionModeField::encode(function_mode); 1780 } 1781 1782 static void GenerateAheadOfTime(Isolate* isolate); 1783 1784 private: function_mode()1785 StubFunctionMode function_mode() const { 1786 return FunctionModeField::decode(minor_key_); 1787 } 1788 1789 class FunctionModeField : public BitField<StubFunctionMode, 0, 1> {}; 1790 1791 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); 1792 DEFINE_PLATFORM_CODE_STUB(StubFailureTrampoline, PlatformCodeStub); 1793 }; 1794 1795 1796 class ProfileEntryHookStub : public PlatformCodeStub { 1797 public: ProfileEntryHookStub(Isolate * isolate)1798 explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {} 1799 1800 // The profile entry hook function is not allowed to cause a GC. SometimesSetsUpAFrame()1801 bool SometimesSetsUpAFrame() override { return false; } 1802 1803 // Generates a call to the entry hook if it's enabled. 1804 static void MaybeCallEntryHook(MacroAssembler* masm); 1805 1806 private: 1807 static void EntryHookTrampoline(intptr_t function, 1808 intptr_t stack_pointer, 1809 Isolate* isolate); 1810 1811 // ProfileEntryHookStub is called at the start of a function, so it has the 1812 // same register set. 1813 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction) 1814 DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub); 1815 }; 1816 1817 1818 class StoreBufferOverflowStub : public PlatformCodeStub { 1819 public: StoreBufferOverflowStub(Isolate * isolate,SaveFPRegsMode save_fp)1820 StoreBufferOverflowStub(Isolate* isolate, SaveFPRegsMode save_fp) 1821 : PlatformCodeStub(isolate) { 1822 minor_key_ = SaveDoublesBits::encode(save_fp == kSaveFPRegs); 1823 } 1824 1825 static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate); SometimesSetsUpAFrame()1826 bool SometimesSetsUpAFrame() override { return false; } 1827 1828 private: save_doubles()1829 bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); } 1830 1831 class SaveDoublesBits : public BitField<bool, 0, 1> {}; 1832 1833 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); 1834 DEFINE_PLATFORM_CODE_STUB(StoreBufferOverflow, PlatformCodeStub); 1835 }; 1836 1837 class SubStringStub : public TurboFanCodeStub { 1838 public: SubStringStub(Isolate * isolate)1839 explicit SubStringStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 1840 1841 static compiler::Node* Generate(CodeStubAssembler* assembler, 1842 compiler::Node* string, compiler::Node* from, 1843 compiler::Node* to, compiler::Node* context); 1844 1845 DEFINE_CALL_INTERFACE_DESCRIPTOR(SubString); 1846 DEFINE_TURBOFAN_CODE_STUB(SubString, TurboFanCodeStub); 1847 }; 1848 1849 1850 #undef DEFINE_CALL_INTERFACE_DESCRIPTOR 1851 #undef DEFINE_PLATFORM_CODE_STUB 1852 #undef DEFINE_HANDLER_CODE_STUB 1853 #undef DEFINE_HYDROGEN_CODE_STUB 1854 #undef DEFINE_CODE_STUB 1855 #undef DEFINE_CODE_STUB_BASE 1856 1857 } // namespace internal 1858 } // namespace v8 1859 1860 #endif // V8_CODE_STUBS_H_ 1861