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