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) \
54 V(FunctionPrototype) \
56 V(StoreBufferOverflow) \
60 V(WriteInt32ToHeapNumber) \
65 V(FastCloneShallowArray) \
66 V(FastCloneShallowObject) \
67 V(CreateAllocationSite) \
71 V(RegExpConstructResult) \
78 V(ArrayNoArgumentConstructor) \
79 V(ArraySingleArgumentConstructor) \
80 V(ArrayNArgumentsConstructor) \
81 V(InternalArrayNoArgumentConstructor) \
82 V(InternalArraySingleArgumentConstructor) \
83 V(InternalArrayNArgumentsConstructor) \
84 V(KeyedStoreElement) \
85 V(DebuggerStatement) \
86 V(NameDictionaryLookup) \
87 V(ElementsTransitionAndStore) \
88 V(TransitionElementsKind) \
89 V(StoreArrayLiteralElement) \
90 V(StubFailureTrampoline) \
92 V(InternalArrayConstructor) \
97 /* IC Handler stubs */ \
103 // List of code stubs only used on ARM 32 bits 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 ARM 64 bits platforms.
115 #if V8_TARGET_ARCH_ARM64
116 #define CODE_STUB_LIST_ARM64(V) \
121 V(StoreRegistersState) \
122 V(RestoreRegistersState)
124 #define CODE_STUB_LIST_ARM64(V)
127 // List of code stubs only used on MIPS platforms.
128 #if V8_TARGET_ARCH_MIPS
129 #define CODE_STUB_LIST_MIPS(V) \
132 V(StoreRegistersState) \
133 V(RestoreRegistersState)
135 #define CODE_STUB_LIST_MIPS(V)
138 // Combined list of code stubs.
139 #define CODE_STUB_LIST(V) \
140 CODE_STUB_LIST_ALL_PLATFORMS(V) \
141 CODE_STUB_LIST_ARM(V) \
142 CODE_STUB_LIST_ARM64(V) \
143 CODE_STUB_LIST_MIPS(V)
145 // Stub is base classes of all stubs.
146 class CodeStub BASE_EMBEDDED {
149 UninitializedMajorKey = 0,
150 #define DEF_ENUM(name) name,
151 CODE_STUB_LIST(DEF_ENUM)
153 NoCache, // marker for stubs that do custom caching
157 // Retrieve the code for the stub. Generate the code if needed.
158 Handle<Code> GetCode(Isolate* isolate);
160 // Retrieve the code for the stub, make and return a copy of the code.
161 Handle<Code> GetCodeCopy(
162 Isolate* isolate, const Code::FindAndReplacePattern& pattern);
164 static Major MajorKeyFromKey(uint32_t key) {
165 return static_cast<Major>(MajorKeyBits::decode(key));
167 static int MinorKeyFromKey(uint32_t key) {
168 return MinorKeyBits::decode(key);
171 // Gets the major key from a code object that is a code stub or binary op IC.
172 static Major GetMajorKey(Code* code_stub) {
173 return static_cast<Major>(code_stub->major_key());
176 static const char* MajorName(Major major_key, bool allow_unknown_keys);
178 virtual ~CodeStub() {}
180 static void GenerateStubsAheadOfTime(Isolate* isolate);
181 static void GenerateFPStubs(Isolate* isolate);
183 // Some stubs put untagged junk on the stack that cannot be scanned by the
184 // GC. This means that we must be statically sure that no GC can occur while
185 // they are running. If that is the case they should override this to return
186 // true, which will cause an assertion if we try to call something that can
187 // GC or if we try to put a stack frame on top of the junk, which would not
188 // result in a traversable stack.
189 virtual bool SometimesSetsUpAFrame() { return true; }
191 // Lookup the code in the (possibly custom) cache.
192 bool FindCodeInCache(Code** code_out, Isolate* isolate);
194 // Returns information for computing the number key.
195 virtual Major MajorKey() = 0;
196 virtual int MinorKey() = 0;
198 virtual InlineCacheState GetICState() {
199 return UNINITIALIZED;
201 virtual ExtraICState GetExtraICState() {
202 return kNoExtraICState;
204 virtual Code::StubType GetStubType() {
208 virtual void PrintName(StringStream* stream);
210 // Returns a name for logging/debugging purposes.
211 SmartArrayPointer<const char> GetName();
214 static bool CanUseFPRegisters();
216 // Generates the assembler code for the stub.
217 virtual Handle<Code> GenerateCode(Isolate* isolate) = 0;
219 virtual void VerifyPlatformFeatures(Isolate* isolate);
221 // Returns whether the code generated for this stub needs to be allocated as
222 // a fixed (non-moveable) code object.
223 virtual bool NeedsImmovableCode() { return false; }
225 virtual void PrintBaseName(StringStream* stream);
226 virtual void PrintState(StringStream* stream) { }
229 // Perform bookkeeping required after code generation when stub code is
230 // initially generated.
231 void RecordCodeGeneration(Code* code, Isolate* isolate);
233 // Finish the code object after it has been generated.
234 virtual void FinishCode(Handle<Code> code) { }
236 // Activate newly generated stub. Is called after
237 // registering stub in the stub cache.
238 virtual void Activate(Code* code) { }
240 // BinaryOpStub needs to override this.
241 virtual Code::Kind GetCodeKind() const;
243 // Add the code to a specialized cache, specific to an individual
244 // stub type. Please note, this method must add the code object to a
245 // roots object, otherwise we will remove the code during GC.
246 virtual void AddToSpecialCache(Handle<Code> new_object) { }
248 // Find code in a specialized cache, work is delegated to the specific stub.
249 virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate) {
253 // If a stub uses a special cache override this.
254 virtual bool UseSpecialCache() { return false; }
256 // Computes the key based on major and minor.
258 ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
259 return MinorKeyBits::encode(MinorKey()) |
260 MajorKeyBits::encode(MajorKey());
263 STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
264 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
265 class MinorKeyBits: public BitField<uint32_t,
266 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT
268 friend class BreakPointIterator;
272 class PlatformCodeStub : public CodeStub {
274 // Retrieve the code for the stub. Generate the code if needed.
275 virtual Handle<Code> GenerateCode(Isolate* isolate);
277 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
280 // Generates the assembler code for the stub.
281 virtual void Generate(MacroAssembler* masm) = 0;
285 enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
286 enum HandlerArgumentsMode { DONT_PASS_ARGUMENTS, PASS_ARGUMENTS };
288 struct CodeStubInterfaceDescriptor {
289 CodeStubInterfaceDescriptor();
290 int register_param_count_;
292 Register stack_parameter_count_;
293 // if hint_stack_parameter_count_ > 0, the code stub can optimize the
294 // return sequence. Default value is -1, which means it is ignored.
295 int hint_stack_parameter_count_;
296 StubFunctionMode function_mode_;
297 Register* register_params_;
299 Address deoptimization_handler_;
300 HandlerArgumentsMode handler_arguments_mode_;
302 bool initialized() const { return register_param_count_ >= 0; }
304 int environment_length() const {
305 return register_param_count_;
308 void SetMissHandler(ExternalReference handler) {
309 miss_handler_ = handler;
310 has_miss_handler_ = true;
311 // Our miss handler infrastructure doesn't currently support
312 // variable stack parameter counts.
313 ASSERT(!stack_parameter_count_.is_valid());
316 ExternalReference miss_handler() {
317 ASSERT(has_miss_handler_);
318 return miss_handler_;
321 bool has_miss_handler() {
322 return has_miss_handler_;
325 Register GetParameterRegister(int index) const {
326 return register_params_[index];
329 bool IsParameterCountRegister(int index) {
330 return GetParameterRegister(index).is(stack_parameter_count_);
333 int GetHandlerParameterCount() {
334 int params = environment_length();
335 if (handler_arguments_mode_ == PASS_ARGUMENTS) {
342 ExternalReference miss_handler_;
343 bool has_miss_handler_;
347 struct PlatformCallInterfaceDescriptor;
350 struct CallInterfaceDescriptor {
351 CallInterfaceDescriptor()
352 : register_param_count_(-1),
353 register_params_(NULL),
354 param_representations_(NULL),
355 platform_specific_descriptor_(NULL) { }
357 bool initialized() const { return register_param_count_ >= 0; }
359 int environment_length() const {
360 return register_param_count_;
363 Representation GetParameterRepresentation(int index) const {
364 return param_representations_[index];
367 Register GetParameterRegister(int index) const {
368 return register_params_[index];
371 PlatformCallInterfaceDescriptor* platform_specific_descriptor() const {
372 return platform_specific_descriptor_;
375 int register_param_count_;
376 Register* register_params_;
377 Representation* param_representations_;
378 PlatformCallInterfaceDescriptor* platform_specific_descriptor_;
382 class HydrogenCodeStub : public CodeStub {
384 enum InitializationState {
389 explicit HydrogenCodeStub(InitializationState state = INITIALIZED) {
390 is_uninitialized_ = (state == UNINITIALIZED);
393 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
395 CodeStubInterfaceDescriptor* GetInterfaceDescriptor(Isolate* isolate) {
396 return isolate->code_stub_interface_descriptor(MajorKey());
399 bool IsUninitialized() { return is_uninitialized_; }
401 template<class SubClass>
402 static Handle<Code> GetUninitialized(Isolate* isolate) {
403 SubClass::GenerateAheadOfTime(isolate);
404 return SubClass().GetCode(isolate);
407 virtual void InitializeInterfaceDescriptor(
409 CodeStubInterfaceDescriptor* descriptor) = 0;
411 // Retrieve the code for the stub. Generate the code if needed.
412 virtual Handle<Code> GenerateCode(Isolate* isolate) = 0;
414 virtual int NotMissMinorKey() = 0;
416 Handle<Code> GenerateLightweightMissCode(Isolate* isolate);
418 template<class StateType>
419 void TraceTransition(StateType from, StateType to);
422 class MinorKeyBits: public BitField<int, 0, kStubMinorKeyBits - 1> {};
423 class IsMissBits: public BitField<bool, kStubMinorKeyBits - 1, 1> {};
425 void GenerateLightweightMiss(MacroAssembler* masm);
426 virtual int MinorKey() {
427 return IsMissBits::encode(is_uninitialized_) |
428 MinorKeyBits::encode(NotMissMinorKey());
431 bool is_uninitialized_;
435 // Helper interface to prepare to/restore after making runtime calls.
436 class RuntimeCallHelper {
438 virtual ~RuntimeCallHelper() {}
440 virtual void BeforeCall(MacroAssembler* masm) const = 0;
442 virtual void AfterCall(MacroAssembler* masm) const = 0;
445 RuntimeCallHelper() {}
448 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
452 } } // namespace v8::internal
454 #if V8_TARGET_ARCH_IA32
455 #include "ia32/code-stubs-ia32.h"
456 #elif V8_TARGET_ARCH_X64
457 #include "x64/code-stubs-x64.h"
458 #elif V8_TARGET_ARCH_ARM64
459 #include "arm64/code-stubs-arm64.h"
460 #elif V8_TARGET_ARCH_ARM
461 #include "arm/code-stubs-arm.h"
462 #elif V8_TARGET_ARCH_MIPS
463 #include "mips/code-stubs-mips.h"
465 #error Unsupported target architecture.
472 // RuntimeCallHelper implementation used in stubs: enters/leaves a
473 // newly created internal frame before/after the runtime call.
474 class StubRuntimeCallHelper : public RuntimeCallHelper {
476 StubRuntimeCallHelper() {}
478 virtual void BeforeCall(MacroAssembler* masm) const;
480 virtual void AfterCall(MacroAssembler* masm) const;
484 // Trivial RuntimeCallHelper implementation.
485 class NopRuntimeCallHelper : public RuntimeCallHelper {
487 NopRuntimeCallHelper() {}
489 virtual void BeforeCall(MacroAssembler* masm) const {}
491 virtual void AfterCall(MacroAssembler* masm) const {}
495 class ToNumberStub: public HydrogenCodeStub {
499 virtual Handle<Code> GenerateCode(Isolate* isolate);
501 virtual void InitializeInterfaceDescriptor(
503 CodeStubInterfaceDescriptor* descriptor);
505 static void InstallDescriptors(Isolate* isolate) {
507 stub.InitializeInterfaceDescriptor(
509 isolate->code_stub_interface_descriptor(CodeStub::ToNumber));
513 Major MajorKey() { return ToNumber; }
514 int NotMissMinorKey() { return 0; }
518 class NumberToStringStub V8_FINAL : public HydrogenCodeStub {
520 NumberToStringStub() {}
522 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
524 virtual void InitializeInterfaceDescriptor(
526 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
528 static void InstallDescriptors(Isolate* isolate);
530 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
531 static const int kNumber = 0;
534 virtual Major MajorKey() V8_OVERRIDE { return NumberToString; }
535 virtual int NotMissMinorKey() V8_OVERRIDE { return 0; }
539 class FastNewClosureStub : public HydrogenCodeStub {
541 explicit FastNewClosureStub(StrictMode strict_mode, bool is_generator)
542 : strict_mode_(strict_mode),
543 is_generator_(is_generator) { }
545 virtual Handle<Code> GenerateCode(Isolate* isolate);
547 virtual void InitializeInterfaceDescriptor(
549 CodeStubInterfaceDescriptor* descriptor);
551 static void InstallDescriptors(Isolate* isolate);
553 StrictMode strict_mode() const { return strict_mode_; }
554 bool is_generator() const { return is_generator_; }
557 class StrictModeBits: public BitField<bool, 0, 1> {};
558 class IsGeneratorBits: public BitField<bool, 1, 1> {};
560 Major MajorKey() { return FastNewClosure; }
561 int NotMissMinorKey() {
562 return StrictModeBits::encode(strict_mode_ == STRICT) |
563 IsGeneratorBits::encode(is_generator_);
566 StrictMode strict_mode_;
571 class FastNewContextStub V8_FINAL : public HydrogenCodeStub {
573 static const int kMaximumSlots = 64;
575 explicit FastNewContextStub(int slots) : slots_(slots) {
576 ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
579 virtual Handle<Code> GenerateCode(Isolate* isolate);
581 virtual void InitializeInterfaceDescriptor(
583 CodeStubInterfaceDescriptor* descriptor);
585 static void InstallDescriptors(Isolate* isolate);
587 int slots() const { return slots_; }
589 virtual Major MajorKey() V8_OVERRIDE { return FastNewContext; }
590 virtual int NotMissMinorKey() V8_OVERRIDE { return slots_; }
592 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
593 static const int kFunction = 0;
600 class FastCloneShallowArrayStub : public HydrogenCodeStub {
602 // Maximum length of copied elements array.
603 static const int kMaximumClonedLength = 8;
606 CLONE_DOUBLE_ELEMENTS,
607 COPY_ON_WRITE_ELEMENTS,
609 LAST_CLONE_MODE = CLONE_ANY_ELEMENTS
612 static const int kFastCloneModeCount = LAST_CLONE_MODE + 1;
614 FastCloneShallowArrayStub(Mode mode,
615 AllocationSiteMode allocation_site_mode,
618 allocation_site_mode_(allocation_site_mode),
619 length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
620 ASSERT_GE(length_, 0);
621 ASSERT_LE(length_, kMaximumClonedLength);
624 Mode mode() const { return mode_; }
625 int length() const { return length_; }
626 AllocationSiteMode allocation_site_mode() const {
627 return allocation_site_mode_;
630 ElementsKind ComputeElementsKind() const {
633 case COPY_ON_WRITE_ELEMENTS:
634 return FAST_ELEMENTS;
635 case CLONE_DOUBLE_ELEMENTS:
636 return FAST_DOUBLE_ELEMENTS;
637 case CLONE_ANY_ELEMENTS:
641 return LAST_ELEMENTS_KIND;
644 virtual Handle<Code> GenerateCode(Isolate* isolate);
646 virtual void InitializeInterfaceDescriptor(
648 CodeStubInterfaceDescriptor* descriptor);
650 static void InstallDescriptors(Isolate* isolate);
654 AllocationSiteMode allocation_site_mode_;
657 class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
658 class ModeBits: public BitField<Mode, 1, 4> {};
659 class LengthBits: public BitField<int, 5, 4> {};
660 // Ensure data fits within available bits.
661 STATIC_ASSERT(LAST_ALLOCATION_SITE_MODE == 1);
662 STATIC_ASSERT(kFastCloneModeCount < 16);
663 STATIC_ASSERT(kMaximumClonedLength < 16);
664 Major MajorKey() { return FastCloneShallowArray; }
665 int NotMissMinorKey() {
666 return AllocationSiteModeBits::encode(allocation_site_mode_)
667 | ModeBits::encode(mode_)
668 | LengthBits::encode(length_);
673 class FastCloneShallowObjectStub : public HydrogenCodeStub {
675 // Maximum number of properties in copied object.
676 static const int kMaximumClonedProperties = 6;
678 explicit FastCloneShallowObjectStub(int length) : length_(length) {
679 ASSERT_GE(length_, 0);
680 ASSERT_LE(length_, kMaximumClonedProperties);
683 int length() const { return length_; }
685 virtual Handle<Code> GenerateCode(Isolate* isolate);
687 virtual void InitializeInterfaceDescriptor(
689 CodeStubInterfaceDescriptor* descriptor);
694 Major MajorKey() { return FastCloneShallowObject; }
695 int NotMissMinorKey() { return length_; }
697 DISALLOW_COPY_AND_ASSIGN(FastCloneShallowObjectStub);
701 class CreateAllocationSiteStub : public HydrogenCodeStub {
703 explicit CreateAllocationSiteStub() { }
705 virtual Handle<Code> GenerateCode(Isolate* isolate);
707 static void GenerateAheadOfTime(Isolate* isolate);
709 virtual void InitializeInterfaceDescriptor(
711 CodeStubInterfaceDescriptor* descriptor);
714 Major MajorKey() { return CreateAllocationSite; }
715 int NotMissMinorKey() { return 0; }
717 DISALLOW_COPY_AND_ASSIGN(CreateAllocationSiteStub);
721 class InstanceofStub: public PlatformCodeStub {
725 kArgsInRegisters = 1 << 0,
726 kCallSiteInlineCheck = 1 << 1,
727 kReturnTrueFalseObject = 1 << 2
730 explicit InstanceofStub(Flags flags) : flags_(flags) { }
732 static Register left();
733 static Register right();
735 void Generate(MacroAssembler* masm);
738 Major MajorKey() { return Instanceof; }
739 int MinorKey() { return static_cast<int>(flags_); }
741 bool HasArgsInRegisters() const {
742 return (flags_ & kArgsInRegisters) != 0;
745 bool HasCallSiteInlineCheck() const {
746 return (flags_ & kCallSiteInlineCheck) != 0;
749 bool ReturnTrueFalseObject() const {
750 return (flags_ & kReturnTrueFalseObject) != 0;
753 virtual void PrintName(StringStream* stream);
759 enum AllocationSiteOverrideMode {
761 DISABLE_ALLOCATION_SITES,
762 LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
766 class ArrayConstructorStub: public PlatformCodeStub {
768 enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
769 ArrayConstructorStub(Isolate* isolate, int argument_count);
770 explicit ArrayConstructorStub(Isolate* isolate);
772 void Generate(MacroAssembler* masm);
775 void GenerateDispatchToArrayStub(MacroAssembler* masm,
776 AllocationSiteOverrideMode mode);
777 virtual void PrintName(StringStream* stream);
779 virtual CodeStub::Major MajorKey() { return ArrayConstructor; }
780 virtual int MinorKey() { return argument_count_; }
782 ArgumentCountKey argument_count_;
786 class InternalArrayConstructorStub: public PlatformCodeStub {
788 explicit InternalArrayConstructorStub(Isolate* isolate);
790 void Generate(MacroAssembler* masm);
793 virtual CodeStub::Major MajorKey() { return InternalArrayConstructor; }
794 virtual int MinorKey() { return 0; }
796 void GenerateCase(MacroAssembler* masm, ElementsKind kind);
800 class MathPowStub: public PlatformCodeStub {
802 enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK };
804 explicit MathPowStub(ExponentType exponent_type)
805 : exponent_type_(exponent_type) { }
806 virtual void Generate(MacroAssembler* masm);
809 virtual CodeStub::Major MajorKey() { return MathPow; }
810 virtual int MinorKey() { return exponent_type_; }
812 ExponentType exponent_type_;
816 class ICStub: public PlatformCodeStub {
818 explicit ICStub(Code::Kind kind) : kind_(kind) { }
819 virtual Code::Kind GetCodeKind() const { return kind_; }
820 virtual InlineCacheState GetICState() { return MONOMORPHIC; }
822 bool Describes(Code* code) {
823 return GetMajorKey(code) == MajorKey() && code->stub_info() == MinorKey();
827 class KindBits: public BitField<Code::Kind, 0, 4> {};
828 virtual void FinishCode(Handle<Code> code) {
829 code->set_stub_info(MinorKey());
831 Code::Kind kind() { return kind_; }
833 virtual int MinorKey() {
834 return KindBits::encode(kind_);
842 class FunctionPrototypeStub: public ICStub {
844 explicit FunctionPrototypeStub(Code::Kind kind) : ICStub(kind) { }
845 virtual void Generate(MacroAssembler* masm);
848 virtual CodeStub::Major MajorKey() { return FunctionPrototype; }
852 class StoreICStub: public ICStub {
854 StoreICStub(Code::Kind kind, StrictMode strict_mode)
855 : ICStub(kind), strict_mode_(strict_mode) { }
858 virtual ExtraICState GetExtraICState() {
859 return StoreIC::ComputeExtraICState(strict_mode_);
863 STATIC_ASSERT(KindBits::kSize == 4);
864 class StrictModeBits: public BitField<bool, 4, 1> {};
865 virtual int MinorKey() {
866 return KindBits::encode(kind()) | StrictModeBits::encode(strict_mode_);
869 StrictMode strict_mode_;
873 class HICStub: public HydrogenCodeStub {
875 virtual Code::Kind GetCodeKind() const { return kind(); }
876 virtual InlineCacheState GetICState() { return MONOMORPHIC; }
879 class KindBits: public BitField<Code::Kind, 0, 4> {};
880 virtual Code::Kind kind() const = 0;
884 class HandlerStub: public HICStub {
886 virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
887 virtual ExtraICState GetExtraICState() { return kind(); }
890 HandlerStub() : HICStub() { }
891 virtual int NotMissMinorKey() { return bit_field_; }
896 class LoadFieldStub: public HandlerStub {
898 LoadFieldStub(bool inobject, int index, Representation representation) {
899 Initialize(Code::LOAD_IC, inobject, index, representation);
902 virtual Handle<Code> GenerateCode(Isolate* isolate);
904 virtual void InitializeInterfaceDescriptor(
906 CodeStubInterfaceDescriptor* descriptor);
908 Representation representation() {
909 if (unboxed_double()) return Representation::Double();
910 return Representation::Tagged();
913 virtual Code::Kind kind() const {
914 return KindBits::decode(bit_field_);
918 return InobjectBits::decode(bit_field_);
922 int index = IndexBits::decode(bit_field_);
923 int offset = index * kPointerSize;
924 if (is_inobject()) return offset;
925 return FixedArray::kHeaderSize + offset;
928 bool unboxed_double() {
929 return UnboxedDoubleBits::decode(bit_field_);
932 virtual Code::StubType GetStubType() { return Code::FAST; }
935 LoadFieldStub() : HandlerStub() { }
937 void Initialize(Code::Kind kind,
940 Representation representation) {
941 bit_field_ = KindBits::encode(kind)
942 | InobjectBits::encode(inobject)
943 | IndexBits::encode(index)
944 | UnboxedDoubleBits::encode(representation.IsDouble());
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 StringLengthStub: public HandlerStub {
958 explicit StringLengthStub() : HandlerStub() {
959 Initialize(Code::LOAD_IC);
961 virtual Handle<Code> GenerateCode(Isolate* isolate);
962 virtual void InitializeInterfaceDescriptor(
964 CodeStubInterfaceDescriptor* descriptor);
967 virtual Code::Kind kind() const {
968 return KindBits::decode(bit_field_);
971 void Initialize(Code::Kind kind) {
972 bit_field_ = KindBits::encode(kind);
976 virtual CodeStub::Major MajorKey() { return StringLength; }
980 class KeyedStringLengthStub: public StringLengthStub {
982 explicit KeyedStringLengthStub() : StringLengthStub() {
983 Initialize(Code::KEYED_LOAD_IC);
985 virtual void InitializeInterfaceDescriptor(
987 CodeStubInterfaceDescriptor* descriptor);
990 virtual CodeStub::Major MajorKey() { return KeyedStringLength; }
994 class StoreGlobalStub : public HandlerStub {
996 explicit StoreGlobalStub(bool is_constant, bool check_global) {
997 bit_field_ = IsConstantBits::encode(is_constant) |
998 CheckGlobalBits::encode(check_global);
1001 static Handle<HeapObject> global_placeholder(Isolate* isolate) {
1002 return isolate->factory()->uninitialized_value();
1005 Handle<Code> GetCodeCopyFromTemplate(Isolate* isolate,
1006 Handle<GlobalObject> global,
1007 Handle<PropertyCell> cell) {
1008 if (check_global()) {
1009 Code::FindAndReplacePattern pattern;
1010 pattern.Add(Handle<Map>(global_placeholder(isolate)->map()), global);
1011 pattern.Add(isolate->factory()->meta_map(), Handle<Map>(global->map()));
1012 pattern.Add(isolate->factory()->global_property_cell_map(), cell);
1013 return CodeStub::GetCodeCopy(isolate, pattern);
1015 Code::FindAndReplacePattern pattern;
1016 pattern.Add(isolate->factory()->global_property_cell_map(), cell);
1017 return CodeStub::GetCodeCopy(isolate, pattern);
1021 virtual Code::Kind kind() const { return Code::STORE_IC; }
1023 virtual Handle<Code> GenerateCode(Isolate* isolate);
1025 virtual void InitializeInterfaceDescriptor(
1027 CodeStubInterfaceDescriptor* descriptor);
1029 bool is_constant() const {
1030 return IsConstantBits::decode(bit_field_);
1032 bool check_global() const {
1033 return CheckGlobalBits::decode(bit_field_);
1035 void set_is_constant(bool value) {
1036 bit_field_ = IsConstantBits::update(bit_field_, value);
1039 Representation representation() {
1040 return Representation::FromKind(RepresentationBits::decode(bit_field_));
1042 void set_representation(Representation r) {
1043 bit_field_ = RepresentationBits::update(bit_field_, r.kind());
1047 Major MajorKey() { return StoreGlobal; }
1049 class IsConstantBits: public BitField<bool, 0, 1> {};
1050 class RepresentationBits: public BitField<Representation::Kind, 1, 8> {};
1051 class CheckGlobalBits: public BitField<bool, 9, 1> {};
1053 DISALLOW_COPY_AND_ASSIGN(StoreGlobalStub);
1057 class CallApiFunctionStub : public PlatformCodeStub {
1059 CallApiFunctionStub(bool is_store,
1060 bool call_data_undefined,
1063 IsStoreBits::encode(is_store) |
1064 CallDataUndefinedBits::encode(call_data_undefined) |
1065 ArgumentBits::encode(argc);
1066 ASSERT(!is_store || argc == 1);
1070 virtual void Generate(MacroAssembler* masm) V8_OVERRIDE;
1071 virtual Major MajorKey() V8_OVERRIDE { return CallApiFunction; }
1072 virtual int MinorKey() V8_OVERRIDE { return bit_field_; }
1074 class IsStoreBits: public BitField<bool, 0, 1> {};
1075 class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
1076 class ArgumentBits: public BitField<int, 2, Code::kArgumentsBits> {};
1080 DISALLOW_COPY_AND_ASSIGN(CallApiFunctionStub);
1084 class CallApiGetterStub : public PlatformCodeStub {
1086 CallApiGetterStub() {}
1089 virtual void Generate(MacroAssembler* masm) V8_OVERRIDE;
1090 virtual Major MajorKey() V8_OVERRIDE { return CallApiGetter; }
1091 virtual int MinorKey() V8_OVERRIDE { return 0; }
1093 DISALLOW_COPY_AND_ASSIGN(CallApiGetterStub);
1097 class KeyedLoadFieldStub: public LoadFieldStub {
1099 KeyedLoadFieldStub(bool inobject, int index, Representation representation)
1101 Initialize(Code::KEYED_LOAD_IC, inobject, index, representation);
1104 virtual void InitializeInterfaceDescriptor(
1106 CodeStubInterfaceDescriptor* descriptor);
1109 virtual CodeStub::Major MajorKey() { return KeyedLoadField; }
1113 class BinaryOpICStub : public HydrogenCodeStub {
1115 BinaryOpICStub(Token::Value op, OverwriteMode mode)
1116 : HydrogenCodeStub(UNINITIALIZED), state_(op, mode) {}
1118 explicit BinaryOpICStub(const BinaryOpIC::State& state) : state_(state) {}
1120 static void GenerateAheadOfTime(Isolate* isolate);
1122 virtual void InitializeInterfaceDescriptor(
1123 Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1125 static void InstallDescriptors(Isolate* isolate);
1127 virtual Code::Kind GetCodeKind() const V8_OVERRIDE {
1128 return Code::BINARY_OP_IC;
1131 virtual InlineCacheState GetICState() V8_FINAL V8_OVERRIDE {
1132 return state_.GetICState();
1135 virtual ExtraICState GetExtraICState() V8_FINAL V8_OVERRIDE {
1136 return state_.GetExtraICState();
1139 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_FINAL V8_OVERRIDE {
1140 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1143 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
1145 const BinaryOpIC::State& state() const { return state_; }
1147 virtual void PrintState(StringStream* stream) V8_FINAL V8_OVERRIDE;
1149 virtual Major MajorKey() V8_OVERRIDE { return BinaryOpIC; }
1150 virtual int NotMissMinorKey() V8_FINAL V8_OVERRIDE {
1151 return GetExtraICState();
1154 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1155 static const int kLeft = 0;
1156 static const int kRight = 1;
1159 static void GenerateAheadOfTime(Isolate* isolate,
1160 const BinaryOpIC::State& state);
1162 BinaryOpIC::State state_;
1164 DISALLOW_COPY_AND_ASSIGN(BinaryOpICStub);
1168 class ArrayPushStub: public PlatformCodeStub {
1170 ArrayPushStub(ElementsKind kind, int argc) {
1171 bit_field_ = ElementsKindBits::encode(kind) | ArgcBits::encode(argc);
1174 void Generate(MacroAssembler* masm);
1177 int arguments_count() { return ArgcBits::decode(bit_field_); }
1178 ElementsKind elements_kind() {
1179 return ElementsKindBits::decode(bit_field_);
1182 virtual CodeStub::Major MajorKey() { return ArrayPush; }
1183 virtual int MinorKey() { return bit_field_; }
1185 class ElementsKindBits: public BitField<ElementsKind, 0, 3> {};
1186 class ArgcBits: public BitField<int, 3, Code::kArgumentsBits> {};
1192 // TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
1193 // call support for stubs in Hydrogen.
1194 class BinaryOpICWithAllocationSiteStub V8_FINAL : public PlatformCodeStub {
1196 explicit BinaryOpICWithAllocationSiteStub(const BinaryOpIC::State& state)
1199 static void GenerateAheadOfTime(Isolate* isolate);
1201 Handle<Code> GetCodeCopyFromTemplate(Isolate* isolate,
1202 Handle<AllocationSite> allocation_site) {
1203 Code::FindAndReplacePattern pattern;
1204 pattern.Add(isolate->factory()->oddball_map(), allocation_site);
1205 return CodeStub::GetCodeCopy(isolate, pattern);
1208 virtual Code::Kind GetCodeKind() const V8_OVERRIDE {
1209 return Code::BINARY_OP_IC;
1212 virtual InlineCacheState GetICState() V8_OVERRIDE {
1213 return state_.GetICState();
1216 virtual ExtraICState GetExtraICState() V8_OVERRIDE {
1217 return state_.GetExtraICState();
1220 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
1221 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1224 virtual void Generate(MacroAssembler* masm) V8_OVERRIDE;
1226 virtual void PrintState(StringStream* stream) V8_OVERRIDE;
1228 virtual Major MajorKey() V8_OVERRIDE { return BinaryOpICWithAllocationSite; }
1229 virtual int MinorKey() V8_OVERRIDE { return GetExtraICState(); }
1232 static void GenerateAheadOfTime(Isolate* isolate,
1233 const BinaryOpIC::State& state);
1235 BinaryOpIC::State state_;
1237 DISALLOW_COPY_AND_ASSIGN(BinaryOpICWithAllocationSiteStub);
1241 class BinaryOpWithAllocationSiteStub V8_FINAL : public BinaryOpICStub {
1243 BinaryOpWithAllocationSiteStub(Token::Value op, OverwriteMode mode)
1244 : BinaryOpICStub(op, mode) {}
1246 explicit BinaryOpWithAllocationSiteStub(const BinaryOpIC::State& state)
1247 : BinaryOpICStub(state) {}
1249 virtual void InitializeInterfaceDescriptor(
1250 Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1252 static void InstallDescriptors(Isolate* isolate);
1254 virtual Code::Kind GetCodeKind() const V8_FINAL V8_OVERRIDE {
1258 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
1260 virtual Major MajorKey() V8_OVERRIDE {
1261 return BinaryOpWithAllocationSite;
1264 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1265 static const int kAllocationSite = 0;
1266 static const int kLeft = 1;
1267 static const int kRight = 2;
1271 enum StringAddFlags {
1272 // Omit both parameter checks.
1273 STRING_ADD_CHECK_NONE = 0,
1274 // Check left parameter.
1275 STRING_ADD_CHECK_LEFT = 1 << 0,
1276 // Check right parameter.
1277 STRING_ADD_CHECK_RIGHT = 1 << 1,
1278 // Check both parameters.
1279 STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT
1283 class StringAddStub V8_FINAL : public HydrogenCodeStub {
1285 StringAddStub(StringAddFlags flags, PretenureFlag pretenure_flag)
1286 : bit_field_(StringAddFlagsBits::encode(flags) |
1287 PretenureFlagBits::encode(pretenure_flag)) {}
1289 StringAddFlags flags() const {
1290 return StringAddFlagsBits::decode(bit_field_);
1293 PretenureFlag pretenure_flag() const {
1294 return PretenureFlagBits::decode(bit_field_);
1297 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
1298 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1301 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
1303 virtual void InitializeInterfaceDescriptor(
1305 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1307 static void InstallDescriptors(Isolate* isolate);
1309 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1310 static const int kLeft = 0;
1311 static const int kRight = 1;
1314 class StringAddFlagsBits: public BitField<StringAddFlags, 0, 2> {};
1315 class PretenureFlagBits: public BitField<PretenureFlag, 2, 1> {};
1316 uint32_t bit_field_;
1318 virtual Major MajorKey() V8_OVERRIDE { return StringAdd; }
1319 virtual int NotMissMinorKey() V8_OVERRIDE { return bit_field_; }
1321 virtual void PrintBaseName(StringStream* stream) V8_OVERRIDE;
1323 DISALLOW_COPY_AND_ASSIGN(StringAddStub);
1327 class ICCompareStub: public PlatformCodeStub {
1329 ICCompareStub(Token::Value op,
1330 CompareIC::State left,
1331 CompareIC::State right,
1332 CompareIC::State handler)
1337 ASSERT(Token::IsCompareOp(op));
1340 virtual void Generate(MacroAssembler* masm);
1342 void set_known_map(Handle<Map> map) { known_map_ = map; }
1344 static void DecodeMinorKey(int minor_key,
1345 CompareIC::State* left_state,
1346 CompareIC::State* right_state,
1347 CompareIC::State* handler_state,
1350 virtual InlineCacheState GetICState();
1353 class OpField: public BitField<int, 0, 3> { };
1354 class LeftStateField: public BitField<int, 3, 4> { };
1355 class RightStateField: public BitField<int, 7, 4> { };
1356 class HandlerStateField: public BitField<int, 11, 4> { };
1358 virtual void FinishCode(Handle<Code> code) {
1359 code->set_stub_info(MinorKey());
1362 virtual CodeStub::Major MajorKey() { return CompareIC; }
1363 virtual int MinorKey();
1365 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_IC; }
1367 void GenerateSmis(MacroAssembler* masm);
1368 void GenerateNumbers(MacroAssembler* masm);
1369 void GenerateInternalizedStrings(MacroAssembler* masm);
1370 void GenerateStrings(MacroAssembler* masm);
1371 void GenerateUniqueNames(MacroAssembler* masm);
1372 void GenerateObjects(MacroAssembler* masm);
1373 void GenerateMiss(MacroAssembler* masm);
1374 void GenerateKnownObjects(MacroAssembler* masm);
1375 void GenerateGeneric(MacroAssembler* masm);
1377 bool strict() const { return op_ == Token::EQ_STRICT; }
1378 Condition GetCondition() const { return CompareIC::ComputeCondition(op_); }
1380 virtual void AddToSpecialCache(Handle<Code> new_object);
1381 virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate);
1382 virtual bool UseSpecialCache() { return state_ == CompareIC::KNOWN_OBJECT; }
1385 CompareIC::State left_;
1386 CompareIC::State right_;
1387 CompareIC::State state_;
1388 Handle<Map> known_map_;
1392 class CompareNilICStub : public HydrogenCodeStub {
1394 Type* GetType(Zone* zone, Handle<Map> map = Handle<Map>());
1395 Type* GetInputType(Zone* zone, Handle<Map> map);
1397 explicit CompareNilICStub(NilValue nil) : nil_value_(nil) { }
1399 CompareNilICStub(ExtraICState ic_state,
1400 InitializationState init_state = INITIALIZED)
1401 : HydrogenCodeStub(init_state),
1402 nil_value_(NilValueField::decode(ic_state)),
1403 state_(State(TypesField::decode(ic_state))) {
1406 static Handle<Code> GetUninitialized(Isolate* isolate,
1408 return CompareNilICStub(nil, UNINITIALIZED).GetCode(isolate);
1411 virtual void InitializeInterfaceDescriptor(
1413 CodeStubInterfaceDescriptor* descriptor);
1415 static void InstallDescriptors(Isolate* isolate) {
1416 CompareNilICStub compare_stub(kNullValue, UNINITIALIZED);
1417 compare_stub.InitializeInterfaceDescriptor(
1419 isolate->code_stub_interface_descriptor(CodeStub::CompareNilIC));
1422 virtual InlineCacheState GetICState() {
1423 if (state_.Contains(GENERIC)) {
1425 } else if (state_.Contains(MONOMORPHIC_MAP)) {
1428 return PREMONOMORPHIC;
1432 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_NIL_IC; }
1434 virtual Handle<Code> GenerateCode(Isolate* isolate);
1436 virtual ExtraICState GetExtraICState() {
1437 return NilValueField::encode(nil_value_) |
1438 TypesField::encode(state_.ToIntegral());
1441 void UpdateStatus(Handle<Object> object);
1443 bool IsMonomorphic() const { return state_.Contains(MONOMORPHIC_MAP); }
1444 NilValue GetNilValue() const { return nil_value_; }
1445 void ClearState() { state_.RemoveAll(); }
1447 virtual void PrintState(StringStream* stream);
1448 virtual void PrintBaseName(StringStream* stream);
1451 friend class CompareNilIC;
1453 enum CompareNilType {
1461 // At most 6 different types can be distinguished, because the Code object
1462 // only has room for a single byte to hold a set and there are two more
1463 // boolean flags we need to store. :-P
1464 STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
1466 class State : public EnumSet<CompareNilType, byte> {
1468 State() : EnumSet<CompareNilType, byte>(0) { }
1469 explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
1471 void Print(StringStream* stream) const;
1474 CompareNilICStub(NilValue nil, InitializationState init_state)
1475 : HydrogenCodeStub(init_state), nil_value_(nil) { }
1477 class NilValueField : public BitField<NilValue, 0, 1> {};
1478 class TypesField : public BitField<byte, 1, NUMBER_OF_TYPES> {};
1480 virtual CodeStub::Major MajorKey() { return CompareNilIC; }
1481 virtual int NotMissMinorKey() { return GetExtraICState(); }
1483 NilValue nil_value_;
1486 DISALLOW_COPY_AND_ASSIGN(CompareNilICStub);
1490 class CEntryStub : public PlatformCodeStub {
1492 explicit CEntryStub(int result_size,
1493 SaveFPRegsMode save_doubles = kDontSaveFPRegs)
1494 : result_size_(result_size), save_doubles_(save_doubles) { }
1496 void Generate(MacroAssembler* masm);
1498 // The version of this stub that doesn't save doubles is generated ahead of
1499 // time, so it's OK to call it from other stubs that can't cope with GC during
1500 // their code generation. On machines that always have gp registers (x64) we
1501 // can generate both variants ahead of time.
1502 static void GenerateAheadOfTime(Isolate* isolate);
1505 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
1506 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1510 void GenerateCore(MacroAssembler* masm,
1511 Label* throw_normal_exception,
1512 Label* throw_termination_exception,
1514 bool always_allocate_scope);
1516 // Number of pointers/values returned.
1518 const int result_size_;
1519 SaveFPRegsMode save_doubles_;
1521 Major MajorKey() { return CEntry; }
1524 bool NeedsImmovableCode();
1528 class JSEntryStub : public PlatformCodeStub {
1532 void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
1535 void GenerateBody(MacroAssembler* masm, bool is_construct);
1538 Major MajorKey() { return JSEntry; }
1539 int MinorKey() { return 0; }
1541 virtual void FinishCode(Handle<Code> code);
1543 int handler_offset_;
1547 class JSConstructEntryStub : public JSEntryStub {
1549 JSConstructEntryStub() { }
1551 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
1554 int MinorKey() { return 1; }
1556 virtual void PrintName(StringStream* stream) {
1557 stream->Add("JSConstructEntryStub");
1562 class ArgumentsAccessStub: public PlatformCodeStub {
1571 explicit ArgumentsAccessStub(Type type) : type_(type) { }
1576 Major MajorKey() { return ArgumentsAccess; }
1577 int MinorKey() { return type_; }
1579 void Generate(MacroAssembler* masm);
1580 void GenerateReadElement(MacroAssembler* masm);
1581 void GenerateNewStrict(MacroAssembler* masm);
1582 void GenerateNewSloppyFast(MacroAssembler* masm);
1583 void GenerateNewSloppySlow(MacroAssembler* masm);
1585 virtual void PrintName(StringStream* stream);
1589 class RegExpExecStub: public PlatformCodeStub {
1591 RegExpExecStub() { }
1594 Major MajorKey() { return RegExpExec; }
1595 int MinorKey() { return 0; }
1597 void Generate(MacroAssembler* masm);
1601 class RegExpConstructResultStub V8_FINAL : public HydrogenCodeStub {
1603 RegExpConstructResultStub() { }
1605 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
1607 virtual void InitializeInterfaceDescriptor(
1609 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1611 virtual Major MajorKey() V8_OVERRIDE { return RegExpConstructResult; }
1612 virtual int NotMissMinorKey() V8_OVERRIDE { return 0; }
1614 static void InstallDescriptors(Isolate* isolate);
1616 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1617 static const int kLength = 0;
1618 static const int kIndex = 1;
1619 static const int kInput = 2;
1622 DISALLOW_COPY_AND_ASSIGN(RegExpConstructResultStub);
1626 class CallFunctionStub: public PlatformCodeStub {
1628 CallFunctionStub(int argc, CallFunctionFlags flags)
1629 : argc_(argc), flags_(flags) { }
1631 void Generate(MacroAssembler* masm);
1633 virtual void FinishCode(Handle<Code> code) {
1634 code->set_has_function_cache(RecordCallTarget());
1637 static int ExtractArgcFromMinorKey(int minor_key) {
1638 return ArgcBits::decode(minor_key);
1643 CallFunctionFlags flags_;
1645 virtual void PrintName(StringStream* stream);
1647 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
1648 class FlagBits: public BitField<CallFunctionFlags, 0, 2> {};
1649 class ArgcBits: public BitField<unsigned, 2, 32 - 2> {};
1651 Major MajorKey() { return CallFunction; }
1653 // Encode the parameters in a unique 32 bit value.
1654 return FlagBits::encode(flags_) | ArgcBits::encode(argc_);
1657 bool RecordCallTarget() {
1658 return flags_ == RECORD_CALL_TARGET;
1661 bool CallAsMethod() {
1662 return flags_ == CALL_AS_METHOD || flags_ == WRAP_AND_CALL;
1665 bool NeedsChecks() {
1666 return flags_ != WRAP_AND_CALL;
1671 class CallConstructStub: public PlatformCodeStub {
1673 explicit CallConstructStub(CallFunctionFlags flags) : flags_(flags) {}
1675 void Generate(MacroAssembler* masm);
1677 virtual void FinishCode(Handle<Code> code) {
1678 code->set_has_function_cache(RecordCallTarget());
1682 CallFunctionFlags flags_;
1684 virtual void PrintName(StringStream* stream);
1686 Major MajorKey() { return CallConstruct; }
1687 int MinorKey() { return flags_; }
1689 bool RecordCallTarget() {
1690 return (flags_ & RECORD_CALL_TARGET) != 0;
1693 bool CallAsMethod() {
1694 return (flags_ & CALL_AS_METHOD) != 0;
1699 enum StringIndexFlags {
1700 // Accepts smis or heap numbers.
1701 STRING_INDEX_IS_NUMBER,
1703 // Accepts smis or heap numbers that are valid array indices
1704 // (ECMA-262 15.4). Invalid indices are reported as being out of
1706 STRING_INDEX_IS_ARRAY_INDEX
1710 // Generates code implementing String.prototype.charCodeAt.
1712 // Only supports the case when the receiver is a string and the index
1713 // is a number (smi or heap number) that is a valid index into the
1714 // string. Additional index constraints are specified by the
1715 // flags. Otherwise, bails out to the provided labels.
1717 // Register usage: |object| may be changed to another string in a way
1718 // that doesn't affect charCodeAt/charAt semantics, |index| is
1719 // preserved, |scratch| and |result| are clobbered.
1720 class StringCharCodeAtGenerator {
1722 StringCharCodeAtGenerator(Register object,
1725 Label* receiver_not_string,
1726 Label* index_not_number,
1727 Label* index_out_of_range,
1728 StringIndexFlags index_flags)
1732 receiver_not_string_(receiver_not_string),
1733 index_not_number_(index_not_number),
1734 index_out_of_range_(index_out_of_range),
1735 index_flags_(index_flags) {
1736 ASSERT(!result_.is(object_));
1737 ASSERT(!result_.is(index_));
1740 // Generates the fast case code. On the fallthrough path |result|
1741 // register contains the result.
1742 void GenerateFast(MacroAssembler* masm);
1744 // Generates the slow case code. Must not be naturally
1745 // reachable. Expected to be put after a ret instruction (e.g., in
1746 // deferred code). Always jumps back to the fast case.
1747 void GenerateSlow(MacroAssembler* masm,
1748 const RuntimeCallHelper& call_helper);
1750 // Skip handling slow case and directly jump to bailout.
1751 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1752 masm->bind(&index_not_smi_);
1753 masm->bind(&call_runtime_);
1762 Label* receiver_not_string_;
1763 Label* index_not_number_;
1764 Label* index_out_of_range_;
1766 StringIndexFlags index_flags_;
1768 Label call_runtime_;
1769 Label index_not_smi_;
1770 Label got_smi_index_;
1773 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
1777 // Generates code for creating a one-char string from a char code.
1778 class StringCharFromCodeGenerator {
1780 StringCharFromCodeGenerator(Register code,
1784 ASSERT(!code_.is(result_));
1787 // Generates the fast case code. On the fallthrough path |result|
1788 // register contains the result.
1789 void GenerateFast(MacroAssembler* masm);
1791 // Generates the slow case code. Must not be naturally
1792 // reachable. Expected to be put after a ret instruction (e.g., in
1793 // deferred code). Always jumps back to the fast case.
1794 void GenerateSlow(MacroAssembler* masm,
1795 const RuntimeCallHelper& call_helper);
1797 // Skip handling slow case and directly jump to bailout.
1798 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1799 masm->bind(&slow_case_);
1810 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
1814 // Generates code implementing String.prototype.charAt.
1816 // Only supports the case when the receiver is a string and the index
1817 // is a number (smi or heap number) that is a valid index into the
1818 // string. Additional index constraints are specified by the
1819 // flags. Otherwise, bails out to the provided labels.
1821 // Register usage: |object| may be changed to another string in a way
1822 // that doesn't affect charCodeAt/charAt semantics, |index| is
1823 // preserved, |scratch1|, |scratch2|, and |result| are clobbered.
1824 class StringCharAtGenerator {
1826 StringCharAtGenerator(Register object,
1830 Label* receiver_not_string,
1831 Label* index_not_number,
1832 Label* index_out_of_range,
1833 StringIndexFlags index_flags)
1834 : char_code_at_generator_(object,
1837 receiver_not_string,
1841 char_from_code_generator_(scratch, result) {}
1843 // Generates the fast case code. On the fallthrough path |result|
1844 // register contains the result.
1845 void GenerateFast(MacroAssembler* masm) {
1846 char_code_at_generator_.GenerateFast(masm);
1847 char_from_code_generator_.GenerateFast(masm);
1850 // Generates the slow case code. Must not be naturally
1851 // reachable. Expected to be put after a ret instruction (e.g., in
1852 // deferred code). Always jumps back to the fast case.
1853 void GenerateSlow(MacroAssembler* masm,
1854 const RuntimeCallHelper& call_helper) {
1855 char_code_at_generator_.GenerateSlow(masm, call_helper);
1856 char_from_code_generator_.GenerateSlow(masm, call_helper);
1859 // Skip handling slow case and directly jump to bailout.
1860 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1861 char_code_at_generator_.SkipSlow(masm, bailout);
1862 char_from_code_generator_.SkipSlow(masm, bailout);
1866 StringCharCodeAtGenerator char_code_at_generator_;
1867 StringCharFromCodeGenerator char_from_code_generator_;
1869 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
1873 class KeyedLoadDictionaryElementStub : public HydrogenCodeStub {
1875 KeyedLoadDictionaryElementStub() {}
1877 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
1879 virtual void InitializeInterfaceDescriptor(
1881 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1884 Major MajorKey() { return KeyedLoadElement; }
1885 int NotMissMinorKey() { return DICTIONARY_ELEMENTS; }
1887 DISALLOW_COPY_AND_ASSIGN(KeyedLoadDictionaryElementStub);
1891 class KeyedLoadDictionaryElementPlatformStub : public PlatformCodeStub {
1893 KeyedLoadDictionaryElementPlatformStub() {}
1895 void Generate(MacroAssembler* masm);
1898 Major MajorKey() { return KeyedLoadElement; }
1899 int MinorKey() { return DICTIONARY_ELEMENTS; }
1901 DISALLOW_COPY_AND_ASSIGN(KeyedLoadDictionaryElementPlatformStub);
1905 class DoubleToIStub : public PlatformCodeStub {
1907 DoubleToIStub(Register source,
1908 Register destination,
1911 bool skip_fastpath = false) : bit_field_(0) {
1912 bit_field_ = SourceRegisterBits::encode(source.code()) |
1913 DestinationRegisterBits::encode(destination.code()) |
1914 OffsetBits::encode(offset) |
1915 IsTruncatingBits::encode(is_truncating) |
1916 SkipFastPathBits::encode(skip_fastpath) |
1917 SSEBits::encode(CpuFeatures::IsSafeForSnapshot(SSE2) ?
1918 CpuFeatures::IsSafeForSnapshot(SSE3) ? 2 : 1 : 0);
1922 return Register::from_code(SourceRegisterBits::decode(bit_field_));
1925 Register destination() {
1926 return Register::from_code(DestinationRegisterBits::decode(bit_field_));
1929 bool is_truncating() {
1930 return IsTruncatingBits::decode(bit_field_);
1933 bool skip_fastpath() {
1934 return SkipFastPathBits::decode(bit_field_);
1938 return OffsetBits::decode(bit_field_);
1941 void Generate(MacroAssembler* masm);
1943 virtual bool SometimesSetsUpAFrame() { return false; }
1946 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
1947 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1951 static const int kBitsPerRegisterNumber = 6;
1952 STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
1953 class SourceRegisterBits:
1954 public BitField<int, 0, kBitsPerRegisterNumber> {}; // NOLINT
1955 class DestinationRegisterBits:
1956 public BitField<int, kBitsPerRegisterNumber,
1957 kBitsPerRegisterNumber> {}; // NOLINT
1958 class IsTruncatingBits:
1959 public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {}; // NOLINT
1961 public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {}; // NOLINT
1962 class SkipFastPathBits:
1963 public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {}; // NOLINT
1965 public BitField<int, 2 * kBitsPerRegisterNumber + 5, 2> {}; // NOLINT
1967 Major MajorKey() { return DoubleToI; }
1968 int MinorKey() { return bit_field_; }
1972 DISALLOW_COPY_AND_ASSIGN(DoubleToIStub);
1976 class KeyedLoadFastElementStub : public HydrogenCodeStub {
1978 KeyedLoadFastElementStub(bool is_js_array, ElementsKind elements_kind) {
1979 bit_field_ = ElementsKindBits::encode(elements_kind) |
1980 IsJSArrayBits::encode(is_js_array);
1983 bool is_js_array() const {
1984 return IsJSArrayBits::decode(bit_field_);
1987 ElementsKind elements_kind() const {
1988 return ElementsKindBits::decode(bit_field_);
1991 virtual Handle<Code> GenerateCode(Isolate* isolate);
1993 virtual void InitializeInterfaceDescriptor(
1995 CodeStubInterfaceDescriptor* descriptor);
1998 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
1999 class IsJSArrayBits: public BitField<bool, 8, 1> {};
2000 uint32_t bit_field_;
2002 Major MajorKey() { return KeyedLoadElement; }
2003 int NotMissMinorKey() { return bit_field_; }
2005 DISALLOW_COPY_AND_ASSIGN(KeyedLoadFastElementStub);
2009 class KeyedStoreFastElementStub : public HydrogenCodeStub {
2011 KeyedStoreFastElementStub(bool is_js_array,
2012 ElementsKind elements_kind,
2013 KeyedAccessStoreMode mode) {
2014 bit_field_ = ElementsKindBits::encode(elements_kind) |
2015 IsJSArrayBits::encode(is_js_array) |
2016 StoreModeBits::encode(mode);
2019 bool is_js_array() const {
2020 return IsJSArrayBits::decode(bit_field_);
2023 ElementsKind elements_kind() const {
2024 return ElementsKindBits::decode(bit_field_);
2027 KeyedAccessStoreMode store_mode() const {
2028 return StoreModeBits::decode(bit_field_);
2031 virtual Handle<Code> GenerateCode(Isolate* isolate);
2033 virtual void InitializeInterfaceDescriptor(
2035 CodeStubInterfaceDescriptor* descriptor);
2038 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2039 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
2040 class IsJSArrayBits: public BitField<bool, 12, 1> {};
2041 uint32_t bit_field_;
2043 Major MajorKey() { return KeyedStoreElement; }
2044 int NotMissMinorKey() { return bit_field_; }
2046 DISALLOW_COPY_AND_ASSIGN(KeyedStoreFastElementStub);
2050 class TransitionElementsKindStub : public HydrogenCodeStub {
2052 TransitionElementsKindStub(ElementsKind from_kind,
2053 ElementsKind to_kind,
2055 bit_field_ = FromKindBits::encode(from_kind) |
2056 ToKindBits::encode(to_kind) |
2057 IsJSArrayBits::encode(is_js_array);
2060 ElementsKind from_kind() const {
2061 return FromKindBits::decode(bit_field_);
2064 ElementsKind to_kind() const {
2065 return ToKindBits::decode(bit_field_);
2068 bool is_js_array() const {
2069 return IsJSArrayBits::decode(bit_field_);
2072 virtual Handle<Code> GenerateCode(Isolate* isolate);
2074 virtual void InitializeInterfaceDescriptor(
2076 CodeStubInterfaceDescriptor* descriptor);
2079 class FromKindBits: public BitField<ElementsKind, 8, 8> {};
2080 class ToKindBits: public BitField<ElementsKind, 0, 8> {};
2081 class IsJSArrayBits: public BitField<bool, 16, 1> {};
2082 uint32_t bit_field_;
2084 Major MajorKey() { return TransitionElementsKind; }
2085 int NotMissMinorKey() { return bit_field_; }
2087 DISALLOW_COPY_AND_ASSIGN(TransitionElementsKindStub);
2091 class ArrayConstructorStubBase : public HydrogenCodeStub {
2093 ArrayConstructorStubBase(ElementsKind kind,
2094 AllocationSiteOverrideMode override_mode) {
2095 // It only makes sense to override local allocation site behavior
2096 // if there is a difference between the global allocation site policy
2097 // for an ElementsKind and the desired usage of the stub.
2098 ASSERT(override_mode != DISABLE_ALLOCATION_SITES ||
2099 AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
2100 bit_field_ = ElementsKindBits::encode(kind) |
2101 AllocationSiteOverrideModeBits::encode(override_mode);
2104 ElementsKind elements_kind() const {
2105 return ElementsKindBits::decode(bit_field_);
2108 AllocationSiteOverrideMode override_mode() const {
2109 return AllocationSiteOverrideModeBits::decode(bit_field_);
2112 static void GenerateStubsAheadOfTime(Isolate* isolate);
2113 static void InstallDescriptors(Isolate* isolate);
2115 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2116 static const int kConstructor = 0;
2117 static const int kAllocationSite = 1;
2120 void BasePrintName(const char* name, StringStream* stream);
2123 int NotMissMinorKey() { return bit_field_; }
2125 // Ensure data fits within available bits.
2126 STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
2128 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2129 class AllocationSiteOverrideModeBits: public
2130 BitField<AllocationSiteOverrideMode, 8, 1> {}; // NOLINT
2131 uint32_t bit_field_;
2133 DISALLOW_COPY_AND_ASSIGN(ArrayConstructorStubBase);
2137 class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
2139 ArrayNoArgumentConstructorStub(
2141 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2142 : ArrayConstructorStubBase(kind, override_mode) {
2145 virtual Handle<Code> GenerateCode(Isolate* isolate);
2147 virtual void InitializeInterfaceDescriptor(
2149 CodeStubInterfaceDescriptor* descriptor);
2152 Major MajorKey() { return ArrayNoArgumentConstructor; }
2154 virtual void PrintName(StringStream* stream) {
2155 BasePrintName("ArrayNoArgumentConstructorStub", stream);
2158 DISALLOW_COPY_AND_ASSIGN(ArrayNoArgumentConstructorStub);
2162 class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
2164 ArraySingleArgumentConstructorStub(
2166 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2167 : ArrayConstructorStubBase(kind, override_mode) {
2170 virtual Handle<Code> GenerateCode(Isolate* isolate);
2172 virtual void InitializeInterfaceDescriptor(
2174 CodeStubInterfaceDescriptor* descriptor);
2177 Major MajorKey() { return ArraySingleArgumentConstructor; }
2179 virtual void PrintName(StringStream* stream) {
2180 BasePrintName("ArraySingleArgumentConstructorStub", stream);
2183 DISALLOW_COPY_AND_ASSIGN(ArraySingleArgumentConstructorStub);
2187 class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
2189 ArrayNArgumentsConstructorStub(
2191 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2192 : ArrayConstructorStubBase(kind, override_mode) {
2195 virtual Handle<Code> GenerateCode(Isolate* isolate);
2197 virtual void InitializeInterfaceDescriptor(
2199 CodeStubInterfaceDescriptor* descriptor);
2202 Major MajorKey() { return ArrayNArgumentsConstructor; }
2204 virtual void PrintName(StringStream* stream) {
2205 BasePrintName("ArrayNArgumentsConstructorStub", stream);
2208 DISALLOW_COPY_AND_ASSIGN(ArrayNArgumentsConstructorStub);
2212 class InternalArrayConstructorStubBase : public HydrogenCodeStub {
2214 explicit InternalArrayConstructorStubBase(ElementsKind kind) {
2218 static void GenerateStubsAheadOfTime(Isolate* isolate);
2219 static void InstallDescriptors(Isolate* isolate);
2221 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2222 static const int kConstructor = 0;
2224 ElementsKind elements_kind() const { return kind_; }
2227 int NotMissMinorKey() { return kind_; }
2231 DISALLOW_COPY_AND_ASSIGN(InternalArrayConstructorStubBase);
2235 class InternalArrayNoArgumentConstructorStub : public
2236 InternalArrayConstructorStubBase {
2238 explicit InternalArrayNoArgumentConstructorStub(ElementsKind kind)
2239 : InternalArrayConstructorStubBase(kind) { }
2241 virtual Handle<Code> GenerateCode(Isolate* isolate);
2243 virtual void InitializeInterfaceDescriptor(
2245 CodeStubInterfaceDescriptor* descriptor);
2248 Major MajorKey() { return InternalArrayNoArgumentConstructor; }
2250 DISALLOW_COPY_AND_ASSIGN(InternalArrayNoArgumentConstructorStub);
2254 class InternalArraySingleArgumentConstructorStub : public
2255 InternalArrayConstructorStubBase {
2257 explicit InternalArraySingleArgumentConstructorStub(ElementsKind kind)
2258 : InternalArrayConstructorStubBase(kind) { }
2260 virtual Handle<Code> GenerateCode(Isolate* isolate);
2262 virtual void InitializeInterfaceDescriptor(
2264 CodeStubInterfaceDescriptor* descriptor);
2267 Major MajorKey() { return InternalArraySingleArgumentConstructor; }
2269 DISALLOW_COPY_AND_ASSIGN(InternalArraySingleArgumentConstructorStub);
2273 class InternalArrayNArgumentsConstructorStub : public
2274 InternalArrayConstructorStubBase {
2276 explicit InternalArrayNArgumentsConstructorStub(ElementsKind kind)
2277 : InternalArrayConstructorStubBase(kind) { }
2279 virtual Handle<Code> GenerateCode(Isolate* isolate);
2281 virtual void InitializeInterfaceDescriptor(
2283 CodeStubInterfaceDescriptor* descriptor);
2286 Major MajorKey() { return InternalArrayNArgumentsConstructor; }
2288 DISALLOW_COPY_AND_ASSIGN(InternalArrayNArgumentsConstructorStub);
2292 class KeyedStoreElementStub : public PlatformCodeStub {
2294 KeyedStoreElementStub(bool is_js_array,
2295 ElementsKind elements_kind,
2296 KeyedAccessStoreMode store_mode)
2297 : is_js_array_(is_js_array),
2298 elements_kind_(elements_kind),
2299 store_mode_(store_mode),
2300 fp_registers_(CanUseFPRegisters()) { }
2302 Major MajorKey() { return KeyedStoreElement; }
2304 return ElementsKindBits::encode(elements_kind_) |
2305 IsJSArrayBits::encode(is_js_array_) |
2306 StoreModeBits::encode(store_mode_) |
2307 FPRegisters::encode(fp_registers_);
2310 void Generate(MacroAssembler* masm);
2313 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2314 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
2315 class IsJSArrayBits: public BitField<bool, 12, 1> {};
2316 class FPRegisters: public BitField<bool, 13, 1> {};
2319 ElementsKind elements_kind_;
2320 KeyedAccessStoreMode store_mode_;
2323 DISALLOW_COPY_AND_ASSIGN(KeyedStoreElementStub);
2327 class ToBooleanStub: public HydrogenCodeStub {
2343 // At most 8 different types can be distinguished, because the Code object
2344 // only has room for a single byte to hold a set of these types. :-P
2345 STATIC_ASSERT(NUMBER_OF_TYPES <= 10);
2347 class Types : public EnumSet<Type, int> {
2349 Types() : EnumSet<Type, int>(0) {}
2350 explicit Types(int bits) : EnumSet<Type, int>(bits) {}
2352 void Print(StringStream* stream) const;
2353 bool UpdateStatus(Handle<Object> object);
2354 bool NeedsMap() const;
2355 bool CanBeUndetectable() const;
2356 bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
2358 static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
2361 explicit ToBooleanStub(Types types = Types())
2363 explicit ToBooleanStub(ExtraICState state)
2364 : types_(static_cast<int>(state)) { }
2366 bool UpdateStatus(Handle<Object> object);
2367 Types GetTypes() { return types_; }
2369 virtual Handle<Code> GenerateCode(Isolate* isolate);
2370 virtual void InitializeInterfaceDescriptor(
2372 CodeStubInterfaceDescriptor* descriptor);
2374 virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; }
2375 virtual void PrintState(StringStream* stream);
2377 virtual bool SometimesSetsUpAFrame() { return false; }
2379 static void InstallDescriptors(Isolate* isolate) {
2381 stub.InitializeInterfaceDescriptor(
2383 isolate->code_stub_interface_descriptor(CodeStub::ToBoolean));
2386 static Handle<Code> GetUninitialized(Isolate* isolate) {
2387 return ToBooleanStub(UNINITIALIZED).GetCode(isolate);
2390 virtual ExtraICState GetExtraICState() {
2391 return types_.ToIntegral();
2394 virtual InlineCacheState GetICState() {
2395 if (types_.IsEmpty()) {
2396 return ::v8::internal::UNINITIALIZED;
2403 Major MajorKey() { return ToBoolean; }
2404 int NotMissMinorKey() { return GetExtraICState(); }
2406 explicit ToBooleanStub(InitializationState init_state) :
2407 HydrogenCodeStub(init_state) {}
2413 class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
2415 ElementsTransitionAndStoreStub(ElementsKind from_kind,
2416 ElementsKind to_kind,
2418 KeyedAccessStoreMode store_mode)
2419 : from_kind_(from_kind),
2421 is_jsarray_(is_jsarray),
2422 store_mode_(store_mode) {}
2424 ElementsKind from_kind() const { return from_kind_; }
2425 ElementsKind to_kind() const { return to_kind_; }
2426 bool is_jsarray() const { return is_jsarray_; }
2427 KeyedAccessStoreMode store_mode() const { return store_mode_; }
2429 virtual Handle<Code> GenerateCode(Isolate* isolate);
2431 void InitializeInterfaceDescriptor(
2433 CodeStubInterfaceDescriptor* descriptor);
2436 class FromBits: public BitField<ElementsKind, 0, 8> {};
2437 class ToBits: public BitField<ElementsKind, 8, 8> {};
2438 class IsJSArrayBits: public BitField<bool, 16, 1> {};
2439 class StoreModeBits: public BitField<KeyedAccessStoreMode, 17, 4> {};
2441 Major MajorKey() { return ElementsTransitionAndStore; }
2442 int NotMissMinorKey() {
2443 return FromBits::encode(from_kind_) |
2444 ToBits::encode(to_kind_) |
2445 IsJSArrayBits::encode(is_jsarray_) |
2446 StoreModeBits::encode(store_mode_);
2449 ElementsKind from_kind_;
2450 ElementsKind to_kind_;
2452 KeyedAccessStoreMode store_mode_;
2454 DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub);
2458 class StoreArrayLiteralElementStub : public PlatformCodeStub {
2460 StoreArrayLiteralElementStub()
2461 : fp_registers_(CanUseFPRegisters()) { }
2464 class FPRegisters: public BitField<bool, 0, 1> {};
2466 Major MajorKey() { return StoreArrayLiteralElement; }
2467 int MinorKey() { return FPRegisters::encode(fp_registers_); }
2469 void Generate(MacroAssembler* masm);
2473 DISALLOW_COPY_AND_ASSIGN(StoreArrayLiteralElementStub);
2477 class StubFailureTrampolineStub : public PlatformCodeStub {
2479 explicit StubFailureTrampolineStub(StubFunctionMode function_mode)
2480 : fp_registers_(CanUseFPRegisters()), function_mode_(function_mode) {}
2482 static void GenerateAheadOfTime(Isolate* isolate);
2485 class FPRegisters: public BitField<bool, 0, 1> {};
2486 class FunctionModeField: public BitField<StubFunctionMode, 1, 1> {};
2488 Major MajorKey() { return StubFailureTrampoline; }
2490 return FPRegisters::encode(fp_registers_) |
2491 FunctionModeField::encode(function_mode_);
2494 void Generate(MacroAssembler* masm);
2497 StubFunctionMode function_mode_;
2499 DISALLOW_COPY_AND_ASSIGN(StubFailureTrampolineStub);
2503 class ProfileEntryHookStub : public PlatformCodeStub {
2505 explicit ProfileEntryHookStub() {}
2507 // The profile entry hook function is not allowed to cause a GC.
2508 virtual bool SometimesSetsUpAFrame() { return false; }
2510 // Generates a call to the entry hook if it's enabled.
2511 static void MaybeCallEntryHook(MacroAssembler* masm);
2514 static void EntryHookTrampoline(intptr_t function,
2515 intptr_t stack_pointer,
2518 Major MajorKey() { return ProfileEntryHook; }
2519 int MinorKey() { return 0; }
2521 void Generate(MacroAssembler* masm);
2523 DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub);
2527 class CallDescriptors {
2529 static void InitializeForIsolate(Isolate* isolate);
2532 } } // namespace v8::internal
2534 #endif // V8_CODE_STUBS_H_