1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_CODE_STUBS_H_ 29 #define V8_CODE_STUBS_H_ 30 31 #include "allocation.h" 32 #include "assembler.h" 33 #include "codegen.h" 34 #include "globals.h" 35 #include "macro-assembler.h" 36 37 namespace v8 { 38 namespace internal { 39 40 // List of code stubs used on all platforms. 41 #define CODE_STUB_LIST_ALL_PLATFORMS(V) \ 42 V(CallFunction) \ 43 V(CallConstruct) \ 44 V(BinaryOpIC) \ 45 V(StringAdd) \ 46 V(NewStringAdd) \ 47 V(SubString) \ 48 V(StringCompare) \ 49 V(Compare) \ 50 V(CompareIC) \ 51 V(CompareNilIC) \ 52 V(MathPow) \ 53 V(StringLength) \ 54 V(FunctionPrototype) \ 55 V(StoreArrayLength) \ 56 V(RecordWrite) \ 57 V(StoreBufferOverflow) \ 58 V(RegExpExec) \ 59 V(TranscendentalCache) \ 60 V(Instanceof) \ 61 V(ConvertToDouble) \ 62 V(WriteInt32ToHeapNumber) \ 63 V(StackCheck) \ 64 V(Interrupt) \ 65 V(FastNewClosure) \ 66 V(FastNewContext) \ 67 V(FastNewBlockContext) \ 68 V(FastCloneShallowArray) \ 69 V(FastCloneShallowObject) \ 70 V(CreateAllocationSite) \ 71 V(ToBoolean) \ 72 V(ToNumber) \ 73 V(ArgumentsAccess) \ 74 V(RegExpConstructResult) \ 75 V(NumberToString) \ 76 V(DoubleToI) \ 77 V(CEntry) \ 78 V(JSEntry) \ 79 V(KeyedLoadElement) \ 80 V(ArrayNoArgumentConstructor) \ 81 V(ArraySingleArgumentConstructor) \ 82 V(ArrayNArgumentsConstructor) \ 83 V(InternalArrayNoArgumentConstructor) \ 84 V(InternalArraySingleArgumentConstructor) \ 85 V(InternalArrayNArgumentsConstructor) \ 86 V(KeyedStoreElement) \ 87 V(DebuggerStatement) \ 88 V(NameDictionaryLookup) \ 89 V(ElementsTransitionAndStore) \ 90 V(TransitionElementsKind) \ 91 V(StoreArrayLiteralElement) \ 92 V(StubFailureTrampoline) \ 93 V(StubFailureTailCallTrampoline) \ 94 V(ArrayConstructor) \ 95 V(InternalArrayConstructor) \ 96 V(ProfileEntryHook) \ 97 V(StoreGlobal) \ 98 /* IC Handler stubs */ \ 99 V(LoadField) \ 100 V(KeyedLoadField) \ 101 V(KeyedArrayCall) 102 103 // List of code stubs only used on ARM platforms. 104 #if V8_TARGET_ARCH_ARM 105 #define CODE_STUB_LIST_ARM(V) \ 106 V(GetProperty) \ 107 V(SetProperty) \ 108 V(InvokeBuiltin) \ 109 V(DirectCEntry) 110 #else 111 #define CODE_STUB_LIST_ARM(V) 112 #endif 113 114 // List of code stubs only used on MIPS platforms. 115 #if V8_TARGET_ARCH_MIPS 116 #define CODE_STUB_LIST_MIPS(V) \ 117 V(RegExpCEntry) \ 118 V(DirectCEntry) 119 #else 120 #define CODE_STUB_LIST_MIPS(V) 121 #endif 122 123 // Combined list of code stubs. 124 #define CODE_STUB_LIST(V) \ 125 CODE_STUB_LIST_ALL_PLATFORMS(V) \ 126 CODE_STUB_LIST_ARM(V) \ 127 CODE_STUB_LIST_MIPS(V) 128 129 // Stub is base classes of all stubs. 130 class CodeStub BASE_EMBEDDED { 131 public: 132 enum Major { 133 UninitializedMajorKey = 0, 134 #define DEF_ENUM(name) name, 135 CODE_STUB_LIST(DEF_ENUM) 136 #undef DEF_ENUM 137 NoCache, // marker for stubs that do custom caching 138 NUMBER_OF_IDS 139 }; 140 141 // Retrieve the code for the stub. Generate the code if needed. 142 Handle<Code> GetCode(Isolate* isolate); 143 144 // Retrieve the code for the stub, make and return a copy of the code. 145 Handle<Code> GetCodeCopyFromTemplate(Isolate* isolate); 146 static Major MajorKeyFromKey(uint32_t key) { 147 return static_cast<Major>(MajorKeyBits::decode(key)); 148 } 149 static int MinorKeyFromKey(uint32_t key) { 150 return MinorKeyBits::decode(key); 151 } 152 153 // Gets the major key from a code object that is a code stub or binary op IC. 154 static Major GetMajorKey(Code* code_stub) { 155 return static_cast<Major>(code_stub->major_key()); 156 } 157 158 static const char* MajorName(Major major_key, bool allow_unknown_keys); 159 160 virtual ~CodeStub() {} 161 162 static void GenerateStubsAheadOfTime(Isolate* isolate); 163 static void GenerateStubsRequiringBuiltinsAheadOfTime(Isolate* isolate); 164 static void GenerateFPStubs(Isolate* isolate); 165 166 // Some stubs put untagged junk on the stack that cannot be scanned by the 167 // GC. This means that we must be statically sure that no GC can occur while 168 // they are running. If that is the case they should override this to return 169 // true, which will cause an assertion if we try to call something that can 170 // GC or if we try to put a stack frame on top of the junk, which would not 171 // result in a traversable stack. 172 virtual bool SometimesSetsUpAFrame() { return true; } 173 174 // Lookup the code in the (possibly custom) cache. 175 bool FindCodeInCache(Code** code_out, Isolate* isolate); 176 177 // Returns information for computing the number key. 178 virtual Major MajorKey() = 0; 179 virtual int MinorKey() = 0; 180 181 virtual InlineCacheState GetICState() { 182 return UNINITIALIZED; 183 } 184 virtual ExtraICState GetExtraICState() { 185 return kNoExtraICState; 186 } 187 virtual Code::StubType GetStubType() { 188 return Code::NORMAL; 189 } 190 virtual int GetStubFlags() { 191 return -1; 192 } 193 194 virtual void PrintName(StringStream* stream); 195 196 // Returns a name for logging/debugging purposes. 197 SmartArrayPointer<const char> GetName(); 198 199 protected: 200 static bool CanUseFPRegisters(); 201 202 // Generates the assembler code for the stub. 203 virtual Handle<Code> GenerateCode(Isolate* isolate) = 0; 204 205 virtual void VerifyPlatformFeatures(Isolate* isolate); 206 207 // Returns whether the code generated for this stub needs to be allocated as 208 // a fixed (non-moveable) code object. 209 virtual bool NeedsImmovableCode() { return false; } 210 211 virtual void PrintBaseName(StringStream* stream); 212 virtual void PrintState(StringStream* stream) { } 213 214 private: 215 // Perform bookkeeping required after code generation when stub code is 216 // initially generated. 217 void RecordCodeGeneration(Code* code, Isolate* isolate); 218 219 // Finish the code object after it has been generated. 220 virtual void FinishCode(Handle<Code> code) { } 221 222 // Activate newly generated stub. Is called after 223 // registering stub in the stub cache. 224 virtual void Activate(Code* code) { } 225 226 // BinaryOpStub needs to override this. 227 virtual Code::Kind GetCodeKind() const; 228 229 // Add the code to a specialized cache, specific to an individual 230 // stub type. Please note, this method must add the code object to a 231 // roots object, otherwise we will remove the code during GC. 232 virtual void AddToSpecialCache(Handle<Code> new_object) { } 233 234 // Find code in a specialized cache, work is delegated to the specific stub. 235 virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate) { 236 return false; 237 } 238 239 // If a stub uses a special cache override this. 240 virtual bool UseSpecialCache() { return false; } 241 242 // Computes the key based on major and minor. 243 uint32_t GetKey() { 244 ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS); 245 return MinorKeyBits::encode(MinorKey()) | 246 MajorKeyBits::encode(MajorKey()); 247 } 248 249 STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits)); 250 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {}; 251 class MinorKeyBits: public BitField<uint32_t, 252 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT 253 254 friend class BreakPointIterator; 255 }; 256 257 258 class PlatformCodeStub : public CodeStub { 259 public: 260 // Retrieve the code for the stub. Generate the code if needed. 261 virtual Handle<Code> GenerateCode(Isolate* isolate); 262 263 virtual Code::Kind GetCodeKind() const { return Code::STUB; } 264 265 protected: 266 // Generates the assembler code for the stub. 267 virtual void Generate(MacroAssembler* masm) = 0; 268 }; 269 270 271 enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE }; 272 enum HandlerArgumentsMode { DONT_PASS_ARGUMENTS, PASS_ARGUMENTS }; 273 274 enum ContinuationType { NORMAL_CONTINUATION, TAIL_CALL_CONTINUATION }; 275 276 277 struct CodeStubInterfaceDescriptor { 278 CodeStubInterfaceDescriptor(); 279 int register_param_count_; 280 281 Register stack_parameter_count_; 282 // if hint_stack_parameter_count_ > 0, the code stub can optimize the 283 // return sequence. Default value is -1, which means it is ignored. 284 int hint_stack_parameter_count_; 285 ContinuationType continuation_type_; 286 StubFunctionMode function_mode_; 287 Register* register_params_; 288 289 Address deoptimization_handler_; 290 HandlerArgumentsMode handler_arguments_mode_; 291 292 bool initialized() const { return register_param_count_ >= 0; } 293 294 bool HasTailCallContinuation() const { 295 return continuation_type_ == TAIL_CALL_CONTINUATION; 296 } 297 298 int environment_length() const { 299 return register_param_count_; 300 } 301 302 void SetMissHandler(ExternalReference handler) { 303 miss_handler_ = handler; 304 has_miss_handler_ = true; 305 // Our miss handler infrastructure doesn't currently support 306 // variable stack parameter counts. 307 ASSERT(!stack_parameter_count_.is_valid()); 308 } 309 310 ExternalReference miss_handler() { 311 ASSERT(has_miss_handler_); 312 return miss_handler_; 313 } 314 315 bool has_miss_handler() { 316 return has_miss_handler_; 317 } 318 319 Register GetParameterRegister(int index) { 320 return register_params_[index]; 321 } 322 323 bool IsParameterCountRegister(int index) { 324 return GetParameterRegister(index).is(stack_parameter_count_); 325 } 326 327 int GetHandlerParameterCount() { 328 int params = environment_length(); 329 if (handler_arguments_mode_ == PASS_ARGUMENTS) { 330 params += 1; 331 } 332 return params; 333 } 334 335 private: 336 ExternalReference miss_handler_; 337 bool has_miss_handler_; 338 }; 339 340 341 class HydrogenCodeStub : public CodeStub { 342 public: 343 enum InitializationState { 344 UNINITIALIZED, 345 INITIALIZED 346 }; 347 348 explicit HydrogenCodeStub(InitializationState state = INITIALIZED) { 349 is_uninitialized_ = (state == UNINITIALIZED); 350 } 351 352 virtual Code::Kind GetCodeKind() const { return Code::STUB; } 353 354 CodeStubInterfaceDescriptor* GetInterfaceDescriptor(Isolate* isolate) { 355 return isolate->code_stub_interface_descriptor(MajorKey()); 356 } 357 358 bool IsUninitialized() { return is_uninitialized_; } 359 360 template<class SubClass> 361 static Handle<Code> GetUninitialized(Isolate* isolate) { 362 SubClass::GenerateAheadOfTime(isolate); 363 return SubClass().GetCode(isolate); 364 } 365 366 virtual void InitializeInterfaceDescriptor( 367 Isolate* isolate, 368 CodeStubInterfaceDescriptor* descriptor) = 0; 369 370 // Retrieve the code for the stub. Generate the code if needed. 371 virtual Handle<Code> GenerateCode(Isolate* isolate) = 0; 372 373 virtual int NotMissMinorKey() = 0; 374 375 Handle<Code> GenerateLightweightMissCode(Isolate* isolate); 376 377 template<class StateType> 378 void TraceTransition(StateType from, StateType to); 379 380 private: 381 class MinorKeyBits: public BitField<int, 0, kStubMinorKeyBits - 1> {}; 382 class IsMissBits: public BitField<bool, kStubMinorKeyBits - 1, 1> {}; 383 384 void GenerateLightweightMiss(MacroAssembler* masm); 385 virtual int MinorKey() { 386 return IsMissBits::encode(is_uninitialized_) | 387 MinorKeyBits::encode(NotMissMinorKey()); 388 } 389 390 bool is_uninitialized_; 391 }; 392 393 394 // Helper interface to prepare to/restore after making runtime calls. 395 class RuntimeCallHelper { 396 public: 397 virtual ~RuntimeCallHelper() {} 398 399 virtual void BeforeCall(MacroAssembler* masm) const = 0; 400 401 virtual void AfterCall(MacroAssembler* masm) const = 0; 402 403 protected: 404 RuntimeCallHelper() {} 405 406 private: 407 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper); 408 }; 409 410 411 // TODO(bmeurer): Move to the StringAddStub declaration once we're 412 // done with the translation to a hydrogen code stub. 413 enum StringAddFlags { 414 // Omit both parameter checks. 415 STRING_ADD_CHECK_NONE = 0, 416 // Check left parameter. 417 STRING_ADD_CHECK_LEFT = 1 << 0, 418 // Check right parameter. 419 STRING_ADD_CHECK_RIGHT = 1 << 1, 420 // Check both parameters. 421 STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT 422 }; 423 424 } } // namespace v8::internal 425 426 #if V8_TARGET_ARCH_IA32 427 #include "ia32/code-stubs-ia32.h" 428 #elif V8_TARGET_ARCH_X64 429 #include "x64/code-stubs-x64.h" 430 #elif V8_TARGET_ARCH_ARM 431 #include "arm/code-stubs-arm.h" 432 #elif V8_TARGET_ARCH_MIPS 433 #include "mips/code-stubs-mips.h" 434 #else 435 #error Unsupported target architecture. 436 #endif 437 438 namespace v8 { 439 namespace internal { 440 441 442 // RuntimeCallHelper implementation used in stubs: enters/leaves a 443 // newly created internal frame before/after the runtime call. 444 class StubRuntimeCallHelper : public RuntimeCallHelper { 445 public: 446 StubRuntimeCallHelper() {} 447 448 virtual void BeforeCall(MacroAssembler* masm) const; 449 450 virtual void AfterCall(MacroAssembler* masm) const; 451 }; 452 453 454 // Trivial RuntimeCallHelper implementation. 455 class NopRuntimeCallHelper : public RuntimeCallHelper { 456 public: 457 NopRuntimeCallHelper() {} 458 459 virtual void BeforeCall(MacroAssembler* masm) const {} 460 461 virtual void AfterCall(MacroAssembler* masm) const {} 462 }; 463 464 465 class ToNumberStub: public HydrogenCodeStub { 466 public: 467 ToNumberStub() { } 468 469 virtual Handle<Code> GenerateCode(Isolate* isolate); 470 471 virtual void InitializeInterfaceDescriptor( 472 Isolate* isolate, 473 CodeStubInterfaceDescriptor* descriptor); 474 475 private: 476 Major MajorKey() { return ToNumber; } 477 int NotMissMinorKey() { return 0; } 478 }; 479 480 481 class NumberToStringStub V8_FINAL : public HydrogenCodeStub { 482 public: 483 NumberToStringStub() {} 484 485 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE; 486 487 virtual void InitializeInterfaceDescriptor( 488 Isolate* isolate, 489 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE; 490 491 static void InstallDescriptors(Isolate* isolate); 492 493 // Parameters accessed via CodeStubGraphBuilder::GetParameter() 494 static const int kNumber = 0; 495 496 private: 497 virtual Major MajorKey() V8_OVERRIDE { return NumberToString; } 498 virtual int NotMissMinorKey() V8_OVERRIDE { return 0; } 499 }; 500 501 502 class FastNewClosureStub : public HydrogenCodeStub { 503 public: 504 explicit FastNewClosureStub(LanguageMode language_mode, bool is_generator) 505 : language_mode_(language_mode), 506 is_generator_(is_generator) { } 507 508 virtual Handle<Code> GenerateCode(Isolate* isolate); 509 510 virtual void InitializeInterfaceDescriptor( 511 Isolate* isolate, 512 CodeStubInterfaceDescriptor* descriptor); 513 514 static void InstallDescriptors(Isolate* isolate); 515 516 LanguageMode language_mode() const { return language_mode_; } 517 bool is_generator() const { return is_generator_; } 518 519 private: 520 class StrictModeBits: public BitField<bool, 0, 1> {}; 521 class IsGeneratorBits: public BitField<bool, 1, 1> {}; 522 523 Major MajorKey() { return FastNewClosure; } 524 int NotMissMinorKey() { 525 return StrictModeBits::encode(language_mode_ != CLASSIC_MODE) | 526 IsGeneratorBits::encode(is_generator_); 527 } 528 529 LanguageMode language_mode_; 530 bool is_generator_; 531 }; 532 533 534 class FastNewContextStub : public PlatformCodeStub { 535 public: 536 static const int kMaximumSlots = 64; 537 538 explicit FastNewContextStub(int slots) : slots_(slots) { 539 ASSERT(slots_ > 0 && slots_ <= kMaximumSlots); 540 } 541 542 void Generate(MacroAssembler* masm); 543 544 private: 545 int slots_; 546 547 Major MajorKey() { return FastNewContext; } 548 int MinorKey() { return slots_; } 549 }; 550 551 552 class FastNewBlockContextStub : public PlatformCodeStub { 553 public: 554 static const int kMaximumSlots = 64; 555 556 explicit FastNewBlockContextStub(int slots) : slots_(slots) { 557 ASSERT(slots_ > 0 && slots_ <= kMaximumSlots); 558 } 559 560 void Generate(MacroAssembler* masm); 561 562 private: 563 int slots_; 564 565 Major MajorKey() { return FastNewBlockContext; } 566 int MinorKey() { return slots_; } 567 }; 568 569 class FastCloneShallowArrayStub : public HydrogenCodeStub { 570 public: 571 // Maximum length of copied elements array. 572 static const int kMaximumClonedLength = 8; 573 enum Mode { 574 CLONE_ELEMENTS, 575 CLONE_DOUBLE_ELEMENTS, 576 COPY_ON_WRITE_ELEMENTS, 577 CLONE_ANY_ELEMENTS, 578 LAST_CLONE_MODE = CLONE_ANY_ELEMENTS 579 }; 580 581 static const int kFastCloneModeCount = LAST_CLONE_MODE + 1; 582 583 FastCloneShallowArrayStub(Mode mode, 584 AllocationSiteMode allocation_site_mode, 585 int length) 586 : mode_(mode), 587 allocation_site_mode_(allocation_site_mode), 588 length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) { 589 ASSERT_GE(length_, 0); 590 ASSERT_LE(length_, kMaximumClonedLength); 591 } 592 593 Mode mode() const { return mode_; } 594 int length() const { return length_; } 595 AllocationSiteMode allocation_site_mode() const { 596 return allocation_site_mode_; 597 } 598 599 ElementsKind ComputeElementsKind() const { 600 switch (mode()) { 601 case CLONE_ELEMENTS: 602 case COPY_ON_WRITE_ELEMENTS: 603 return FAST_ELEMENTS; 604 case CLONE_DOUBLE_ELEMENTS: 605 return FAST_DOUBLE_ELEMENTS; 606 case CLONE_ANY_ELEMENTS: 607 /*fall-through*/; 608 } 609 UNREACHABLE(); 610 return LAST_ELEMENTS_KIND; 611 } 612 613 virtual Handle<Code> GenerateCode(Isolate* isolate); 614 615 virtual void InitializeInterfaceDescriptor( 616 Isolate* isolate, 617 CodeStubInterfaceDescriptor* descriptor); 618 619 private: 620 Mode mode_; 621 AllocationSiteMode allocation_site_mode_; 622 int length_; 623 624 class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {}; 625 class ModeBits: public BitField<Mode, 1, 4> {}; 626 class LengthBits: public BitField<int, 5, 4> {}; 627 // Ensure data fits within available bits. 628 STATIC_ASSERT(LAST_ALLOCATION_SITE_MODE == 1); 629 STATIC_ASSERT(kFastCloneModeCount < 16); 630 STATIC_ASSERT(kMaximumClonedLength < 16); 631 Major MajorKey() { return FastCloneShallowArray; } 632 int NotMissMinorKey() { 633 return AllocationSiteModeBits::encode(allocation_site_mode_) 634 | ModeBits::encode(mode_) 635 | LengthBits::encode(length_); 636 } 637 }; 638 639 640 class FastCloneShallowObjectStub : public HydrogenCodeStub { 641 public: 642 // Maximum number of properties in copied object. 643 static const int kMaximumClonedProperties = 6; 644 645 explicit FastCloneShallowObjectStub(int length) 646 : length_(length) { 647 ASSERT_GE(length_, 0); 648 ASSERT_LE(length_, kMaximumClonedProperties); 649 } 650 651 int length() const { return length_; } 652 653 virtual Handle<Code> GenerateCode(Isolate* isolate); 654 655 virtual void InitializeInterfaceDescriptor( 656 Isolate* isolate, 657 CodeStubInterfaceDescriptor* descriptor); 658 659 private: 660 int length_; 661 662 Major MajorKey() { return FastCloneShallowObject; } 663 int NotMissMinorKey() { return length_; } 664 665 DISALLOW_COPY_AND_ASSIGN(FastCloneShallowObjectStub); 666 }; 667 668 669 class CreateAllocationSiteStub : public HydrogenCodeStub { 670 public: 671 explicit CreateAllocationSiteStub() { } 672 673 virtual Handle<Code> GenerateCode(Isolate* isolate); 674 675 static void GenerateAheadOfTime(Isolate* isolate); 676 677 virtual void InitializeInterfaceDescriptor( 678 Isolate* isolate, 679 CodeStubInterfaceDescriptor* descriptor); 680 681 private: 682 Major MajorKey() { return CreateAllocationSite; } 683 int NotMissMinorKey() { return 0; } 684 685 DISALLOW_COPY_AND_ASSIGN(CreateAllocationSiteStub); 686 }; 687 688 689 class InstanceofStub: public PlatformCodeStub { 690 public: 691 enum Flags { 692 kNoFlags = 0, 693 kArgsInRegisters = 1 << 0, 694 kCallSiteInlineCheck = 1 << 1, 695 kReturnTrueFalseObject = 1 << 2 696 }; 697 698 explicit InstanceofStub(Flags flags) : flags_(flags) { } 699 700 static Register left(); 701 static Register right(); 702 703 void Generate(MacroAssembler* masm); 704 705 private: 706 Major MajorKey() { return Instanceof; } 707 int MinorKey() { return static_cast<int>(flags_); } 708 709 bool HasArgsInRegisters() const { 710 return (flags_ & kArgsInRegisters) != 0; 711 } 712 713 bool HasCallSiteInlineCheck() const { 714 return (flags_ & kCallSiteInlineCheck) != 0; 715 } 716 717 bool ReturnTrueFalseObject() const { 718 return (flags_ & kReturnTrueFalseObject) != 0; 719 } 720 721 virtual void PrintName(StringStream* stream); 722 723 Flags flags_; 724 }; 725 726 727 enum AllocationSiteOverrideMode { 728 DONT_OVERRIDE, 729 DISABLE_ALLOCATION_SITES, 730 LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES 731 }; 732 733 734 class ArrayConstructorStub: public PlatformCodeStub { 735 public: 736 enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE }; 737 ArrayConstructorStub(Isolate* isolate, int argument_count); 738 explicit ArrayConstructorStub(Isolate* isolate); 739 740 void Generate(MacroAssembler* masm); 741 742 private: 743 void GenerateDispatchToArrayStub(MacroAssembler* masm, 744 AllocationSiteOverrideMode mode); 745 746 virtual CodeStub::Major MajorKey() { return ArrayConstructor; } 747 virtual int MinorKey() { return argument_count_; } 748 749 ArgumentCountKey argument_count_; 750 }; 751 752 753 class InternalArrayConstructorStub: public PlatformCodeStub { 754 public: 755 explicit InternalArrayConstructorStub(Isolate* isolate); 756 757 void Generate(MacroAssembler* masm); 758 759 private: 760 virtual CodeStub::Major MajorKey() { return InternalArrayConstructor; } 761 virtual int MinorKey() { return 0; } 762 763 void GenerateCase(MacroAssembler* masm, ElementsKind kind); 764 }; 765 766 767 class MathPowStub: public PlatformCodeStub { 768 public: 769 enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK }; 770 771 explicit MathPowStub(ExponentType exponent_type) 772 : exponent_type_(exponent_type) { } 773 virtual void Generate(MacroAssembler* masm); 774 775 private: 776 virtual CodeStub::Major MajorKey() { return MathPow; } 777 virtual int MinorKey() { return exponent_type_; } 778 779 ExponentType exponent_type_; 780 }; 781 782 783 class ICStub: public PlatformCodeStub { 784 public: 785 explicit ICStub(Code::Kind kind) : kind_(kind) { } 786 virtual Code::Kind GetCodeKind() const { return kind_; } 787 virtual InlineCacheState GetICState() { return MONOMORPHIC; } 788 789 bool Describes(Code* code) { 790 return GetMajorKey(code) == MajorKey() && code->stub_info() == MinorKey(); 791 } 792 793 protected: 794 class KindBits: public BitField<Code::Kind, 0, 4> {}; 795 virtual void FinishCode(Handle<Code> code) { 796 code->set_stub_info(MinorKey()); 797 } 798 Code::Kind kind() { return kind_; } 799 800 virtual int MinorKey() { 801 return KindBits::encode(kind_); 802 } 803 804 private: 805 Code::Kind kind_; 806 }; 807 808 809 class FunctionPrototypeStub: public ICStub { 810 public: 811 explicit FunctionPrototypeStub(Code::Kind kind) : ICStub(kind) { } 812 virtual void Generate(MacroAssembler* masm); 813 814 private: 815 virtual CodeStub::Major MajorKey() { return FunctionPrototype; } 816 }; 817 818 819 class StringLengthStub: public ICStub { 820 public: 821 explicit StringLengthStub(Code::Kind kind) : ICStub(kind) { } 822 virtual void Generate(MacroAssembler* masm); 823 824 private: 825 STATIC_ASSERT(KindBits::kSize == 4); 826 virtual CodeStub::Major MajorKey() { return StringLength; } 827 }; 828 829 830 class StoreICStub: public ICStub { 831 public: 832 StoreICStub(Code::Kind kind, StrictModeFlag strict_mode) 833 : ICStub(kind), strict_mode_(strict_mode) { } 834 835 protected: 836 virtual ExtraICState GetExtraICState() { 837 return StoreIC::ComputeExtraICState(strict_mode_); 838 } 839 840 private: 841 STATIC_ASSERT(KindBits::kSize == 4); 842 class StrictModeBits: public BitField<bool, 4, 1> {}; 843 virtual int MinorKey() { 844 return KindBits::encode(kind()) | StrictModeBits::encode(strict_mode_); 845 } 846 847 StrictModeFlag strict_mode_; 848 }; 849 850 851 class StoreArrayLengthStub: public StoreICStub { 852 public: 853 explicit StoreArrayLengthStub(Code::Kind kind, StrictModeFlag strict_mode) 854 : StoreICStub(kind, strict_mode) { } 855 virtual void Generate(MacroAssembler* masm); 856 857 private: 858 virtual CodeStub::Major MajorKey() { return StoreArrayLength; } 859 }; 860 861 862 class HICStub: public HydrogenCodeStub { 863 public: 864 virtual Code::Kind GetCodeKind() const { return kind(); } 865 virtual InlineCacheState GetICState() { return MONOMORPHIC; } 866 867 protected: 868 class KindBits: public BitField<Code::Kind, 0, 4> {}; 869 virtual Code::Kind kind() const = 0; 870 }; 871 872 873 class HandlerStub: public HICStub { 874 public: 875 virtual Code::Kind GetCodeKind() const { return Code::HANDLER; } 876 virtual int GetStubFlags() { return kind(); } 877 878 protected: 879 HandlerStub() : HICStub() { } 880 virtual int NotMissMinorKey() { return bit_field_; } 881 int bit_field_; 882 }; 883 884 885 class LoadFieldStub: public HandlerStub { 886 public: 887 LoadFieldStub(bool inobject, int index, Representation representation) { 888 Initialize(Code::LOAD_IC, inobject, index, representation); 889 } 890 891 virtual Handle<Code> GenerateCode(Isolate* isolate); 892 893 virtual void InitializeInterfaceDescriptor( 894 Isolate* isolate, 895 CodeStubInterfaceDescriptor* descriptor); 896 897 Representation representation() { 898 if (unboxed_double()) return Representation::Double(); 899 return Representation::Tagged(); 900 } 901 902 virtual Code::Kind kind() const { 903 return KindBits::decode(bit_field_); 904 } 905 906 bool is_inobject() { 907 return InobjectBits::decode(bit_field_); 908 } 909 910 int offset() { 911 int index = IndexBits::decode(bit_field_); 912 int offset = index * kPointerSize; 913 if (is_inobject()) return offset; 914 return FixedArray::kHeaderSize + offset; 915 } 916 917 bool unboxed_double() { 918 return UnboxedDoubleBits::decode(bit_field_); 919 } 920 921 virtual Code::StubType GetStubType() { return Code::FAST; } 922 923 protected: 924 LoadFieldStub() : HandlerStub() { } 925 926 void Initialize(Code::Kind kind, 927 bool inobject, 928 int index, 929 Representation representation) { 930 bool unboxed_double = FLAG_track_double_fields && representation.IsDouble(); 931 bit_field_ = KindBits::encode(kind) 932 | InobjectBits::encode(inobject) 933 | IndexBits::encode(index) 934 | UnboxedDoubleBits::encode(unboxed_double); 935 } 936 937 private: 938 STATIC_ASSERT(KindBits::kSize == 4); 939 class InobjectBits: public BitField<bool, 4, 1> {}; 940 class IndexBits: public BitField<int, 5, 11> {}; 941 class UnboxedDoubleBits: public BitField<bool, 16, 1> {}; 942 virtual CodeStub::Major MajorKey() { return LoadField; } 943 }; 944 945 946 class StoreGlobalStub : public HandlerStub { 947 public: 948 explicit StoreGlobalStub(bool is_constant) { 949 bit_field_ = IsConstantBits::encode(is_constant); 950 } 951 952 Handle<Code> GetCodeCopyFromTemplate(Isolate* isolate, 953 Map* receiver_map, 954 PropertyCell* cell) { 955 Handle<Code> code = CodeStub::GetCodeCopyFromTemplate(isolate); 956 // Replace the placeholder cell and global object map with the actual global 957 // cell and receiver map. 958 Map* cell_map = isolate->heap()->global_property_cell_map(); 959 code->ReplaceNthObject(1, cell_map, cell); 960 code->ReplaceNthObject(1, isolate->heap()->meta_map(), receiver_map); 961 return code; 962 } 963 964 virtual Code::Kind kind() const { return Code::STORE_IC; } 965 966 virtual Handle<Code> GenerateCode(Isolate* isolate); 967 968 virtual void InitializeInterfaceDescriptor( 969 Isolate* isolate, 970 CodeStubInterfaceDescriptor* descriptor); 971 972 virtual ExtraICState GetExtraICState() { return bit_field_; } 973 974 bool is_constant() { 975 return IsConstantBits::decode(bit_field_); 976 } 977 void set_is_constant(bool value) { 978 bit_field_ = IsConstantBits::update(bit_field_, value); 979 } 980 981 Representation representation() { 982 return Representation::FromKind(RepresentationBits::decode(bit_field_)); 983 } 984 void set_representation(Representation r) { 985 bit_field_ = RepresentationBits::update(bit_field_, r.kind()); 986 } 987 988 private: 989 virtual int NotMissMinorKey() { return GetExtraICState(); } 990 Major MajorKey() { return StoreGlobal; } 991 992 class IsConstantBits: public BitField<bool, 0, 1> {}; 993 class RepresentationBits: public BitField<Representation::Kind, 1, 8> {}; 994 995 int bit_field_; 996 997 DISALLOW_COPY_AND_ASSIGN(StoreGlobalStub); 998 }; 999 1000 1001 class KeyedLoadFieldStub: public LoadFieldStub { 1002 public: 1003 KeyedLoadFieldStub(bool inobject, int index, Representation representation) 1004 : LoadFieldStub() { 1005 Initialize(Code::KEYED_LOAD_IC, inobject, index, representation); 1006 } 1007 1008 virtual void InitializeInterfaceDescriptor( 1009 Isolate* isolate, 1010 CodeStubInterfaceDescriptor* descriptor); 1011 1012 virtual Handle<Code> GenerateCode(Isolate* isolate); 1013 1014 private: 1015 virtual CodeStub::Major MajorKey() { return KeyedLoadField; } 1016 }; 1017 1018 1019 class KeyedArrayCallStub: public HICStub { 1020 public: 1021 KeyedArrayCallStub(bool holey, int argc) : HICStub(), argc_(argc) { 1022 bit_field_ = ContextualBits::encode(false) | HoleyBits::encode(holey); 1023 } 1024 1025 virtual Code::Kind kind() const { return Code::KEYED_CALL_IC; } 1026 virtual ExtraICState GetExtraICState() { return bit_field_; } 1027 1028 ElementsKind elements_kind() { 1029 return HoleyBits::decode(bit_field_) ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS; 1030 } 1031 1032 int argc() { return argc_; } 1033 virtual int GetStubFlags() { return argc(); } 1034 1035 static bool IsHoley(Handle<Code> code) { 1036 ExtraICState state = code->extra_ic_state(); 1037 return HoleyBits::decode(state); 1038 } 1039 1040 virtual void InitializeInterfaceDescriptor( 1041 Isolate* isolate, 1042 CodeStubInterfaceDescriptor* descriptor); 1043 1044 virtual Handle<Code> GenerateCode(Isolate* isolate); 1045 1046 private: 1047 virtual int NotMissMinorKey() { 1048 return GetExtraICState() | ArgcBits::encode(argc_); 1049 } 1050 1051 class ContextualBits: public BitField<bool, 0, 1> {}; 1052 STATIC_ASSERT(CallICBase::Contextual::kShift == ContextualBits::kShift); 1053 STATIC_ASSERT(CallICBase::Contextual::kSize == ContextualBits::kSize); 1054 class HoleyBits: public BitField<bool, 1, 1> {}; 1055 STATIC_ASSERT(Code::kArgumentsBits <= kStubMinorKeyBits - 2); 1056 class ArgcBits: public BitField<int, 2, Code::kArgumentsBits> {}; 1057 virtual CodeStub::Major MajorKey() { return KeyedArrayCall; } 1058 int bit_field_; 1059 int argc_; 1060 }; 1061 1062 1063 class BinaryOpICStub V8_FINAL : public HydrogenCodeStub { 1064 public: 1065 BinaryOpICStub(Token::Value op, OverwriteMode mode) 1066 : HydrogenCodeStub(UNINITIALIZED), state_(op, mode) {} 1067 1068 explicit BinaryOpICStub(const BinaryOpIC::State& state) : state_(state) {} 1069 1070 static void GenerateAheadOfTime(Isolate* isolate); 1071 1072 virtual void InitializeInterfaceDescriptor( 1073 Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE; 1074 1075 static void InstallDescriptors(Isolate* isolate); 1076 1077 virtual Code::Kind GetCodeKind() const V8_OVERRIDE { 1078 return Code::BINARY_OP_IC; 1079 } 1080 1081 virtual InlineCacheState GetICState() V8_OVERRIDE { 1082 return state_.GetICState(); 1083 } 1084 1085 virtual ExtraICState GetExtraICState() V8_OVERRIDE { 1086 return state_.GetExtraICState(); 1087 } 1088 1089 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE { 1090 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2)); 1091 } 1092 1093 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE; 1094 1095 const BinaryOpIC::State& state() const { return state_; } 1096 1097 virtual void PrintState(StringStream* stream) V8_OVERRIDE; 1098 1099 // Parameters accessed via CodeStubGraphBuilder::GetParameter() 1100 static const int kLeft = 0; 1101 static const int kRight = 1; 1102 1103 private: 1104 static void GenerateAheadOfTime(Isolate* isolate, 1105 const BinaryOpIC::State& state); 1106 1107 virtual Major MajorKey() V8_OVERRIDE { return BinaryOpIC; } 1108 virtual int NotMissMinorKey() V8_OVERRIDE { return GetExtraICState(); } 1109 1110 BinaryOpIC::State state_; 1111 1112 DISALLOW_COPY_AND_ASSIGN(BinaryOpICStub); 1113 }; 1114 1115 1116 // TODO(bmeurer): Rename to StringAddStub once we dropped the old StringAddStub. 1117 class NewStringAddStub V8_FINAL : public HydrogenCodeStub { 1118 public: 1119 NewStringAddStub(StringAddFlags flags, PretenureFlag pretenure_flag) 1120 : bit_field_(StringAddFlagsBits::encode(flags) | 1121 PretenureFlagBits::encode(pretenure_flag)) {} 1122 1123 StringAddFlags flags() const { 1124 return StringAddFlagsBits::decode(bit_field_); 1125 } 1126 1127 PretenureFlag pretenure_flag() const { 1128 return PretenureFlagBits::decode(bit_field_); 1129 } 1130 1131 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE; 1132 1133 virtual void InitializeInterfaceDescriptor( 1134 Isolate* isolate, 1135 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE; 1136 1137 static void InstallDescriptors(Isolate* isolate); 1138 1139 // Parameters accessed via CodeStubGraphBuilder::GetParameter() 1140 static const int kLeft = 0; 1141 static const int kRight = 1; 1142 1143 private: 1144 class StringAddFlagsBits: public BitField<StringAddFlags, 0, 2> {}; 1145 class PretenureFlagBits: public BitField<PretenureFlag, 2, 1> {}; 1146 uint32_t bit_field_; 1147 1148 virtual Major MajorKey() V8_OVERRIDE { return NewStringAdd; } 1149 virtual int NotMissMinorKey() V8_OVERRIDE { return bit_field_; } 1150 1151 virtual void PrintBaseName(StringStream* stream) V8_OVERRIDE; 1152 1153 DISALLOW_COPY_AND_ASSIGN(NewStringAddStub); 1154 }; 1155 1156 1157 class ICCompareStub: public PlatformCodeStub { 1158 public: 1159 ICCompareStub(Token::Value op, 1160 CompareIC::State left, 1161 CompareIC::State right, 1162 CompareIC::State handler) 1163 : op_(op), 1164 left_(left), 1165 right_(right), 1166 state_(handler) { 1167 ASSERT(Token::IsCompareOp(op)); 1168 } 1169 1170 virtual void Generate(MacroAssembler* masm); 1171 1172 void set_known_map(Handle<Map> map) { known_map_ = map; } 1173 1174 static void DecodeMinorKey(int minor_key, 1175 CompareIC::State* left_state, 1176 CompareIC::State* right_state, 1177 CompareIC::State* handler_state, 1178 Token::Value* op); 1179 1180 static CompareIC::State CompareState(int minor_key) { 1181 return static_cast<CompareIC::State>(HandlerStateField::decode(minor_key)); 1182 } 1183 1184 virtual InlineCacheState GetICState(); 1185 1186 private: 1187 class OpField: public BitField<int, 0, 3> { }; 1188 class LeftStateField: public BitField<int, 3, 4> { }; 1189 class RightStateField: public BitField<int, 7, 4> { }; 1190 class HandlerStateField: public BitField<int, 11, 4> { }; 1191 1192 virtual void FinishCode(Handle<Code> code) { 1193 code->set_stub_info(MinorKey()); 1194 } 1195 1196 virtual CodeStub::Major MajorKey() { return CompareIC; } 1197 virtual int MinorKey(); 1198 1199 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_IC; } 1200 1201 void GenerateSmis(MacroAssembler* masm); 1202 void GenerateNumbers(MacroAssembler* masm); 1203 void GenerateInternalizedStrings(MacroAssembler* masm); 1204 void GenerateStrings(MacroAssembler* masm); 1205 void GenerateUniqueNames(MacroAssembler* masm); 1206 void GenerateObjects(MacroAssembler* masm); 1207 void GenerateMiss(MacroAssembler* masm); 1208 void GenerateKnownObjects(MacroAssembler* masm); 1209 void GenerateGeneric(MacroAssembler* masm); 1210 1211 bool strict() const { return op_ == Token::EQ_STRICT; } 1212 Condition GetCondition() const { return CompareIC::ComputeCondition(op_); } 1213 1214 virtual void AddToSpecialCache(Handle<Code> new_object); 1215 virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate); 1216 virtual bool UseSpecialCache() { return state_ == CompareIC::KNOWN_OBJECT; } 1217 1218 Token::Value op_; 1219 CompareIC::State left_; 1220 CompareIC::State right_; 1221 CompareIC::State state_; 1222 Handle<Map> known_map_; 1223 }; 1224 1225 1226 class CompareNilICStub : public HydrogenCodeStub { 1227 public: 1228 Handle<Type> GetType(Isolate* isolate, Handle<Map> map = Handle<Map>()); 1229 Handle<Type> GetInputType(Isolate* isolate, Handle<Map> map); 1230 1231 explicit CompareNilICStub(NilValue nil) : nil_value_(nil) { } 1232 1233 CompareNilICStub(ExtraICState ic_state, 1234 InitializationState init_state = INITIALIZED) 1235 : HydrogenCodeStub(init_state), 1236 nil_value_(NilValueField::decode(ic_state)), 1237 state_(State(TypesField::decode(ic_state))) { 1238 } 1239 1240 static Handle<Code> GetUninitialized(Isolate* isolate, 1241 NilValue nil) { 1242 return CompareNilICStub(nil, UNINITIALIZED).GetCode(isolate); 1243 } 1244 1245 virtual void InitializeInterfaceDescriptor( 1246 Isolate* isolate, 1247 CodeStubInterfaceDescriptor* descriptor); 1248 1249 static void InitializeForIsolate(Isolate* isolate) { 1250 CompareNilICStub compare_stub(kNullValue, UNINITIALIZED); 1251 compare_stub.InitializeInterfaceDescriptor( 1252 isolate, 1253 isolate->code_stub_interface_descriptor(CodeStub::CompareNilIC)); 1254 } 1255 1256 virtual InlineCacheState GetICState() { 1257 if (state_.Contains(GENERIC)) { 1258 return MEGAMORPHIC; 1259 } else if (state_.Contains(MONOMORPHIC_MAP)) { 1260 return MONOMORPHIC; 1261 } else { 1262 return PREMONOMORPHIC; 1263 } 1264 } 1265 1266 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_NIL_IC; } 1267 1268 virtual Handle<Code> GenerateCode(Isolate* isolate); 1269 1270 virtual ExtraICState GetExtraICState() { 1271 return NilValueField::encode(nil_value_) | 1272 TypesField::encode(state_.ToIntegral()); 1273 } 1274 1275 void UpdateStatus(Handle<Object> object); 1276 1277 bool IsMonomorphic() const { return state_.Contains(MONOMORPHIC_MAP); } 1278 NilValue GetNilValue() const { return nil_value_; } 1279 void ClearState() { state_.RemoveAll(); } 1280 1281 virtual void PrintState(StringStream* stream); 1282 virtual void PrintBaseName(StringStream* stream); 1283 1284 private: 1285 friend class CompareNilIC; 1286 1287 enum CompareNilType { 1288 UNDEFINED, 1289 NULL_TYPE, 1290 MONOMORPHIC_MAP, 1291 GENERIC, 1292 NUMBER_OF_TYPES 1293 }; 1294 1295 // At most 6 different types can be distinguished, because the Code object 1296 // only has room for a single byte to hold a set and there are two more 1297 // boolean flags we need to store. :-P 1298 STATIC_ASSERT(NUMBER_OF_TYPES <= 6); 1299 1300 class State : public EnumSet<CompareNilType, byte> { 1301 public: 1302 State() : EnumSet<CompareNilType, byte>(0) { } 1303 explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { } 1304 1305 void Print(StringStream* stream) const; 1306 }; 1307 1308 CompareNilICStub(NilValue nil, InitializationState init_state) 1309 : HydrogenCodeStub(init_state), nil_value_(nil) { } 1310 1311 class NilValueField : public BitField<NilValue, 0, 1> {}; 1312 class TypesField : public BitField<byte, 1, NUMBER_OF_TYPES> {}; 1313 1314 virtual CodeStub::Major MajorKey() { return CompareNilIC; } 1315 virtual int NotMissMinorKey() { return GetExtraICState(); } 1316 1317 NilValue nil_value_; 1318 State state_; 1319 1320 DISALLOW_COPY_AND_ASSIGN(CompareNilICStub); 1321 }; 1322 1323 1324 class CEntryStub : public PlatformCodeStub { 1325 public: 1326 explicit CEntryStub(int result_size, 1327 SaveFPRegsMode save_doubles = kDontSaveFPRegs) 1328 : result_size_(result_size), save_doubles_(save_doubles) { } 1329 1330 void Generate(MacroAssembler* masm); 1331 1332 // The version of this stub that doesn't save doubles is generated ahead of 1333 // time, so it's OK to call it from other stubs that can't cope with GC during 1334 // their code generation. On machines that always have gp registers (x64) we 1335 // can generate both variants ahead of time. 1336 static void GenerateAheadOfTime(Isolate* isolate); 1337 1338 protected: 1339 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE { 1340 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2)); 1341 }; 1342 1343 private: 1344 void GenerateCore(MacroAssembler* masm, 1345 Label* throw_normal_exception, 1346 Label* throw_termination_exception, 1347 Label* throw_out_of_memory_exception, 1348 bool do_gc, 1349 bool always_allocate_scope); 1350 1351 // Number of pointers/values returned. 1352 Isolate* isolate_; 1353 const int result_size_; 1354 SaveFPRegsMode save_doubles_; 1355 1356 Major MajorKey() { return CEntry; } 1357 int MinorKey(); 1358 1359 bool NeedsImmovableCode(); 1360 }; 1361 1362 1363 class JSEntryStub : public PlatformCodeStub { 1364 public: 1365 JSEntryStub() { } 1366 1367 void Generate(MacroAssembler* masm) { GenerateBody(masm, false); } 1368 1369 protected: 1370 void GenerateBody(MacroAssembler* masm, bool is_construct); 1371 1372 private: 1373 Major MajorKey() { return JSEntry; } 1374 int MinorKey() { return 0; } 1375 1376 virtual void FinishCode(Handle<Code> code); 1377 1378 int handler_offset_; 1379 }; 1380 1381 1382 class JSConstructEntryStub : public JSEntryStub { 1383 public: 1384 JSConstructEntryStub() { } 1385 1386 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); } 1387 1388 private: 1389 int MinorKey() { return 1; } 1390 1391 virtual void PrintName(StringStream* stream) { 1392 stream->Add("JSConstructEntryStub"); 1393 } 1394 }; 1395 1396 1397 class ArgumentsAccessStub: public PlatformCodeStub { 1398 public: 1399 enum Type { 1400 READ_ELEMENT, 1401 NEW_NON_STRICT_FAST, 1402 NEW_NON_STRICT_SLOW, 1403 NEW_STRICT 1404 }; 1405 1406 explicit ArgumentsAccessStub(Type type) : type_(type) { } 1407 1408 private: 1409 Type type_; 1410 1411 Major MajorKey() { return ArgumentsAccess; } 1412 int MinorKey() { return type_; } 1413 1414 void Generate(MacroAssembler* masm); 1415 void GenerateReadElement(MacroAssembler* masm); 1416 void GenerateNewStrict(MacroAssembler* masm); 1417 void GenerateNewNonStrictFast(MacroAssembler* masm); 1418 void GenerateNewNonStrictSlow(MacroAssembler* masm); 1419 1420 virtual void PrintName(StringStream* stream); 1421 }; 1422 1423 1424 class RegExpExecStub: public PlatformCodeStub { 1425 public: 1426 RegExpExecStub() { } 1427 1428 private: 1429 Major MajorKey() { return RegExpExec; } 1430 int MinorKey() { return 0; } 1431 1432 void Generate(MacroAssembler* masm); 1433 }; 1434 1435 1436 class RegExpConstructResultStub: public PlatformCodeStub { 1437 public: 1438 RegExpConstructResultStub() { } 1439 1440 private: 1441 Major MajorKey() { return RegExpConstructResult; } 1442 int MinorKey() { return 0; } 1443 1444 void Generate(MacroAssembler* masm); 1445 }; 1446 1447 1448 class CallFunctionStub: public PlatformCodeStub { 1449 public: 1450 CallFunctionStub(int argc, CallFunctionFlags flags) 1451 : argc_(argc), flags_(flags) { } 1452 1453 void Generate(MacroAssembler* masm); 1454 1455 virtual void FinishCode(Handle<Code> code) { 1456 code->set_has_function_cache(RecordCallTarget()); 1457 } 1458 1459 static int ExtractArgcFromMinorKey(int minor_key) { 1460 return ArgcBits::decode(minor_key); 1461 } 1462 1463 private: 1464 int argc_; 1465 CallFunctionFlags flags_; 1466 1467 virtual void PrintName(StringStream* stream); 1468 1469 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>. 1470 class FlagBits: public BitField<CallFunctionFlags, 0, 2> {}; 1471 class ArgcBits: public BitField<unsigned, 2, 32 - 2> {}; 1472 1473 Major MajorKey() { return CallFunction; } 1474 int MinorKey() { 1475 // Encode the parameters in a unique 32 bit value. 1476 return FlagBits::encode(flags_) | ArgcBits::encode(argc_); 1477 } 1478 1479 bool ReceiverMightBeImplicit() { 1480 return (flags_ & RECEIVER_MIGHT_BE_IMPLICIT) != 0; 1481 } 1482 1483 bool RecordCallTarget() { 1484 return (flags_ & RECORD_CALL_TARGET) != 0; 1485 } 1486 }; 1487 1488 1489 class CallConstructStub: public PlatformCodeStub { 1490 public: 1491 explicit CallConstructStub(CallFunctionFlags flags) : flags_(flags) {} 1492 1493 void Generate(MacroAssembler* masm); 1494 1495 virtual void FinishCode(Handle<Code> code) { 1496 code->set_has_function_cache(RecordCallTarget()); 1497 } 1498 1499 private: 1500 CallFunctionFlags flags_; 1501 1502 virtual void PrintName(StringStream* stream); 1503 1504 Major MajorKey() { return CallConstruct; } 1505 int MinorKey() { return flags_; } 1506 1507 bool RecordCallTarget() { 1508 return (flags_ & RECORD_CALL_TARGET) != 0; 1509 } 1510 }; 1511 1512 1513 enum StringIndexFlags { 1514 // Accepts smis or heap numbers. 1515 STRING_INDEX_IS_NUMBER, 1516 1517 // Accepts smis or heap numbers that are valid array indices 1518 // (ECMA-262 15.4). Invalid indices are reported as being out of 1519 // range. 1520 STRING_INDEX_IS_ARRAY_INDEX 1521 }; 1522 1523 1524 // Generates code implementing String.prototype.charCodeAt. 1525 // 1526 // Only supports the case when the receiver is a string and the index 1527 // is a number (smi or heap number) that is a valid index into the 1528 // string. Additional index constraints are specified by the 1529 // flags. Otherwise, bails out to the provided labels. 1530 // 1531 // Register usage: |object| may be changed to another string in a way 1532 // that doesn't affect charCodeAt/charAt semantics, |index| is 1533 // preserved, |scratch| and |result| are clobbered. 1534 class StringCharCodeAtGenerator { 1535 public: 1536 StringCharCodeAtGenerator(Register object, 1537 Register index, 1538 Register result, 1539 Label* receiver_not_string, 1540 Label* index_not_number, 1541 Label* index_out_of_range, 1542 StringIndexFlags index_flags) 1543 : object_(object), 1544 index_(index), 1545 result_(result), 1546 receiver_not_string_(receiver_not_string), 1547 index_not_number_(index_not_number), 1548 index_out_of_range_(index_out_of_range), 1549 index_flags_(index_flags) { 1550 ASSERT(!result_.is(object_)); 1551 ASSERT(!result_.is(index_)); 1552 } 1553 1554 // Generates the fast case code. On the fallthrough path |result| 1555 // register contains the result. 1556 void GenerateFast(MacroAssembler* masm); 1557 1558 // Generates the slow case code. Must not be naturally 1559 // reachable. Expected to be put after a ret instruction (e.g., in 1560 // deferred code). Always jumps back to the fast case. 1561 void GenerateSlow(MacroAssembler* masm, 1562 const RuntimeCallHelper& call_helper); 1563 1564 // Skip handling slow case and directly jump to bailout. 1565 void SkipSlow(MacroAssembler* masm, Label* bailout) { 1566 masm->bind(&index_not_smi_); 1567 masm->bind(&call_runtime_); 1568 masm->jmp(bailout); 1569 } 1570 1571 private: 1572 Register object_; 1573 Register index_; 1574 Register result_; 1575 1576 Label* receiver_not_string_; 1577 Label* index_not_number_; 1578 Label* index_out_of_range_; 1579 1580 StringIndexFlags index_flags_; 1581 1582 Label call_runtime_; 1583 Label index_not_smi_; 1584 Label got_smi_index_; 1585 Label exit_; 1586 1587 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator); 1588 }; 1589 1590 1591 // Generates code for creating a one-char string from a char code. 1592 class StringCharFromCodeGenerator { 1593 public: 1594 StringCharFromCodeGenerator(Register code, 1595 Register result) 1596 : code_(code), 1597 result_(result) { 1598 ASSERT(!code_.is(result_)); 1599 } 1600 1601 // Generates the fast case code. On the fallthrough path |result| 1602 // register contains the result. 1603 void GenerateFast(MacroAssembler* masm); 1604 1605 // Generates the slow case code. Must not be naturally 1606 // reachable. Expected to be put after a ret instruction (e.g., in 1607 // deferred code). Always jumps back to the fast case. 1608 void GenerateSlow(MacroAssembler* masm, 1609 const RuntimeCallHelper& call_helper); 1610 1611 // Skip handling slow case and directly jump to bailout. 1612 void SkipSlow(MacroAssembler* masm, Label* bailout) { 1613 masm->bind(&slow_case_); 1614 masm->jmp(bailout); 1615 } 1616 1617 private: 1618 Register code_; 1619 Register result_; 1620 1621 Label slow_case_; 1622 Label exit_; 1623 1624 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator); 1625 }; 1626 1627 1628 // Generates code implementing String.prototype.charAt. 1629 // 1630 // Only supports the case when the receiver is a string and the index 1631 // is a number (smi or heap number) that is a valid index into the 1632 // string. Additional index constraints are specified by the 1633 // flags. Otherwise, bails out to the provided labels. 1634 // 1635 // Register usage: |object| may be changed to another string in a way 1636 // that doesn't affect charCodeAt/charAt semantics, |index| is 1637 // preserved, |scratch1|, |scratch2|, and |result| are clobbered. 1638 class StringCharAtGenerator { 1639 public: 1640 StringCharAtGenerator(Register object, 1641 Register index, 1642 Register scratch, 1643 Register result, 1644 Label* receiver_not_string, 1645 Label* index_not_number, 1646 Label* index_out_of_range, 1647 StringIndexFlags index_flags) 1648 : char_code_at_generator_(object, 1649 index, 1650 scratch, 1651 receiver_not_string, 1652 index_not_number, 1653 index_out_of_range, 1654 index_flags), 1655 char_from_code_generator_(scratch, result) {} 1656 1657 // Generates the fast case code. On the fallthrough path |result| 1658 // register contains the result. 1659 void GenerateFast(MacroAssembler* masm) { 1660 char_code_at_generator_.GenerateFast(masm); 1661 char_from_code_generator_.GenerateFast(masm); 1662 } 1663 1664 // Generates the slow case code. Must not be naturally 1665 // reachable. Expected to be put after a ret instruction (e.g., in 1666 // deferred code). Always jumps back to the fast case. 1667 void GenerateSlow(MacroAssembler* masm, 1668 const RuntimeCallHelper& call_helper) { 1669 char_code_at_generator_.GenerateSlow(masm, call_helper); 1670 char_from_code_generator_.GenerateSlow(masm, call_helper); 1671 } 1672 1673 // Skip handling slow case and directly jump to bailout. 1674 void SkipSlow(MacroAssembler* masm, Label* bailout) { 1675 char_code_at_generator_.SkipSlow(masm, bailout); 1676 char_from_code_generator_.SkipSlow(masm, bailout); 1677 } 1678 1679 private: 1680 StringCharCodeAtGenerator char_code_at_generator_; 1681 StringCharFromCodeGenerator char_from_code_generator_; 1682 1683 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator); 1684 }; 1685 1686 1687 class KeyedLoadDictionaryElementStub : public HydrogenCodeStub { 1688 public: 1689 KeyedLoadDictionaryElementStub() {} 1690 1691 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE; 1692 1693 virtual void InitializeInterfaceDescriptor( 1694 Isolate* isolate, 1695 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE; 1696 1697 private: 1698 Major MajorKey() { return KeyedLoadElement; } 1699 int NotMissMinorKey() { return DICTIONARY_ELEMENTS; } 1700 1701 DISALLOW_COPY_AND_ASSIGN(KeyedLoadDictionaryElementStub); 1702 }; 1703 1704 1705 class KeyedLoadDictionaryElementPlatformStub : public PlatformCodeStub { 1706 public: 1707 KeyedLoadDictionaryElementPlatformStub() {} 1708 1709 void Generate(MacroAssembler* masm); 1710 1711 private: 1712 Major MajorKey() { return KeyedLoadElement; } 1713 int MinorKey() { return DICTIONARY_ELEMENTS; } 1714 1715 DISALLOW_COPY_AND_ASSIGN(KeyedLoadDictionaryElementPlatformStub); 1716 }; 1717 1718 1719 class DoubleToIStub : public PlatformCodeStub { 1720 public: 1721 DoubleToIStub(Register source, 1722 Register destination, 1723 int offset, 1724 bool is_truncating, 1725 bool skip_fastpath = false) : bit_field_(0) { 1726 bit_field_ = SourceRegisterBits::encode(source.code_) | 1727 DestinationRegisterBits::encode(destination.code_) | 1728 OffsetBits::encode(offset) | 1729 IsTruncatingBits::encode(is_truncating) | 1730 SkipFastPathBits::encode(skip_fastpath) | 1731 SSEBits::encode(CpuFeatures::IsSafeForSnapshot(SSE2) ? 1732 CpuFeatures::IsSafeForSnapshot(SSE3) ? 2 : 1 : 0); 1733 } 1734 1735 Register source() { 1736 Register result = { SourceRegisterBits::decode(bit_field_) }; 1737 return result; 1738 } 1739 1740 Register destination() { 1741 Register result = { DestinationRegisterBits::decode(bit_field_) }; 1742 return result; 1743 } 1744 1745 bool is_truncating() { 1746 return IsTruncatingBits::decode(bit_field_); 1747 } 1748 1749 bool skip_fastpath() { 1750 return SkipFastPathBits::decode(bit_field_); 1751 } 1752 1753 int offset() { 1754 return OffsetBits::decode(bit_field_); 1755 } 1756 1757 void Generate(MacroAssembler* masm); 1758 1759 virtual bool SometimesSetsUpAFrame() { return false; } 1760 1761 protected: 1762 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE { 1763 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2)); 1764 } 1765 1766 private: 1767 static const int kBitsPerRegisterNumber = 6; 1768 STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters); 1769 class SourceRegisterBits: 1770 public BitField<int, 0, kBitsPerRegisterNumber> {}; // NOLINT 1771 class DestinationRegisterBits: 1772 public BitField<int, kBitsPerRegisterNumber, 1773 kBitsPerRegisterNumber> {}; // NOLINT 1774 class IsTruncatingBits: 1775 public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {}; // NOLINT 1776 class OffsetBits: 1777 public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {}; // NOLINT 1778 class SkipFastPathBits: 1779 public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {}; // NOLINT 1780 class SSEBits: 1781 public BitField<int, 2 * kBitsPerRegisterNumber + 5, 2> {}; // NOLINT 1782 1783 Major MajorKey() { return DoubleToI; } 1784 int MinorKey() { return bit_field_; } 1785 1786 int bit_field_; 1787 1788 DISALLOW_COPY_AND_ASSIGN(DoubleToIStub); 1789 }; 1790 1791 1792 class KeyedLoadFastElementStub : public HydrogenCodeStub { 1793 public: 1794 KeyedLoadFastElementStub(bool is_js_array, ElementsKind elements_kind) { 1795 bit_field_ = ElementsKindBits::encode(elements_kind) | 1796 IsJSArrayBits::encode(is_js_array); 1797 } 1798 1799 bool is_js_array() const { 1800 return IsJSArrayBits::decode(bit_field_); 1801 } 1802 1803 ElementsKind elements_kind() const { 1804 return ElementsKindBits::decode(bit_field_); 1805 } 1806 1807 virtual Handle<Code> GenerateCode(Isolate* isolate); 1808 1809 virtual void InitializeInterfaceDescriptor( 1810 Isolate* isolate, 1811 CodeStubInterfaceDescriptor* descriptor); 1812 1813 private: 1814 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {}; 1815 class IsJSArrayBits: public BitField<bool, 8, 1> {}; 1816 uint32_t bit_field_; 1817 1818 Major MajorKey() { return KeyedLoadElement; } 1819 int NotMissMinorKey() { return bit_field_; } 1820 1821 DISALLOW_COPY_AND_ASSIGN(KeyedLoadFastElementStub); 1822 }; 1823 1824 1825 class KeyedStoreFastElementStub : public HydrogenCodeStub { 1826 public: 1827 KeyedStoreFastElementStub(bool is_js_array, 1828 ElementsKind elements_kind, 1829 KeyedAccessStoreMode mode) { 1830 bit_field_ = ElementsKindBits::encode(elements_kind) | 1831 IsJSArrayBits::encode(is_js_array) | 1832 StoreModeBits::encode(mode); 1833 } 1834 1835 bool is_js_array() const { 1836 return IsJSArrayBits::decode(bit_field_); 1837 } 1838 1839 ElementsKind elements_kind() const { 1840 return ElementsKindBits::decode(bit_field_); 1841 } 1842 1843 KeyedAccessStoreMode store_mode() const { 1844 return StoreModeBits::decode(bit_field_); 1845 } 1846 1847 virtual Handle<Code> GenerateCode(Isolate* isolate); 1848 1849 virtual void InitializeInterfaceDescriptor( 1850 Isolate* isolate, 1851 CodeStubInterfaceDescriptor* descriptor); 1852 1853 private: 1854 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {}; 1855 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {}; 1856 class IsJSArrayBits: public BitField<bool, 12, 1> {}; 1857 uint32_t bit_field_; 1858 1859 Major MajorKey() { return KeyedStoreElement; } 1860 int NotMissMinorKey() { return bit_field_; } 1861 1862 DISALLOW_COPY_AND_ASSIGN(KeyedStoreFastElementStub); 1863 }; 1864 1865 1866 class TransitionElementsKindStub : public HydrogenCodeStub { 1867 public: 1868 TransitionElementsKindStub(ElementsKind from_kind, 1869 ElementsKind to_kind) { 1870 bit_field_ = FromKindBits::encode(from_kind) | 1871 ToKindBits::encode(to_kind); 1872 } 1873 1874 ElementsKind from_kind() const { 1875 return FromKindBits::decode(bit_field_); 1876 } 1877 1878 ElementsKind to_kind() const { 1879 return ToKindBits::decode(bit_field_); 1880 } 1881 1882 virtual Handle<Code> GenerateCode(Isolate* isolate); 1883 1884 virtual void InitializeInterfaceDescriptor( 1885 Isolate* isolate, 1886 CodeStubInterfaceDescriptor* descriptor); 1887 1888 private: 1889 class FromKindBits: public BitField<ElementsKind, 8, 8> {}; 1890 class ToKindBits: public BitField<ElementsKind, 0, 8> {}; 1891 uint32_t bit_field_; 1892 1893 Major MajorKey() { return TransitionElementsKind; } 1894 int NotMissMinorKey() { return bit_field_; } 1895 1896 DISALLOW_COPY_AND_ASSIGN(TransitionElementsKindStub); 1897 }; 1898 1899 1900 enum ContextCheckMode { 1901 CONTEXT_CHECK_REQUIRED, 1902 CONTEXT_CHECK_NOT_REQUIRED, 1903 LAST_CONTEXT_CHECK_MODE = CONTEXT_CHECK_NOT_REQUIRED 1904 }; 1905 1906 1907 class ArrayConstructorStubBase : public HydrogenCodeStub { 1908 public: 1909 ArrayConstructorStubBase(ElementsKind kind, ContextCheckMode context_mode, 1910 AllocationSiteOverrideMode override_mode) { 1911 // It only makes sense to override local allocation site behavior 1912 // if there is a difference between the global allocation site policy 1913 // for an ElementsKind and the desired usage of the stub. 1914 ASSERT(!(FLAG_track_allocation_sites && 1915 override_mode == DISABLE_ALLOCATION_SITES) || 1916 AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE); 1917 bit_field_ = ElementsKindBits::encode(kind) | 1918 AllocationSiteOverrideModeBits::encode(override_mode) | 1919 ContextCheckModeBits::encode(context_mode); 1920 } 1921 1922 ElementsKind elements_kind() const { 1923 return ElementsKindBits::decode(bit_field_); 1924 } 1925 1926 AllocationSiteOverrideMode override_mode() const { 1927 return AllocationSiteOverrideModeBits::decode(bit_field_); 1928 } 1929 1930 ContextCheckMode context_mode() const { 1931 return ContextCheckModeBits::decode(bit_field_); 1932 } 1933 1934 static void GenerateStubsAheadOfTime(Isolate* isolate); 1935 static void InstallDescriptors(Isolate* isolate); 1936 1937 // Parameters accessed via CodeStubGraphBuilder::GetParameter() 1938 static const int kConstructor = 0; 1939 static const int kPropertyCell = 1; 1940 1941 private: 1942 int NotMissMinorKey() { return bit_field_; } 1943 1944 // Ensure data fits within available bits. 1945 STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1); 1946 STATIC_ASSERT(LAST_CONTEXT_CHECK_MODE == 1); 1947 1948 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {}; 1949 class AllocationSiteOverrideModeBits: public 1950 BitField<AllocationSiteOverrideMode, 8, 1> {}; // NOLINT 1951 class ContextCheckModeBits: public BitField<ContextCheckMode, 9, 1> {}; 1952 uint32_t bit_field_; 1953 1954 DISALLOW_COPY_AND_ASSIGN(ArrayConstructorStubBase); 1955 }; 1956 1957 1958 class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase { 1959 public: 1960 ArrayNoArgumentConstructorStub( 1961 ElementsKind kind, 1962 ContextCheckMode context_mode = CONTEXT_CHECK_REQUIRED, 1963 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE) 1964 : ArrayConstructorStubBase(kind, context_mode, override_mode) { 1965 } 1966 1967 virtual Handle<Code> GenerateCode(Isolate* isolate); 1968 1969 virtual void InitializeInterfaceDescriptor( 1970 Isolate* isolate, 1971 CodeStubInterfaceDescriptor* descriptor); 1972 1973 private: 1974 Major MajorKey() { return ArrayNoArgumentConstructor; } 1975 1976 DISALLOW_COPY_AND_ASSIGN(ArrayNoArgumentConstructorStub); 1977 }; 1978 1979 1980 class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase { 1981 public: 1982 ArraySingleArgumentConstructorStub( 1983 ElementsKind kind, 1984 ContextCheckMode context_mode = CONTEXT_CHECK_REQUIRED, 1985 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE) 1986 : ArrayConstructorStubBase(kind, context_mode, override_mode) { 1987 } 1988 1989 virtual Handle<Code> GenerateCode(Isolate* isolate); 1990 1991 virtual void InitializeInterfaceDescriptor( 1992 Isolate* isolate, 1993 CodeStubInterfaceDescriptor* descriptor); 1994 1995 private: 1996 Major MajorKey() { return ArraySingleArgumentConstructor; } 1997 1998 DISALLOW_COPY_AND_ASSIGN(ArraySingleArgumentConstructorStub); 1999 }; 2000 2001 2002 class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase { 2003 public: 2004 ArrayNArgumentsConstructorStub( 2005 ElementsKind kind, 2006 ContextCheckMode context_mode = CONTEXT_CHECK_REQUIRED, 2007 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE) 2008 : ArrayConstructorStubBase(kind, context_mode, override_mode) { 2009 } 2010 2011 virtual Handle<Code> GenerateCode(Isolate* isolate); 2012 2013 virtual void InitializeInterfaceDescriptor( 2014 Isolate* isolate, 2015 CodeStubInterfaceDescriptor* descriptor); 2016 2017 private: 2018 Major MajorKey() { return ArrayNArgumentsConstructor; } 2019 2020 DISALLOW_COPY_AND_ASSIGN(ArrayNArgumentsConstructorStub); 2021 }; 2022 2023 2024 class InternalArrayConstructorStubBase : public HydrogenCodeStub { 2025 public: 2026 explicit InternalArrayConstructorStubBase(ElementsKind kind) { 2027 kind_ = kind; 2028 } 2029 2030 static void GenerateStubsAheadOfTime(Isolate* isolate); 2031 static void InstallDescriptors(Isolate* isolate); 2032 2033 // Parameters accessed via CodeStubGraphBuilder::GetParameter() 2034 static const int kConstructor = 0; 2035 2036 ElementsKind elements_kind() const { return kind_; } 2037 2038 private: 2039 int NotMissMinorKey() { return kind_; } 2040 2041 ElementsKind kind_; 2042 2043 DISALLOW_COPY_AND_ASSIGN(InternalArrayConstructorStubBase); 2044 }; 2045 2046 2047 class InternalArrayNoArgumentConstructorStub : public 2048 InternalArrayConstructorStubBase { 2049 public: 2050 explicit InternalArrayNoArgumentConstructorStub(ElementsKind kind) 2051 : InternalArrayConstructorStubBase(kind) { } 2052 2053 virtual Handle<Code> GenerateCode(Isolate* isolate); 2054 2055 virtual void InitializeInterfaceDescriptor( 2056 Isolate* isolate, 2057 CodeStubInterfaceDescriptor* descriptor); 2058 2059 private: 2060 Major MajorKey() { return InternalArrayNoArgumentConstructor; } 2061 2062 DISALLOW_COPY_AND_ASSIGN(InternalArrayNoArgumentConstructorStub); 2063 }; 2064 2065 2066 class InternalArraySingleArgumentConstructorStub : public 2067 InternalArrayConstructorStubBase { 2068 public: 2069 explicit InternalArraySingleArgumentConstructorStub(ElementsKind kind) 2070 : InternalArrayConstructorStubBase(kind) { } 2071 2072 virtual Handle<Code> GenerateCode(Isolate* isolate); 2073 2074 virtual void InitializeInterfaceDescriptor( 2075 Isolate* isolate, 2076 CodeStubInterfaceDescriptor* descriptor); 2077 2078 private: 2079 Major MajorKey() { return InternalArraySingleArgumentConstructor; } 2080 2081 DISALLOW_COPY_AND_ASSIGN(InternalArraySingleArgumentConstructorStub); 2082 }; 2083 2084 2085 class InternalArrayNArgumentsConstructorStub : public 2086 InternalArrayConstructorStubBase { 2087 public: 2088 explicit InternalArrayNArgumentsConstructorStub(ElementsKind kind) 2089 : InternalArrayConstructorStubBase(kind) { } 2090 2091 virtual Handle<Code> GenerateCode(Isolate* isolate); 2092 2093 virtual void InitializeInterfaceDescriptor( 2094 Isolate* isolate, 2095 CodeStubInterfaceDescriptor* descriptor); 2096 2097 private: 2098 Major MajorKey() { return InternalArrayNArgumentsConstructor; } 2099 2100 DISALLOW_COPY_AND_ASSIGN(InternalArrayNArgumentsConstructorStub); 2101 }; 2102 2103 2104 class KeyedStoreElementStub : public PlatformCodeStub { 2105 public: 2106 KeyedStoreElementStub(bool is_js_array, 2107 ElementsKind elements_kind, 2108 KeyedAccessStoreMode store_mode) 2109 : is_js_array_(is_js_array), 2110 elements_kind_(elements_kind), 2111 store_mode_(store_mode), 2112 fp_registers_(CanUseFPRegisters()) { } 2113 2114 Major MajorKey() { return KeyedStoreElement; } 2115 int MinorKey() { 2116 return ElementsKindBits::encode(elements_kind_) | 2117 IsJSArrayBits::encode(is_js_array_) | 2118 StoreModeBits::encode(store_mode_) | 2119 FPRegisters::encode(fp_registers_); 2120 } 2121 2122 void Generate(MacroAssembler* masm); 2123 2124 private: 2125 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {}; 2126 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {}; 2127 class IsJSArrayBits: public BitField<bool, 12, 1> {}; 2128 class FPRegisters: public BitField<bool, 13, 1> {}; 2129 2130 bool is_js_array_; 2131 ElementsKind elements_kind_; 2132 KeyedAccessStoreMode store_mode_; 2133 bool fp_registers_; 2134 2135 DISALLOW_COPY_AND_ASSIGN(KeyedStoreElementStub); 2136 }; 2137 2138 2139 class ToBooleanStub: public HydrogenCodeStub { 2140 public: 2141 enum Type { 2142 UNDEFINED, 2143 BOOLEAN, 2144 NULL_TYPE, 2145 SMI, 2146 SPEC_OBJECT, 2147 STRING, 2148 SYMBOL, 2149 HEAP_NUMBER, 2150 NUMBER_OF_TYPES 2151 }; 2152 2153 // At most 8 different types can be distinguished, because the Code object 2154 // only has room for a single byte to hold a set of these types. :-P 2155 STATIC_ASSERT(NUMBER_OF_TYPES <= 8); 2156 2157 class Types : public EnumSet<Type, byte> { 2158 public: 2159 Types() : EnumSet<Type, byte>(0) {} 2160 explicit Types(byte bits) : EnumSet<Type, byte>(bits) {} 2161 2162 byte ToByte() const { return ToIntegral(); } 2163 void Print(StringStream* stream) const; 2164 bool UpdateStatus(Handle<Object> object); 2165 bool NeedsMap() const; 2166 bool CanBeUndetectable() const; 2167 bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); } 2168 2169 static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); } 2170 }; 2171 2172 explicit ToBooleanStub(Types types = Types()) 2173 : types_(types) { } 2174 explicit ToBooleanStub(ExtraICState state) 2175 : types_(static_cast<byte>(state)) { } 2176 2177 bool UpdateStatus(Handle<Object> object); 2178 Types GetTypes() { return types_; } 2179 2180 virtual Handle<Code> GenerateCode(Isolate* isolate); 2181 virtual void InitializeInterfaceDescriptor( 2182 Isolate* isolate, 2183 CodeStubInterfaceDescriptor* descriptor); 2184 2185 virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; } 2186 virtual void PrintState(StringStream* stream); 2187 2188 virtual bool SometimesSetsUpAFrame() { return false; } 2189 2190 static void InitializeForIsolate(Isolate* isolate) { 2191 ToBooleanStub stub; 2192 stub.InitializeInterfaceDescriptor( 2193 isolate, 2194 isolate->code_stub_interface_descriptor(CodeStub::ToBoolean)); 2195 } 2196 2197 static Handle<Code> GetUninitialized(Isolate* isolate) { 2198 return ToBooleanStub(UNINITIALIZED).GetCode(isolate); 2199 } 2200 2201 virtual ExtraICState GetExtraICState() { 2202 return types_.ToIntegral(); 2203 } 2204 2205 virtual InlineCacheState GetICState() { 2206 if (types_.IsEmpty()) { 2207 return ::v8::internal::UNINITIALIZED; 2208 } else { 2209 return MONOMORPHIC; 2210 } 2211 } 2212 2213 private: 2214 Major MajorKey() { return ToBoolean; } 2215 int NotMissMinorKey() { return GetExtraICState(); } 2216 2217 explicit ToBooleanStub(InitializationState init_state) : 2218 HydrogenCodeStub(init_state) {} 2219 2220 Types types_; 2221 }; 2222 2223 2224 class ElementsTransitionAndStoreStub : public HydrogenCodeStub { 2225 public: 2226 ElementsTransitionAndStoreStub(ElementsKind from_kind, 2227 ElementsKind to_kind, 2228 bool is_jsarray, 2229 KeyedAccessStoreMode store_mode) 2230 : from_kind_(from_kind), 2231 to_kind_(to_kind), 2232 is_jsarray_(is_jsarray), 2233 store_mode_(store_mode) {} 2234 2235 ElementsKind from_kind() const { return from_kind_; } 2236 ElementsKind to_kind() const { return to_kind_; } 2237 bool is_jsarray() const { return is_jsarray_; } 2238 KeyedAccessStoreMode store_mode() const { return store_mode_; } 2239 2240 virtual Handle<Code> GenerateCode(Isolate* isolate); 2241 2242 void InitializeInterfaceDescriptor( 2243 Isolate* isolate, 2244 CodeStubInterfaceDescriptor* descriptor); 2245 2246 private: 2247 class FromBits: public BitField<ElementsKind, 0, 8> {}; 2248 class ToBits: public BitField<ElementsKind, 8, 8> {}; 2249 class IsJSArrayBits: public BitField<bool, 16, 1> {}; 2250 class StoreModeBits: public BitField<KeyedAccessStoreMode, 17, 4> {}; 2251 2252 Major MajorKey() { return ElementsTransitionAndStore; } 2253 int NotMissMinorKey() { 2254 return FromBits::encode(from_kind_) | 2255 ToBits::encode(to_kind_) | 2256 IsJSArrayBits::encode(is_jsarray_) | 2257 StoreModeBits::encode(store_mode_); 2258 } 2259 2260 ElementsKind from_kind_; 2261 ElementsKind to_kind_; 2262 bool is_jsarray_; 2263 KeyedAccessStoreMode store_mode_; 2264 2265 DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub); 2266 }; 2267 2268 2269 class StoreArrayLiteralElementStub : public PlatformCodeStub { 2270 public: 2271 StoreArrayLiteralElementStub() 2272 : fp_registers_(CanUseFPRegisters()) { } 2273 2274 private: 2275 class FPRegisters: public BitField<bool, 0, 1> {}; 2276 2277 Major MajorKey() { return StoreArrayLiteralElement; } 2278 int MinorKey() { return FPRegisters::encode(fp_registers_); } 2279 2280 void Generate(MacroAssembler* masm); 2281 2282 bool fp_registers_; 2283 2284 DISALLOW_COPY_AND_ASSIGN(StoreArrayLiteralElementStub); 2285 }; 2286 2287 2288 class StubFailureTrampolineStub : public PlatformCodeStub { 2289 public: 2290 explicit StubFailureTrampolineStub(StubFunctionMode function_mode) 2291 : fp_registers_(CanUseFPRegisters()), function_mode_(function_mode) {} 2292 2293 static void GenerateAheadOfTime(Isolate* isolate); 2294 2295 private: 2296 class FPRegisters: public BitField<bool, 0, 1> {}; 2297 class FunctionModeField: public BitField<StubFunctionMode, 1, 1> {}; 2298 2299 Major MajorKey() { return StubFailureTrampoline; } 2300 int MinorKey() { 2301 return FPRegisters::encode(fp_registers_) | 2302 FunctionModeField::encode(function_mode_); 2303 } 2304 2305 void Generate(MacroAssembler* masm); 2306 2307 bool fp_registers_; 2308 StubFunctionMode function_mode_; 2309 2310 DISALLOW_COPY_AND_ASSIGN(StubFailureTrampolineStub); 2311 }; 2312 2313 2314 class StubFailureTailCallTrampolineStub : public PlatformCodeStub { 2315 public: 2316 StubFailureTailCallTrampolineStub() : fp_registers_(CanUseFPRegisters()) {} 2317 2318 static void GenerateAheadOfTime(Isolate* isolate); 2319 2320 private: 2321 class FPRegisters: public BitField<bool, 0, 1> {}; 2322 Major MajorKey() { return StubFailureTailCallTrampoline; } 2323 int MinorKey() { return FPRegisters::encode(fp_registers_); } 2324 2325 void Generate(MacroAssembler* masm); 2326 2327 bool fp_registers_; 2328 2329 DISALLOW_COPY_AND_ASSIGN(StubFailureTailCallTrampolineStub); 2330 }; 2331 2332 2333 class ProfileEntryHookStub : public PlatformCodeStub { 2334 public: 2335 explicit ProfileEntryHookStub() {} 2336 2337 // The profile entry hook function is not allowed to cause a GC. 2338 virtual bool SometimesSetsUpAFrame() { return false; } 2339 2340 // Generates a call to the entry hook if it's enabled. 2341 static void MaybeCallEntryHook(MacroAssembler* masm); 2342 2343 private: 2344 static void EntryHookTrampoline(intptr_t function, 2345 intptr_t stack_pointer, 2346 Isolate* isolate); 2347 2348 Major MajorKey() { return ProfileEntryHook; } 2349 int MinorKey() { return 0; } 2350 2351 void Generate(MacroAssembler* masm); 2352 2353 DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub); 2354 }; 2355 2356 } } // namespace v8::internal 2357 2358 #endif // V8_CODE_STUBS_H_ 2359