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
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.
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.
28 #ifndef V8_CODE_STUBS_H_
29 #define V8_CODE_STUBS_H_
31 #include "allocation.h"
32 #include "assembler.h"
35 #include "macro-assembler.h"
40 // List of code stubs used on all platforms.
41 #define CODE_STUB_LIST_ALL_PLATFORMS(V) \
45 V(BinaryOpICWithAllocationSite) \
46 V(BinaryOpWithAllocationSite) \
55 V(FunctionPrototype) \
58 V(StoreBufferOverflow) \
62 V(WriteInt32ToHeapNumber) \
67 V(FastCloneShallowArray) \
68 V(FastCloneShallowObject) \
69 V(CreateAllocationSite) \
73 V(RegExpConstructResult) \
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) \
94 V(InternalArrayConstructor) \
99 /* IC Handler stubs */ \
103 // List of code stubs only used on ARM platforms.
104 #if V8_TARGET_ARCH_ARM
105 #define CODE_STUB_LIST_ARM(V) \
111 #define CODE_STUB_LIST_ARM(V)
114 // List of code stubs only used on MIPS platforms.
115 #if V8_TARGET_ARCH_MIPS
116 #define CODE_STUB_LIST_MIPS(V) \
119 V(StoreRegistersState) \
120 V(RestoreRegistersState)
122 #define CODE_STUB_LIST_MIPS(V)
125 // Combined list of code stubs.
126 #define CODE_STUB_LIST(V) \
127 CODE_STUB_LIST_ALL_PLATFORMS(V) \
128 CODE_STUB_LIST_ARM(V) \
129 CODE_STUB_LIST_MIPS(V)
131 // Stub is base classes of all stubs.
132 class CodeStub BASE_EMBEDDED {
135 UninitializedMajorKey = 0,
136 #define DEF_ENUM(name) name,
137 CODE_STUB_LIST(DEF_ENUM)
139 NoCache, // marker for stubs that do custom caching
143 // Retrieve the code for the stub. Generate the code if needed.
144 Handle<Code> GetCode(Isolate* isolate);
146 // Retrieve the code for the stub, make and return a copy of the code.
147 Handle<Code> GetCodeCopyFromTemplate(Isolate* isolate);
148 static Major MajorKeyFromKey(uint32_t key) {
149 return static_cast<Major>(MajorKeyBits::decode(key));
151 static int MinorKeyFromKey(uint32_t key) {
152 return MinorKeyBits::decode(key);
155 // Gets the major key from a code object that is a code stub or binary op IC.
156 static Major GetMajorKey(Code* code_stub) {
157 return static_cast<Major>(code_stub->major_key());
160 static const char* MajorName(Major major_key, bool allow_unknown_keys);
162 virtual ~CodeStub() {}
164 static void GenerateStubsAheadOfTime(Isolate* isolate);
165 static void GenerateFPStubs(Isolate* isolate);
167 // Some stubs put untagged junk on the stack that cannot be scanned by the
168 // GC. This means that we must be statically sure that no GC can occur while
169 // they are running. If that is the case they should override this to return
170 // true, which will cause an assertion if we try to call something that can
171 // GC or if we try to put a stack frame on top of the junk, which would not
172 // result in a traversable stack.
173 virtual bool SometimesSetsUpAFrame() { return true; }
175 // Lookup the code in the (possibly custom) cache.
176 bool FindCodeInCache(Code** code_out, Isolate* isolate);
178 // Returns information for computing the number key.
179 virtual Major MajorKey() = 0;
180 virtual int MinorKey() = 0;
182 virtual InlineCacheState GetICState() {
183 return UNINITIALIZED;
185 virtual ExtraICState GetExtraICState() {
186 return kNoExtraICState;
188 virtual Code::StubType GetStubType() {
191 virtual int GetStubFlags() {
195 virtual void PrintName(StringStream* stream);
197 // Returns a name for logging/debugging purposes.
198 SmartArrayPointer<const char> GetName();
201 static bool CanUseFPRegisters();
203 // Generates the assembler code for the stub.
204 virtual Handle<Code> GenerateCode(Isolate* isolate) = 0;
206 virtual void VerifyPlatformFeatures(Isolate* isolate);
208 // Returns whether the code generated for this stub needs to be allocated as
209 // a fixed (non-moveable) code object.
210 virtual bool NeedsImmovableCode() { return false; }
212 virtual void PrintBaseName(StringStream* stream);
213 virtual void PrintState(StringStream* stream) { }
216 // Perform bookkeeping required after code generation when stub code is
217 // initially generated.
218 void RecordCodeGeneration(Code* code, Isolate* isolate);
220 // Finish the code object after it has been generated.
221 virtual void FinishCode(Handle<Code> code) { }
223 // Activate newly generated stub. Is called after
224 // registering stub in the stub cache.
225 virtual void Activate(Code* code) { }
227 // BinaryOpStub needs to override this.
228 virtual Code::Kind GetCodeKind() const;
230 // Add the code to a specialized cache, specific to an individual
231 // stub type. Please note, this method must add the code object to a
232 // roots object, otherwise we will remove the code during GC.
233 virtual void AddToSpecialCache(Handle<Code> new_object) { }
235 // Find code in a specialized cache, work is delegated to the specific stub.
236 virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate) {
240 // If a stub uses a special cache override this.
241 virtual bool UseSpecialCache() { return false; }
243 // Computes the key based on major and minor.
245 ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
246 return MinorKeyBits::encode(MinorKey()) |
247 MajorKeyBits::encode(MajorKey());
250 STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
251 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
252 class MinorKeyBits: public BitField<uint32_t,
253 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT
255 friend class BreakPointIterator;
259 class PlatformCodeStub : public CodeStub {
261 // Retrieve the code for the stub. Generate the code if needed.
262 virtual Handle<Code> GenerateCode(Isolate* isolate);
264 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
267 // Generates the assembler code for the stub.
268 virtual void Generate(MacroAssembler* masm) = 0;
272 enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
273 enum HandlerArgumentsMode { DONT_PASS_ARGUMENTS, PASS_ARGUMENTS };
275 struct CodeStubInterfaceDescriptor {
276 CodeStubInterfaceDescriptor();
277 int register_param_count_;
279 Register stack_parameter_count_;
280 // if hint_stack_parameter_count_ > 0, the code stub can optimize the
281 // return sequence. Default value is -1, which means it is ignored.
282 int hint_stack_parameter_count_;
283 StubFunctionMode function_mode_;
284 Register* register_params_;
286 Address deoptimization_handler_;
287 HandlerArgumentsMode handler_arguments_mode_;
289 bool initialized() const { return register_param_count_ >= 0; }
291 int environment_length() const {
292 return register_param_count_;
295 void SetMissHandler(ExternalReference handler) {
296 miss_handler_ = handler;
297 has_miss_handler_ = true;
298 // Our miss handler infrastructure doesn't currently support
299 // variable stack parameter counts.
300 ASSERT(!stack_parameter_count_.is_valid());
303 ExternalReference miss_handler() {
304 ASSERT(has_miss_handler_);
305 return miss_handler_;
308 bool has_miss_handler() {
309 return has_miss_handler_;
312 Register GetParameterRegister(int index) const {
313 return register_params_[index];
316 bool IsParameterCountRegister(int index) {
317 return GetParameterRegister(index).is(stack_parameter_count_);
320 int GetHandlerParameterCount() {
321 int params = environment_length();
322 if (handler_arguments_mode_ == PASS_ARGUMENTS) {
329 ExternalReference miss_handler_;
330 bool has_miss_handler_;
334 struct PlatformCallInterfaceDescriptor;
337 struct CallInterfaceDescriptor {
338 CallInterfaceDescriptor()
339 : register_param_count_(-1),
340 register_params_(NULL),
341 param_representations_(NULL),
342 platform_specific_descriptor_(NULL) { }
344 bool initialized() const { return register_param_count_ >= 0; }
346 int environment_length() const {
347 return register_param_count_;
350 Representation GetParameterRepresentation(int index) const {
351 return param_representations_[index];
354 Register GetParameterRegister(int index) const {
355 return register_params_[index];
358 PlatformCallInterfaceDescriptor* platform_specific_descriptor() const {
359 return platform_specific_descriptor_;
362 int register_param_count_;
363 Register* register_params_;
364 Representation* param_representations_;
365 PlatformCallInterfaceDescriptor* platform_specific_descriptor_;
369 class HydrogenCodeStub : public CodeStub {
371 enum InitializationState {
376 explicit HydrogenCodeStub(InitializationState state = INITIALIZED) {
377 is_uninitialized_ = (state == UNINITIALIZED);
380 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
382 CodeStubInterfaceDescriptor* GetInterfaceDescriptor(Isolate* isolate) {
383 return isolate->code_stub_interface_descriptor(MajorKey());
386 bool IsUninitialized() { return is_uninitialized_; }
388 template<class SubClass>
389 static Handle<Code> GetUninitialized(Isolate* isolate) {
390 SubClass::GenerateAheadOfTime(isolate);
391 return SubClass().GetCode(isolate);
394 virtual void InitializeInterfaceDescriptor(
396 CodeStubInterfaceDescriptor* descriptor) = 0;
398 // Retrieve the code for the stub. Generate the code if needed.
399 virtual Handle<Code> GenerateCode(Isolate* isolate) = 0;
401 virtual int NotMissMinorKey() = 0;
403 Handle<Code> GenerateLightweightMissCode(Isolate* isolate);
405 template<class StateType>
406 void TraceTransition(StateType from, StateType to);
409 class MinorKeyBits: public BitField<int, 0, kStubMinorKeyBits - 1> {};
410 class IsMissBits: public BitField<bool, kStubMinorKeyBits - 1, 1> {};
412 void GenerateLightweightMiss(MacroAssembler* masm);
413 virtual int MinorKey() {
414 return IsMissBits::encode(is_uninitialized_) |
415 MinorKeyBits::encode(NotMissMinorKey());
418 bool is_uninitialized_;
422 // Helper interface to prepare to/restore after making runtime calls.
423 class RuntimeCallHelper {
425 virtual ~RuntimeCallHelper() {}
427 virtual void BeforeCall(MacroAssembler* masm) const = 0;
429 virtual void AfterCall(MacroAssembler* masm) const = 0;
432 RuntimeCallHelper() {}
435 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
439 } } // namespace v8::internal
441 #if V8_TARGET_ARCH_IA32
442 #include "ia32/code-stubs-ia32.h"
443 #elif V8_TARGET_ARCH_X64
444 #include "x64/code-stubs-x64.h"
445 #elif V8_TARGET_ARCH_ARM
446 #include "arm/code-stubs-arm.h"
447 #elif V8_TARGET_ARCH_MIPS
448 #include "mips/code-stubs-mips.h"
450 #error Unsupported target architecture.
457 // RuntimeCallHelper implementation used in stubs: enters/leaves a
458 // newly created internal frame before/after the runtime call.
459 class StubRuntimeCallHelper : public RuntimeCallHelper {
461 StubRuntimeCallHelper() {}
463 virtual void BeforeCall(MacroAssembler* masm) const;
465 virtual void AfterCall(MacroAssembler* masm) const;
469 // Trivial RuntimeCallHelper implementation.
470 class NopRuntimeCallHelper : public RuntimeCallHelper {
472 NopRuntimeCallHelper() {}
474 virtual void BeforeCall(MacroAssembler* masm) const {}
476 virtual void AfterCall(MacroAssembler* masm) const {}
480 class ToNumberStub: public HydrogenCodeStub {
484 virtual Handle<Code> GenerateCode(Isolate* isolate);
486 virtual void InitializeInterfaceDescriptor(
488 CodeStubInterfaceDescriptor* descriptor);
491 Major MajorKey() { return ToNumber; }
492 int NotMissMinorKey() { return 0; }
496 class NumberToStringStub V8_FINAL : public HydrogenCodeStub {
498 NumberToStringStub() {}
500 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
502 virtual void InitializeInterfaceDescriptor(
504 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
506 static void InstallDescriptors(Isolate* isolate);
508 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
509 static const int kNumber = 0;
512 virtual Major MajorKey() V8_OVERRIDE { return NumberToString; }
513 virtual int NotMissMinorKey() V8_OVERRIDE { return 0; }
517 class FastNewClosureStub : public HydrogenCodeStub {
519 explicit FastNewClosureStub(LanguageMode language_mode, bool is_generator)
520 : language_mode_(language_mode),
521 is_generator_(is_generator) { }
523 virtual Handle<Code> GenerateCode(Isolate* isolate);
525 virtual void InitializeInterfaceDescriptor(
527 CodeStubInterfaceDescriptor* descriptor);
529 static void InstallDescriptors(Isolate* isolate);
531 LanguageMode language_mode() const { return language_mode_; }
532 bool is_generator() const { return is_generator_; }
535 class StrictModeBits: public BitField<bool, 0, 1> {};
536 class IsGeneratorBits: public BitField<bool, 1, 1> {};
538 Major MajorKey() { return FastNewClosure; }
539 int NotMissMinorKey() {
540 return StrictModeBits::encode(language_mode_ != CLASSIC_MODE) |
541 IsGeneratorBits::encode(is_generator_);
544 LanguageMode language_mode_;
549 class FastNewContextStub V8_FINAL : public HydrogenCodeStub {
551 static const int kMaximumSlots = 64;
553 explicit FastNewContextStub(int slots) : slots_(slots) {
554 ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
557 virtual Handle<Code> GenerateCode(Isolate* isolate);
559 virtual void InitializeInterfaceDescriptor(
561 CodeStubInterfaceDescriptor* descriptor);
563 static void InstallDescriptors(Isolate* isolate);
565 int slots() const { return slots_; }
567 virtual Major MajorKey() V8_OVERRIDE { return FastNewContext; }
568 virtual int NotMissMinorKey() V8_OVERRIDE { return slots_; }
570 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
571 static const int kFunction = 0;
578 class FastCloneShallowArrayStub : public HydrogenCodeStub {
580 // Maximum length of copied elements array.
581 static const int kMaximumClonedLength = 8;
584 CLONE_DOUBLE_ELEMENTS,
585 COPY_ON_WRITE_ELEMENTS,
587 LAST_CLONE_MODE = CLONE_ANY_ELEMENTS
590 static const int kFastCloneModeCount = LAST_CLONE_MODE + 1;
592 FastCloneShallowArrayStub(Mode mode,
593 AllocationSiteMode allocation_site_mode,
596 allocation_site_mode_(allocation_site_mode),
597 length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
598 ASSERT_GE(length_, 0);
599 ASSERT_LE(length_, kMaximumClonedLength);
602 Mode mode() const { return mode_; }
603 int length() const { return length_; }
604 AllocationSiteMode allocation_site_mode() const {
605 return allocation_site_mode_;
608 ElementsKind ComputeElementsKind() const {
611 case COPY_ON_WRITE_ELEMENTS:
612 return FAST_ELEMENTS;
613 case CLONE_DOUBLE_ELEMENTS:
614 return FAST_DOUBLE_ELEMENTS;
615 case CLONE_ANY_ELEMENTS:
619 return LAST_ELEMENTS_KIND;
622 virtual Handle<Code> GenerateCode(Isolate* isolate);
624 virtual void InitializeInterfaceDescriptor(
626 CodeStubInterfaceDescriptor* descriptor);
630 AllocationSiteMode allocation_site_mode_;
633 class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
634 class ModeBits: public BitField<Mode, 1, 4> {};
635 class LengthBits: public BitField<int, 5, 4> {};
636 // Ensure data fits within available bits.
637 STATIC_ASSERT(LAST_ALLOCATION_SITE_MODE == 1);
638 STATIC_ASSERT(kFastCloneModeCount < 16);
639 STATIC_ASSERT(kMaximumClonedLength < 16);
640 Major MajorKey() { return FastCloneShallowArray; }
641 int NotMissMinorKey() {
642 return AllocationSiteModeBits::encode(allocation_site_mode_)
643 | ModeBits::encode(mode_)
644 | LengthBits::encode(length_);
649 class FastCloneShallowObjectStub : public HydrogenCodeStub {
651 // Maximum number of properties in copied object.
652 static const int kMaximumClonedProperties = 6;
654 explicit FastCloneShallowObjectStub(int length)
656 ASSERT_GE(length_, 0);
657 ASSERT_LE(length_, kMaximumClonedProperties);
660 int length() const { return length_; }
662 virtual Handle<Code> GenerateCode(Isolate* isolate);
664 virtual void InitializeInterfaceDescriptor(
666 CodeStubInterfaceDescriptor* descriptor);
671 Major MajorKey() { return FastCloneShallowObject; }
672 int NotMissMinorKey() { return length_; }
674 DISALLOW_COPY_AND_ASSIGN(FastCloneShallowObjectStub);
678 class CreateAllocationSiteStub : public HydrogenCodeStub {
680 explicit CreateAllocationSiteStub() { }
682 virtual Handle<Code> GenerateCode(Isolate* isolate);
684 static void GenerateAheadOfTime(Isolate* isolate);
686 virtual void InitializeInterfaceDescriptor(
688 CodeStubInterfaceDescriptor* descriptor);
691 Major MajorKey() { return CreateAllocationSite; }
692 int NotMissMinorKey() { return 0; }
694 DISALLOW_COPY_AND_ASSIGN(CreateAllocationSiteStub);
698 class InstanceofStub: public PlatformCodeStub {
702 kArgsInRegisters = 1 << 0,
703 kCallSiteInlineCheck = 1 << 1,
704 kReturnTrueFalseObject = 1 << 2
707 explicit InstanceofStub(Flags flags) : flags_(flags) { }
709 static Register left();
710 static Register right();
712 void Generate(MacroAssembler* masm);
715 Major MajorKey() { return Instanceof; }
716 int MinorKey() { return static_cast<int>(flags_); }
718 bool HasArgsInRegisters() const {
719 return (flags_ & kArgsInRegisters) != 0;
722 bool HasCallSiteInlineCheck() const {
723 return (flags_ & kCallSiteInlineCheck) != 0;
726 bool ReturnTrueFalseObject() const {
727 return (flags_ & kReturnTrueFalseObject) != 0;
730 virtual void PrintName(StringStream* stream);
736 enum AllocationSiteOverrideMode {
738 DISABLE_ALLOCATION_SITES,
739 LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
743 class ArrayConstructorStub: public PlatformCodeStub {
745 enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
746 ArrayConstructorStub(Isolate* isolate, int argument_count);
747 explicit ArrayConstructorStub(Isolate* isolate);
749 void Generate(MacroAssembler* masm);
752 void GenerateDispatchToArrayStub(MacroAssembler* masm,
753 AllocationSiteOverrideMode mode);
754 virtual void PrintName(StringStream* stream);
756 virtual CodeStub::Major MajorKey() { return ArrayConstructor; }
757 virtual int MinorKey() { return argument_count_; }
759 ArgumentCountKey argument_count_;
763 class InternalArrayConstructorStub: public PlatformCodeStub {
765 explicit InternalArrayConstructorStub(Isolate* isolate);
767 void Generate(MacroAssembler* masm);
770 virtual CodeStub::Major MajorKey() { return InternalArrayConstructor; }
771 virtual int MinorKey() { return 0; }
773 void GenerateCase(MacroAssembler* masm, ElementsKind kind);
777 class MathPowStub: public PlatformCodeStub {
779 enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK };
781 explicit MathPowStub(ExponentType exponent_type)
782 : exponent_type_(exponent_type) { }
783 virtual void Generate(MacroAssembler* masm);
786 virtual CodeStub::Major MajorKey() { return MathPow; }
787 virtual int MinorKey() { return exponent_type_; }
789 ExponentType exponent_type_;
793 class ICStub: public PlatformCodeStub {
795 explicit ICStub(Code::Kind kind) : kind_(kind) { }
796 virtual Code::Kind GetCodeKind() const { return kind_; }
797 virtual InlineCacheState GetICState() { return MONOMORPHIC; }
799 bool Describes(Code* code) {
800 return GetMajorKey(code) == MajorKey() && code->stub_info() == MinorKey();
804 class KindBits: public BitField<Code::Kind, 0, 4> {};
805 virtual void FinishCode(Handle<Code> code) {
806 code->set_stub_info(MinorKey());
808 Code::Kind kind() { return kind_; }
810 virtual int MinorKey() {
811 return KindBits::encode(kind_);
819 class FunctionPrototypeStub: public ICStub {
821 explicit FunctionPrototypeStub(Code::Kind kind) : ICStub(kind) { }
822 virtual void Generate(MacroAssembler* masm);
825 virtual CodeStub::Major MajorKey() { return FunctionPrototype; }
829 class StringLengthStub: public ICStub {
831 explicit StringLengthStub(Code::Kind kind) : ICStub(kind) { }
832 virtual void Generate(MacroAssembler* masm);
835 STATIC_ASSERT(KindBits::kSize == 4);
836 virtual CodeStub::Major MajorKey() { return StringLength; }
840 class StoreICStub: public ICStub {
842 StoreICStub(Code::Kind kind, StrictModeFlag strict_mode)
843 : ICStub(kind), strict_mode_(strict_mode) { }
846 virtual ExtraICState GetExtraICState() {
847 return StoreIC::ComputeExtraICState(strict_mode_);
851 STATIC_ASSERT(KindBits::kSize == 4);
852 class StrictModeBits: public BitField<bool, 4, 1> {};
853 virtual int MinorKey() {
854 return KindBits::encode(kind()) | StrictModeBits::encode(strict_mode_);
857 StrictModeFlag strict_mode_;
861 class StoreArrayLengthStub: public StoreICStub {
863 explicit StoreArrayLengthStub(Code::Kind kind, StrictModeFlag strict_mode)
864 : StoreICStub(kind, strict_mode) { }
865 virtual void Generate(MacroAssembler* masm);
868 virtual CodeStub::Major MajorKey() { return StoreArrayLength; }
872 class HICStub: public HydrogenCodeStub {
874 virtual Code::Kind GetCodeKind() const { return kind(); }
875 virtual InlineCacheState GetICState() { return MONOMORPHIC; }
878 class KindBits: public BitField<Code::Kind, 0, 4> {};
879 virtual Code::Kind kind() const = 0;
883 class HandlerStub: public HICStub {
885 virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
886 virtual int GetStubFlags() { return kind(); }
889 HandlerStub() : HICStub() { }
890 virtual int NotMissMinorKey() { return bit_field_; }
895 class LoadFieldStub: public HandlerStub {
897 LoadFieldStub(bool inobject, int index, Representation representation) {
898 Initialize(Code::LOAD_IC, inobject, index, representation);
901 virtual Handle<Code> GenerateCode(Isolate* isolate);
903 virtual void InitializeInterfaceDescriptor(
905 CodeStubInterfaceDescriptor* descriptor);
907 Representation representation() {
908 if (unboxed_double()) return Representation::Double();
909 return Representation::Tagged();
912 virtual Code::Kind kind() const {
913 return KindBits::decode(bit_field_);
917 return InobjectBits::decode(bit_field_);
921 int index = IndexBits::decode(bit_field_);
922 int offset = index * kPointerSize;
923 if (is_inobject()) return offset;
924 return FixedArray::kHeaderSize + offset;
927 bool unboxed_double() {
928 return UnboxedDoubleBits::decode(bit_field_);
931 virtual Code::StubType GetStubType() { return Code::FAST; }
934 LoadFieldStub() : HandlerStub() { }
936 void Initialize(Code::Kind kind,
939 Representation representation) {
940 bool unboxed_double = FLAG_track_double_fields && representation.IsDouble();
941 bit_field_ = KindBits::encode(kind)
942 | InobjectBits::encode(inobject)
943 | IndexBits::encode(index)
944 | UnboxedDoubleBits::encode(unboxed_double);
948 STATIC_ASSERT(KindBits::kSize == 4);
949 class InobjectBits: public BitField<bool, 4, 1> {};
950 class IndexBits: public BitField<int, 5, 11> {};
951 class UnboxedDoubleBits: public BitField<bool, 16, 1> {};
952 virtual CodeStub::Major MajorKey() { return LoadField; }
956 class StoreGlobalStub : public HandlerStub {
958 explicit StoreGlobalStub(bool is_constant) {
959 bit_field_ = IsConstantBits::encode(is_constant);
962 Handle<Code> GetCodeCopyFromTemplate(Isolate* isolate,
964 PropertyCell* cell) {
965 Handle<Code> code = CodeStub::GetCodeCopyFromTemplate(isolate);
966 // Replace the placeholder cell and global object map with the actual global
967 // cell and receiver map.
968 Map* cell_map = isolate->heap()->global_property_cell_map();
969 code->ReplaceNthObject(1, cell_map, cell);
970 code->ReplaceNthObject(1, isolate->heap()->meta_map(), receiver_map);
974 virtual Code::Kind kind() const { return Code::STORE_IC; }
976 virtual Handle<Code> GenerateCode(Isolate* isolate);
978 virtual void InitializeInterfaceDescriptor(
980 CodeStubInterfaceDescriptor* descriptor);
982 virtual ExtraICState GetExtraICState() { return bit_field_; }
985 return IsConstantBits::decode(bit_field_);
987 void set_is_constant(bool value) {
988 bit_field_ = IsConstantBits::update(bit_field_, value);
991 Representation representation() {
992 return Representation::FromKind(RepresentationBits::decode(bit_field_));
994 void set_representation(Representation r) {
995 bit_field_ = RepresentationBits::update(bit_field_, r.kind());
999 virtual int NotMissMinorKey() { return GetExtraICState(); }
1000 Major MajorKey() { return StoreGlobal; }
1002 class IsConstantBits: public BitField<bool, 0, 1> {};
1003 class RepresentationBits: public BitField<Representation::Kind, 1, 8> {};
1007 DISALLOW_COPY_AND_ASSIGN(StoreGlobalStub);
1011 class CallApiFunctionStub : public PlatformCodeStub {
1013 CallApiFunctionStub(bool restore_context,
1014 bool call_data_undefined,
1017 RestoreContextBits::encode(restore_context) |
1018 CallDataUndefinedBits::encode(call_data_undefined) |
1019 ArgumentBits::encode(argc);
1023 virtual void Generate(MacroAssembler* masm) V8_OVERRIDE;
1024 virtual Major MajorKey() V8_OVERRIDE { return CallApiFunction; }
1025 virtual int MinorKey() V8_OVERRIDE { return bit_field_; }
1027 class RestoreContextBits: public BitField<bool, 0, 1> {};
1028 class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
1029 class ArgumentBits: public BitField<int, 2, Code::kArgumentsBits> {};
1033 DISALLOW_COPY_AND_ASSIGN(CallApiFunctionStub);
1037 class CallApiGetterStub : public PlatformCodeStub {
1039 CallApiGetterStub() {}
1042 virtual void Generate(MacroAssembler* masm) V8_OVERRIDE;
1043 virtual Major MajorKey() V8_OVERRIDE { return CallApiGetter; }
1044 virtual int MinorKey() V8_OVERRIDE { return 0; }
1046 DISALLOW_COPY_AND_ASSIGN(CallApiGetterStub);
1050 class KeyedLoadFieldStub: public LoadFieldStub {
1052 KeyedLoadFieldStub(bool inobject, int index, Representation representation)
1054 Initialize(Code::KEYED_LOAD_IC, inobject, index, representation);
1057 virtual void InitializeInterfaceDescriptor(
1059 CodeStubInterfaceDescriptor* descriptor);
1061 virtual Handle<Code> GenerateCode(Isolate* isolate);
1064 virtual CodeStub::Major MajorKey() { return KeyedLoadField; }
1068 class BinaryOpICStub : public HydrogenCodeStub {
1070 BinaryOpICStub(Token::Value op, OverwriteMode mode)
1071 : HydrogenCodeStub(UNINITIALIZED), state_(op, mode) {}
1073 explicit BinaryOpICStub(const BinaryOpIC::State& state) : state_(state) {}
1075 static void GenerateAheadOfTime(Isolate* isolate);
1077 virtual void InitializeInterfaceDescriptor(
1078 Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1080 static void InstallDescriptors(Isolate* isolate);
1082 virtual Code::Kind GetCodeKind() const V8_OVERRIDE {
1083 return Code::BINARY_OP_IC;
1086 virtual InlineCacheState GetICState() V8_FINAL V8_OVERRIDE {
1087 return state_.GetICState();
1090 virtual ExtraICState GetExtraICState() V8_FINAL V8_OVERRIDE {
1091 return state_.GetExtraICState();
1094 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_FINAL V8_OVERRIDE {
1095 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1098 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
1100 const BinaryOpIC::State& state() const { return state_; }
1102 virtual void PrintState(StringStream* stream) V8_FINAL V8_OVERRIDE;
1104 virtual Major MajorKey() V8_OVERRIDE { return BinaryOpIC; }
1105 virtual int NotMissMinorKey() V8_FINAL V8_OVERRIDE {
1106 return GetExtraICState();
1109 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1110 static const int kLeft = 0;
1111 static const int kRight = 1;
1114 static void GenerateAheadOfTime(Isolate* isolate,
1115 const BinaryOpIC::State& state);
1117 BinaryOpIC::State state_;
1119 DISALLOW_COPY_AND_ASSIGN(BinaryOpICStub);
1123 class ArrayPushStub: public PlatformCodeStub {
1125 ArrayPushStub(ElementsKind kind, int argc) {
1126 bit_field_ = ElementsKindBits::encode(kind) | ArgcBits::encode(argc);
1129 void Generate(MacroAssembler* masm);
1132 int arguments_count() { return ArgcBits::decode(bit_field_); }
1133 ElementsKind elements_kind() {
1134 return ElementsKindBits::decode(bit_field_);
1137 virtual CodeStub::Major MajorKey() { return ArrayPush; }
1138 virtual int MinorKey() { return bit_field_; }
1140 class ElementsKindBits: public BitField<ElementsKind, 0, 3> {};
1141 class ArgcBits: public BitField<int, 3, Code::kArgumentsBits> {};
1147 // TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
1148 // call support for stubs in Hydrogen.
1149 class BinaryOpICWithAllocationSiteStub V8_FINAL : public PlatformCodeStub {
1151 explicit BinaryOpICWithAllocationSiteStub(const BinaryOpIC::State& state)
1154 static void GenerateAheadOfTime(Isolate* isolate);
1156 Handle<Code> GetCodeCopyFromTemplate(Isolate* isolate,
1157 Handle<AllocationSite> allocation_site) {
1158 Handle<Code> code = CodeStub::GetCodeCopyFromTemplate(isolate);
1159 // Replace the placeholder oddball with the actual allocation site.
1160 code->ReplaceNthObject(1, isolate->heap()->oddball_map(), *allocation_site);
1164 virtual Code::Kind GetCodeKind() const V8_OVERRIDE {
1165 return Code::BINARY_OP_IC;
1168 virtual InlineCacheState GetICState() V8_OVERRIDE {
1169 return state_.GetICState();
1172 virtual ExtraICState GetExtraICState() V8_OVERRIDE {
1173 return state_.GetExtraICState();
1176 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
1177 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1180 virtual void Generate(MacroAssembler* masm) V8_OVERRIDE;
1182 virtual void PrintState(StringStream* stream) V8_OVERRIDE;
1184 virtual Major MajorKey() V8_OVERRIDE { return BinaryOpICWithAllocationSite; }
1185 virtual int MinorKey() V8_OVERRIDE { return GetExtraICState(); }
1188 static void GenerateAheadOfTime(Isolate* isolate,
1189 const BinaryOpIC::State& state);
1191 BinaryOpIC::State state_;
1193 DISALLOW_COPY_AND_ASSIGN(BinaryOpICWithAllocationSiteStub);
1197 class BinaryOpWithAllocationSiteStub V8_FINAL : public BinaryOpICStub {
1199 BinaryOpWithAllocationSiteStub(Token::Value op, OverwriteMode mode)
1200 : BinaryOpICStub(op, mode) {}
1202 explicit BinaryOpWithAllocationSiteStub(const BinaryOpIC::State& state)
1203 : BinaryOpICStub(state) {}
1205 virtual void InitializeInterfaceDescriptor(
1206 Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1208 static void InstallDescriptors(Isolate* isolate);
1210 virtual Code::Kind GetCodeKind() const V8_FINAL V8_OVERRIDE {
1214 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
1216 virtual Major MajorKey() V8_OVERRIDE {
1217 return BinaryOpWithAllocationSite;
1220 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1221 static const int kAllocationSite = 0;
1222 static const int kLeft = 1;
1223 static const int kRight = 2;
1227 enum StringAddFlags {
1228 // Omit both parameter checks.
1229 STRING_ADD_CHECK_NONE = 0,
1230 // Check left parameter.
1231 STRING_ADD_CHECK_LEFT = 1 << 0,
1232 // Check right parameter.
1233 STRING_ADD_CHECK_RIGHT = 1 << 1,
1234 // Check both parameters.
1235 STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT
1239 class StringAddStub V8_FINAL : public HydrogenCodeStub {
1241 StringAddStub(StringAddFlags flags, PretenureFlag pretenure_flag)
1242 : bit_field_(StringAddFlagsBits::encode(flags) |
1243 PretenureFlagBits::encode(pretenure_flag)) {}
1245 StringAddFlags flags() const {
1246 return StringAddFlagsBits::decode(bit_field_);
1249 PretenureFlag pretenure_flag() const {
1250 return PretenureFlagBits::decode(bit_field_);
1253 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
1254 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1257 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
1259 virtual void InitializeInterfaceDescriptor(
1261 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1263 static void InstallDescriptors(Isolate* isolate);
1265 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1266 static const int kLeft = 0;
1267 static const int kRight = 1;
1270 class StringAddFlagsBits: public BitField<StringAddFlags, 0, 2> {};
1271 class PretenureFlagBits: public BitField<PretenureFlag, 2, 1> {};
1272 uint32_t bit_field_;
1274 virtual Major MajorKey() V8_OVERRIDE { return StringAdd; }
1275 virtual int NotMissMinorKey() V8_OVERRIDE { return bit_field_; }
1277 virtual void PrintBaseName(StringStream* stream) V8_OVERRIDE;
1279 DISALLOW_COPY_AND_ASSIGN(StringAddStub);
1283 class ICCompareStub: public PlatformCodeStub {
1285 ICCompareStub(Token::Value op,
1286 CompareIC::State left,
1287 CompareIC::State right,
1288 CompareIC::State handler)
1293 ASSERT(Token::IsCompareOp(op));
1296 virtual void Generate(MacroAssembler* masm);
1298 void set_known_map(Handle<Map> map) { known_map_ = map; }
1300 static void DecodeMinorKey(int minor_key,
1301 CompareIC::State* left_state,
1302 CompareIC::State* right_state,
1303 CompareIC::State* handler_state,
1306 virtual InlineCacheState GetICState();
1309 class OpField: public BitField<int, 0, 3> { };
1310 class LeftStateField: public BitField<int, 3, 4> { };
1311 class RightStateField: public BitField<int, 7, 4> { };
1312 class HandlerStateField: public BitField<int, 11, 4> { };
1314 virtual void FinishCode(Handle<Code> code) {
1315 code->set_stub_info(MinorKey());
1318 virtual CodeStub::Major MajorKey() { return CompareIC; }
1319 virtual int MinorKey();
1321 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_IC; }
1323 void GenerateSmis(MacroAssembler* masm);
1324 void GenerateNumbers(MacroAssembler* masm);
1325 void GenerateInternalizedStrings(MacroAssembler* masm);
1326 void GenerateStrings(MacroAssembler* masm);
1327 void GenerateUniqueNames(MacroAssembler* masm);
1328 void GenerateObjects(MacroAssembler* masm);
1329 void GenerateMiss(MacroAssembler* masm);
1330 void GenerateKnownObjects(MacroAssembler* masm);
1331 void GenerateGeneric(MacroAssembler* masm);
1333 bool strict() const { return op_ == Token::EQ_STRICT; }
1334 Condition GetCondition() const { return CompareIC::ComputeCondition(op_); }
1336 virtual void AddToSpecialCache(Handle<Code> new_object);
1337 virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate);
1338 virtual bool UseSpecialCache() { return state_ == CompareIC::KNOWN_OBJECT; }
1341 CompareIC::State left_;
1342 CompareIC::State right_;
1343 CompareIC::State state_;
1344 Handle<Map> known_map_;
1348 class CompareNilICStub : public HydrogenCodeStub {
1350 Type* GetType(Zone* zone, Handle<Map> map = Handle<Map>());
1351 Type* GetInputType(Zone* zone, Handle<Map> map);
1353 explicit CompareNilICStub(NilValue nil) : nil_value_(nil) { }
1355 CompareNilICStub(ExtraICState ic_state,
1356 InitializationState init_state = INITIALIZED)
1357 : HydrogenCodeStub(init_state),
1358 nil_value_(NilValueField::decode(ic_state)),
1359 state_(State(TypesField::decode(ic_state))) {
1362 static Handle<Code> GetUninitialized(Isolate* isolate,
1364 return CompareNilICStub(nil, UNINITIALIZED).GetCode(isolate);
1367 virtual void InitializeInterfaceDescriptor(
1369 CodeStubInterfaceDescriptor* descriptor);
1371 static void InitializeForIsolate(Isolate* isolate) {
1372 CompareNilICStub compare_stub(kNullValue, UNINITIALIZED);
1373 compare_stub.InitializeInterfaceDescriptor(
1375 isolate->code_stub_interface_descriptor(CodeStub::CompareNilIC));
1378 virtual InlineCacheState GetICState() {
1379 if (state_.Contains(GENERIC)) {
1381 } else if (state_.Contains(MONOMORPHIC_MAP)) {
1384 return PREMONOMORPHIC;
1388 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_NIL_IC; }
1390 virtual Handle<Code> GenerateCode(Isolate* isolate);
1392 virtual ExtraICState GetExtraICState() {
1393 return NilValueField::encode(nil_value_) |
1394 TypesField::encode(state_.ToIntegral());
1397 void UpdateStatus(Handle<Object> object);
1399 bool IsMonomorphic() const { return state_.Contains(MONOMORPHIC_MAP); }
1400 NilValue GetNilValue() const { return nil_value_; }
1401 void ClearState() { state_.RemoveAll(); }
1403 virtual void PrintState(StringStream* stream);
1404 virtual void PrintBaseName(StringStream* stream);
1407 friend class CompareNilIC;
1409 enum CompareNilType {
1417 // At most 6 different types can be distinguished, because the Code object
1418 // only has room for a single byte to hold a set and there are two more
1419 // boolean flags we need to store. :-P
1420 STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
1422 class State : public EnumSet<CompareNilType, byte> {
1424 State() : EnumSet<CompareNilType, byte>(0) { }
1425 explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
1427 void Print(StringStream* stream) const;
1430 CompareNilICStub(NilValue nil, InitializationState init_state)
1431 : HydrogenCodeStub(init_state), nil_value_(nil) { }
1433 class NilValueField : public BitField<NilValue, 0, 1> {};
1434 class TypesField : public BitField<byte, 1, NUMBER_OF_TYPES> {};
1436 virtual CodeStub::Major MajorKey() { return CompareNilIC; }
1437 virtual int NotMissMinorKey() { return GetExtraICState(); }
1439 NilValue nil_value_;
1442 DISALLOW_COPY_AND_ASSIGN(CompareNilICStub);
1446 class CEntryStub : public PlatformCodeStub {
1448 explicit CEntryStub(int result_size,
1449 SaveFPRegsMode save_doubles = kDontSaveFPRegs)
1450 : result_size_(result_size), save_doubles_(save_doubles) { }
1452 void Generate(MacroAssembler* masm);
1454 // The version of this stub that doesn't save doubles is generated ahead of
1455 // time, so it's OK to call it from other stubs that can't cope with GC during
1456 // their code generation. On machines that always have gp registers (x64) we
1457 // can generate both variants ahead of time.
1458 static void GenerateAheadOfTime(Isolate* isolate);
1461 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
1462 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1466 void GenerateCore(MacroAssembler* masm,
1467 Label* throw_normal_exception,
1468 Label* throw_termination_exception,
1469 Label* throw_out_of_memory_exception,
1471 bool always_allocate_scope);
1473 // Number of pointers/values returned.
1475 const int result_size_;
1476 SaveFPRegsMode save_doubles_;
1478 Major MajorKey() { return CEntry; }
1481 bool NeedsImmovableCode();
1485 class JSEntryStub : public PlatformCodeStub {
1489 void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
1492 void GenerateBody(MacroAssembler* masm, bool is_construct);
1495 Major MajorKey() { return JSEntry; }
1496 int MinorKey() { return 0; }
1498 virtual void FinishCode(Handle<Code> code);
1500 int handler_offset_;
1504 class JSConstructEntryStub : public JSEntryStub {
1506 JSConstructEntryStub() { }
1508 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
1511 int MinorKey() { return 1; }
1513 virtual void PrintName(StringStream* stream) {
1514 stream->Add("JSConstructEntryStub");
1519 class ArgumentsAccessStub: public PlatformCodeStub {
1523 NEW_NON_STRICT_FAST,
1524 NEW_NON_STRICT_SLOW,
1528 explicit ArgumentsAccessStub(Type type) : type_(type) { }
1533 Major MajorKey() { return ArgumentsAccess; }
1534 int MinorKey() { return type_; }
1536 void Generate(MacroAssembler* masm);
1537 void GenerateReadElement(MacroAssembler* masm);
1538 void GenerateNewStrict(MacroAssembler* masm);
1539 void GenerateNewNonStrictFast(MacroAssembler* masm);
1540 void GenerateNewNonStrictSlow(MacroAssembler* masm);
1542 virtual void PrintName(StringStream* stream);
1546 class RegExpExecStub: public PlatformCodeStub {
1548 RegExpExecStub() { }
1551 Major MajorKey() { return RegExpExec; }
1552 int MinorKey() { return 0; }
1554 void Generate(MacroAssembler* masm);
1558 class RegExpConstructResultStub V8_FINAL : public HydrogenCodeStub {
1560 RegExpConstructResultStub() { }
1562 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
1564 virtual void InitializeInterfaceDescriptor(
1566 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1568 virtual Major MajorKey() V8_OVERRIDE { return RegExpConstructResult; }
1569 virtual int NotMissMinorKey() V8_OVERRIDE { return 0; }
1571 static void InstallDescriptors(Isolate* isolate);
1573 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1574 static const int kLength = 0;
1575 static const int kIndex = 1;
1576 static const int kInput = 2;
1579 DISALLOW_COPY_AND_ASSIGN(RegExpConstructResultStub);
1583 class CallFunctionStub: public PlatformCodeStub {
1585 CallFunctionStub(int argc, CallFunctionFlags flags)
1586 : argc_(argc), flags_(flags) { }
1588 void Generate(MacroAssembler* masm);
1590 virtual void FinishCode(Handle<Code> code) {
1591 code->set_has_function_cache(RecordCallTarget());
1594 static int ExtractArgcFromMinorKey(int minor_key) {
1595 return ArgcBits::decode(minor_key);
1600 CallFunctionFlags flags_;
1602 virtual void PrintName(StringStream* stream);
1604 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
1605 class FlagBits: public BitField<CallFunctionFlags, 0, 2> {};
1606 class ArgcBits: public BitField<unsigned, 2, 32 - 2> {};
1608 Major MajorKey() { return CallFunction; }
1610 // Encode the parameters in a unique 32 bit value.
1611 return FlagBits::encode(flags_) | ArgcBits::encode(argc_);
1614 bool RecordCallTarget() {
1615 return flags_ == RECORD_CALL_TARGET;
1618 bool CallAsMethod() {
1619 return flags_ == CALL_AS_METHOD || flags_ == WRAP_AND_CALL;
1622 bool NeedsChecks() {
1623 return flags_ != WRAP_AND_CALL;
1628 class CallConstructStub: public PlatformCodeStub {
1630 explicit CallConstructStub(CallFunctionFlags flags) : flags_(flags) {}
1632 void Generate(MacroAssembler* masm);
1634 virtual void FinishCode(Handle<Code> code) {
1635 code->set_has_function_cache(RecordCallTarget());
1639 CallFunctionFlags flags_;
1641 virtual void PrintName(StringStream* stream);
1643 Major MajorKey() { return CallConstruct; }
1644 int MinorKey() { return flags_; }
1646 bool RecordCallTarget() {
1647 return (flags_ & RECORD_CALL_TARGET) != 0;
1650 bool CallAsMethod() {
1651 return (flags_ & CALL_AS_METHOD) != 0;
1656 enum StringIndexFlags {
1657 // Accepts smis or heap numbers.
1658 STRING_INDEX_IS_NUMBER,
1660 // Accepts smis or heap numbers that are valid array indices
1661 // (ECMA-262 15.4). Invalid indices are reported as being out of
1663 STRING_INDEX_IS_ARRAY_INDEX
1667 // Generates code implementing String.prototype.charCodeAt.
1669 // Only supports the case when the receiver is a string and the index
1670 // is a number (smi or heap number) that is a valid index into the
1671 // string. Additional index constraints are specified by the
1672 // flags. Otherwise, bails out to the provided labels.
1674 // Register usage: |object| may be changed to another string in a way
1675 // that doesn't affect charCodeAt/charAt semantics, |index| is
1676 // preserved, |scratch| and |result| are clobbered.
1677 class StringCharCodeAtGenerator {
1679 StringCharCodeAtGenerator(Register object,
1682 Label* receiver_not_string,
1683 Label* index_not_number,
1684 Label* index_out_of_range,
1685 StringIndexFlags index_flags)
1689 receiver_not_string_(receiver_not_string),
1690 index_not_number_(index_not_number),
1691 index_out_of_range_(index_out_of_range),
1692 index_flags_(index_flags) {
1693 ASSERT(!result_.is(object_));
1694 ASSERT(!result_.is(index_));
1697 // Generates the fast case code. On the fallthrough path |result|
1698 // register contains the result.
1699 void GenerateFast(MacroAssembler* masm);
1701 // Generates the slow case code. Must not be naturally
1702 // reachable. Expected to be put after a ret instruction (e.g., in
1703 // deferred code). Always jumps back to the fast case.
1704 void GenerateSlow(MacroAssembler* masm,
1705 const RuntimeCallHelper& call_helper);
1707 // Skip handling slow case and directly jump to bailout.
1708 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1709 masm->bind(&index_not_smi_);
1710 masm->bind(&call_runtime_);
1719 Label* receiver_not_string_;
1720 Label* index_not_number_;
1721 Label* index_out_of_range_;
1723 StringIndexFlags index_flags_;
1725 Label call_runtime_;
1726 Label index_not_smi_;
1727 Label got_smi_index_;
1730 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
1734 // Generates code for creating a one-char string from a char code.
1735 class StringCharFromCodeGenerator {
1737 StringCharFromCodeGenerator(Register code,
1741 ASSERT(!code_.is(result_));
1744 // Generates the fast case code. On the fallthrough path |result|
1745 // register contains the result.
1746 void GenerateFast(MacroAssembler* masm);
1748 // Generates the slow case code. Must not be naturally
1749 // reachable. Expected to be put after a ret instruction (e.g., in
1750 // deferred code). Always jumps back to the fast case.
1751 void GenerateSlow(MacroAssembler* masm,
1752 const RuntimeCallHelper& call_helper);
1754 // Skip handling slow case and directly jump to bailout.
1755 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1756 masm->bind(&slow_case_);
1767 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
1771 // Generates code implementing String.prototype.charAt.
1773 // Only supports the case when the receiver is a string and the index
1774 // is a number (smi or heap number) that is a valid index into the
1775 // string. Additional index constraints are specified by the
1776 // flags. Otherwise, bails out to the provided labels.
1778 // Register usage: |object| may be changed to another string in a way
1779 // that doesn't affect charCodeAt/charAt semantics, |index| is
1780 // preserved, |scratch1|, |scratch2|, and |result| are clobbered.
1781 class StringCharAtGenerator {
1783 StringCharAtGenerator(Register object,
1787 Label* receiver_not_string,
1788 Label* index_not_number,
1789 Label* index_out_of_range,
1790 StringIndexFlags index_flags)
1791 : char_code_at_generator_(object,
1794 receiver_not_string,
1798 char_from_code_generator_(scratch, result) {}
1800 // Generates the fast case code. On the fallthrough path |result|
1801 // register contains the result.
1802 void GenerateFast(MacroAssembler* masm) {
1803 char_code_at_generator_.GenerateFast(masm);
1804 char_from_code_generator_.GenerateFast(masm);
1807 // Generates the slow case code. Must not be naturally
1808 // reachable. Expected to be put after a ret instruction (e.g., in
1809 // deferred code). Always jumps back to the fast case.
1810 void GenerateSlow(MacroAssembler* masm,
1811 const RuntimeCallHelper& call_helper) {
1812 char_code_at_generator_.GenerateSlow(masm, call_helper);
1813 char_from_code_generator_.GenerateSlow(masm, call_helper);
1816 // Skip handling slow case and directly jump to bailout.
1817 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1818 char_code_at_generator_.SkipSlow(masm, bailout);
1819 char_from_code_generator_.SkipSlow(masm, bailout);
1823 StringCharCodeAtGenerator char_code_at_generator_;
1824 StringCharFromCodeGenerator char_from_code_generator_;
1826 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
1830 class KeyedLoadDictionaryElementStub : public HydrogenCodeStub {
1832 KeyedLoadDictionaryElementStub() {}
1834 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
1836 virtual void InitializeInterfaceDescriptor(
1838 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1841 Major MajorKey() { return KeyedLoadElement; }
1842 int NotMissMinorKey() { return DICTIONARY_ELEMENTS; }
1844 DISALLOW_COPY_AND_ASSIGN(KeyedLoadDictionaryElementStub);
1848 class KeyedLoadDictionaryElementPlatformStub : public PlatformCodeStub {
1850 KeyedLoadDictionaryElementPlatformStub() {}
1852 void Generate(MacroAssembler* masm);
1855 Major MajorKey() { return KeyedLoadElement; }
1856 int MinorKey() { return DICTIONARY_ELEMENTS; }
1858 DISALLOW_COPY_AND_ASSIGN(KeyedLoadDictionaryElementPlatformStub);
1862 class DoubleToIStub : public PlatformCodeStub {
1864 DoubleToIStub(Register source,
1865 Register destination,
1868 bool skip_fastpath = false) : bit_field_(0) {
1869 bit_field_ = SourceRegisterBits::encode(source.code_) |
1870 DestinationRegisterBits::encode(destination.code_) |
1871 OffsetBits::encode(offset) |
1872 IsTruncatingBits::encode(is_truncating) |
1873 SkipFastPathBits::encode(skip_fastpath) |
1874 SSEBits::encode(CpuFeatures::IsSafeForSnapshot(SSE2) ?
1875 CpuFeatures::IsSafeForSnapshot(SSE3) ? 2 : 1 : 0);
1879 Register result = { SourceRegisterBits::decode(bit_field_) };
1883 Register destination() {
1884 Register result = { DestinationRegisterBits::decode(bit_field_) };
1888 bool is_truncating() {
1889 return IsTruncatingBits::decode(bit_field_);
1892 bool skip_fastpath() {
1893 return SkipFastPathBits::decode(bit_field_);
1897 return OffsetBits::decode(bit_field_);
1900 void Generate(MacroAssembler* masm);
1902 virtual bool SometimesSetsUpAFrame() { return false; }
1905 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
1906 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1910 static const int kBitsPerRegisterNumber = 6;
1911 STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
1912 class SourceRegisterBits:
1913 public BitField<int, 0, kBitsPerRegisterNumber> {}; // NOLINT
1914 class DestinationRegisterBits:
1915 public BitField<int, kBitsPerRegisterNumber,
1916 kBitsPerRegisterNumber> {}; // NOLINT
1917 class IsTruncatingBits:
1918 public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {}; // NOLINT
1920 public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {}; // NOLINT
1921 class SkipFastPathBits:
1922 public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {}; // NOLINT
1924 public BitField<int, 2 * kBitsPerRegisterNumber + 5, 2> {}; // NOLINT
1926 Major MajorKey() { return DoubleToI; }
1927 int MinorKey() { return bit_field_; }
1931 DISALLOW_COPY_AND_ASSIGN(DoubleToIStub);
1935 class KeyedLoadFastElementStub : public HydrogenCodeStub {
1937 KeyedLoadFastElementStub(bool is_js_array, ElementsKind elements_kind) {
1938 bit_field_ = ElementsKindBits::encode(elements_kind) |
1939 IsJSArrayBits::encode(is_js_array);
1942 bool is_js_array() const {
1943 return IsJSArrayBits::decode(bit_field_);
1946 ElementsKind elements_kind() const {
1947 return ElementsKindBits::decode(bit_field_);
1950 virtual Handle<Code> GenerateCode(Isolate* isolate);
1952 virtual void InitializeInterfaceDescriptor(
1954 CodeStubInterfaceDescriptor* descriptor);
1957 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
1958 class IsJSArrayBits: public BitField<bool, 8, 1> {};
1959 uint32_t bit_field_;
1961 Major MajorKey() { return KeyedLoadElement; }
1962 int NotMissMinorKey() { return bit_field_; }
1964 DISALLOW_COPY_AND_ASSIGN(KeyedLoadFastElementStub);
1968 class KeyedStoreFastElementStub : public HydrogenCodeStub {
1970 KeyedStoreFastElementStub(bool is_js_array,
1971 ElementsKind elements_kind,
1972 KeyedAccessStoreMode mode) {
1973 bit_field_ = ElementsKindBits::encode(elements_kind) |
1974 IsJSArrayBits::encode(is_js_array) |
1975 StoreModeBits::encode(mode);
1978 bool is_js_array() const {
1979 return IsJSArrayBits::decode(bit_field_);
1982 ElementsKind elements_kind() const {
1983 return ElementsKindBits::decode(bit_field_);
1986 KeyedAccessStoreMode store_mode() const {
1987 return StoreModeBits::decode(bit_field_);
1990 virtual Handle<Code> GenerateCode(Isolate* isolate);
1992 virtual void InitializeInterfaceDescriptor(
1994 CodeStubInterfaceDescriptor* descriptor);
1997 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
1998 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
1999 class IsJSArrayBits: public BitField<bool, 12, 1> {};
2000 uint32_t bit_field_;
2002 Major MajorKey() { return KeyedStoreElement; }
2003 int NotMissMinorKey() { return bit_field_; }
2005 DISALLOW_COPY_AND_ASSIGN(KeyedStoreFastElementStub);
2009 class TransitionElementsKindStub : public HydrogenCodeStub {
2011 TransitionElementsKindStub(ElementsKind from_kind,
2012 ElementsKind to_kind) {
2013 bit_field_ = FromKindBits::encode(from_kind) |
2014 ToKindBits::encode(to_kind);
2017 ElementsKind from_kind() const {
2018 return FromKindBits::decode(bit_field_);
2021 ElementsKind to_kind() const {
2022 return ToKindBits::decode(bit_field_);
2025 virtual Handle<Code> GenerateCode(Isolate* isolate);
2027 virtual void InitializeInterfaceDescriptor(
2029 CodeStubInterfaceDescriptor* descriptor);
2032 class FromKindBits: public BitField<ElementsKind, 8, 8> {};
2033 class ToKindBits: public BitField<ElementsKind, 0, 8> {};
2034 uint32_t bit_field_;
2036 Major MajorKey() { return TransitionElementsKind; }
2037 int NotMissMinorKey() { return bit_field_; }
2039 DISALLOW_COPY_AND_ASSIGN(TransitionElementsKindStub);
2043 class ArrayConstructorStubBase : public HydrogenCodeStub {
2045 ArrayConstructorStubBase(ElementsKind kind,
2046 AllocationSiteOverrideMode override_mode) {
2047 // It only makes sense to override local allocation site behavior
2048 // if there is a difference between the global allocation site policy
2049 // for an ElementsKind and the desired usage of the stub.
2050 ASSERT(override_mode != DISABLE_ALLOCATION_SITES ||
2051 AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
2052 bit_field_ = ElementsKindBits::encode(kind) |
2053 AllocationSiteOverrideModeBits::encode(override_mode);
2056 ElementsKind elements_kind() const {
2057 return ElementsKindBits::decode(bit_field_);
2060 AllocationSiteOverrideMode override_mode() const {
2061 return AllocationSiteOverrideModeBits::decode(bit_field_);
2064 static void GenerateStubsAheadOfTime(Isolate* isolate);
2065 static void InstallDescriptors(Isolate* isolate);
2067 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2068 static const int kConstructor = 0;
2069 static const int kAllocationSite = 1;
2072 void BasePrintName(const char* name, StringStream* stream);
2075 int NotMissMinorKey() { return bit_field_; }
2077 // Ensure data fits within available bits.
2078 STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
2080 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2081 class AllocationSiteOverrideModeBits: public
2082 BitField<AllocationSiteOverrideMode, 8, 1> {}; // NOLINT
2083 uint32_t bit_field_;
2085 DISALLOW_COPY_AND_ASSIGN(ArrayConstructorStubBase);
2089 class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
2091 ArrayNoArgumentConstructorStub(
2093 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2094 : ArrayConstructorStubBase(kind, override_mode) {
2097 virtual Handle<Code> GenerateCode(Isolate* isolate);
2099 virtual void InitializeInterfaceDescriptor(
2101 CodeStubInterfaceDescriptor* descriptor);
2104 Major MajorKey() { return ArrayNoArgumentConstructor; }
2106 virtual void PrintName(StringStream* stream) {
2107 BasePrintName("ArrayNoArgumentConstructorStub", stream);
2110 DISALLOW_COPY_AND_ASSIGN(ArrayNoArgumentConstructorStub);
2114 class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
2116 ArraySingleArgumentConstructorStub(
2118 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2119 : ArrayConstructorStubBase(kind, override_mode) {
2122 virtual Handle<Code> GenerateCode(Isolate* isolate);
2124 virtual void InitializeInterfaceDescriptor(
2126 CodeStubInterfaceDescriptor* descriptor);
2129 Major MajorKey() { return ArraySingleArgumentConstructor; }
2131 virtual void PrintName(StringStream* stream) {
2132 BasePrintName("ArraySingleArgumentConstructorStub", stream);
2135 DISALLOW_COPY_AND_ASSIGN(ArraySingleArgumentConstructorStub);
2139 class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
2141 ArrayNArgumentsConstructorStub(
2143 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2144 : ArrayConstructorStubBase(kind, override_mode) {
2147 virtual Handle<Code> GenerateCode(Isolate* isolate);
2149 virtual void InitializeInterfaceDescriptor(
2151 CodeStubInterfaceDescriptor* descriptor);
2154 Major MajorKey() { return ArrayNArgumentsConstructor; }
2156 virtual void PrintName(StringStream* stream) {
2157 BasePrintName("ArrayNArgumentsConstructorStub", stream);
2160 DISALLOW_COPY_AND_ASSIGN(ArrayNArgumentsConstructorStub);
2164 class InternalArrayConstructorStubBase : public HydrogenCodeStub {
2166 explicit InternalArrayConstructorStubBase(ElementsKind kind) {
2170 static void GenerateStubsAheadOfTime(Isolate* isolate);
2171 static void InstallDescriptors(Isolate* isolate);
2173 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2174 static const int kConstructor = 0;
2176 ElementsKind elements_kind() const { return kind_; }
2179 int NotMissMinorKey() { return kind_; }
2183 DISALLOW_COPY_AND_ASSIGN(InternalArrayConstructorStubBase);
2187 class InternalArrayNoArgumentConstructorStub : public
2188 InternalArrayConstructorStubBase {
2190 explicit InternalArrayNoArgumentConstructorStub(ElementsKind kind)
2191 : InternalArrayConstructorStubBase(kind) { }
2193 virtual Handle<Code> GenerateCode(Isolate* isolate);
2195 virtual void InitializeInterfaceDescriptor(
2197 CodeStubInterfaceDescriptor* descriptor);
2200 Major MajorKey() { return InternalArrayNoArgumentConstructor; }
2202 DISALLOW_COPY_AND_ASSIGN(InternalArrayNoArgumentConstructorStub);
2206 class InternalArraySingleArgumentConstructorStub : public
2207 InternalArrayConstructorStubBase {
2209 explicit InternalArraySingleArgumentConstructorStub(ElementsKind kind)
2210 : InternalArrayConstructorStubBase(kind) { }
2212 virtual Handle<Code> GenerateCode(Isolate* isolate);
2214 virtual void InitializeInterfaceDescriptor(
2216 CodeStubInterfaceDescriptor* descriptor);
2219 Major MajorKey() { return InternalArraySingleArgumentConstructor; }
2221 DISALLOW_COPY_AND_ASSIGN(InternalArraySingleArgumentConstructorStub);
2225 class InternalArrayNArgumentsConstructorStub : public
2226 InternalArrayConstructorStubBase {
2228 explicit InternalArrayNArgumentsConstructorStub(ElementsKind kind)
2229 : InternalArrayConstructorStubBase(kind) { }
2231 virtual Handle<Code> GenerateCode(Isolate* isolate);
2233 virtual void InitializeInterfaceDescriptor(
2235 CodeStubInterfaceDescriptor* descriptor);
2238 Major MajorKey() { return InternalArrayNArgumentsConstructor; }
2240 DISALLOW_COPY_AND_ASSIGN(InternalArrayNArgumentsConstructorStub);
2244 class KeyedStoreElementStub : public PlatformCodeStub {
2246 KeyedStoreElementStub(bool is_js_array,
2247 ElementsKind elements_kind,
2248 KeyedAccessStoreMode store_mode)
2249 : is_js_array_(is_js_array),
2250 elements_kind_(elements_kind),
2251 store_mode_(store_mode),
2252 fp_registers_(CanUseFPRegisters()) { }
2254 Major MajorKey() { return KeyedStoreElement; }
2256 return ElementsKindBits::encode(elements_kind_) |
2257 IsJSArrayBits::encode(is_js_array_) |
2258 StoreModeBits::encode(store_mode_) |
2259 FPRegisters::encode(fp_registers_);
2262 void Generate(MacroAssembler* masm);
2265 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2266 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
2267 class IsJSArrayBits: public BitField<bool, 12, 1> {};
2268 class FPRegisters: public BitField<bool, 13, 1> {};
2271 ElementsKind elements_kind_;
2272 KeyedAccessStoreMode store_mode_;
2275 DISALLOW_COPY_AND_ASSIGN(KeyedStoreElementStub);
2279 class ToBooleanStub: public HydrogenCodeStub {
2293 // At most 8 different types can be distinguished, because the Code object
2294 // only has room for a single byte to hold a set of these types. :-P
2295 STATIC_ASSERT(NUMBER_OF_TYPES <= 8);
2297 class Types : public EnumSet<Type, byte> {
2299 Types() : EnumSet<Type, byte>(0) {}
2300 explicit Types(byte bits) : EnumSet<Type, byte>(bits) {}
2302 byte ToByte() const { return ToIntegral(); }
2303 void Print(StringStream* stream) const;
2304 bool UpdateStatus(Handle<Object> object);
2305 bool NeedsMap() const;
2306 bool CanBeUndetectable() const;
2307 bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
2309 static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
2312 explicit ToBooleanStub(Types types = Types())
2314 explicit ToBooleanStub(ExtraICState state)
2315 : types_(static_cast<byte>(state)) { }
2317 bool UpdateStatus(Handle<Object> object);
2318 Types GetTypes() { return types_; }
2320 virtual Handle<Code> GenerateCode(Isolate* isolate);
2321 virtual void InitializeInterfaceDescriptor(
2323 CodeStubInterfaceDescriptor* descriptor);
2325 virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; }
2326 virtual void PrintState(StringStream* stream);
2328 virtual bool SometimesSetsUpAFrame() { return false; }
2330 static void InitializeForIsolate(Isolate* isolate) {
2332 stub.InitializeInterfaceDescriptor(
2334 isolate->code_stub_interface_descriptor(CodeStub::ToBoolean));
2337 static Handle<Code> GetUninitialized(Isolate* isolate) {
2338 return ToBooleanStub(UNINITIALIZED).GetCode(isolate);
2341 virtual ExtraICState GetExtraICState() {
2342 return types_.ToIntegral();
2345 virtual InlineCacheState GetICState() {
2346 if (types_.IsEmpty()) {
2347 return ::v8::internal::UNINITIALIZED;
2354 Major MajorKey() { return ToBoolean; }
2355 int NotMissMinorKey() { return GetExtraICState(); }
2357 explicit ToBooleanStub(InitializationState init_state) :
2358 HydrogenCodeStub(init_state) {}
2364 class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
2366 ElementsTransitionAndStoreStub(ElementsKind from_kind,
2367 ElementsKind to_kind,
2369 KeyedAccessStoreMode store_mode)
2370 : from_kind_(from_kind),
2372 is_jsarray_(is_jsarray),
2373 store_mode_(store_mode) {}
2375 ElementsKind from_kind() const { return from_kind_; }
2376 ElementsKind to_kind() const { return to_kind_; }
2377 bool is_jsarray() const { return is_jsarray_; }
2378 KeyedAccessStoreMode store_mode() const { return store_mode_; }
2380 virtual Handle<Code> GenerateCode(Isolate* isolate);
2382 void InitializeInterfaceDescriptor(
2384 CodeStubInterfaceDescriptor* descriptor);
2387 class FromBits: public BitField<ElementsKind, 0, 8> {};
2388 class ToBits: public BitField<ElementsKind, 8, 8> {};
2389 class IsJSArrayBits: public BitField<bool, 16, 1> {};
2390 class StoreModeBits: public BitField<KeyedAccessStoreMode, 17, 4> {};
2392 Major MajorKey() { return ElementsTransitionAndStore; }
2393 int NotMissMinorKey() {
2394 return FromBits::encode(from_kind_) |
2395 ToBits::encode(to_kind_) |
2396 IsJSArrayBits::encode(is_jsarray_) |
2397 StoreModeBits::encode(store_mode_);
2400 ElementsKind from_kind_;
2401 ElementsKind to_kind_;
2403 KeyedAccessStoreMode store_mode_;
2405 DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub);
2409 class StoreArrayLiteralElementStub : public PlatformCodeStub {
2411 StoreArrayLiteralElementStub()
2412 : fp_registers_(CanUseFPRegisters()) { }
2415 class FPRegisters: public BitField<bool, 0, 1> {};
2417 Major MajorKey() { return StoreArrayLiteralElement; }
2418 int MinorKey() { return FPRegisters::encode(fp_registers_); }
2420 void Generate(MacroAssembler* masm);
2424 DISALLOW_COPY_AND_ASSIGN(StoreArrayLiteralElementStub);
2428 class StubFailureTrampolineStub : public PlatformCodeStub {
2430 explicit StubFailureTrampolineStub(StubFunctionMode function_mode)
2431 : fp_registers_(CanUseFPRegisters()), function_mode_(function_mode) {}
2433 static void GenerateAheadOfTime(Isolate* isolate);
2436 class FPRegisters: public BitField<bool, 0, 1> {};
2437 class FunctionModeField: public BitField<StubFunctionMode, 1, 1> {};
2439 Major MajorKey() { return StubFailureTrampoline; }
2441 return FPRegisters::encode(fp_registers_) |
2442 FunctionModeField::encode(function_mode_);
2445 void Generate(MacroAssembler* masm);
2448 StubFunctionMode function_mode_;
2450 DISALLOW_COPY_AND_ASSIGN(StubFailureTrampolineStub);
2454 class ProfileEntryHookStub : public PlatformCodeStub {
2456 explicit ProfileEntryHookStub() {}
2458 // The profile entry hook function is not allowed to cause a GC.
2459 virtual bool SometimesSetsUpAFrame() { return false; }
2461 // Generates a call to the entry hook if it's enabled.
2462 static void MaybeCallEntryHook(MacroAssembler* masm);
2465 static void EntryHookTrampoline(intptr_t function,
2466 intptr_t stack_pointer,
2469 Major MajorKey() { return ProfileEntryHook; }
2470 int MinorKey() { return 0; }
2472 void Generate(MacroAssembler* masm);
2474 DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub);
2478 class CallDescriptors {
2480 static void InitializeForIsolate(Isolate* isolate);
2483 } } // namespace v8::internal
2485 #endif // V8_CODE_STUBS_H_