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/globals.h" 11 #include "src/heap/factory.h" 12 #include "src/interface-descriptors.h" 13 #include "src/macro-assembler.h" 14 #include "src/ostreams.h" 15 #include "src/type-hints.h" 16 17 namespace v8 { 18 namespace internal { 19 20 // Forward declarations. 21 class CodeStubAssembler; 22 namespace compiler { 23 class CodeAssemblerLabel; 24 class CodeAssemblerState; 25 class Node; 26 } 27 28 // List of code stubs used on all platforms. 29 #define CODE_STUB_LIST_ALL_PLATFORMS(V) \ 30 /* --- PlatformCodeStubs --- */ \ 31 V(ArrayConstructor) \ 32 V(CallApiCallback) \ 33 V(CallApiGetter) \ 34 V(InternalArrayConstructor) \ 35 V(JSEntry) \ 36 V(ProfileEntryHook) \ 37 /* --- TurboFanCodeStubs --- */ \ 38 V(StoreSlowElement) \ 39 V(StoreInArrayLiteralSlow) \ 40 V(ArrayNoArgumentConstructor) \ 41 V(ArraySingleArgumentConstructor) \ 42 V(ArrayNArgumentsConstructor) \ 43 V(InternalArrayNoArgumentConstructor) \ 44 V(InternalArraySingleArgumentConstructor) \ 45 V(ElementsTransitionAndStore) \ 46 V(KeyedLoadSloppyArguments) \ 47 V(KeyedStoreSloppyArguments) \ 48 V(StoreFastElement) \ 49 V(StoreInterceptor) \ 50 V(TransitionElementsKind) \ 51 V(LoadIndexedInterceptor) 52 53 // List of code stubs only used on ARM 32 bits platforms. 54 #if V8_TARGET_ARCH_ARM 55 #define CODE_STUB_LIST_ARM(V) V(DirectCEntry) 56 57 #else 58 #define CODE_STUB_LIST_ARM(V) 59 #endif 60 61 // List of code stubs only used on ARM 64 bits platforms. 62 #if V8_TARGET_ARCH_ARM64 63 #define CODE_STUB_LIST_ARM64(V) V(DirectCEntry) 64 65 #else 66 #define CODE_STUB_LIST_ARM64(V) 67 #endif 68 69 // List of code stubs only used on PPC platforms. 70 #ifdef V8_TARGET_ARCH_PPC 71 #define CODE_STUB_LIST_PPC(V) V(DirectCEntry) 72 #else 73 #define CODE_STUB_LIST_PPC(V) 74 #endif 75 76 // List of code stubs only used on MIPS platforms. 77 #if V8_TARGET_ARCH_MIPS 78 #define CODE_STUB_LIST_MIPS(V) V(DirectCEntry) 79 #elif V8_TARGET_ARCH_MIPS64 80 #define CODE_STUB_LIST_MIPS(V) V(DirectCEntry) 81 #else 82 #define CODE_STUB_LIST_MIPS(V) 83 #endif 84 85 // List of code stubs only used on S390 platforms. 86 #ifdef V8_TARGET_ARCH_S390 87 #define CODE_STUB_LIST_S390(V) V(DirectCEntry) 88 #else 89 #define CODE_STUB_LIST_S390(V) 90 #endif 91 92 // Combined list of code stubs. 93 #define CODE_STUB_LIST(V) \ 94 CODE_STUB_LIST_ALL_PLATFORMS(V) \ 95 CODE_STUB_LIST_ARM(V) \ 96 CODE_STUB_LIST_ARM64(V) \ 97 CODE_STUB_LIST_PPC(V) \ 98 CODE_STUB_LIST_MIPS(V) \ 99 CODE_STUB_LIST_S390(V) 100 101 static const int kHasReturnedMinusZeroSentinel = 1; 102 103 class CodeStub : public ZoneObject { 104 public: 105 enum Major { 106 // TODO(mvstanton): eliminate the NoCache key by getting rid 107 // of the non-monomorphic-cache. 108 NoCache = 0, // marker for stubs that do custom caching] 109 #define DEF_ENUM(name) name, 110 CODE_STUB_LIST(DEF_ENUM) 111 #undef DEF_ENUM 112 NUMBER_OF_IDS 113 }; 114 115 // Retrieve the code for the stub. Generate the code if needed. 116 Handle<Code> GetCode(); 117 MajorKeyFromKey(uint32_t key)118 static Major MajorKeyFromKey(uint32_t key) { 119 return static_cast<Major>(MajorKeyBits::decode(key)); 120 } MinorKeyFromKey(uint32_t key)121 static uint32_t MinorKeyFromKey(uint32_t key) { 122 return MinorKeyBits::decode(key); 123 } 124 125 // Gets the major key from a code object that is a code stub or binary op IC. 126 static Major GetMajorKey(Code* code_stub); 127 NoCacheKey()128 static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); } 129 130 static const char* MajorName(Major major_key); 131 CodeStub(Isolate * isolate)132 explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {} ~CodeStub()133 virtual ~CodeStub() {} 134 135 static void GenerateStubsAheadOfTime(Isolate* isolate); 136 137 // Some stubs put untagged junk on the stack that cannot be scanned by the 138 // GC. This means that we must be statically sure that no GC can occur while 139 // they are running. If that is the case they should override this to return 140 // true, which will cause an assertion if we try to call something that can 141 // GC or if we try to put a stack frame on top of the junk, which would not 142 // result in a traversable stack. SometimesSetsUpAFrame()143 virtual bool SometimesSetsUpAFrame() { return true; } 144 145 // Lookup the code in the (possibly custom) cache. 146 bool FindCodeInCache(Code** code_out); 147 148 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() const = 0; 149 GetStackParameterCount()150 virtual int GetStackParameterCount() const { 151 return GetCallInterfaceDescriptor().GetStackParameterCount(); 152 } 153 InitializeDescriptor(CodeStubDescriptor * descriptor)154 virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {} 155 156 static void InitializeDescriptor(Isolate* isolate, uint32_t key, 157 CodeStubDescriptor* desc); 158 159 static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key); 160 161 // Returns information for computing the number key. 162 virtual Major MajorKey() const = 0; MinorKey()163 uint32_t MinorKey() const { return minor_key_; } 164 165 friend std::ostream& operator<<(std::ostream& os, const CodeStub& s) { 166 s.PrintName(os); 167 return os; 168 } 169 isolate()170 Isolate* isolate() const { return isolate_; } set_isolate(Isolate * isolate)171 void set_isolate(Isolate* isolate) { 172 DCHECK_NOT_NULL(isolate); 173 DCHECK(isolate_ == nullptr || isolate_ == isolate); 174 isolate_ = isolate; 175 } 176 177 void DeleteStubFromCacheForTesting(); 178 179 protected: CodeStub(uint32_t key,Isolate * isolate)180 CodeStub(uint32_t key, Isolate* isolate) 181 : minor_key_(MinorKeyFromKey(key)), isolate_(isolate) {} 182 183 // Generates the assembler code for the stub. 184 virtual Handle<Code> GenerateCode() = 0; 185 186 // Returns whether the code generated for this stub needs to be allocated as 187 // a fixed (non-moveable) code object. 188 // TODO(jgruber): Only required by DirectCEntryStub. Can be removed when/if 189 // that is ported to a builtin. NeedsImmovableCode()190 virtual Movability NeedsImmovableCode() { return kMovable; } 191 192 virtual void PrintName(std::ostream& os) const; // NOLINT 193 virtual void PrintBaseName(std::ostream& os) const; // NOLINT PrintState(std::ostream & os)194 virtual void PrintState(std::ostream& os) const { ; } // NOLINT 195 196 // Computes the key based on major and minor. GetKey()197 uint32_t GetKey() { 198 DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS); 199 return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey()); 200 } 201 202 uint32_t minor_key_; 203 204 private: 205 // Perform bookkeeping required after code generation when stub code is 206 // initially generated. 207 void RecordCodeGeneration(Handle<Code> code); 208 209 // Activate newly generated stub. Is called after 210 // registering stub in the stub cache. Activate(Code * code)211 virtual void Activate(Code* code) { } 212 213 // We use this dispatch to statically instantiate the correct code stub for 214 // the given stub key and call the passed function with that code stub. 215 typedef void (*DispatchedCall)(CodeStub* stub, void** value_out); 216 static void Dispatch(Isolate* isolate, uint32_t key, void** value_out, 217 DispatchedCall call); 218 219 static void GetCodeDispatchCall(CodeStub* stub, void** value_out); 220 221 STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits)); 222 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {}; 223 class MinorKeyBits: public BitField<uint32_t, 224 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT 225 226 friend class BreakPointIterator; 227 228 Isolate* isolate_; 229 }; 230 231 232 #define DEFINE_CODE_STUB_BASE(NAME, SUPER) \ 233 public: \ 234 NAME(uint32_t key, Isolate* isolate) : SUPER(key, isolate) {} \ 235 \ 236 private: \ 237 DISALLOW_COPY_AND_ASSIGN(NAME) 238 239 240 #define DEFINE_CODE_STUB(NAME, SUPER) \ 241 public: \ 242 inline Major MajorKey() const override { return NAME; }; \ 243 \ 244 DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER) 245 246 247 #define DEFINE_PLATFORM_CODE_STUB(NAME, SUPER) \ 248 private: \ 249 void Generate(MacroAssembler* masm) override; \ 250 DEFINE_CODE_STUB(NAME, SUPER) 251 252 253 #define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER) \ 254 public: \ 255 void GenerateAssembly(compiler::CodeAssemblerState* state) const override; \ 256 DEFINE_CODE_STUB(NAME, SUPER) 257 258 #define DEFINE_CALL_INTERFACE_DESCRIPTOR(NAME) \ 259 public: \ 260 typedef NAME##Descriptor Descriptor; \ 261 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \ 262 return Descriptor(isolate()); \ 263 } 264 265 // There are some code stubs we just can't describe right now with a 266 // CallInterfaceDescriptor. Isolate behavior for those cases with this macro. 267 // An attempt to retrieve a descriptor will fail. 268 #define DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR() \ 269 public: \ 270 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \ 271 UNREACHABLE(); \ 272 return CallInterfaceDescriptor(); \ 273 } 274 275 276 class PlatformCodeStub : public CodeStub { 277 public: 278 // Retrieve the code for the stub. Generate the code if needed. 279 Handle<Code> GenerateCode() override; 280 281 protected: PlatformCodeStub(Isolate * isolate)282 explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {} 283 284 // Generates the assembler code for the stub. 285 virtual void Generate(MacroAssembler* masm) = 0; 286 287 // Generates the exception handler table for the stub. 288 virtual int GenerateHandlerTable(MacroAssembler* masm); 289 290 DEFINE_CODE_STUB_BASE(PlatformCodeStub, CodeStub); 291 }; 292 293 294 enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE }; 295 296 297 class CodeStubDescriptor { 298 public: 299 explicit CodeStubDescriptor(CodeStub* stub); 300 301 CodeStubDescriptor(Isolate* isolate, uint32_t stub_key); 302 303 void Initialize(Address deoptimization_handler = kNullAddress, 304 int hint_stack_parameter_count = -1, 305 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE); 306 void Initialize(Register stack_parameter_count, 307 Address deoptimization_handler = kNullAddress, 308 int hint_stack_parameter_count = -1, 309 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE); 310 SetMissHandler(Runtime::FunctionId id)311 void SetMissHandler(Runtime::FunctionId id) { 312 miss_handler_id_ = id; 313 miss_handler_ = ExternalReference::Create(Runtime::FunctionForId(id)); 314 has_miss_handler_ = true; 315 // Our miss handler infrastructure doesn't currently support 316 // variable stack parameter counts. 317 DCHECK(!stack_parameter_count_.is_valid()); 318 } 319 set_call_descriptor(CallInterfaceDescriptor d)320 void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; } call_descriptor()321 CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; } 322 GetRegisterParameterCount()323 int GetRegisterParameterCount() const { 324 return call_descriptor().GetRegisterParameterCount(); 325 } 326 GetStackParameterCount()327 int GetStackParameterCount() const { 328 return call_descriptor().GetStackParameterCount(); 329 } 330 GetParameterCount()331 int GetParameterCount() const { 332 return call_descriptor().GetParameterCount(); 333 } 334 GetRegisterParameter(int index)335 Register GetRegisterParameter(int index) const { 336 return call_descriptor().GetRegisterParameter(index); 337 } 338 GetParameterType(int index)339 MachineType GetParameterType(int index) const { 340 return call_descriptor().GetParameterType(index); 341 } 342 miss_handler()343 ExternalReference miss_handler() const { 344 DCHECK(has_miss_handler_); 345 return miss_handler_; 346 } 347 miss_handler_id()348 Runtime::FunctionId miss_handler_id() const { 349 DCHECK(has_miss_handler_); 350 return miss_handler_id_; 351 } 352 has_miss_handler()353 bool has_miss_handler() const { 354 return has_miss_handler_; 355 } 356 GetHandlerParameterCount()357 int GetHandlerParameterCount() const { 358 int params = GetParameterCount(); 359 if (PassesArgumentsToDeoptimizationHandler()) { 360 params += 1; 361 } 362 return params; 363 } 364 hint_stack_parameter_count()365 int hint_stack_parameter_count() const { return hint_stack_parameter_count_; } stack_parameter_count()366 Register stack_parameter_count() const { return stack_parameter_count_; } function_mode()367 StubFunctionMode function_mode() const { return function_mode_; } deoptimization_handler()368 Address deoptimization_handler() const { return deoptimization_handler_; } 369 370 private: PassesArgumentsToDeoptimizationHandler()371 bool PassesArgumentsToDeoptimizationHandler() const { 372 return stack_parameter_count_.is_valid(); 373 } 374 375 Isolate* isolate_; 376 CallInterfaceDescriptor call_descriptor_; 377 Register stack_parameter_count_; 378 // If hint_stack_parameter_count_ > 0, the code stub can optimize the 379 // return sequence. Default value is -1, which means it is ignored. 380 int hint_stack_parameter_count_; 381 StubFunctionMode function_mode_; 382 383 Address deoptimization_handler_; 384 385 ExternalReference miss_handler_; 386 Runtime::FunctionId miss_handler_id_; 387 bool has_miss_handler_; 388 }; 389 390 391 class TurboFanCodeStub : public CodeStub { 392 public: 393 // Retrieve the code for the stub. Generate the code if needed. 394 Handle<Code> GenerateCode() override; 395 GetStackParameterCount()396 int GetStackParameterCount() const override { 397 return GetCallInterfaceDescriptor().GetStackParameterCount(); 398 } 399 400 protected: TurboFanCodeStub(Isolate * isolate)401 explicit TurboFanCodeStub(Isolate* isolate) : CodeStub(isolate) {} 402 403 virtual void GenerateAssembly(compiler::CodeAssemblerState* state) const = 0; 404 405 private: 406 DEFINE_CODE_STUB_BASE(TurboFanCodeStub, CodeStub); 407 }; 408 409 } // namespace internal 410 } // namespace v8 411 412 #if V8_TARGET_ARCH_IA32 413 #elif V8_TARGET_ARCH_X64 414 #elif V8_TARGET_ARCH_ARM64 415 #include "src/arm64/code-stubs-arm64.h" 416 #elif V8_TARGET_ARCH_ARM 417 #include "src/arm/code-stubs-arm.h" 418 #elif V8_TARGET_ARCH_PPC 419 #include "src/ppc/code-stubs-ppc.h" 420 #elif V8_TARGET_ARCH_MIPS 421 #include "src/mips/code-stubs-mips.h" 422 #elif V8_TARGET_ARCH_MIPS64 423 #include "src/mips64/code-stubs-mips64.h" 424 #elif V8_TARGET_ARCH_S390 425 #include "src/s390/code-stubs-s390.h" 426 #else 427 #error Unsupported target architecture. 428 #endif 429 430 namespace v8 { 431 namespace internal { 432 433 // TODO(jgruber): Convert this stub into a builtin. 434 class StoreInterceptorStub : public TurboFanCodeStub { 435 public: StoreInterceptorStub(Isolate * isolate)436 explicit StoreInterceptorStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} 437 438 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); 439 DEFINE_TURBOFAN_CODE_STUB(StoreInterceptor, TurboFanCodeStub); 440 }; 441 442 class TransitionElementsKindStub : public TurboFanCodeStub { 443 public: TransitionElementsKindStub(Isolate * isolate,ElementsKind from_kind,ElementsKind to_kind,bool is_jsarray)444 TransitionElementsKindStub(Isolate* isolate, ElementsKind from_kind, 445 ElementsKind to_kind, bool is_jsarray) 446 : TurboFanCodeStub(isolate) { 447 set_sub_minor_key(FromKindBits::encode(from_kind) | 448 ToKindBits::encode(to_kind) | 449 IsJSArrayBits::encode(is_jsarray)); 450 } 451 set_sub_minor_key(uint32_t key)452 void set_sub_minor_key(uint32_t key) { minor_key_ = key; } 453 sub_minor_key()454 uint32_t sub_minor_key() const { return minor_key_; } 455 from_kind()456 ElementsKind from_kind() const { 457 return FromKindBits::decode(sub_minor_key()); 458 } 459 to_kind()460 ElementsKind to_kind() const { return ToKindBits::decode(sub_minor_key()); } 461 is_jsarray()462 bool is_jsarray() const { return IsJSArrayBits::decode(sub_minor_key()); } 463 464 private: 465 class ToKindBits : public BitField<ElementsKind, 0, 8> {}; 466 class FromKindBits : public BitField<ElementsKind, ToKindBits::kNext, 8> {}; 467 class IsJSArrayBits : public BitField<bool, FromKindBits::kNext, 1> {}; 468 469 DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind); 470 DEFINE_TURBOFAN_CODE_STUB(TransitionElementsKind, TurboFanCodeStub); 471 }; 472 473 // TODO(jgruber): Convert this stub into a builtin. 474 class LoadIndexedInterceptorStub : public TurboFanCodeStub { 475 public: LoadIndexedInterceptorStub(Isolate * isolate)476 explicit LoadIndexedInterceptorStub(Isolate* isolate) 477 : TurboFanCodeStub(isolate) {} 478 479 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector); 480 DEFINE_TURBOFAN_CODE_STUB(LoadIndexedInterceptor, TurboFanCodeStub); 481 }; 482 483 enum AllocationSiteOverrideMode { 484 DONT_OVERRIDE, 485 DISABLE_ALLOCATION_SITES, 486 LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES 487 }; 488 489 // TODO(jgruber): Convert this stub into a builtin. 490 class ArrayConstructorStub: public PlatformCodeStub { 491 public: 492 explicit ArrayConstructorStub(Isolate* isolate); 493 494 private: 495 void GenerateDispatchToArrayStub(MacroAssembler* masm, 496 AllocationSiteOverrideMode mode); 497 498 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor); 499 DEFINE_PLATFORM_CODE_STUB(ArrayConstructor, PlatformCodeStub); 500 }; 501 502 // TODO(jgruber): Convert this stub into a builtin. 503 class InternalArrayConstructorStub: public PlatformCodeStub { 504 public: 505 explicit InternalArrayConstructorStub(Isolate* isolate); 506 507 private: 508 void GenerateCase(MacroAssembler* masm, ElementsKind kind); 509 510 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNArgumentsConstructor); 511 DEFINE_PLATFORM_CODE_STUB(InternalArrayConstructor, PlatformCodeStub); 512 }; 513 514 // TODO(jgruber): Convert this stub into a builtin. 515 class KeyedLoadSloppyArgumentsStub : public TurboFanCodeStub { 516 public: KeyedLoadSloppyArgumentsStub(Isolate * isolate)517 explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate) 518 : TurboFanCodeStub(isolate) {} 519 520 protected: 521 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector); 522 DEFINE_TURBOFAN_CODE_STUB(KeyedLoadSloppyArguments, TurboFanCodeStub); 523 }; 524 525 526 class CommonStoreModeBits : public BitField<KeyedAccessStoreMode, 0, 3> {}; 527 528 class KeyedStoreSloppyArgumentsStub : public TurboFanCodeStub { 529 public: KeyedStoreSloppyArgumentsStub(Isolate * isolate,KeyedAccessStoreMode mode)530 explicit KeyedStoreSloppyArgumentsStub(Isolate* isolate, 531 KeyedAccessStoreMode mode) 532 : TurboFanCodeStub(isolate) { 533 minor_key_ = CommonStoreModeBits::encode(mode); 534 } 535 536 protected: 537 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); 538 DEFINE_TURBOFAN_CODE_STUB(KeyedStoreSloppyArguments, TurboFanCodeStub); 539 }; 540 541 class CallApiCallbackStub : public PlatformCodeStub { 542 public: 543 static const int kArgBits = 7; 544 static const int kArgMax = (1 << kArgBits) - 1; 545 CallApiCallbackStub(Isolate * isolate,int argc)546 CallApiCallbackStub(Isolate* isolate, int argc) 547 : PlatformCodeStub(isolate) { 548 CHECK_LE(0, argc); 549 CHECK_LE(argc, kArgMax); 550 minor_key_ = ArgumentBits::encode(argc); 551 } 552 553 private: argc()554 int argc() const { return ArgumentBits::decode(minor_key_); } 555 556 class ArgumentBits : public BitField<int, 0, kArgBits> {}; 557 558 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiCallback); 559 DEFINE_PLATFORM_CODE_STUB(CallApiCallback, PlatformCodeStub); 560 }; 561 562 // TODO(jgruber): Convert this stub into a builtin. 563 class CallApiGetterStub : public PlatformCodeStub { 564 public: CallApiGetterStub(Isolate * isolate)565 explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {} 566 567 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiGetter); 568 DEFINE_PLATFORM_CODE_STUB(CallApiGetter, PlatformCodeStub); 569 }; 570 571 class JSEntryStub : public PlatformCodeStub { 572 public: 573 enum class SpecialTarget { kNone, kRunMicrotasks }; JSEntryStub(Isolate * isolate,StackFrame::Type type)574 JSEntryStub(Isolate* isolate, StackFrame::Type type) 575 : PlatformCodeStub(isolate) { 576 DCHECK(type == StackFrame::ENTRY || type == StackFrame::CONSTRUCT_ENTRY); 577 minor_key_ = StackFrameTypeBits::encode(type) | 578 SpecialTargetBits::encode(SpecialTarget::kNone); 579 } 580 JSEntryStub(Isolate * isolate,SpecialTarget target)581 JSEntryStub(Isolate* isolate, SpecialTarget target) 582 : PlatformCodeStub(isolate) { 583 minor_key_ = StackFrameTypeBits::encode(StackFrame::ENTRY) | 584 SpecialTargetBits::encode(target); 585 } 586 587 private: 588 int GenerateHandlerTable(MacroAssembler* masm) override; 589 PrintName(std::ostream & os)590 void PrintName(std::ostream& os) const override { // NOLINT 591 os << (type() == StackFrame::ENTRY ? "JSEntryStub" 592 : "JSConstructEntryStub"); 593 } 594 type()595 StackFrame::Type type() const { 596 return StackFrameTypeBits::decode(minor_key_); 597 } 598 special_target()599 SpecialTarget special_target() const { 600 return SpecialTargetBits::decode(minor_key_); 601 } 602 EntryTrampoline()603 Handle<Code> EntryTrampoline() { 604 switch (special_target()) { 605 case SpecialTarget::kNone: 606 return (type() == StackFrame::CONSTRUCT_ENTRY) 607 ? BUILTIN_CODE(isolate(), JSConstructEntryTrampoline) 608 : BUILTIN_CODE(isolate(), JSEntryTrampoline); 609 case SpecialTarget::kRunMicrotasks: 610 return BUILTIN_CODE(isolate(), RunMicrotasks); 611 } 612 UNREACHABLE(); 613 return Handle<Code>(); 614 } 615 616 class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {}; 617 class SpecialTargetBits 618 : public BitField<SpecialTarget, StackFrameTypeBits::kNext, 1> {}; 619 620 int handler_offset_; 621 622 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); 623 DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub); 624 }; 625 626 class StoreFastElementStub : public TurboFanCodeStub { 627 public: StoreFastElementStub(Isolate * isolate,bool is_js_array,ElementsKind elements_kind,KeyedAccessStoreMode mode)628 StoreFastElementStub(Isolate* isolate, bool is_js_array, 629 ElementsKind elements_kind, KeyedAccessStoreMode mode) 630 : TurboFanCodeStub(isolate) { 631 minor_key_ = CommonStoreModeBits::encode(mode) | 632 ElementsKindBits::encode(elements_kind) | 633 IsJSArrayBits::encode(is_js_array); 634 } 635 636 static void GenerateAheadOfTime(Isolate* isolate); 637 is_js_array()638 bool is_js_array() const { return IsJSArrayBits::decode(minor_key_); } 639 elements_kind()640 ElementsKind elements_kind() const { 641 return ElementsKindBits::decode(minor_key_); 642 } 643 store_mode()644 KeyedAccessStoreMode store_mode() const { 645 return CommonStoreModeBits::decode(minor_key_); 646 } 647 648 private: 649 class ElementsKindBits 650 : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {}; 651 class IsJSArrayBits : public BitField<bool, ElementsKindBits::kNext, 1> {}; 652 653 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); 654 DEFINE_TURBOFAN_CODE_STUB(StoreFastElement, TurboFanCodeStub); 655 }; 656 657 658 class CommonArrayConstructorStub : public TurboFanCodeStub { 659 protected: 660 CommonArrayConstructorStub(Isolate* isolate, ElementsKind kind, 661 AllocationSiteOverrideMode override_mode); 662 set_sub_minor_key(uint32_t key)663 void set_sub_minor_key(uint32_t key) { minor_key_ = key; } 664 sub_minor_key()665 uint32_t sub_minor_key() const { return minor_key_; } 666 CommonArrayConstructorStub(uint32_t key,Isolate * isolate)667 CommonArrayConstructorStub(uint32_t key, Isolate* isolate) 668 : TurboFanCodeStub(key, isolate) {} 669 670 public: elements_kind()671 ElementsKind elements_kind() const { 672 return ElementsKindBits::decode(sub_minor_key()); 673 } 674 override_mode()675 AllocationSiteOverrideMode override_mode() const { 676 return AllocationSiteOverrideModeBits::decode(sub_minor_key()); 677 } 678 679 static void GenerateStubsAheadOfTime(Isolate* isolate); 680 681 private: 682 // Ensure data fits within available bits. 683 STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1); 684 685 class ElementsKindBits : public BitField<ElementsKind, 0, 8> {}; 686 class AllocationSiteOverrideModeBits 687 : public BitField<AllocationSiteOverrideMode, 8, 1> {}; // NOLINT 688 }; 689 690 class ArrayNoArgumentConstructorStub : public CommonArrayConstructorStub { 691 public: 692 ArrayNoArgumentConstructorStub( 693 Isolate* isolate, ElementsKind kind, 694 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE) CommonArrayConstructorStub(isolate,kind,override_mode)695 : CommonArrayConstructorStub(isolate, kind, override_mode) {} 696 697 private: PrintName(std::ostream & os)698 void PrintName(std::ostream& os) const override { // NOLINT 699 os << "ArrayNoArgumentConstructorStub"; 700 } 701 702 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNoArgumentConstructor); 703 DEFINE_TURBOFAN_CODE_STUB(ArrayNoArgumentConstructor, 704 CommonArrayConstructorStub); 705 }; 706 707 class InternalArrayNoArgumentConstructorStub 708 : public CommonArrayConstructorStub { 709 public: InternalArrayNoArgumentConstructorStub(Isolate * isolate,ElementsKind kind)710 InternalArrayNoArgumentConstructorStub(Isolate* isolate, ElementsKind kind) 711 : CommonArrayConstructorStub(isolate, kind, DONT_OVERRIDE) {} 712 713 private: PrintName(std::ostream & os)714 void PrintName(std::ostream& os) const override { // NOLINT 715 os << "InternalArrayNoArgumentConstructorStub"; 716 } 717 718 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNoArgumentConstructor); 719 DEFINE_TURBOFAN_CODE_STUB(InternalArrayNoArgumentConstructor, 720 CommonArrayConstructorStub); 721 }; 722 723 class ArraySingleArgumentConstructorStub : public CommonArrayConstructorStub { 724 public: 725 ArraySingleArgumentConstructorStub( 726 Isolate* isolate, ElementsKind kind, 727 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE) CommonArrayConstructorStub(isolate,kind,override_mode)728 : CommonArrayConstructorStub(isolate, kind, override_mode) {} 729 730 private: PrintName(std::ostream & os)731 void PrintName(std::ostream& os) const override { // NOLINT 732 os << "ArraySingleArgumentConstructorStub"; 733 } 734 735 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArraySingleArgumentConstructor); 736 DEFINE_TURBOFAN_CODE_STUB(ArraySingleArgumentConstructor, 737 CommonArrayConstructorStub); 738 }; 739 740 class InternalArraySingleArgumentConstructorStub 741 : public CommonArrayConstructorStub { 742 public: InternalArraySingleArgumentConstructorStub(Isolate * isolate,ElementsKind kind)743 InternalArraySingleArgumentConstructorStub(Isolate* isolate, 744 ElementsKind kind) 745 : CommonArrayConstructorStub(isolate, kind, DONT_OVERRIDE) {} 746 747 private: PrintName(std::ostream & os)748 void PrintName(std::ostream& os) const override { // NOLINT 749 os << "InternalArraySingleArgumentConstructorStub"; 750 } 751 752 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArraySingleArgumentConstructor); 753 DEFINE_TURBOFAN_CODE_STUB(InternalArraySingleArgumentConstructor, 754 CommonArrayConstructorStub); 755 }; 756 757 // TODO(jgruber): Convert this stub into a builtin. 758 class ArrayNArgumentsConstructorStub : public PlatformCodeStub { 759 public: ArrayNArgumentsConstructorStub(Isolate * isolate)760 explicit ArrayNArgumentsConstructorStub(Isolate* isolate) 761 : PlatformCodeStub(isolate) {} 762 GetCallInterfaceDescriptor()763 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { 764 return ArrayNArgumentsConstructorDescriptor(isolate()); 765 } 766 767 private: 768 DEFINE_PLATFORM_CODE_STUB(ArrayNArgumentsConstructor, PlatformCodeStub); 769 }; 770 771 class StoreSlowElementStub : public TurboFanCodeStub { 772 public: StoreSlowElementStub(Isolate * isolate,KeyedAccessStoreMode mode)773 StoreSlowElementStub(Isolate* isolate, KeyedAccessStoreMode mode) 774 : TurboFanCodeStub(isolate) { 775 minor_key_ = CommonStoreModeBits::encode(mode); 776 } 777 778 private: 779 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); 780 DEFINE_TURBOFAN_CODE_STUB(StoreSlowElement, TurboFanCodeStub); 781 }; 782 783 class StoreInArrayLiteralSlowStub : public TurboFanCodeStub { 784 public: StoreInArrayLiteralSlowStub(Isolate * isolate,KeyedAccessStoreMode mode)785 StoreInArrayLiteralSlowStub(Isolate* isolate, KeyedAccessStoreMode mode) 786 : TurboFanCodeStub(isolate) { 787 minor_key_ = CommonStoreModeBits::encode(mode); 788 } 789 790 private: 791 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); 792 DEFINE_TURBOFAN_CODE_STUB(StoreInArrayLiteralSlow, TurboFanCodeStub); 793 }; 794 795 class ElementsTransitionAndStoreStub : public TurboFanCodeStub { 796 public: ElementsTransitionAndStoreStub(Isolate * isolate,ElementsKind from_kind,ElementsKind to_kind,bool is_jsarray,KeyedAccessStoreMode store_mode)797 ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind, 798 ElementsKind to_kind, bool is_jsarray, 799 KeyedAccessStoreMode store_mode) 800 : TurboFanCodeStub(isolate) { 801 minor_key_ = CommonStoreModeBits::encode(store_mode) | 802 FromBits::encode(from_kind) | ToBits::encode(to_kind) | 803 IsJSArrayBits::encode(is_jsarray); 804 } 805 from_kind()806 ElementsKind from_kind() const { return FromBits::decode(minor_key_); } to_kind()807 ElementsKind to_kind() const { return ToBits::decode(minor_key_); } is_jsarray()808 bool is_jsarray() const { return IsJSArrayBits::decode(minor_key_); } store_mode()809 KeyedAccessStoreMode store_mode() const { 810 return CommonStoreModeBits::decode(minor_key_); 811 } 812 813 private: 814 class FromBits 815 : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {}; 816 class ToBits : public BitField<ElementsKind, 11, 8> {}; 817 class IsJSArrayBits : public BitField<bool, 19, 1> {}; 818 819 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreTransition); 820 DEFINE_TURBOFAN_CODE_STUB(ElementsTransitionAndStore, TurboFanCodeStub); 821 }; 822 823 // TODO(jgruber): Convert this stub into a builtin. 824 class ProfileEntryHookStub : public PlatformCodeStub { 825 public: ProfileEntryHookStub(Isolate * isolate)826 explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {} 827 828 // The profile entry hook function is not allowed to cause a GC. SometimesSetsUpAFrame()829 bool SometimesSetsUpAFrame() override { return false; } 830 831 // Generates a call to the entry hook if it's enabled. 832 static void MaybeCallEntryHook(MacroAssembler* masm); 833 static void MaybeCallEntryHookDelayed(TurboAssembler* tasm, Zone* zone); 834 835 private: 836 static void EntryHookTrampoline(intptr_t function, 837 intptr_t stack_pointer, 838 Isolate* isolate); 839 840 // ProfileEntryHookStub is called at the start of a function, so it has the 841 // same register set. 842 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction) 843 DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub); 844 }; 845 846 847 #undef DEFINE_CALL_INTERFACE_DESCRIPTOR 848 #undef DEFINE_PLATFORM_CODE_STUB 849 #undef DEFINE_CODE_STUB 850 #undef DEFINE_CODE_STUB_BASE 851 852 } // namespace internal 853 } // namespace v8 854 855 #endif // V8_CODE_STUBS_H_ 856