1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef V8_CODE_STUBS_H_
6 #define V8_CODE_STUBS_H_
8 #include "src/allocation.h"
9 #include "src/assembler.h"
10 #include "src/codegen.h"
11 #include "src/globals.h"
12 #include "src/macro-assembler.h"
13 #include "src/ostreams.h"
18 // List of code stubs used on all platforms.
19 #define CODE_STUB_LIST_ALL_PLATFORMS(V) \
23 V(BinaryOpICWithAllocationSite) \
24 V(BinaryOpWithAllocationSite) \
34 V(FunctionPrototype) \
36 V(StoreBufferOverflow) \
40 V(WriteInt32ToHeapNumber) \
45 V(FastCloneShallowArray) \
46 V(FastCloneShallowObject) \
47 V(CreateAllocationSite) \
51 V(RegExpConstructResult) \
58 V(ArrayNoArgumentConstructor) \
59 V(ArraySingleArgumentConstructor) \
60 V(ArrayNArgumentsConstructor) \
61 V(InternalArrayNoArgumentConstructor) \
62 V(InternalArraySingleArgumentConstructor) \
63 V(InternalArrayNArgumentsConstructor) \
65 V(DebuggerStatement) \
66 V(NameDictionaryLookup) \
67 V(ElementsTransitionAndStore) \
68 V(TransitionElementsKind) \
69 V(StoreArrayLiteralElement) \
70 V(StubFailureTrampoline) \
72 V(InternalArrayConstructor) \
77 /* IC Handler stubs */ \
83 // List of code stubs only used on ARM 32 bits platforms.
84 #if V8_TARGET_ARCH_ARM
85 #define CODE_STUB_LIST_ARM(V) \
91 #define CODE_STUB_LIST_ARM(V)
94 // List of code stubs only used on ARM 64 bits platforms.
95 #if V8_TARGET_ARCH_ARM64
96 #define CODE_STUB_LIST_ARM64(V) \
101 V(StoreRegistersState) \
102 V(RestoreRegistersState)
104 #define CODE_STUB_LIST_ARM64(V)
107 // List of code stubs only used on MIPS platforms.
108 #if V8_TARGET_ARCH_MIPS
109 #define CODE_STUB_LIST_MIPS(V) \
112 V(StoreRegistersState) \
113 V(RestoreRegistersState)
114 #elif V8_TARGET_ARCH_MIPS64
115 #define CODE_STUB_LIST_MIPS(V) \
118 V(StoreRegistersState) \
119 V(RestoreRegistersState)
121 #define CODE_STUB_LIST_MIPS(V)
124 // Combined list of code stubs.
125 #define CODE_STUB_LIST(V) \
126 CODE_STUB_LIST_ALL_PLATFORMS(V) \
127 CODE_STUB_LIST_ARM(V) \
128 CODE_STUB_LIST_ARM64(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();
146 // Retrieve the code for the stub, make and return a copy of the code.
147 Handle<Code> GetCodeCopy(const Code::FindAndReplacePattern& pattern);
149 static Major MajorKeyFromKey(uint32_t key) {
150 return static_cast<Major>(MajorKeyBits::decode(key));
152 static int MinorKeyFromKey(uint32_t key) {
153 return MinorKeyBits::decode(key);
156 // Gets the major key from a code object that is a code stub or binary op IC.
157 static Major GetMajorKey(Code* code_stub) {
158 return MajorKeyFromKey(code_stub->stub_key());
161 static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }
163 static const char* MajorName(Major major_key, bool allow_unknown_keys);
165 explicit CodeStub(Isolate* isolate) : isolate_(isolate) { }
166 virtual ~CodeStub() {}
168 static void GenerateStubsAheadOfTime(Isolate* isolate);
169 static void GenerateFPStubs(Isolate* isolate);
171 // Some stubs put untagged junk on the stack that cannot be scanned by the
172 // GC. This means that we must be statically sure that no GC can occur while
173 // they are running. If that is the case they should override this to return
174 // true, which will cause an assertion if we try to call something that can
175 // GC or if we try to put a stack frame on top of the junk, which would not
176 // result in a traversable stack.
177 virtual bool SometimesSetsUpAFrame() { return true; }
179 // Lookup the code in the (possibly custom) cache.
180 bool FindCodeInCache(Code** code_out);
182 // Returns information for computing the number key.
183 virtual Major MajorKey() const = 0;
184 virtual int MinorKey() const = 0;
186 virtual InlineCacheState GetICState() const { return UNINITIALIZED; }
187 virtual ExtraICState GetExtraICState() const { return kNoExtraICState; }
188 virtual Code::StubType GetStubType() {
192 friend OStream& operator<<(OStream& os, const CodeStub& s) {
197 Isolate* isolate() const { return isolate_; }
200 // Generates the assembler code for the stub.
201 virtual Handle<Code> GenerateCode() = 0;
203 // Returns whether the code generated for this stub needs to be allocated as
204 // a fixed (non-moveable) code object.
205 virtual bool NeedsImmovableCode() { return false; }
207 virtual void PrintName(OStream& os) const; // NOLINT
208 virtual void PrintBaseName(OStream& os) const; // NOLINT
209 virtual void PrintState(OStream& os) const { ; } // NOLINT
211 // Computes the key based on major and minor.
213 DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
214 return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey());
218 // Perform bookkeeping required after code generation when stub code is
219 // initially generated.
220 void RecordCodeGeneration(Handle<Code> code);
222 // Finish the code object after it has been generated.
223 virtual void FinishCode(Handle<Code> code) { }
225 // Activate newly generated stub. Is called after
226 // registering stub in the stub cache.
227 virtual void Activate(Code* code) { }
229 // BinaryOpStub needs to override this.
230 virtual Code::Kind GetCodeKind() const;
232 // Add the code to a specialized cache, specific to an individual
233 // stub type. Please note, this method must add the code object to a
234 // roots object, otherwise we will remove the code during GC.
235 virtual void AddToSpecialCache(Handle<Code> new_object) { }
237 // Find code in a specialized cache, work is delegated to the specific stub.
238 virtual bool FindCodeInSpecialCache(Code** code_out) {
242 // If a stub uses a special cache override this.
243 virtual bool UseSpecialCache() { return false; }
245 STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
246 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
247 class MinorKeyBits: public BitField<uint32_t,
248 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT
250 friend class BreakPointIterator;
256 class PlatformCodeStub : public CodeStub {
258 explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) { }
260 // Retrieve the code for the stub. Generate the code if needed.
261 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
263 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
266 // Generates the assembler code for the stub.
267 virtual void Generate(MacroAssembler* masm) = 0;
271 enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
272 enum HandlerArgumentsMode { DONT_PASS_ARGUMENTS, PASS_ARGUMENTS };
275 class PlatformInterfaceDescriptor;
278 class InterfaceDescriptor {
280 bool IsInitialized() const { return register_param_count_ >= 0; }
282 int GetEnvironmentLength() const { return register_param_count_; }
284 int GetRegisterParameterCount() const { return register_param_count_; }
286 Register GetParameterRegister(int index) const {
287 return register_params_[index];
290 Representation GetParameterRepresentation(int index) const {
291 DCHECK(index < register_param_count_);
292 if (register_param_representations_.get() == NULL) {
293 return Representation::Tagged();
296 return register_param_representations_[index];
299 // "Environment" versions of parameter functions. The first register
300 // parameter (context) is not included.
301 int GetEnvironmentParameterCount() const {
302 return GetEnvironmentLength() - 1;
305 Register GetEnvironmentParameterRegister(int index) const {
306 return GetParameterRegister(index + 1);
309 Representation GetEnvironmentParameterRepresentation(int index) const {
310 return GetParameterRepresentation(index + 1);
313 // Some platforms have extra information to associate with the descriptor.
314 PlatformInterfaceDescriptor* platform_specific_descriptor() const {
315 return platform_specific_descriptor_;
318 static const Register ContextRegister();
321 InterfaceDescriptor();
322 virtual ~InterfaceDescriptor() {}
324 void Initialize(int register_parameter_count, Register* registers,
325 Representation* register_param_representations,
326 PlatformInterfaceDescriptor* platform_descriptor = NULL);
329 int register_param_count_;
331 // The Register params are allocated dynamically by the
332 // InterfaceDescriptor, and freed on destruction. This is because static
333 // arrays of Registers cause creation of runtime static initializers
334 // which we don't want.
335 SmartArrayPointer<Register> register_params_;
336 // Specifies Representations for the stub's parameter. Points to an array of
337 // Representations of the same length of the numbers of parameters to the
338 // stub, or if NULL (the default value), Representation of each parameter
339 // assumed to be Tagged().
340 SmartArrayPointer<Representation> register_param_representations_;
342 PlatformInterfaceDescriptor* platform_specific_descriptor_;
344 DISALLOW_COPY_AND_ASSIGN(InterfaceDescriptor);
348 class CodeStubInterfaceDescriptor: public InterfaceDescriptor {
350 CodeStubInterfaceDescriptor();
352 void Initialize(CodeStub::Major major, int register_parameter_count,
353 Register* registers, Address deoptimization_handler = NULL,
354 Representation* register_param_representations = NULL,
355 int hint_stack_parameter_count = -1,
356 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
357 void Initialize(CodeStub::Major major, int register_parameter_count,
358 Register* registers, Register stack_parameter_count,
359 Address deoptimization_handler = NULL,
360 Representation* register_param_representations = NULL,
361 int hint_stack_parameter_count = -1,
362 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE,
363 HandlerArgumentsMode handler_mode = DONT_PASS_ARGUMENTS);
365 void SetMissHandler(ExternalReference handler) {
366 miss_handler_ = handler;
367 has_miss_handler_ = true;
368 // Our miss handler infrastructure doesn't currently support
369 // variable stack parameter counts.
370 DCHECK(!stack_parameter_count_.is_valid());
373 ExternalReference miss_handler() const {
374 DCHECK(has_miss_handler_);
375 return miss_handler_;
378 bool has_miss_handler() const {
379 return has_miss_handler_;
382 bool IsEnvironmentParameterCountRegister(int index) const {
383 return GetEnvironmentParameterRegister(index).is(stack_parameter_count_);
386 int GetHandlerParameterCount() const {
387 int params = GetEnvironmentParameterCount();
388 if (handler_arguments_mode_ == PASS_ARGUMENTS) {
394 int hint_stack_parameter_count() const { return hint_stack_parameter_count_; }
395 Register stack_parameter_count() const { return stack_parameter_count_; }
396 StubFunctionMode function_mode() const { return function_mode_; }
397 Address deoptimization_handler() const { return deoptimization_handler_; }
398 CodeStub::Major MajorKey() const { return major_; }
401 Register stack_parameter_count_;
402 // If hint_stack_parameter_count_ > 0, the code stub can optimize the
403 // return sequence. Default value is -1, which means it is ignored.
404 int hint_stack_parameter_count_;
405 StubFunctionMode function_mode_;
407 Address deoptimization_handler_;
408 HandlerArgumentsMode handler_arguments_mode_;
410 ExternalReference miss_handler_;
411 bool has_miss_handler_;
412 CodeStub::Major major_;
416 class CallInterfaceDescriptor: public InterfaceDescriptor {
418 CallInterfaceDescriptor() { }
420 // A copy of the passed in registers and param_representations is made
421 // and owned by the CallInterfaceDescriptor.
423 // TODO(mvstanton): Instead of taking parallel arrays register and
424 // param_representations, how about a struct that puts the representation
425 // and register side by side (eg, RegRep(r1, Representation::Tagged()).
426 // The same should go for the CodeStubInterfaceDescriptor class.
427 void Initialize(int register_parameter_count, Register* registers,
428 Representation* param_representations,
429 PlatformInterfaceDescriptor* platform_descriptor = NULL);
433 class HydrogenCodeStub : public CodeStub {
435 enum InitializationState {
440 explicit HydrogenCodeStub(Isolate* isolate,
441 InitializationState state = INITIALIZED)
442 : CodeStub(isolate) {
443 is_uninitialized_ = (state == UNINITIALIZED);
446 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
448 CodeStubInterfaceDescriptor* GetInterfaceDescriptor() {
449 return isolate()->code_stub_interface_descriptor(MajorKey());
452 bool IsUninitialized() { return is_uninitialized_; }
454 template<class SubClass>
455 static Handle<Code> GetUninitialized(Isolate* isolate) {
456 SubClass::GenerateAheadOfTime(isolate);
457 return SubClass().GetCode(isolate);
460 virtual void InitializeInterfaceDescriptor(
461 CodeStubInterfaceDescriptor* descriptor) = 0;
463 // Retrieve the code for the stub. Generate the code if needed.
464 virtual Handle<Code> GenerateCode() = 0;
466 virtual int NotMissMinorKey() const = 0;
468 Handle<Code> GenerateLightweightMissCode();
470 template<class StateType>
471 void TraceTransition(StateType from, StateType to);
474 class MinorKeyBits: public BitField<int, 0, kStubMinorKeyBits - 1> {};
475 class IsMissBits: public BitField<bool, kStubMinorKeyBits - 1, 1> {};
477 void GenerateLightweightMiss(MacroAssembler* masm);
478 virtual int MinorKey() const {
479 return IsMissBits::encode(is_uninitialized_) |
480 MinorKeyBits::encode(NotMissMinorKey());
483 bool is_uninitialized_;
487 // Helper interface to prepare to/restore after making runtime calls.
488 class RuntimeCallHelper {
490 virtual ~RuntimeCallHelper() {}
492 virtual void BeforeCall(MacroAssembler* masm) const = 0;
494 virtual void AfterCall(MacroAssembler* masm) const = 0;
497 RuntimeCallHelper() {}
500 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
504 } } // namespace v8::internal
506 #if V8_TARGET_ARCH_IA32
507 #include "src/ia32/code-stubs-ia32.h"
508 #elif V8_TARGET_ARCH_X64
509 #include "src/x64/code-stubs-x64.h"
510 #elif V8_TARGET_ARCH_ARM64
511 #include "src/arm64/code-stubs-arm64.h"
512 #elif V8_TARGET_ARCH_ARM
513 #include "src/arm/code-stubs-arm.h"
514 #elif V8_TARGET_ARCH_MIPS
515 #include "src/mips/code-stubs-mips.h"
516 #elif V8_TARGET_ARCH_MIPS64
517 #include "src/mips64/code-stubs-mips64.h"
518 #elif V8_TARGET_ARCH_X87
519 #include "src/x87/code-stubs-x87.h"
521 #error Unsupported target architecture.
528 // RuntimeCallHelper implementation used in stubs: enters/leaves a
529 // newly created internal frame before/after the runtime call.
530 class StubRuntimeCallHelper : public RuntimeCallHelper {
532 StubRuntimeCallHelper() {}
534 virtual void BeforeCall(MacroAssembler* masm) const;
536 virtual void AfterCall(MacroAssembler* masm) const;
540 // Trivial RuntimeCallHelper implementation.
541 class NopRuntimeCallHelper : public RuntimeCallHelper {
543 NopRuntimeCallHelper() {}
545 virtual void BeforeCall(MacroAssembler* masm) const {}
547 virtual void AfterCall(MacroAssembler* masm) const {}
551 class ToNumberStub: public HydrogenCodeStub {
553 explicit ToNumberStub(Isolate* isolate) : HydrogenCodeStub(isolate) { }
555 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
557 virtual void InitializeInterfaceDescriptor(
558 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
560 static void InstallDescriptors(Isolate* isolate) {
561 ToNumberStub stub(isolate);
562 stub.InitializeInterfaceDescriptor(
563 isolate->code_stub_interface_descriptor(CodeStub::ToNumber));
567 Major MajorKey() const { return ToNumber; }
568 int NotMissMinorKey() const { return 0; }
572 class NumberToStringStub V8_FINAL : public HydrogenCodeStub {
574 explicit NumberToStringStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
576 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
578 virtual void InitializeInterfaceDescriptor(
579 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
581 static void InstallDescriptors(Isolate* isolate);
583 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
584 static const int kNumber = 0;
587 virtual Major MajorKey() const V8_OVERRIDE { return NumberToString; }
588 virtual int NotMissMinorKey() const V8_OVERRIDE { return 0; }
592 class FastNewClosureStub : public HydrogenCodeStub {
594 FastNewClosureStub(Isolate* isolate,
595 StrictMode strict_mode,
597 : HydrogenCodeStub(isolate),
598 strict_mode_(strict_mode),
599 is_generator_(is_generator) { }
601 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
603 virtual void InitializeInterfaceDescriptor(
604 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
606 static void InstallDescriptors(Isolate* isolate);
608 StrictMode strict_mode() const { return strict_mode_; }
609 bool is_generator() const { return is_generator_; }
612 class StrictModeBits: public BitField<bool, 0, 1> {};
613 class IsGeneratorBits: public BitField<bool, 1, 1> {};
615 Major MajorKey() const { return FastNewClosure; }
616 int NotMissMinorKey() const {
617 return StrictModeBits::encode(strict_mode_ == STRICT) |
618 IsGeneratorBits::encode(is_generator_);
621 StrictMode strict_mode_;
626 class FastNewContextStub V8_FINAL : public HydrogenCodeStub {
628 static const int kMaximumSlots = 64;
630 FastNewContextStub(Isolate* isolate, int slots)
631 : HydrogenCodeStub(isolate), slots_(slots) {
632 DCHECK(slots_ > 0 && slots_ <= kMaximumSlots);
635 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
637 virtual void InitializeInterfaceDescriptor(
638 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
640 static void InstallDescriptors(Isolate* isolate);
642 int slots() const { return slots_; }
644 virtual Major MajorKey() const V8_OVERRIDE { return FastNewContext; }
645 virtual int NotMissMinorKey() const V8_OVERRIDE { return slots_; }
647 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
648 static const int kFunction = 0;
655 class FastCloneShallowArrayStub : public HydrogenCodeStub {
657 FastCloneShallowArrayStub(Isolate* isolate,
658 AllocationSiteMode allocation_site_mode)
659 : HydrogenCodeStub(isolate),
660 allocation_site_mode_(allocation_site_mode) {}
662 AllocationSiteMode allocation_site_mode() const {
663 return allocation_site_mode_;
666 virtual Handle<Code> GenerateCode();
668 virtual void InitializeInterfaceDescriptor(
669 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
671 static void InstallDescriptors(Isolate* isolate);
674 AllocationSiteMode allocation_site_mode_;
676 class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
677 // Ensure data fits within available bits.
678 Major MajorKey() const { return FastCloneShallowArray; }
679 int NotMissMinorKey() const {
680 return AllocationSiteModeBits::encode(allocation_site_mode_);
685 class FastCloneShallowObjectStub : public HydrogenCodeStub {
687 // Maximum number of properties in copied object.
688 static const int kMaximumClonedProperties = 6;
690 FastCloneShallowObjectStub(Isolate* isolate, int length)
691 : HydrogenCodeStub(isolate), length_(length) {
692 DCHECK_GE(length_, 0);
693 DCHECK_LE(length_, kMaximumClonedProperties);
696 int length() const { return length_; }
698 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
700 virtual void InitializeInterfaceDescriptor(
701 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
706 Major MajorKey() const { return FastCloneShallowObject; }
707 int NotMissMinorKey() const { return length_; }
709 DISALLOW_COPY_AND_ASSIGN(FastCloneShallowObjectStub);
713 class CreateAllocationSiteStub : public HydrogenCodeStub {
715 explicit CreateAllocationSiteStub(Isolate* isolate)
716 : HydrogenCodeStub(isolate) { }
718 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
720 static void GenerateAheadOfTime(Isolate* isolate);
722 virtual void InitializeInterfaceDescriptor(
723 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
726 Major MajorKey() const { return CreateAllocationSite; }
727 int NotMissMinorKey() const { return 0; }
729 DISALLOW_COPY_AND_ASSIGN(CreateAllocationSiteStub);
733 class InstanceofStub: public PlatformCodeStub {
737 kArgsInRegisters = 1 << 0,
738 kCallSiteInlineCheck = 1 << 1,
739 kReturnTrueFalseObject = 1 << 2
742 InstanceofStub(Isolate* isolate, Flags flags)
743 : PlatformCodeStub(isolate), flags_(flags) { }
745 static Register left();
746 static Register right();
748 void Generate(MacroAssembler* masm);
750 virtual void InitializeInterfaceDescriptor(
751 CodeStubInterfaceDescriptor* descriptor);
754 Major MajorKey() const { return Instanceof; }
755 int MinorKey() const { return static_cast<int>(flags_); }
757 bool HasArgsInRegisters() const {
758 return (flags_ & kArgsInRegisters) != 0;
761 bool HasCallSiteInlineCheck() const {
762 return (flags_ & kCallSiteInlineCheck) != 0;
765 bool ReturnTrueFalseObject() const {
766 return (flags_ & kReturnTrueFalseObject) != 0;
769 virtual void PrintName(OStream& os) const V8_OVERRIDE; // NOLINT
775 enum AllocationSiteOverrideMode {
777 DISABLE_ALLOCATION_SITES,
778 LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
782 class ArrayConstructorStub: public PlatformCodeStub {
784 enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
785 ArrayConstructorStub(Isolate* isolate, int argument_count);
786 explicit ArrayConstructorStub(Isolate* isolate);
788 void Generate(MacroAssembler* masm);
791 void GenerateDispatchToArrayStub(MacroAssembler* masm,
792 AllocationSiteOverrideMode mode);
793 virtual void PrintName(OStream& os) const V8_OVERRIDE; // NOLINT
795 virtual CodeStub::Major MajorKey() const { return ArrayConstructor; }
796 virtual int MinorKey() const { return argument_count_; }
798 ArgumentCountKey argument_count_;
802 class InternalArrayConstructorStub: public PlatformCodeStub {
804 explicit InternalArrayConstructorStub(Isolate* isolate);
806 void Generate(MacroAssembler* masm);
809 virtual CodeStub::Major MajorKey() const { return InternalArrayConstructor; }
810 virtual int MinorKey() const { return 0; }
812 void GenerateCase(MacroAssembler* masm, ElementsKind kind);
816 class MathPowStub: public PlatformCodeStub {
818 enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK };
820 MathPowStub(Isolate* isolate, ExponentType exponent_type)
821 : PlatformCodeStub(isolate), exponent_type_(exponent_type) { }
822 virtual void Generate(MacroAssembler* masm);
825 virtual CodeStub::Major MajorKey() const { return MathPow; }
826 virtual int MinorKey() const { return exponent_type_; }
828 ExponentType exponent_type_;
832 class CallICStub: public PlatformCodeStub {
834 CallICStub(Isolate* isolate, const CallIC::State& state)
835 : PlatformCodeStub(isolate), state_(state) {}
837 bool CallAsMethod() const { return state_.CallAsMethod(); }
839 int arg_count() const { return state_.arg_count(); }
841 static int ExtractArgcFromMinorKey(int minor_key) {
842 CallIC::State state((ExtraICState) minor_key);
843 return state.arg_count();
846 virtual void Generate(MacroAssembler* masm);
848 virtual Code::Kind GetCodeKind() const V8_OVERRIDE {
849 return Code::CALL_IC;
852 virtual InlineCacheState GetICState() const V8_OVERRIDE { return DEFAULT; }
854 virtual ExtraICState GetExtraICState() const V8_FINAL V8_OVERRIDE {
855 return state_.GetExtraICState();
859 virtual int MinorKey() const { return GetExtraICState(); }
860 virtual void PrintState(OStream& os) const V8_OVERRIDE; // NOLINT
862 virtual CodeStub::Major MajorKey() const { return CallIC; }
864 // Code generation helpers.
865 void GenerateMiss(MacroAssembler* masm, IC::UtilityId id);
867 const CallIC::State state_;
871 class CallIC_ArrayStub: public CallICStub {
873 CallIC_ArrayStub(Isolate* isolate, const CallIC::State& state_in)
874 : CallICStub(isolate, state_in) {}
876 virtual void Generate(MacroAssembler* masm);
878 virtual InlineCacheState GetICState() const V8_FINAL V8_OVERRIDE {
883 virtual void PrintState(OStream& os) const V8_OVERRIDE; // NOLINT
885 virtual CodeStub::Major MajorKey() const { return CallIC_Array; }
889 // TODO(verwaest): Translate to hydrogen code stub.
890 class FunctionPrototypeStub : public PlatformCodeStub {
892 explicit FunctionPrototypeStub(Isolate* isolate)
893 : PlatformCodeStub(isolate) {}
894 virtual void Generate(MacroAssembler* masm);
895 virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
898 virtual CodeStub::Major MajorKey() const { return FunctionPrototype; }
899 virtual int MinorKey() const { return 0; }
903 class HandlerStub : public HydrogenCodeStub {
905 virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
906 virtual ExtraICState GetExtraICState() const { return kind(); }
907 virtual InlineCacheState GetICState() const { return MONOMORPHIC; }
909 virtual void InitializeInterfaceDescriptor(
910 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
913 explicit HandlerStub(Isolate* isolate)
914 : HydrogenCodeStub(isolate), bit_field_(0) {}
915 virtual int NotMissMinorKey() const { return bit_field_; }
916 virtual Code::Kind kind() const = 0;
921 class LoadFieldStub: public HandlerStub {
923 LoadFieldStub(Isolate* isolate, FieldIndex index)
924 : HandlerStub(isolate), index_(index) {
925 int property_index_key = index_.GetFieldAccessStubKey();
926 bit_field_ = EncodedLoadFieldByIndexBits::encode(property_index_key);
929 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
931 FieldIndex index() const { return index_; }
934 explicit LoadFieldStub(Isolate* isolate);
935 virtual Code::Kind kind() const { return Code::LOAD_IC; }
936 virtual Code::StubType GetStubType() { return Code::FAST; }
939 class EncodedLoadFieldByIndexBits : public BitField<int, 0, 13> {};
940 virtual CodeStub::Major MajorKey() const { return LoadField; }
945 class LoadConstantStub : public HandlerStub {
947 LoadConstantStub(Isolate* isolate, int descriptor) : HandlerStub(isolate) {
948 bit_field_ = descriptor;
951 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
953 int descriptor() const { return bit_field_; }
956 explicit LoadConstantStub(Isolate* isolate);
957 virtual Code::Kind kind() const { return Code::LOAD_IC; }
958 virtual Code::StubType GetStubType() { return Code::FAST; }
961 virtual CodeStub::Major MajorKey() const { return LoadConstant; }
965 class StringLengthStub: public HandlerStub {
967 explicit StringLengthStub(Isolate* isolate) : HandlerStub(isolate) {}
968 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
971 virtual Code::Kind kind() const { return Code::LOAD_IC; }
972 virtual Code::StubType GetStubType() { return Code::FAST; }
975 virtual CodeStub::Major MajorKey() const { return StringLength; }
979 class StoreFieldStub : public HandlerStub {
981 StoreFieldStub(Isolate* isolate, FieldIndex index,
982 Representation representation)
983 : HandlerStub(isolate), index_(index), representation_(representation) {
984 int property_index_key = index_.GetFieldAccessStubKey();
985 bit_field_ = EncodedStoreFieldByIndexBits::encode(property_index_key) |
986 RepresentationBits::encode(
987 PropertyDetails::EncodeRepresentation(representation));
990 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
992 FieldIndex index() const { return index_; }
993 Representation representation() { return representation_; }
994 static void InstallDescriptors(Isolate* isolate);
997 explicit StoreFieldStub(Isolate* isolate);
998 virtual Code::Kind kind() const { return Code::STORE_IC; }
999 virtual Code::StubType GetStubType() { return Code::FAST; }
1002 class EncodedStoreFieldByIndexBits : public BitField<int, 0, 13> {};
1003 class RepresentationBits : public BitField<int, 13, 4> {};
1004 virtual CodeStub::Major MajorKey() const { return StoreField; }
1006 Representation representation_;
1010 class StoreGlobalStub : public HandlerStub {
1012 StoreGlobalStub(Isolate* isolate, bool is_constant, bool check_global)
1013 : HandlerStub(isolate) {
1014 bit_field_ = IsConstantBits::encode(is_constant) |
1015 CheckGlobalBits::encode(check_global);
1018 static Handle<HeapObject> global_placeholder(Isolate* isolate) {
1019 return isolate->factory()->uninitialized_value();
1022 Handle<Code> GetCodeCopyFromTemplate(Handle<GlobalObject> global,
1023 Handle<PropertyCell> cell) {
1024 if (check_global()) {
1025 Code::FindAndReplacePattern pattern;
1026 pattern.Add(Handle<Map>(global_placeholder(isolate())->map()), global);
1027 pattern.Add(isolate()->factory()->meta_map(), Handle<Map>(global->map()));
1028 pattern.Add(isolate()->factory()->global_property_cell_map(), cell);
1029 return CodeStub::GetCodeCopy(pattern);
1031 Code::FindAndReplacePattern pattern;
1032 pattern.Add(isolate()->factory()->global_property_cell_map(), cell);
1033 return CodeStub::GetCodeCopy(pattern);
1037 virtual Code::Kind kind() const { return Code::STORE_IC; }
1039 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
1041 bool is_constant() const {
1042 return IsConstantBits::decode(bit_field_);
1044 bool check_global() const {
1045 return CheckGlobalBits::decode(bit_field_);
1047 void set_is_constant(bool value) {
1048 bit_field_ = IsConstantBits::update(bit_field_, value);
1051 Representation representation() {
1052 return Representation::FromKind(RepresentationBits::decode(bit_field_));
1054 void set_representation(Representation r) {
1055 bit_field_ = RepresentationBits::update(bit_field_, r.kind());
1059 Major MajorKey() const { return StoreGlobal; }
1061 class IsConstantBits: public BitField<bool, 0, 1> {};
1062 class RepresentationBits: public BitField<Representation::Kind, 1, 8> {};
1063 class CheckGlobalBits: public BitField<bool, 9, 1> {};
1065 DISALLOW_COPY_AND_ASSIGN(StoreGlobalStub);
1069 class CallApiFunctionStub : public PlatformCodeStub {
1071 CallApiFunctionStub(Isolate* isolate,
1073 bool call_data_undefined,
1074 int argc) : PlatformCodeStub(isolate) {
1076 IsStoreBits::encode(is_store) |
1077 CallDataUndefinedBits::encode(call_data_undefined) |
1078 ArgumentBits::encode(argc);
1079 DCHECK(!is_store || argc == 1);
1083 virtual void Generate(MacroAssembler* masm) V8_OVERRIDE;
1084 virtual Major MajorKey() const V8_OVERRIDE { return CallApiFunction; }
1085 virtual int MinorKey() const V8_OVERRIDE { return bit_field_; }
1087 class IsStoreBits: public BitField<bool, 0, 1> {};
1088 class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
1089 class ArgumentBits: public BitField<int, 2, Code::kArgumentsBits> {};
1093 DISALLOW_COPY_AND_ASSIGN(CallApiFunctionStub);
1097 class CallApiGetterStub : public PlatformCodeStub {
1099 explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1102 virtual void Generate(MacroAssembler* masm) V8_OVERRIDE;
1103 virtual Major MajorKey() const V8_OVERRIDE { return CallApiGetter; }
1104 virtual int MinorKey() const V8_OVERRIDE { return 0; }
1106 DISALLOW_COPY_AND_ASSIGN(CallApiGetterStub);
1110 class BinaryOpICStub : public HydrogenCodeStub {
1112 BinaryOpICStub(Isolate* isolate, Token::Value op,
1113 OverwriteMode mode = NO_OVERWRITE)
1114 : HydrogenCodeStub(isolate, UNINITIALIZED), state_(isolate, op, mode) {}
1116 explicit BinaryOpICStub(Isolate* isolate, const BinaryOpIC::State& state)
1117 : HydrogenCodeStub(isolate), state_(state) {}
1119 static void GenerateAheadOfTime(Isolate* isolate);
1121 virtual void InitializeInterfaceDescriptor(
1122 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1124 static void InstallDescriptors(Isolate* isolate);
1126 virtual Code::Kind GetCodeKind() const V8_OVERRIDE {
1127 return Code::BINARY_OP_IC;
1130 virtual InlineCacheState GetICState() const V8_FINAL V8_OVERRIDE {
1131 return state_.GetICState();
1134 virtual ExtraICState GetExtraICState() const V8_FINAL V8_OVERRIDE {
1135 return state_.GetExtraICState();
1138 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
1140 const BinaryOpIC::State& state() const { return state_; }
1142 virtual void PrintState(OStream& os) const V8_FINAL V8_OVERRIDE; // NOLINT
1144 virtual Major MajorKey() const V8_OVERRIDE { return BinaryOpIC; }
1145 virtual int NotMissMinorKey() const V8_FINAL V8_OVERRIDE {
1146 return GetExtraICState();
1149 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1150 static const int kLeft = 0;
1151 static const int kRight = 1;
1154 static void GenerateAheadOfTime(Isolate* isolate,
1155 const BinaryOpIC::State& state);
1157 BinaryOpIC::State state_;
1159 DISALLOW_COPY_AND_ASSIGN(BinaryOpICStub);
1163 // TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
1164 // call support for stubs in Hydrogen.
1165 class BinaryOpICWithAllocationSiteStub V8_FINAL : public PlatformCodeStub {
1167 BinaryOpICWithAllocationSiteStub(Isolate* isolate,
1168 const BinaryOpIC::State& state)
1169 : PlatformCodeStub(isolate), state_(state) {}
1171 static void GenerateAheadOfTime(Isolate* isolate);
1173 Handle<Code> GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site) {
1174 Code::FindAndReplacePattern pattern;
1175 pattern.Add(isolate()->factory()->undefined_map(), allocation_site);
1176 return CodeStub::GetCodeCopy(pattern);
1179 virtual Code::Kind GetCodeKind() const V8_OVERRIDE {
1180 return Code::BINARY_OP_IC;
1183 virtual InlineCacheState GetICState() const V8_OVERRIDE {
1184 return state_.GetICState();
1187 virtual ExtraICState GetExtraICState() const V8_OVERRIDE {
1188 return state_.GetExtraICState();
1191 virtual void Generate(MacroAssembler* masm) V8_OVERRIDE;
1193 virtual void PrintState(OStream& os) const V8_OVERRIDE; // NOLINT
1195 virtual Major MajorKey() const V8_OVERRIDE {
1196 return BinaryOpICWithAllocationSite;
1198 virtual int MinorKey() const V8_OVERRIDE { return GetExtraICState(); }
1201 static void GenerateAheadOfTime(Isolate* isolate,
1202 const BinaryOpIC::State& state);
1204 BinaryOpIC::State state_;
1206 DISALLOW_COPY_AND_ASSIGN(BinaryOpICWithAllocationSiteStub);
1210 class BinaryOpWithAllocationSiteStub V8_FINAL : public BinaryOpICStub {
1212 BinaryOpWithAllocationSiteStub(Isolate* isolate,
1215 : BinaryOpICStub(isolate, op, mode) {}
1217 BinaryOpWithAllocationSiteStub(Isolate* isolate,
1218 const BinaryOpIC::State& state)
1219 : BinaryOpICStub(isolate, state) {}
1221 virtual void InitializeInterfaceDescriptor(
1222 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1224 static void InstallDescriptors(Isolate* isolate);
1226 virtual Code::Kind GetCodeKind() const V8_FINAL V8_OVERRIDE {
1230 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
1232 virtual Major MajorKey() const V8_OVERRIDE {
1233 return BinaryOpWithAllocationSite;
1236 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1237 static const int kAllocationSite = 0;
1238 static const int kLeft = 1;
1239 static const int kRight = 2;
1243 enum StringAddFlags {
1244 // Omit both parameter checks.
1245 STRING_ADD_CHECK_NONE = 0,
1246 // Check left parameter.
1247 STRING_ADD_CHECK_LEFT = 1 << 0,
1248 // Check right parameter.
1249 STRING_ADD_CHECK_RIGHT = 1 << 1,
1250 // Check both parameters.
1251 STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT
1255 class StringAddStub V8_FINAL : public HydrogenCodeStub {
1257 StringAddStub(Isolate* isolate,
1258 StringAddFlags flags,
1259 PretenureFlag pretenure_flag)
1260 : HydrogenCodeStub(isolate),
1261 bit_field_(StringAddFlagsBits::encode(flags) |
1262 PretenureFlagBits::encode(pretenure_flag)) {}
1264 StringAddFlags flags() const {
1265 return StringAddFlagsBits::decode(bit_field_);
1268 PretenureFlag pretenure_flag() const {
1269 return PretenureFlagBits::decode(bit_field_);
1272 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
1274 virtual void InitializeInterfaceDescriptor(
1275 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1277 static void InstallDescriptors(Isolate* isolate);
1279 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1280 static const int kLeft = 0;
1281 static const int kRight = 1;
1284 class StringAddFlagsBits: public BitField<StringAddFlags, 0, 2> {};
1285 class PretenureFlagBits: public BitField<PretenureFlag, 2, 1> {};
1286 uint32_t bit_field_;
1288 virtual Major MajorKey() const V8_OVERRIDE { return StringAdd; }
1289 virtual int NotMissMinorKey() const V8_OVERRIDE { return bit_field_; }
1291 virtual void PrintBaseName(OStream& os) const V8_OVERRIDE; // NOLINT
1293 DISALLOW_COPY_AND_ASSIGN(StringAddStub);
1297 class ICCompareStub: public PlatformCodeStub {
1299 ICCompareStub(Isolate* isolate,
1301 CompareIC::State left,
1302 CompareIC::State right,
1303 CompareIC::State handler)
1304 : PlatformCodeStub(isolate),
1309 DCHECK(Token::IsCompareOp(op));
1312 virtual void Generate(MacroAssembler* masm);
1314 void set_known_map(Handle<Map> map) { known_map_ = map; }
1316 static void DecodeKey(uint32_t stub_key, CompareIC::State* left_state,
1317 CompareIC::State* right_state,
1318 CompareIC::State* handler_state, Token::Value* op);
1320 virtual InlineCacheState GetICState() const;
1323 class OpField: public BitField<int, 0, 3> { };
1324 class LeftStateField: public BitField<int, 3, 4> { };
1325 class RightStateField: public BitField<int, 7, 4> { };
1326 class HandlerStateField: public BitField<int, 11, 4> { };
1328 virtual CodeStub::Major MajorKey() const { return CompareIC; }
1329 virtual int MinorKey() const;
1331 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_IC; }
1333 void GenerateSmis(MacroAssembler* masm);
1334 void GenerateNumbers(MacroAssembler* masm);
1335 void GenerateInternalizedStrings(MacroAssembler* masm);
1336 void GenerateStrings(MacroAssembler* masm);
1337 void GenerateUniqueNames(MacroAssembler* masm);
1338 void GenerateObjects(MacroAssembler* masm);
1339 void GenerateMiss(MacroAssembler* masm);
1340 void GenerateKnownObjects(MacroAssembler* masm);
1341 void GenerateGeneric(MacroAssembler* masm);
1343 bool strict() const { return op_ == Token::EQ_STRICT; }
1344 Condition GetCondition() const { return CompareIC::ComputeCondition(op_); }
1346 virtual void AddToSpecialCache(Handle<Code> new_object);
1347 virtual bool FindCodeInSpecialCache(Code** code_out);
1348 virtual bool UseSpecialCache() { return state_ == CompareIC::KNOWN_OBJECT; }
1351 CompareIC::State left_;
1352 CompareIC::State right_;
1353 CompareIC::State state_;
1354 Handle<Map> known_map_;
1358 class CompareNilICStub : public HydrogenCodeStub {
1360 Type* GetType(Zone* zone, Handle<Map> map = Handle<Map>());
1361 Type* GetInputType(Zone* zone, Handle<Map> map);
1363 CompareNilICStub(Isolate* isolate, NilValue nil)
1364 : HydrogenCodeStub(isolate), nil_value_(nil) { }
1366 CompareNilICStub(Isolate* isolate,
1367 ExtraICState ic_state,
1368 InitializationState init_state = INITIALIZED)
1369 : HydrogenCodeStub(isolate, init_state),
1370 nil_value_(NilValueField::decode(ic_state)),
1371 state_(State(TypesField::decode(ic_state))) {
1374 static Handle<Code> GetUninitialized(Isolate* isolate,
1376 return CompareNilICStub(isolate, nil, UNINITIALIZED).GetCode();
1379 virtual void InitializeInterfaceDescriptor(
1380 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1382 static void InstallDescriptors(Isolate* isolate) {
1383 CompareNilICStub compare_stub(isolate, kNullValue, UNINITIALIZED);
1384 compare_stub.InitializeInterfaceDescriptor(
1385 isolate->code_stub_interface_descriptor(CodeStub::CompareNilIC));
1388 virtual InlineCacheState GetICState() const {
1389 if (state_.Contains(GENERIC)) {
1391 } else if (state_.Contains(MONOMORPHIC_MAP)) {
1394 return PREMONOMORPHIC;
1398 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_NIL_IC; }
1400 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
1402 virtual ExtraICState GetExtraICState() const {
1403 return NilValueField::encode(nil_value_) |
1404 TypesField::encode(state_.ToIntegral());
1407 void UpdateStatus(Handle<Object> object);
1409 bool IsMonomorphic() const { return state_.Contains(MONOMORPHIC_MAP); }
1410 NilValue GetNilValue() const { return nil_value_; }
1411 void ClearState() { state_.RemoveAll(); }
1413 virtual void PrintState(OStream& os) const V8_OVERRIDE; // NOLINT
1414 virtual void PrintBaseName(OStream& os) const V8_OVERRIDE; // NOLINT
1417 friend class CompareNilIC;
1419 enum CompareNilType {
1427 // At most 6 different types can be distinguished, because the Code object
1428 // only has room for a single byte to hold a set and there are two more
1429 // boolean flags we need to store. :-P
1430 STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
1432 class State : public EnumSet<CompareNilType, byte> {
1434 State() : EnumSet<CompareNilType, byte>(0) { }
1435 explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
1437 friend OStream& operator<<(OStream& os, const State& s);
1439 CompareNilICStub(Isolate* isolate,
1441 InitializationState init_state)
1442 : HydrogenCodeStub(isolate, init_state), nil_value_(nil) { }
1444 class NilValueField : public BitField<NilValue, 0, 1> {};
1445 class TypesField : public BitField<byte, 1, NUMBER_OF_TYPES> {};
1447 virtual CodeStub::Major MajorKey() const { return CompareNilIC; }
1448 virtual int NotMissMinorKey() const { return GetExtraICState(); }
1450 NilValue nil_value_;
1453 DISALLOW_COPY_AND_ASSIGN(CompareNilICStub);
1457 OStream& operator<<(OStream& os, const CompareNilICStub::State& s);
1460 class CEntryStub : public PlatformCodeStub {
1462 CEntryStub(Isolate* isolate,
1464 SaveFPRegsMode save_doubles = kDontSaveFPRegs)
1465 : PlatformCodeStub(isolate),
1466 result_size_(result_size),
1467 save_doubles_(save_doubles) { }
1469 void Generate(MacroAssembler* masm);
1471 // The version of this stub that doesn't save doubles is generated ahead of
1472 // time, so it's OK to call it from other stubs that can't cope with GC during
1473 // their code generation. On machines that always have gp registers (x64) we
1474 // can generate both variants ahead of time.
1475 static void GenerateAheadOfTime(Isolate* isolate);
1478 // Number of pointers/values returned.
1479 const int result_size_;
1480 SaveFPRegsMode save_doubles_;
1482 Major MajorKey() const { return CEntry; }
1483 int MinorKey() const;
1485 bool NeedsImmovableCode();
1489 class JSEntryStub : public PlatformCodeStub {
1491 explicit JSEntryStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
1493 void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
1496 void GenerateBody(MacroAssembler* masm, bool is_construct);
1499 Major MajorKey() const { return JSEntry; }
1500 int MinorKey() const { return 0; }
1502 virtual void FinishCode(Handle<Code> code);
1504 int handler_offset_;
1508 class JSConstructEntryStub : public JSEntryStub {
1510 explicit JSConstructEntryStub(Isolate* isolate) : JSEntryStub(isolate) { }
1512 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
1515 int MinorKey() const { return 1; }
1517 virtual void PrintName(OStream& os) const V8_OVERRIDE { // NOLINT
1518 os << "JSConstructEntryStub";
1523 class ArgumentsAccessStub: public PlatformCodeStub {
1532 ArgumentsAccessStub(Isolate* isolate, Type type)
1533 : PlatformCodeStub(isolate), type_(type) { }
1538 Major MajorKey() const { return ArgumentsAccess; }
1539 int MinorKey() const { return type_; }
1541 void Generate(MacroAssembler* masm);
1542 void GenerateReadElement(MacroAssembler* masm);
1543 void GenerateNewStrict(MacroAssembler* masm);
1544 void GenerateNewSloppyFast(MacroAssembler* masm);
1545 void GenerateNewSloppySlow(MacroAssembler* masm);
1547 virtual void PrintName(OStream& os) const V8_OVERRIDE; // NOLINT
1551 class RegExpExecStub: public PlatformCodeStub {
1553 explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
1556 Major MajorKey() const { return RegExpExec; }
1557 int MinorKey() const { return 0; }
1559 void Generate(MacroAssembler* masm);
1563 class RegExpConstructResultStub V8_FINAL : public HydrogenCodeStub {
1565 explicit RegExpConstructResultStub(Isolate* isolate)
1566 : HydrogenCodeStub(isolate) { }
1568 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
1570 virtual void InitializeInterfaceDescriptor(
1571 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1573 virtual Major MajorKey() const V8_OVERRIDE { return RegExpConstructResult; }
1574 virtual int NotMissMinorKey() const V8_OVERRIDE { return 0; }
1576 static void InstallDescriptors(Isolate* isolate);
1578 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1579 static const int kLength = 0;
1580 static const int kIndex = 1;
1581 static const int kInput = 2;
1584 DISALLOW_COPY_AND_ASSIGN(RegExpConstructResultStub);
1588 class CallFunctionStub: public PlatformCodeStub {
1590 CallFunctionStub(Isolate* isolate, int argc, CallFunctionFlags flags)
1591 : PlatformCodeStub(isolate), argc_(argc), flags_(flags) {
1592 DCHECK(argc <= Code::kMaxArguments);
1595 void Generate(MacroAssembler* masm);
1597 static int ExtractArgcFromMinorKey(int minor_key) {
1598 return ArgcBits::decode(minor_key);
1601 virtual void InitializeInterfaceDescriptor(
1602 CodeStubInterfaceDescriptor* descriptor);
1606 CallFunctionFlags flags_;
1608 virtual void PrintName(OStream& os) const V8_OVERRIDE; // NOLINT
1610 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
1611 class FlagBits: public BitField<CallFunctionFlags, 0, 2> {};
1612 class ArgcBits : public BitField<unsigned, 2, Code::kArgumentsBits> {};
1614 STATIC_ASSERT(Code::kArgumentsBits + 2 <= kStubMinorKeyBits);
1616 Major MajorKey() const { return CallFunction; }
1617 int MinorKey() const {
1618 // Encode the parameters in a unique 32 bit value.
1619 return FlagBits::encode(flags_) | ArgcBits::encode(argc_);
1622 bool CallAsMethod() {
1623 return flags_ == CALL_AS_METHOD || flags_ == WRAP_AND_CALL;
1626 bool NeedsChecks() {
1627 return flags_ != WRAP_AND_CALL;
1632 class CallConstructStub: public PlatformCodeStub {
1634 CallConstructStub(Isolate* isolate, CallConstructorFlags flags)
1635 : PlatformCodeStub(isolate), flags_(flags) {}
1637 void Generate(MacroAssembler* masm);
1639 virtual void FinishCode(Handle<Code> code) {
1640 code->set_has_function_cache(RecordCallTarget());
1643 virtual void InitializeInterfaceDescriptor(
1644 CodeStubInterfaceDescriptor* descriptor);
1647 CallConstructorFlags flags_;
1649 virtual void PrintName(OStream& os) const V8_OVERRIDE; // NOLINT
1651 Major MajorKey() const { return CallConstruct; }
1652 int MinorKey() const { return flags_; }
1654 bool RecordCallTarget() const {
1655 return (flags_ & RECORD_CONSTRUCTOR_TARGET) != 0;
1660 enum StringIndexFlags {
1661 // Accepts smis or heap numbers.
1662 STRING_INDEX_IS_NUMBER,
1664 // Accepts smis or heap numbers that are valid array indices
1665 // (ECMA-262 15.4). Invalid indices are reported as being out of
1667 STRING_INDEX_IS_ARRAY_INDEX
1671 // Generates code implementing String.prototype.charCodeAt.
1673 // Only supports the case when the receiver is a string and the index
1674 // is a number (smi or heap number) that is a valid index into the
1675 // string. Additional index constraints are specified by the
1676 // flags. Otherwise, bails out to the provided labels.
1678 // Register usage: |object| may be changed to another string in a way
1679 // that doesn't affect charCodeAt/charAt semantics, |index| is
1680 // preserved, |scratch| and |result| are clobbered.
1681 class StringCharCodeAtGenerator {
1683 StringCharCodeAtGenerator(Register object,
1686 Label* receiver_not_string,
1687 Label* index_not_number,
1688 Label* index_out_of_range,
1689 StringIndexFlags index_flags)
1693 receiver_not_string_(receiver_not_string),
1694 index_not_number_(index_not_number),
1695 index_out_of_range_(index_out_of_range),
1696 index_flags_(index_flags) {
1697 DCHECK(!result_.is(object_));
1698 DCHECK(!result_.is(index_));
1701 // Generates the fast case code. On the fallthrough path |result|
1702 // register contains the result.
1703 void GenerateFast(MacroAssembler* masm);
1705 // Generates the slow case code. Must not be naturally
1706 // reachable. Expected to be put after a ret instruction (e.g., in
1707 // deferred code). Always jumps back to the fast case.
1708 void GenerateSlow(MacroAssembler* masm,
1709 const RuntimeCallHelper& call_helper);
1711 // Skip handling slow case and directly jump to bailout.
1712 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1713 masm->bind(&index_not_smi_);
1714 masm->bind(&call_runtime_);
1723 Label* receiver_not_string_;
1724 Label* index_not_number_;
1725 Label* index_out_of_range_;
1727 StringIndexFlags index_flags_;
1729 Label call_runtime_;
1730 Label index_not_smi_;
1731 Label got_smi_index_;
1734 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
1738 // Generates code for creating a one-char string from a char code.
1739 class StringCharFromCodeGenerator {
1741 StringCharFromCodeGenerator(Register code,
1745 DCHECK(!code_.is(result_));
1748 // Generates the fast case code. On the fallthrough path |result|
1749 // register contains the result.
1750 void GenerateFast(MacroAssembler* masm);
1752 // Generates the slow case code. Must not be naturally
1753 // reachable. Expected to be put after a ret instruction (e.g., in
1754 // deferred code). Always jumps back to the fast case.
1755 void GenerateSlow(MacroAssembler* masm,
1756 const RuntimeCallHelper& call_helper);
1758 // Skip handling slow case and directly jump to bailout.
1759 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1760 masm->bind(&slow_case_);
1771 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
1775 // Generates code implementing String.prototype.charAt.
1777 // Only supports the case when the receiver is a string and the index
1778 // is a number (smi or heap number) that is a valid index into the
1779 // string. Additional index constraints are specified by the
1780 // flags. Otherwise, bails out to the provided labels.
1782 // Register usage: |object| may be changed to another string in a way
1783 // that doesn't affect charCodeAt/charAt semantics, |index| is
1784 // preserved, |scratch1|, |scratch2|, and |result| are clobbered.
1785 class StringCharAtGenerator {
1787 StringCharAtGenerator(Register object,
1791 Label* receiver_not_string,
1792 Label* index_not_number,
1793 Label* index_out_of_range,
1794 StringIndexFlags index_flags)
1795 : char_code_at_generator_(object,
1798 receiver_not_string,
1802 char_from_code_generator_(scratch, result) {}
1804 // Generates the fast case code. On the fallthrough path |result|
1805 // register contains the result.
1806 void GenerateFast(MacroAssembler* masm) {
1807 char_code_at_generator_.GenerateFast(masm);
1808 char_from_code_generator_.GenerateFast(masm);
1811 // Generates the slow case code. Must not be naturally
1812 // reachable. Expected to be put after a ret instruction (e.g., in
1813 // deferred code). Always jumps back to the fast case.
1814 void GenerateSlow(MacroAssembler* masm,
1815 const RuntimeCallHelper& call_helper) {
1816 char_code_at_generator_.GenerateSlow(masm, call_helper);
1817 char_from_code_generator_.GenerateSlow(masm, call_helper);
1820 // Skip handling slow case and directly jump to bailout.
1821 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1822 char_code_at_generator_.SkipSlow(masm, bailout);
1823 char_from_code_generator_.SkipSlow(masm, bailout);
1827 StringCharCodeAtGenerator char_code_at_generator_;
1828 StringCharFromCodeGenerator char_from_code_generator_;
1830 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
1834 class LoadDictionaryElementStub : public HydrogenCodeStub {
1836 explicit LoadDictionaryElementStub(Isolate* isolate)
1837 : HydrogenCodeStub(isolate) {}
1839 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
1841 virtual void InitializeInterfaceDescriptor(
1842 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1845 Major MajorKey() const { return LoadElement; }
1846 int NotMissMinorKey() const { return DICTIONARY_ELEMENTS; }
1848 DISALLOW_COPY_AND_ASSIGN(LoadDictionaryElementStub);
1852 class LoadDictionaryElementPlatformStub : public PlatformCodeStub {
1854 explicit LoadDictionaryElementPlatformStub(Isolate* isolate)
1855 : PlatformCodeStub(isolate) {}
1857 void Generate(MacroAssembler* masm);
1860 Major MajorKey() const { return LoadElement; }
1861 int MinorKey() const { return DICTIONARY_ELEMENTS; }
1863 DISALLOW_COPY_AND_ASSIGN(LoadDictionaryElementPlatformStub);
1867 class KeyedLoadGenericStub : public HydrogenCodeStub {
1869 explicit KeyedLoadGenericStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
1871 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
1873 virtual void InitializeInterfaceDescriptor(
1874 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1876 static void InstallDescriptors(Isolate* isolate);
1878 virtual Code::Kind GetCodeKind() const { return Code::KEYED_LOAD_IC; }
1879 virtual InlineCacheState GetICState() const { return GENERIC; }
1882 Major MajorKey() const { return KeyedLoadGeneric; }
1883 int NotMissMinorKey() const { return 0; }
1885 DISALLOW_COPY_AND_ASSIGN(KeyedLoadGenericStub);
1889 class DoubleToIStub : public PlatformCodeStub {
1891 DoubleToIStub(Isolate* isolate,
1893 Register destination,
1896 bool skip_fastpath = false)
1897 : PlatformCodeStub(isolate), bit_field_(0) {
1898 bit_field_ = SourceRegisterBits::encode(source.code()) |
1899 DestinationRegisterBits::encode(destination.code()) |
1900 OffsetBits::encode(offset) |
1901 IsTruncatingBits::encode(is_truncating) |
1902 SkipFastPathBits::encode(skip_fastpath) |
1903 SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0);
1907 return Register::from_code(SourceRegisterBits::decode(bit_field_));
1910 Register destination() {
1911 return Register::from_code(DestinationRegisterBits::decode(bit_field_));
1914 bool is_truncating() {
1915 return IsTruncatingBits::decode(bit_field_);
1918 bool skip_fastpath() {
1919 return SkipFastPathBits::decode(bit_field_);
1923 return OffsetBits::decode(bit_field_);
1926 void Generate(MacroAssembler* masm);
1928 virtual bool SometimesSetsUpAFrame() { return false; }
1931 static const int kBitsPerRegisterNumber = 6;
1932 STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
1933 class SourceRegisterBits:
1934 public BitField<int, 0, kBitsPerRegisterNumber> {}; // NOLINT
1935 class DestinationRegisterBits:
1936 public BitField<int, kBitsPerRegisterNumber,
1937 kBitsPerRegisterNumber> {}; // NOLINT
1938 class IsTruncatingBits:
1939 public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {}; // NOLINT
1941 public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {}; // NOLINT
1942 class SkipFastPathBits:
1943 public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {}; // NOLINT
1945 public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {}; // NOLINT
1947 Major MajorKey() const { return DoubleToI; }
1948 int MinorKey() const { return bit_field_; }
1952 DISALLOW_COPY_AND_ASSIGN(DoubleToIStub);
1956 class LoadFastElementStub : public HydrogenCodeStub {
1958 LoadFastElementStub(Isolate* isolate, bool is_js_array,
1959 ElementsKind elements_kind)
1960 : HydrogenCodeStub(isolate) {
1961 bit_field_ = ElementsKindBits::encode(elements_kind) |
1962 IsJSArrayBits::encode(is_js_array);
1965 bool is_js_array() const {
1966 return IsJSArrayBits::decode(bit_field_);
1969 ElementsKind elements_kind() const {
1970 return ElementsKindBits::decode(bit_field_);
1973 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
1975 virtual void InitializeInterfaceDescriptor(
1976 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1979 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
1980 class IsJSArrayBits: public BitField<bool, 8, 1> {};
1981 uint32_t bit_field_;
1983 Major MajorKey() const { return LoadElement; }
1984 int NotMissMinorKey() const { return bit_field_; }
1986 DISALLOW_COPY_AND_ASSIGN(LoadFastElementStub);
1990 class StoreFastElementStub : public HydrogenCodeStub {
1992 StoreFastElementStub(Isolate* isolate, bool is_js_array,
1993 ElementsKind elements_kind, KeyedAccessStoreMode mode)
1994 : HydrogenCodeStub(isolate) {
1995 bit_field_ = ElementsKindBits::encode(elements_kind) |
1996 IsJSArrayBits::encode(is_js_array) |
1997 StoreModeBits::encode(mode);
2000 bool is_js_array() const {
2001 return IsJSArrayBits::decode(bit_field_);
2004 ElementsKind elements_kind() const {
2005 return ElementsKindBits::decode(bit_field_);
2008 KeyedAccessStoreMode store_mode() const {
2009 return StoreModeBits::decode(bit_field_);
2012 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
2014 virtual void InitializeInterfaceDescriptor(
2015 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
2018 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2019 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
2020 class IsJSArrayBits: public BitField<bool, 12, 1> {};
2021 uint32_t bit_field_;
2023 Major MajorKey() const { return StoreElement; }
2024 int NotMissMinorKey() const { return bit_field_; }
2026 DISALLOW_COPY_AND_ASSIGN(StoreFastElementStub);
2030 class TransitionElementsKindStub : public HydrogenCodeStub {
2032 TransitionElementsKindStub(Isolate* isolate,
2033 ElementsKind from_kind,
2034 ElementsKind to_kind,
2035 bool is_js_array) : HydrogenCodeStub(isolate) {
2036 bit_field_ = FromKindBits::encode(from_kind) |
2037 ToKindBits::encode(to_kind) |
2038 IsJSArrayBits::encode(is_js_array);
2041 ElementsKind from_kind() const {
2042 return FromKindBits::decode(bit_field_);
2045 ElementsKind to_kind() const {
2046 return ToKindBits::decode(bit_field_);
2049 bool is_js_array() const {
2050 return IsJSArrayBits::decode(bit_field_);
2053 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
2055 virtual void InitializeInterfaceDescriptor(
2056 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
2059 class FromKindBits: public BitField<ElementsKind, 8, 8> {};
2060 class ToKindBits: public BitField<ElementsKind, 0, 8> {};
2061 class IsJSArrayBits: public BitField<bool, 16, 1> {};
2062 uint32_t bit_field_;
2064 Major MajorKey() const { return TransitionElementsKind; }
2065 int NotMissMinorKey() const { return bit_field_; }
2067 DISALLOW_COPY_AND_ASSIGN(TransitionElementsKindStub);
2071 class ArrayConstructorStubBase : public HydrogenCodeStub {
2073 ArrayConstructorStubBase(Isolate* isolate,
2075 AllocationSiteOverrideMode override_mode)
2076 : HydrogenCodeStub(isolate) {
2077 // It only makes sense to override local allocation site behavior
2078 // if there is a difference between the global allocation site policy
2079 // for an ElementsKind and the desired usage of the stub.
2080 DCHECK(override_mode != DISABLE_ALLOCATION_SITES ||
2081 AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
2082 bit_field_ = ElementsKindBits::encode(kind) |
2083 AllocationSiteOverrideModeBits::encode(override_mode);
2086 ElementsKind elements_kind() const {
2087 return ElementsKindBits::decode(bit_field_);
2090 AllocationSiteOverrideMode override_mode() const {
2091 return AllocationSiteOverrideModeBits::decode(bit_field_);
2094 static void GenerateStubsAheadOfTime(Isolate* isolate);
2095 static void InstallDescriptors(Isolate* isolate);
2097 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2098 static const int kConstructor = 0;
2099 static const int kAllocationSite = 1;
2102 OStream& BasePrintName(OStream& os, const char* name) const; // NOLINT
2105 int NotMissMinorKey() const { return bit_field_; }
2107 // Ensure data fits within available bits.
2108 STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
2110 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2111 class AllocationSiteOverrideModeBits: public
2112 BitField<AllocationSiteOverrideMode, 8, 1> {}; // NOLINT
2113 uint32_t bit_field_;
2115 DISALLOW_COPY_AND_ASSIGN(ArrayConstructorStubBase);
2119 class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
2121 ArrayNoArgumentConstructorStub(
2124 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2125 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2128 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
2130 virtual void InitializeInterfaceDescriptor(
2131 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
2134 Major MajorKey() const { return ArrayNoArgumentConstructor; }
2136 virtual void PrintName(OStream& os) const V8_OVERRIDE { // NOLINT
2137 BasePrintName(os, "ArrayNoArgumentConstructorStub");
2140 DISALLOW_COPY_AND_ASSIGN(ArrayNoArgumentConstructorStub);
2144 class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
2146 ArraySingleArgumentConstructorStub(
2149 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2150 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2153 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
2155 virtual void InitializeInterfaceDescriptor(
2156 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
2159 Major MajorKey() const { return ArraySingleArgumentConstructor; }
2161 virtual void PrintName(OStream& os) const { // NOLINT
2162 BasePrintName(os, "ArraySingleArgumentConstructorStub");
2165 DISALLOW_COPY_AND_ASSIGN(ArraySingleArgumentConstructorStub);
2169 class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
2171 ArrayNArgumentsConstructorStub(
2174 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2175 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2178 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
2180 virtual void InitializeInterfaceDescriptor(
2181 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
2184 Major MajorKey() const { return ArrayNArgumentsConstructor; }
2186 virtual void PrintName(OStream& os) const { // NOLINT
2187 BasePrintName(os, "ArrayNArgumentsConstructorStub");
2190 DISALLOW_COPY_AND_ASSIGN(ArrayNArgumentsConstructorStub);
2194 class InternalArrayConstructorStubBase : public HydrogenCodeStub {
2196 InternalArrayConstructorStubBase(Isolate* isolate, ElementsKind kind)
2197 : HydrogenCodeStub(isolate) {
2201 static void GenerateStubsAheadOfTime(Isolate* isolate);
2202 static void InstallDescriptors(Isolate* isolate);
2204 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2205 static const int kConstructor = 0;
2207 ElementsKind elements_kind() const { return kind_; }
2210 int NotMissMinorKey() const { return kind_; }
2214 DISALLOW_COPY_AND_ASSIGN(InternalArrayConstructorStubBase);
2218 class InternalArrayNoArgumentConstructorStub : public
2219 InternalArrayConstructorStubBase {
2221 InternalArrayNoArgumentConstructorStub(Isolate* isolate,
2223 : InternalArrayConstructorStubBase(isolate, kind) { }
2225 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
2227 virtual void InitializeInterfaceDescriptor(
2228 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
2231 Major MajorKey() const { return InternalArrayNoArgumentConstructor; }
2233 DISALLOW_COPY_AND_ASSIGN(InternalArrayNoArgumentConstructorStub);
2237 class InternalArraySingleArgumentConstructorStub : public
2238 InternalArrayConstructorStubBase {
2240 InternalArraySingleArgumentConstructorStub(Isolate* isolate,
2242 : InternalArrayConstructorStubBase(isolate, kind) { }
2244 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
2246 virtual void InitializeInterfaceDescriptor(
2247 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
2250 Major MajorKey() const { return InternalArraySingleArgumentConstructor; }
2252 DISALLOW_COPY_AND_ASSIGN(InternalArraySingleArgumentConstructorStub);
2256 class InternalArrayNArgumentsConstructorStub : public
2257 InternalArrayConstructorStubBase {
2259 InternalArrayNArgumentsConstructorStub(Isolate* isolate, ElementsKind kind)
2260 : InternalArrayConstructorStubBase(isolate, kind) { }
2262 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
2264 virtual void InitializeInterfaceDescriptor(
2265 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
2268 Major MajorKey() const { return InternalArrayNArgumentsConstructor; }
2270 DISALLOW_COPY_AND_ASSIGN(InternalArrayNArgumentsConstructorStub);
2274 class StoreElementStub : public PlatformCodeStub {
2276 StoreElementStub(Isolate* isolate, bool is_js_array,
2277 ElementsKind elements_kind, KeyedAccessStoreMode store_mode)
2278 : PlatformCodeStub(isolate),
2279 is_js_array_(is_js_array),
2280 elements_kind_(elements_kind),
2281 store_mode_(store_mode) {}
2283 Major MajorKey() const { return StoreElement; }
2284 int MinorKey() const {
2285 return ElementsKindBits::encode(elements_kind_) |
2286 IsJSArrayBits::encode(is_js_array_) |
2287 StoreModeBits::encode(store_mode_);
2290 void Generate(MacroAssembler* masm);
2293 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2294 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
2295 class IsJSArrayBits: public BitField<bool, 12, 1> {};
2298 ElementsKind elements_kind_;
2299 KeyedAccessStoreMode store_mode_;
2301 DISALLOW_COPY_AND_ASSIGN(StoreElementStub);
2305 class ToBooleanStub: public HydrogenCodeStub {
2320 RESULT_AS_SMI, // For Smi(1) on truthy value, Smi(0) otherwise.
2321 RESULT_AS_ODDBALL, // For {true} on truthy value, {false} otherwise.
2322 RESULT_AS_INVERSE_ODDBALL // For {false} on truthy value, {true} otherwise.
2325 // At most 8 different types can be distinguished, because the Code object
2326 // only has room for a single byte to hold a set of these types. :-P
2327 STATIC_ASSERT(NUMBER_OF_TYPES <= 8);
2329 class Types : public EnumSet<Type, byte> {
2331 Types() : EnumSet<Type, byte>(0) {}
2332 explicit Types(byte bits) : EnumSet<Type, byte>(bits) {}
2334 byte ToByte() const { return ToIntegral(); }
2335 bool UpdateStatus(Handle<Object> object);
2336 bool NeedsMap() const;
2337 bool CanBeUndetectable() const;
2338 bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
2340 static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
2343 ToBooleanStub(Isolate* isolate, ResultMode mode, Types types = Types())
2344 : HydrogenCodeStub(isolate), types_(types), mode_(mode) {}
2345 ToBooleanStub(Isolate* isolate, ExtraICState state)
2346 : HydrogenCodeStub(isolate),
2347 types_(static_cast<byte>(state)),
2348 mode_(RESULT_AS_SMI) {}
2350 bool UpdateStatus(Handle<Object> object);
2351 Types GetTypes() { return types_; }
2352 ResultMode GetMode() { return mode_; }
2354 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
2355 virtual void InitializeInterfaceDescriptor(
2356 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
2358 virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; }
2359 virtual void PrintState(OStream& os) const V8_OVERRIDE; // NOLINT
2361 virtual bool SometimesSetsUpAFrame() { return false; }
2363 static void InstallDescriptors(Isolate* isolate) {
2364 ToBooleanStub stub(isolate, RESULT_AS_SMI);
2365 stub.InitializeInterfaceDescriptor(
2366 isolate->code_stub_interface_descriptor(CodeStub::ToBoolean));
2369 static Handle<Code> GetUninitialized(Isolate* isolate) {
2370 return ToBooleanStub(isolate, UNINITIALIZED).GetCode();
2373 virtual ExtraICState GetExtraICState() const { return types_.ToIntegral(); }
2375 virtual InlineCacheState GetICState() const {
2376 if (types_.IsEmpty()) {
2377 return ::v8::internal::UNINITIALIZED;
2384 class TypesBits : public BitField<byte, 0, NUMBER_OF_TYPES> {};
2385 class ResultModeBits : public BitField<ResultMode, NUMBER_OF_TYPES, 2> {};
2387 Major MajorKey() const { return ToBoolean; }
2388 int NotMissMinorKey() const {
2389 return TypesBits::encode(types_.ToByte()) | ResultModeBits::encode(mode_);
2392 ToBooleanStub(Isolate* isolate, InitializationState init_state)
2393 : HydrogenCodeStub(isolate, init_state), mode_(RESULT_AS_SMI) {}
2400 OStream& operator<<(OStream& os, const ToBooleanStub::Types& t);
2403 class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
2405 ElementsTransitionAndStoreStub(Isolate* isolate,
2406 ElementsKind from_kind,
2407 ElementsKind to_kind,
2409 KeyedAccessStoreMode store_mode)
2410 : HydrogenCodeStub(isolate),
2411 from_kind_(from_kind),
2413 is_jsarray_(is_jsarray),
2414 store_mode_(store_mode) {}
2416 ElementsKind from_kind() const { return from_kind_; }
2417 ElementsKind to_kind() const { return to_kind_; }
2418 bool is_jsarray() const { return is_jsarray_; }
2419 KeyedAccessStoreMode store_mode() const { return store_mode_; }
2421 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
2423 virtual void InitializeInterfaceDescriptor(
2424 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
2426 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2427 enum ParameterIndices {
2435 static const Register ValueRegister() {
2436 return KeyedStoreIC::ValueRegister();
2438 static const Register MapRegister() { return KeyedStoreIC::MapRegister(); }
2439 static const Register KeyRegister() { return KeyedStoreIC::NameRegister(); }
2440 static const Register ObjectRegister() {
2441 return KeyedStoreIC::ReceiverRegister();
2445 class FromBits: public BitField<ElementsKind, 0, 8> {};
2446 class ToBits: public BitField<ElementsKind, 8, 8> {};
2447 class IsJSArrayBits: public BitField<bool, 16, 1> {};
2448 class StoreModeBits: public BitField<KeyedAccessStoreMode, 17, 4> {};
2450 Major MajorKey() const { return ElementsTransitionAndStore; }
2451 int NotMissMinorKey() const {
2452 return FromBits::encode(from_kind_) |
2453 ToBits::encode(to_kind_) |
2454 IsJSArrayBits::encode(is_jsarray_) |
2455 StoreModeBits::encode(store_mode_);
2458 ElementsKind from_kind_;
2459 ElementsKind to_kind_;
2461 KeyedAccessStoreMode store_mode_;
2463 DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub);
2467 class StoreArrayLiteralElementStub : public PlatformCodeStub {
2469 explicit StoreArrayLiteralElementStub(Isolate* isolate)
2470 : PlatformCodeStub(isolate) { }
2473 Major MajorKey() const { return StoreArrayLiteralElement; }
2474 int MinorKey() const { return 0; }
2476 void Generate(MacroAssembler* masm);
2478 DISALLOW_COPY_AND_ASSIGN(StoreArrayLiteralElementStub);
2482 class StubFailureTrampolineStub : public PlatformCodeStub {
2484 StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode)
2485 : PlatformCodeStub(isolate),
2486 function_mode_(function_mode) {}
2488 static void GenerateAheadOfTime(Isolate* isolate);
2491 class FunctionModeField: public BitField<StubFunctionMode, 0, 1> {};
2493 Major MajorKey() const { return StubFailureTrampoline; }
2494 int MinorKey() const { return FunctionModeField::encode(function_mode_); }
2496 void Generate(MacroAssembler* masm);
2498 StubFunctionMode function_mode_;
2500 DISALLOW_COPY_AND_ASSIGN(StubFailureTrampolineStub);
2504 class ProfileEntryHookStub : public PlatformCodeStub {
2506 explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2508 // The profile entry hook function is not allowed to cause a GC.
2509 virtual bool SometimesSetsUpAFrame() { return false; }
2511 // Generates a call to the entry hook if it's enabled.
2512 static void MaybeCallEntryHook(MacroAssembler* masm);
2515 static void EntryHookTrampoline(intptr_t function,
2516 intptr_t stack_pointer,
2519 Major MajorKey() const { return ProfileEntryHook; }
2520 int MinorKey() const { return 0; }
2522 void Generate(MacroAssembler* masm);
2524 DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub);
2528 class CallDescriptors {
2530 static void InitializeForIsolate(Isolate* isolate);
2533 } } // namespace v8::internal
2535 #endif // V8_CODE_STUBS_H_