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