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