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