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/ic/ic.h"
13 #include "src/macro-assembler.h"
14 #include "src/ostreams.h"
19 // List of code stubs used on all platforms.
20 #define CODE_STUB_LIST_ALL_PLATFORMS(V) \
24 V(BinaryOpICWithAllocationSite) \
25 V(BinaryOpWithAllocationSite) \
35 V(FunctionPrototype) \
37 V(StoreBufferOverflow) \
41 V(WriteInt32ToHeapNumber) \
46 V(FastCloneShallowArray) \
47 V(FastCloneShallowObject) \
48 V(CreateAllocationSite) \
52 V(RegExpConstructResult) \
59 V(ArrayNoArgumentConstructor) \
60 V(ArraySingleArgumentConstructor) \
61 V(ArrayNArgumentsConstructor) \
62 V(InternalArrayNoArgumentConstructor) \
63 V(InternalArraySingleArgumentConstructor) \
64 V(InternalArrayNArgumentsConstructor) \
66 V(DebuggerStatement) \
67 V(NameDictionaryLookup) \
68 V(ElementsTransitionAndStore) \
69 V(TransitionElementsKind) \
70 V(StoreArrayLiteralElement) \
71 V(StubFailureTrampoline) \
73 V(InternalArrayConstructor) \
78 /* IC Handler stubs */ \
84 // List of code stubs only used on ARM 32 bits platforms.
85 #if V8_TARGET_ARCH_ARM
86 #define CODE_STUB_LIST_ARM(V) \
92 #define CODE_STUB_LIST_ARM(V)
95 // List of code stubs only used on ARM 64 bits platforms.
96 #if V8_TARGET_ARCH_ARM64
97 #define CODE_STUB_LIST_ARM64(V) \
102 V(StoreRegistersState) \
103 V(RestoreRegistersState)
105 #define CODE_STUB_LIST_ARM64(V)
108 // List of code stubs only used on MIPS platforms.
109 #if V8_TARGET_ARCH_MIPS
110 #define CODE_STUB_LIST_MIPS(V) \
113 V(StoreRegistersState) \
114 V(RestoreRegistersState)
115 #elif V8_TARGET_ARCH_MIPS64
116 #define CODE_STUB_LIST_MIPS(V) \
119 V(StoreRegistersState) \
120 V(RestoreRegistersState)
122 #define CODE_STUB_LIST_MIPS(V)
125 // Combined list of code stubs.
126 #define CODE_STUB_LIST(V) \
127 CODE_STUB_LIST_ALL_PLATFORMS(V) \
128 CODE_STUB_LIST_ARM(V) \
129 CODE_STUB_LIST_ARM64(V) \
130 CODE_STUB_LIST_MIPS(V)
132 // Stub is base classes of all stubs.
133 class CodeStub BASE_EMBEDDED {
136 UninitializedMajorKey = 0,
137 #define DEF_ENUM(name) name,
138 CODE_STUB_LIST(DEF_ENUM)
140 NoCache, // marker for stubs that do custom caching
144 // Retrieve the code for the stub. Generate the code if needed.
145 Handle<Code> GetCode();
147 // Retrieve the code for the stub, make and return a copy of the code.
148 Handle<Code> GetCodeCopy(const Code::FindAndReplacePattern& pattern);
150 static Major MajorKeyFromKey(uint32_t key) {
151 return static_cast<Major>(MajorKeyBits::decode(key));
153 static int MinorKeyFromKey(uint32_t key) {
154 return MinorKeyBits::decode(key);
157 // Gets the major key from a code object that is a code stub or binary op IC.
158 static Major GetMajorKey(Code* code_stub) {
159 return MajorKeyFromKey(code_stub->stub_key());
162 static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }
164 static const char* MajorName(Major major_key, bool allow_unknown_keys);
166 explicit CodeStub(Isolate* isolate) : isolate_(isolate) { }
167 virtual ~CodeStub() {}
169 static void GenerateStubsAheadOfTime(Isolate* isolate);
170 static void GenerateFPStubs(Isolate* isolate);
172 // Some stubs put untagged junk on the stack that cannot be scanned by the
173 // GC. This means that we must be statically sure that no GC can occur while
174 // they are running. If that is the case they should override this to return
175 // true, which will cause an assertion if we try to call something that can
176 // GC or if we try to put a stack frame on top of the junk, which would not
177 // result in a traversable stack.
178 virtual bool SometimesSetsUpAFrame() { return true; }
180 // Lookup the code in the (possibly custom) cache.
181 bool FindCodeInCache(Code** code_out);
183 // Returns information for computing the number key.
184 virtual Major MajorKey() const = 0;
185 virtual int MinorKey() const = 0;
187 virtual InlineCacheState GetICState() const { return UNINITIALIZED; }
188 virtual ExtraICState GetExtraICState() const { return kNoExtraICState; }
189 virtual Code::StubType GetStubType() {
193 friend OStream& operator<<(OStream& os, const CodeStub& s) {
198 Isolate* isolate() const { return isolate_; }
201 // Generates the assembler code for the stub.
202 virtual Handle<Code> GenerateCode() = 0;
204 // Returns whether the code generated for this stub needs to be allocated as
205 // a fixed (non-moveable) code object.
206 virtual bool NeedsImmovableCode() { return false; }
208 virtual void PrintName(OStream& os) const; // NOLINT
209 virtual void PrintBaseName(OStream& os) const; // NOLINT
210 virtual void PrintState(OStream& os) const { ; } // NOLINT
212 // Computes the key based on major and minor.
214 DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
215 return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey());
219 // Perform bookkeeping required after code generation when stub code is
220 // initially generated.
221 void RecordCodeGeneration(Handle<Code> code);
223 // Finish the code object after it has been generated.
224 virtual void FinishCode(Handle<Code> code) { }
226 // Activate newly generated stub. Is called after
227 // registering stub in the stub cache.
228 virtual void Activate(Code* code) { }
230 // BinaryOpStub needs to override this.
231 virtual Code::Kind GetCodeKind() const;
233 // Add the code to a specialized cache, specific to an individual
234 // stub type. Please note, this method must add the code object to a
235 // roots object, otherwise we will remove the code during GC.
236 virtual void AddToSpecialCache(Handle<Code> new_object) { }
238 // Find code in a specialized cache, work is delegated to the specific stub.
239 virtual bool FindCodeInSpecialCache(Code** code_out) {
243 // If a stub uses a special cache override this.
244 virtual bool UseSpecialCache() { return false; }
246 STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
247 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
248 class MinorKeyBits: public BitField<uint32_t,
249 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT
251 friend class BreakPointIterator;
257 class PlatformCodeStub : public CodeStub {
259 explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) { }
261 // Retrieve the code for the stub. Generate the code if needed.
262 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
264 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
267 // Generates the assembler code for the stub.
268 virtual void Generate(MacroAssembler* masm) = 0;
272 enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
273 enum HandlerArgumentsMode { DONT_PASS_ARGUMENTS, PASS_ARGUMENTS };
276 class PlatformInterfaceDescriptor;
279 class InterfaceDescriptor {
281 bool IsInitialized() const { return register_param_count_ >= 0; }
283 int GetEnvironmentLength() const { return register_param_count_; }
285 int GetRegisterParameterCount() const { return register_param_count_; }
287 Register GetParameterRegister(int index) const {
288 return register_params_[index];
291 Representation GetParameterRepresentation(int index) const {
292 DCHECK(index < register_param_count_);
293 if (register_param_representations_.get() == NULL) {
294 return Representation::Tagged();
297 return register_param_representations_[index];
300 // "Environment" versions of parameter functions. The first register
301 // parameter (context) is not included.
302 int GetEnvironmentParameterCount() const {
303 return GetEnvironmentLength() - 1;
306 Register GetEnvironmentParameterRegister(int index) const {
307 return GetParameterRegister(index + 1);
310 Representation GetEnvironmentParameterRepresentation(int index) const {
311 return GetParameterRepresentation(index + 1);
314 // Some platforms have extra information to associate with the descriptor.
315 PlatformInterfaceDescriptor* platform_specific_descriptor() const {
316 return platform_specific_descriptor_;
319 static const Register ContextRegister();
322 InterfaceDescriptor();
323 virtual ~InterfaceDescriptor() {}
325 void Initialize(int register_parameter_count, Register* registers,
326 Representation* register_param_representations,
327 PlatformInterfaceDescriptor* platform_descriptor = NULL);
330 int register_param_count_;
332 // The Register params are allocated dynamically by the
333 // InterfaceDescriptor, and freed on destruction. This is because static
334 // arrays of Registers cause creation of runtime static initializers
335 // which we don't want.
336 SmartArrayPointer<Register> register_params_;
337 // Specifies Representations for the stub's parameter. Points to an array of
338 // Representations of the same length of the numbers of parameters to the
339 // stub, or if NULL (the default value), Representation of each parameter
340 // assumed to be Tagged().
341 SmartArrayPointer<Representation> register_param_representations_;
343 PlatformInterfaceDescriptor* platform_specific_descriptor_;
345 DISALLOW_COPY_AND_ASSIGN(InterfaceDescriptor);
349 class CodeStubInterfaceDescriptor: public InterfaceDescriptor {
351 CodeStubInterfaceDescriptor();
353 void Initialize(CodeStub::Major major, int register_parameter_count,
354 Register* registers, Address deoptimization_handler = NULL,
355 Representation* register_param_representations = NULL,
356 int hint_stack_parameter_count = -1,
357 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
358 void Initialize(CodeStub::Major major, int register_parameter_count,
359 Register* registers, Register stack_parameter_count,
360 Address deoptimization_handler = NULL,
361 Representation* register_param_representations = NULL,
362 int hint_stack_parameter_count = -1,
363 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE,
364 HandlerArgumentsMode handler_mode = DONT_PASS_ARGUMENTS);
366 void SetMissHandler(ExternalReference handler) {
367 miss_handler_ = handler;
368 has_miss_handler_ = true;
369 // Our miss handler infrastructure doesn't currently support
370 // variable stack parameter counts.
371 DCHECK(!stack_parameter_count_.is_valid());
374 ExternalReference miss_handler() const {
375 DCHECK(has_miss_handler_);
376 return miss_handler_;
379 bool has_miss_handler() const {
380 return has_miss_handler_;
383 bool IsEnvironmentParameterCountRegister(int index) const {
384 return GetEnvironmentParameterRegister(index).is(stack_parameter_count_);
387 int GetHandlerParameterCount() const {
388 int params = GetEnvironmentParameterCount();
389 if (handler_arguments_mode_ == PASS_ARGUMENTS) {
395 int hint_stack_parameter_count() const { return hint_stack_parameter_count_; }
396 Register stack_parameter_count() const { return stack_parameter_count_; }
397 StubFunctionMode function_mode() const { return function_mode_; }
398 Address deoptimization_handler() const { return deoptimization_handler_; }
399 CodeStub::Major MajorKey() const { return major_; }
402 Register stack_parameter_count_;
403 // If hint_stack_parameter_count_ > 0, the code stub can optimize the
404 // return sequence. Default value is -1, which means it is ignored.
405 int hint_stack_parameter_count_;
406 StubFunctionMode function_mode_;
408 Address deoptimization_handler_;
409 HandlerArgumentsMode handler_arguments_mode_;
411 ExternalReference miss_handler_;
412 bool has_miss_handler_;
413 CodeStub::Major major_;
417 class CallInterfaceDescriptor: public InterfaceDescriptor {
419 CallInterfaceDescriptor() { }
421 // A copy of the passed in registers and param_representations is made
422 // and owned by the CallInterfaceDescriptor.
424 // TODO(mvstanton): Instead of taking parallel arrays register and
425 // param_representations, how about a struct that puts the representation
426 // and register side by side (eg, RegRep(r1, Representation::Tagged()).
427 // The same should go for the CodeStubInterfaceDescriptor class.
428 void Initialize(int register_parameter_count, Register* registers,
429 Representation* param_representations,
430 PlatformInterfaceDescriptor* platform_descriptor = NULL);
434 class HydrogenCodeStub : public CodeStub {
436 enum InitializationState {
441 explicit HydrogenCodeStub(Isolate* isolate,
442 InitializationState state = INITIALIZED)
443 : CodeStub(isolate) {
444 is_uninitialized_ = (state == UNINITIALIZED);
447 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
449 CodeStubInterfaceDescriptor* GetInterfaceDescriptor() {
450 return isolate()->code_stub_interface_descriptor(MajorKey());
453 bool IsUninitialized() { return is_uninitialized_; }
455 template<class SubClass>
456 static Handle<Code> GetUninitialized(Isolate* isolate) {
457 SubClass::GenerateAheadOfTime(isolate);
458 return SubClass().GetCode(isolate);
461 virtual void InitializeInterfaceDescriptor(
462 CodeStubInterfaceDescriptor* descriptor) = 0;
464 // Retrieve the code for the stub. Generate the code if needed.
465 virtual Handle<Code> GenerateCode() = 0;
467 virtual int NotMissMinorKey() const = 0;
469 Handle<Code> GenerateLightweightMissCode();
471 template<class StateType>
472 void TraceTransition(StateType from, StateType to);
475 class MinorKeyBits: public BitField<int, 0, kStubMinorKeyBits - 1> {};
476 class IsMissBits: public BitField<bool, kStubMinorKeyBits - 1, 1> {};
478 void GenerateLightweightMiss(MacroAssembler* masm);
479 virtual int MinorKey() const {
480 return IsMissBits::encode(is_uninitialized_) |
481 MinorKeyBits::encode(NotMissMinorKey());
484 bool is_uninitialized_;
488 // Helper interface to prepare to/restore after making runtime calls.
489 class RuntimeCallHelper {
491 virtual ~RuntimeCallHelper() {}
493 virtual void BeforeCall(MacroAssembler* masm) const = 0;
495 virtual void AfterCall(MacroAssembler* masm) const = 0;
498 RuntimeCallHelper() {}
501 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
505 } } // namespace v8::internal
507 #if V8_TARGET_ARCH_IA32
508 #include "src/ia32/code-stubs-ia32.h"
509 #elif V8_TARGET_ARCH_X64
510 #include "src/x64/code-stubs-x64.h"
511 #elif V8_TARGET_ARCH_ARM64
512 #include "src/arm64/code-stubs-arm64.h"
513 #elif V8_TARGET_ARCH_ARM
514 #include "src/arm/code-stubs-arm.h"
515 #elif V8_TARGET_ARCH_MIPS
516 #include "src/mips/code-stubs-mips.h"
517 #elif V8_TARGET_ARCH_MIPS64
518 #include "src/mips64/code-stubs-mips64.h"
519 #elif V8_TARGET_ARCH_X87
520 #include "src/x87/code-stubs-x87.h"
522 #error Unsupported target architecture.
529 // RuntimeCallHelper implementation used in stubs: enters/leaves a
530 // newly created internal frame before/after the runtime call.
531 class StubRuntimeCallHelper : public RuntimeCallHelper {
533 StubRuntimeCallHelper() {}
535 virtual void BeforeCall(MacroAssembler* masm) const;
537 virtual void AfterCall(MacroAssembler* masm) const;
541 // Trivial RuntimeCallHelper implementation.
542 class NopRuntimeCallHelper : public RuntimeCallHelper {
544 NopRuntimeCallHelper() {}
546 virtual void BeforeCall(MacroAssembler* masm) const {}
548 virtual void AfterCall(MacroAssembler* masm) const {}
552 class ToNumberStub: public HydrogenCodeStub {
554 explicit ToNumberStub(Isolate* isolate) : HydrogenCodeStub(isolate) { }
556 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
558 virtual void InitializeInterfaceDescriptor(
559 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
561 static void InstallDescriptors(Isolate* isolate) {
562 ToNumberStub stub(isolate);
563 stub.InitializeInterfaceDescriptor(
564 isolate->code_stub_interface_descriptor(CodeStub::ToNumber));
568 Major MajorKey() const { return ToNumber; }
569 int NotMissMinorKey() const { return 0; }
573 class NumberToStringStub V8_FINAL : public HydrogenCodeStub {
575 explicit NumberToStringStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
577 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
579 virtual void InitializeInterfaceDescriptor(
580 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
582 static void InstallDescriptors(Isolate* isolate);
584 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
585 static const int kNumber = 0;
588 virtual Major MajorKey() const V8_OVERRIDE { return NumberToString; }
589 virtual int NotMissMinorKey() const V8_OVERRIDE { return 0; }
593 class FastNewClosureStub : public HydrogenCodeStub {
595 FastNewClosureStub(Isolate* isolate,
596 StrictMode strict_mode,
598 : HydrogenCodeStub(isolate),
599 strict_mode_(strict_mode),
600 is_generator_(is_generator) { }
602 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
604 virtual void InitializeInterfaceDescriptor(
605 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
607 static void InstallDescriptors(Isolate* isolate);
609 StrictMode strict_mode() const { return strict_mode_; }
610 bool is_generator() const { return is_generator_; }
613 class StrictModeBits: public BitField<bool, 0, 1> {};
614 class IsGeneratorBits: public BitField<bool, 1, 1> {};
616 Major MajorKey() const { return FastNewClosure; }
617 int NotMissMinorKey() const {
618 return StrictModeBits::encode(strict_mode_ == STRICT) |
619 IsGeneratorBits::encode(is_generator_);
622 StrictMode strict_mode_;
627 class FastNewContextStub V8_FINAL : public HydrogenCodeStub {
629 static const int kMaximumSlots = 64;
631 FastNewContextStub(Isolate* isolate, int slots)
632 : HydrogenCodeStub(isolate), slots_(slots) {
633 DCHECK(slots_ > 0 && slots_ <= kMaximumSlots);
636 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
638 virtual void InitializeInterfaceDescriptor(
639 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
641 static void InstallDescriptors(Isolate* isolate);
643 int slots() const { return slots_; }
645 virtual Major MajorKey() const V8_OVERRIDE { return FastNewContext; }
646 virtual int NotMissMinorKey() const V8_OVERRIDE { return slots_; }
648 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
649 static const int kFunction = 0;
656 class FastCloneShallowArrayStub : public HydrogenCodeStub {
658 FastCloneShallowArrayStub(Isolate* isolate,
659 AllocationSiteMode allocation_site_mode)
660 : HydrogenCodeStub(isolate),
661 allocation_site_mode_(allocation_site_mode) {}
663 AllocationSiteMode allocation_site_mode() const {
664 return allocation_site_mode_;
667 virtual Handle<Code> GenerateCode();
669 virtual void InitializeInterfaceDescriptor(
670 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
672 static void InstallDescriptors(Isolate* isolate);
675 AllocationSiteMode allocation_site_mode_;
677 class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
678 // Ensure data fits within available bits.
679 Major MajorKey() const { return FastCloneShallowArray; }
680 int NotMissMinorKey() const {
681 return AllocationSiteModeBits::encode(allocation_site_mode_);
686 class FastCloneShallowObjectStub : public HydrogenCodeStub {
688 // Maximum number of properties in copied object.
689 static const int kMaximumClonedProperties = 6;
691 FastCloneShallowObjectStub(Isolate* isolate, int length)
692 : HydrogenCodeStub(isolate), length_(length) {
693 DCHECK_GE(length_, 0);
694 DCHECK_LE(length_, kMaximumClonedProperties);
697 int length() const { return length_; }
699 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
701 virtual void InitializeInterfaceDescriptor(
702 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
707 Major MajorKey() const { return FastCloneShallowObject; }
708 int NotMissMinorKey() const { return length_; }
710 DISALLOW_COPY_AND_ASSIGN(FastCloneShallowObjectStub);
714 class CreateAllocationSiteStub : public HydrogenCodeStub {
716 explicit CreateAllocationSiteStub(Isolate* isolate)
717 : HydrogenCodeStub(isolate) { }
719 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
721 static void GenerateAheadOfTime(Isolate* isolate);
723 virtual void InitializeInterfaceDescriptor(
724 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
727 Major MajorKey() const { return CreateAllocationSite; }
728 int NotMissMinorKey() const { return 0; }
730 DISALLOW_COPY_AND_ASSIGN(CreateAllocationSiteStub);
734 class InstanceofStub: public PlatformCodeStub {
738 kArgsInRegisters = 1 << 0,
739 kCallSiteInlineCheck = 1 << 1,
740 kReturnTrueFalseObject = 1 << 2
743 InstanceofStub(Isolate* isolate, Flags flags)
744 : PlatformCodeStub(isolate), flags_(flags) { }
746 static Register left();
747 static Register right();
749 void Generate(MacroAssembler* masm);
751 virtual void InitializeInterfaceDescriptor(
752 CodeStubInterfaceDescriptor* descriptor);
755 Major MajorKey() const { return Instanceof; }
756 int MinorKey() const { return static_cast<int>(flags_); }
758 bool HasArgsInRegisters() const {
759 return (flags_ & kArgsInRegisters) != 0;
762 bool HasCallSiteInlineCheck() const {
763 return (flags_ & kCallSiteInlineCheck) != 0;
766 bool ReturnTrueFalseObject() const {
767 return (flags_ & kReturnTrueFalseObject) != 0;
770 virtual void PrintName(OStream& os) const V8_OVERRIDE; // NOLINT
776 enum AllocationSiteOverrideMode {
778 DISABLE_ALLOCATION_SITES,
779 LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
783 class ArrayConstructorStub: public PlatformCodeStub {
785 enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
786 ArrayConstructorStub(Isolate* isolate, int argument_count);
787 explicit ArrayConstructorStub(Isolate* isolate);
789 void Generate(MacroAssembler* masm);
792 void GenerateDispatchToArrayStub(MacroAssembler* masm,
793 AllocationSiteOverrideMode mode);
794 virtual void PrintName(OStream& os) const V8_OVERRIDE; // NOLINT
796 virtual CodeStub::Major MajorKey() const { return ArrayConstructor; }
797 virtual int MinorKey() const { return argument_count_; }
799 ArgumentCountKey argument_count_;
803 class InternalArrayConstructorStub: public PlatformCodeStub {
805 explicit InternalArrayConstructorStub(Isolate* isolate);
807 void Generate(MacroAssembler* masm);
810 virtual CodeStub::Major MajorKey() const { return InternalArrayConstructor; }
811 virtual int MinorKey() const { return 0; }
813 void GenerateCase(MacroAssembler* masm, ElementsKind kind);
817 class MathPowStub: public PlatformCodeStub {
819 enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK };
821 MathPowStub(Isolate* isolate, ExponentType exponent_type)
822 : PlatformCodeStub(isolate), exponent_type_(exponent_type) { }
823 virtual void Generate(MacroAssembler* masm);
826 virtual CodeStub::Major MajorKey() const { return MathPow; }
827 virtual int MinorKey() const { return exponent_type_; }
829 ExponentType exponent_type_;
833 class CallICStub: public PlatformCodeStub {
835 CallICStub(Isolate* isolate, const CallIC::State& state)
836 : PlatformCodeStub(isolate), state_(state) {}
838 bool CallAsMethod() const { return state_.CallAsMethod(); }
840 int arg_count() const { return state_.arg_count(); }
842 static int ExtractArgcFromMinorKey(int minor_key) {
843 CallIC::State state((ExtraICState) minor_key);
844 return state.arg_count();
847 virtual void Generate(MacroAssembler* masm);
849 virtual Code::Kind GetCodeKind() const V8_OVERRIDE {
850 return Code::CALL_IC;
853 virtual InlineCacheState GetICState() const V8_OVERRIDE { return DEFAULT; }
855 virtual ExtraICState GetExtraICState() const V8_FINAL V8_OVERRIDE {
856 return state_.GetExtraICState();
860 virtual int MinorKey() const { return GetExtraICState(); }
861 virtual void PrintState(OStream& os) const V8_OVERRIDE; // NOLINT
863 virtual CodeStub::Major MajorKey() const { return CallIC; }
865 // Code generation helpers.
866 void GenerateMiss(MacroAssembler* masm, IC::UtilityId id);
868 const CallIC::State state_;
872 class CallIC_ArrayStub: public CallICStub {
874 CallIC_ArrayStub(Isolate* isolate, const CallIC::State& state_in)
875 : CallICStub(isolate, state_in) {}
877 virtual void Generate(MacroAssembler* masm);
879 virtual InlineCacheState GetICState() const V8_FINAL V8_OVERRIDE {
884 virtual void PrintState(OStream& os) const V8_OVERRIDE; // NOLINT
886 virtual CodeStub::Major MajorKey() const { return CallIC_Array; }
890 // TODO(verwaest): Translate to hydrogen code stub.
891 class FunctionPrototypeStub : public PlatformCodeStub {
893 explicit FunctionPrototypeStub(Isolate* isolate)
894 : PlatformCodeStub(isolate) {}
895 virtual void Generate(MacroAssembler* masm);
896 virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
899 virtual CodeStub::Major MajorKey() const { return FunctionPrototype; }
900 virtual int MinorKey() const { return 0; }
904 class HandlerStub : public HydrogenCodeStub {
906 virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
907 virtual ExtraICState GetExtraICState() const { return kind(); }
908 virtual InlineCacheState GetICState() const { return MONOMORPHIC; }
910 virtual void InitializeInterfaceDescriptor(
911 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
914 explicit HandlerStub(Isolate* isolate)
915 : HydrogenCodeStub(isolate), bit_field_(0) {}
916 virtual int NotMissMinorKey() const { return bit_field_; }
917 virtual Code::Kind kind() const = 0;
922 class LoadFieldStub: public HandlerStub {
924 LoadFieldStub(Isolate* isolate, FieldIndex index)
925 : HandlerStub(isolate), index_(index) {
926 int property_index_key = index_.GetFieldAccessStubKey();
927 bit_field_ = EncodedLoadFieldByIndexBits::encode(property_index_key);
930 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
932 FieldIndex index() const { return index_; }
935 explicit LoadFieldStub(Isolate* isolate);
936 virtual Code::Kind kind() const { return Code::LOAD_IC; }
937 virtual Code::StubType GetStubType() { return Code::FAST; }
940 class EncodedLoadFieldByIndexBits : public BitField<int, 0, 13> {};
941 virtual CodeStub::Major MajorKey() const { return LoadField; }
946 class LoadConstantStub : public HandlerStub {
948 LoadConstantStub(Isolate* isolate, int descriptor) : HandlerStub(isolate) {
949 bit_field_ = descriptor;
952 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
954 int descriptor() const { return bit_field_; }
957 explicit LoadConstantStub(Isolate* isolate);
958 virtual Code::Kind kind() const { return Code::LOAD_IC; }
959 virtual Code::StubType GetStubType() { return Code::FAST; }
962 virtual CodeStub::Major MajorKey() const { return LoadConstant; }
966 class StringLengthStub: public HandlerStub {
968 explicit StringLengthStub(Isolate* isolate) : HandlerStub(isolate) {}
969 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
972 virtual Code::Kind kind() const { return Code::LOAD_IC; }
973 virtual Code::StubType GetStubType() { return Code::FAST; }
976 virtual CodeStub::Major MajorKey() const { return StringLength; }
980 class StoreFieldStub : public HandlerStub {
982 StoreFieldStub(Isolate* isolate, FieldIndex index,
983 Representation representation)
984 : HandlerStub(isolate), index_(index), representation_(representation) {
985 int property_index_key = index_.GetFieldAccessStubKey();
986 bit_field_ = EncodedStoreFieldByIndexBits::encode(property_index_key) |
987 RepresentationBits::encode(
988 PropertyDetails::EncodeRepresentation(representation));
991 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
993 FieldIndex index() const { return index_; }
994 Representation representation() { return representation_; }
995 static void InstallDescriptors(Isolate* isolate);
998 explicit StoreFieldStub(Isolate* isolate);
999 virtual Code::Kind kind() const { return Code::STORE_IC; }
1000 virtual Code::StubType GetStubType() { return Code::FAST; }
1003 class EncodedStoreFieldByIndexBits : public BitField<int, 0, 13> {};
1004 class RepresentationBits : public BitField<int, 13, 4> {};
1005 virtual CodeStub::Major MajorKey() const { return StoreField; }
1007 Representation representation_;
1011 class StoreGlobalStub : public HandlerStub {
1013 StoreGlobalStub(Isolate* isolate, bool is_constant, bool check_global)
1014 : HandlerStub(isolate) {
1015 bit_field_ = IsConstantBits::encode(is_constant) |
1016 CheckGlobalBits::encode(check_global);
1019 static Handle<HeapObject> global_placeholder(Isolate* isolate) {
1020 return isolate->factory()->uninitialized_value();
1023 Handle<Code> GetCodeCopyFromTemplate(Handle<GlobalObject> global,
1024 Handle<PropertyCell> cell) {
1025 if (check_global()) {
1026 Code::FindAndReplacePattern pattern;
1027 pattern.Add(Handle<Map>(global_placeholder(isolate())->map()), global);
1028 pattern.Add(isolate()->factory()->meta_map(), Handle<Map>(global->map()));
1029 pattern.Add(isolate()->factory()->global_property_cell_map(), cell);
1030 return CodeStub::GetCodeCopy(pattern);
1032 Code::FindAndReplacePattern pattern;
1033 pattern.Add(isolate()->factory()->global_property_cell_map(), cell);
1034 return CodeStub::GetCodeCopy(pattern);
1038 virtual Code::Kind kind() const { return Code::STORE_IC; }
1040 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
1042 bool is_constant() const {
1043 return IsConstantBits::decode(bit_field_);
1045 bool check_global() const {
1046 return CheckGlobalBits::decode(bit_field_);
1048 void set_is_constant(bool value) {
1049 bit_field_ = IsConstantBits::update(bit_field_, value);
1052 Representation representation() {
1053 return Representation::FromKind(RepresentationBits::decode(bit_field_));
1055 void set_representation(Representation r) {
1056 bit_field_ = RepresentationBits::update(bit_field_, r.kind());
1060 Major MajorKey() const { return StoreGlobal; }
1062 class IsConstantBits: public BitField<bool, 0, 1> {};
1063 class RepresentationBits: public BitField<Representation::Kind, 1, 8> {};
1064 class CheckGlobalBits: public BitField<bool, 9, 1> {};
1066 DISALLOW_COPY_AND_ASSIGN(StoreGlobalStub);
1070 class CallApiFunctionStub : public PlatformCodeStub {
1072 CallApiFunctionStub(Isolate* isolate,
1074 bool call_data_undefined,
1075 int argc) : PlatformCodeStub(isolate) {
1077 IsStoreBits::encode(is_store) |
1078 CallDataUndefinedBits::encode(call_data_undefined) |
1079 ArgumentBits::encode(argc);
1080 DCHECK(!is_store || argc == 1);
1084 virtual void Generate(MacroAssembler* masm) V8_OVERRIDE;
1085 virtual Major MajorKey() const V8_OVERRIDE { return CallApiFunction; }
1086 virtual int MinorKey() const V8_OVERRIDE { return bit_field_; }
1088 class IsStoreBits: public BitField<bool, 0, 1> {};
1089 class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
1090 class ArgumentBits: public BitField<int, 2, Code::kArgumentsBits> {};
1094 DISALLOW_COPY_AND_ASSIGN(CallApiFunctionStub);
1098 class CallApiGetterStub : public PlatformCodeStub {
1100 explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1103 virtual void Generate(MacroAssembler* masm) V8_OVERRIDE;
1104 virtual Major MajorKey() const V8_OVERRIDE { return CallApiGetter; }
1105 virtual int MinorKey() const V8_OVERRIDE { return 0; }
1107 DISALLOW_COPY_AND_ASSIGN(CallApiGetterStub);
1111 class BinaryOpICStub : public HydrogenCodeStub {
1113 BinaryOpICStub(Isolate* isolate, Token::Value op,
1114 OverwriteMode mode = NO_OVERWRITE)
1115 : HydrogenCodeStub(isolate, UNINITIALIZED), state_(isolate, op, mode) {}
1117 explicit BinaryOpICStub(Isolate* isolate, const BinaryOpIC::State& state)
1118 : HydrogenCodeStub(isolate), state_(state) {}
1120 static void GenerateAheadOfTime(Isolate* isolate);
1122 virtual void InitializeInterfaceDescriptor(
1123 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() const V8_FINAL V8_OVERRIDE {
1132 return state_.GetICState();
1135 virtual ExtraICState GetExtraICState() const V8_FINAL V8_OVERRIDE {
1136 return state_.GetExtraICState();
1139 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
1141 const BinaryOpIC::State& state() const { return state_; }
1143 virtual void PrintState(OStream& os) const V8_FINAL V8_OVERRIDE; // NOLINT
1145 virtual Major MajorKey() const V8_OVERRIDE { return BinaryOpIC; }
1146 virtual int NotMissMinorKey() const V8_FINAL V8_OVERRIDE {
1147 return GetExtraICState();
1150 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1151 static const int kLeft = 0;
1152 static const int kRight = 1;
1155 static void GenerateAheadOfTime(Isolate* isolate,
1156 const BinaryOpIC::State& state);
1158 BinaryOpIC::State state_;
1160 DISALLOW_COPY_AND_ASSIGN(BinaryOpICStub);
1164 // TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
1165 // call support for stubs in Hydrogen.
1166 class BinaryOpICWithAllocationSiteStub V8_FINAL : public PlatformCodeStub {
1168 BinaryOpICWithAllocationSiteStub(Isolate* isolate,
1169 const BinaryOpIC::State& state)
1170 : PlatformCodeStub(isolate), state_(state) {}
1172 static void GenerateAheadOfTime(Isolate* isolate);
1174 Handle<Code> GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site) {
1175 Code::FindAndReplacePattern pattern;
1176 pattern.Add(isolate()->factory()->undefined_map(), allocation_site);
1177 return CodeStub::GetCodeCopy(pattern);
1180 virtual Code::Kind GetCodeKind() const V8_OVERRIDE {
1181 return Code::BINARY_OP_IC;
1184 virtual InlineCacheState GetICState() const V8_OVERRIDE {
1185 return state_.GetICState();
1188 virtual ExtraICState GetExtraICState() const V8_OVERRIDE {
1189 return state_.GetExtraICState();
1192 virtual void Generate(MacroAssembler* masm) V8_OVERRIDE;
1194 virtual void PrintState(OStream& os) const V8_OVERRIDE; // NOLINT
1196 virtual Major MajorKey() const V8_OVERRIDE {
1197 return BinaryOpICWithAllocationSite;
1199 virtual int MinorKey() const V8_OVERRIDE { return GetExtraICState(); }
1202 static void GenerateAheadOfTime(Isolate* isolate,
1203 const BinaryOpIC::State& state);
1205 BinaryOpIC::State state_;
1207 DISALLOW_COPY_AND_ASSIGN(BinaryOpICWithAllocationSiteStub);
1211 class BinaryOpWithAllocationSiteStub V8_FINAL : public BinaryOpICStub {
1213 BinaryOpWithAllocationSiteStub(Isolate* isolate,
1216 : BinaryOpICStub(isolate, op, mode) {}
1218 BinaryOpWithAllocationSiteStub(Isolate* isolate,
1219 const BinaryOpIC::State& state)
1220 : BinaryOpICStub(isolate, state) {}
1222 virtual void InitializeInterfaceDescriptor(
1223 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1225 static void InstallDescriptors(Isolate* isolate);
1227 virtual Code::Kind GetCodeKind() const V8_FINAL V8_OVERRIDE {
1231 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
1233 virtual Major MajorKey() const V8_OVERRIDE {
1234 return BinaryOpWithAllocationSite;
1237 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1238 static const int kAllocationSite = 0;
1239 static const int kLeft = 1;
1240 static const int kRight = 2;
1244 enum StringAddFlags {
1245 // Omit both parameter checks.
1246 STRING_ADD_CHECK_NONE = 0,
1247 // Check left parameter.
1248 STRING_ADD_CHECK_LEFT = 1 << 0,
1249 // Check right parameter.
1250 STRING_ADD_CHECK_RIGHT = 1 << 1,
1251 // Check both parameters.
1252 STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT
1256 class StringAddStub V8_FINAL : public HydrogenCodeStub {
1258 StringAddStub(Isolate* isolate,
1259 StringAddFlags flags,
1260 PretenureFlag pretenure_flag)
1261 : HydrogenCodeStub(isolate),
1262 bit_field_(StringAddFlagsBits::encode(flags) |
1263 PretenureFlagBits::encode(pretenure_flag)) {}
1265 StringAddFlags flags() const {
1266 return StringAddFlagsBits::decode(bit_field_);
1269 PretenureFlag pretenure_flag() const {
1270 return PretenureFlagBits::decode(bit_field_);
1273 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
1275 virtual void InitializeInterfaceDescriptor(
1276 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1278 static void InstallDescriptors(Isolate* isolate);
1280 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1281 static const int kLeft = 0;
1282 static const int kRight = 1;
1285 class StringAddFlagsBits: public BitField<StringAddFlags, 0, 2> {};
1286 class PretenureFlagBits: public BitField<PretenureFlag, 2, 1> {};
1287 uint32_t bit_field_;
1289 virtual Major MajorKey() const V8_OVERRIDE { return StringAdd; }
1290 virtual int NotMissMinorKey() const V8_OVERRIDE { return bit_field_; }
1292 virtual void PrintBaseName(OStream& os) const V8_OVERRIDE; // NOLINT
1294 DISALLOW_COPY_AND_ASSIGN(StringAddStub);
1298 class ICCompareStub: public PlatformCodeStub {
1300 ICCompareStub(Isolate* isolate,
1302 CompareIC::State left,
1303 CompareIC::State right,
1304 CompareIC::State handler)
1305 : PlatformCodeStub(isolate),
1310 DCHECK(Token::IsCompareOp(op));
1313 virtual void Generate(MacroAssembler* masm);
1315 void set_known_map(Handle<Map> map) { known_map_ = map; }
1317 static void DecodeKey(uint32_t stub_key, CompareIC::State* left_state,
1318 CompareIC::State* right_state,
1319 CompareIC::State* handler_state, Token::Value* op);
1321 virtual InlineCacheState GetICState() const;
1324 class OpField: public BitField<int, 0, 3> { };
1325 class LeftStateField: public BitField<int, 3, 4> { };
1326 class RightStateField: public BitField<int, 7, 4> { };
1327 class HandlerStateField: public BitField<int, 11, 4> { };
1329 virtual CodeStub::Major MajorKey() const { return CompareIC; }
1330 virtual int MinorKey() const;
1332 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_IC; }
1334 void GenerateSmis(MacroAssembler* masm);
1335 void GenerateNumbers(MacroAssembler* masm);
1336 void GenerateInternalizedStrings(MacroAssembler* masm);
1337 void GenerateStrings(MacroAssembler* masm);
1338 void GenerateUniqueNames(MacroAssembler* masm);
1339 void GenerateObjects(MacroAssembler* masm);
1340 void GenerateMiss(MacroAssembler* masm);
1341 void GenerateKnownObjects(MacroAssembler* masm);
1342 void GenerateGeneric(MacroAssembler* masm);
1344 bool strict() const { return op_ == Token::EQ_STRICT; }
1345 Condition GetCondition() const { return CompareIC::ComputeCondition(op_); }
1347 virtual void AddToSpecialCache(Handle<Code> new_object);
1348 virtual bool FindCodeInSpecialCache(Code** code_out);
1349 virtual bool UseSpecialCache() { return state_ == CompareIC::KNOWN_OBJECT; }
1352 CompareIC::State left_;
1353 CompareIC::State right_;
1354 CompareIC::State state_;
1355 Handle<Map> known_map_;
1359 class CompareNilICStub : public HydrogenCodeStub {
1361 Type* GetType(Zone* zone, Handle<Map> map = Handle<Map>());
1362 Type* GetInputType(Zone* zone, Handle<Map> map);
1364 CompareNilICStub(Isolate* isolate, NilValue nil)
1365 : HydrogenCodeStub(isolate), nil_value_(nil) { }
1367 CompareNilICStub(Isolate* isolate,
1368 ExtraICState ic_state,
1369 InitializationState init_state = INITIALIZED)
1370 : HydrogenCodeStub(isolate, init_state),
1371 nil_value_(NilValueField::decode(ic_state)),
1372 state_(State(TypesField::decode(ic_state))) {
1375 static Handle<Code> GetUninitialized(Isolate* isolate,
1377 return CompareNilICStub(isolate, nil, UNINITIALIZED).GetCode();
1380 virtual void InitializeInterfaceDescriptor(
1381 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1383 static void InstallDescriptors(Isolate* isolate) {
1384 CompareNilICStub compare_stub(isolate, kNullValue, UNINITIALIZED);
1385 compare_stub.InitializeInterfaceDescriptor(
1386 isolate->code_stub_interface_descriptor(CodeStub::CompareNilIC));
1389 virtual InlineCacheState GetICState() const {
1390 if (state_.Contains(GENERIC)) {
1392 } else if (state_.Contains(MONOMORPHIC_MAP)) {
1395 return PREMONOMORPHIC;
1399 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_NIL_IC; }
1401 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
1403 virtual ExtraICState GetExtraICState() const {
1404 return NilValueField::encode(nil_value_) |
1405 TypesField::encode(state_.ToIntegral());
1408 void UpdateStatus(Handle<Object> object);
1410 bool IsMonomorphic() const { return state_.Contains(MONOMORPHIC_MAP); }
1411 NilValue GetNilValue() const { return nil_value_; }
1412 void ClearState() { state_.RemoveAll(); }
1414 virtual void PrintState(OStream& os) const V8_OVERRIDE; // NOLINT
1415 virtual void PrintBaseName(OStream& os) const V8_OVERRIDE; // NOLINT
1418 friend class CompareNilIC;
1420 enum CompareNilType {
1428 // At most 6 different types can be distinguished, because the Code object
1429 // only has room for a single byte to hold a set and there are two more
1430 // boolean flags we need to store. :-P
1431 STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
1433 class State : public EnumSet<CompareNilType, byte> {
1435 State() : EnumSet<CompareNilType, byte>(0) { }
1436 explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
1438 friend OStream& operator<<(OStream& os, const State& s);
1440 CompareNilICStub(Isolate* isolate,
1442 InitializationState init_state)
1443 : HydrogenCodeStub(isolate, init_state), nil_value_(nil) { }
1445 class NilValueField : public BitField<NilValue, 0, 1> {};
1446 class TypesField : public BitField<byte, 1, NUMBER_OF_TYPES> {};
1448 virtual CodeStub::Major MajorKey() const { return CompareNilIC; }
1449 virtual int NotMissMinorKey() const { return GetExtraICState(); }
1451 NilValue nil_value_;
1454 DISALLOW_COPY_AND_ASSIGN(CompareNilICStub);
1458 OStream& operator<<(OStream& os, const CompareNilICStub::State& s);
1461 class CEntryStub : public PlatformCodeStub {
1463 CEntryStub(Isolate* isolate,
1465 SaveFPRegsMode save_doubles = kDontSaveFPRegs)
1466 : PlatformCodeStub(isolate),
1467 result_size_(result_size),
1468 save_doubles_(save_doubles) { }
1470 void Generate(MacroAssembler* masm);
1472 // The version of this stub that doesn't save doubles is generated ahead of
1473 // time, so it's OK to call it from other stubs that can't cope with GC during
1474 // their code generation. On machines that always have gp registers (x64) we
1475 // can generate both variants ahead of time.
1476 static void GenerateAheadOfTime(Isolate* isolate);
1479 // Number of pointers/values returned.
1480 const int result_size_;
1481 SaveFPRegsMode save_doubles_;
1483 Major MajorKey() const { return CEntry; }
1484 int MinorKey() const;
1486 bool NeedsImmovableCode();
1490 class JSEntryStub : public PlatformCodeStub {
1492 explicit JSEntryStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
1494 void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
1497 void GenerateBody(MacroAssembler* masm, bool is_construct);
1500 Major MajorKey() const { return JSEntry; }
1501 int MinorKey() const { return 0; }
1503 virtual void FinishCode(Handle<Code> code);
1505 int handler_offset_;
1509 class JSConstructEntryStub : public JSEntryStub {
1511 explicit JSConstructEntryStub(Isolate* isolate) : JSEntryStub(isolate) { }
1513 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
1516 int MinorKey() const { return 1; }
1518 virtual void PrintName(OStream& os) const V8_OVERRIDE { // NOLINT
1519 os << "JSConstructEntryStub";
1524 class ArgumentsAccessStub: public PlatformCodeStub {
1533 ArgumentsAccessStub(Isolate* isolate, Type type)
1534 : PlatformCodeStub(isolate), type_(type) { }
1539 Major MajorKey() const { return ArgumentsAccess; }
1540 int MinorKey() const { return type_; }
1542 void Generate(MacroAssembler* masm);
1543 void GenerateReadElement(MacroAssembler* masm);
1544 void GenerateNewStrict(MacroAssembler* masm);
1545 void GenerateNewSloppyFast(MacroAssembler* masm);
1546 void GenerateNewSloppySlow(MacroAssembler* masm);
1548 virtual void PrintName(OStream& os) const V8_OVERRIDE; // NOLINT
1552 class RegExpExecStub: public PlatformCodeStub {
1554 explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
1557 Major MajorKey() const { return RegExpExec; }
1558 int MinorKey() const { return 0; }
1560 void Generate(MacroAssembler* masm);
1564 class RegExpConstructResultStub V8_FINAL : public HydrogenCodeStub {
1566 explicit RegExpConstructResultStub(Isolate* isolate)
1567 : HydrogenCodeStub(isolate) { }
1569 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
1571 virtual void InitializeInterfaceDescriptor(
1572 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1574 virtual Major MajorKey() const V8_OVERRIDE { return RegExpConstructResult; }
1575 virtual int NotMissMinorKey() const V8_OVERRIDE { return 0; }
1577 static void InstallDescriptors(Isolate* isolate);
1579 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1580 static const int kLength = 0;
1581 static const int kIndex = 1;
1582 static const int kInput = 2;
1585 DISALLOW_COPY_AND_ASSIGN(RegExpConstructResultStub);
1589 class CallFunctionStub: public PlatformCodeStub {
1591 CallFunctionStub(Isolate* isolate, int argc, CallFunctionFlags flags)
1592 : PlatformCodeStub(isolate), argc_(argc), flags_(flags) {
1593 DCHECK(argc <= Code::kMaxArguments);
1596 void Generate(MacroAssembler* masm);
1598 static int ExtractArgcFromMinorKey(int minor_key) {
1599 return ArgcBits::decode(minor_key);
1602 virtual void InitializeInterfaceDescriptor(
1603 CodeStubInterfaceDescriptor* descriptor);
1607 CallFunctionFlags flags_;
1609 virtual void PrintName(OStream& os) const V8_OVERRIDE; // NOLINT
1611 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
1612 class FlagBits: public BitField<CallFunctionFlags, 0, 2> {};
1613 class ArgcBits : public BitField<unsigned, 2, Code::kArgumentsBits> {};
1615 STATIC_ASSERT(Code::kArgumentsBits + 2 <= kStubMinorKeyBits);
1617 Major MajorKey() const { return CallFunction; }
1618 int MinorKey() const {
1619 // Encode the parameters in a unique 32 bit value.
1620 return FlagBits::encode(flags_) | ArgcBits::encode(argc_);
1623 bool CallAsMethod() {
1624 return flags_ == CALL_AS_METHOD || flags_ == WRAP_AND_CALL;
1627 bool NeedsChecks() {
1628 return flags_ != WRAP_AND_CALL;
1633 class CallConstructStub: public PlatformCodeStub {
1635 CallConstructStub(Isolate* isolate, CallConstructorFlags flags)
1636 : PlatformCodeStub(isolate), flags_(flags) {}
1638 void Generate(MacroAssembler* masm);
1640 virtual void FinishCode(Handle<Code> code) {
1641 code->set_has_function_cache(RecordCallTarget());
1644 virtual void InitializeInterfaceDescriptor(
1645 CodeStubInterfaceDescriptor* descriptor);
1648 CallConstructorFlags flags_;
1650 virtual void PrintName(OStream& os) const V8_OVERRIDE; // NOLINT
1652 Major MajorKey() const { return CallConstruct; }
1653 int MinorKey() const { return flags_; }
1655 bool RecordCallTarget() const {
1656 return (flags_ & RECORD_CONSTRUCTOR_TARGET) != 0;
1661 enum StringIndexFlags {
1662 // Accepts smis or heap numbers.
1663 STRING_INDEX_IS_NUMBER,
1665 // Accepts smis or heap numbers that are valid array indices
1666 // (ECMA-262 15.4). Invalid indices are reported as being out of
1668 STRING_INDEX_IS_ARRAY_INDEX
1672 // Generates code implementing String.prototype.charCodeAt.
1674 // Only supports the case when the receiver is a string and the index
1675 // is a number (smi or heap number) that is a valid index into the
1676 // string. Additional index constraints are specified by the
1677 // flags. Otherwise, bails out to the provided labels.
1679 // Register usage: |object| may be changed to another string in a way
1680 // that doesn't affect charCodeAt/charAt semantics, |index| is
1681 // preserved, |scratch| and |result| are clobbered.
1682 class StringCharCodeAtGenerator {
1684 StringCharCodeAtGenerator(Register object,
1687 Label* receiver_not_string,
1688 Label* index_not_number,
1689 Label* index_out_of_range,
1690 StringIndexFlags index_flags)
1694 receiver_not_string_(receiver_not_string),
1695 index_not_number_(index_not_number),
1696 index_out_of_range_(index_out_of_range),
1697 index_flags_(index_flags) {
1698 DCHECK(!result_.is(object_));
1699 DCHECK(!result_.is(index_));
1702 // Generates the fast case code. On the fallthrough path |result|
1703 // register contains the result.
1704 void GenerateFast(MacroAssembler* masm);
1706 // Generates the slow case code. Must not be naturally
1707 // reachable. Expected to be put after a ret instruction (e.g., in
1708 // deferred code). Always jumps back to the fast case.
1709 void GenerateSlow(MacroAssembler* masm,
1710 const RuntimeCallHelper& call_helper);
1712 // Skip handling slow case and directly jump to bailout.
1713 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1714 masm->bind(&index_not_smi_);
1715 masm->bind(&call_runtime_);
1724 Label* receiver_not_string_;
1725 Label* index_not_number_;
1726 Label* index_out_of_range_;
1728 StringIndexFlags index_flags_;
1730 Label call_runtime_;
1731 Label index_not_smi_;
1732 Label got_smi_index_;
1735 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
1739 // Generates code for creating a one-char string from a char code.
1740 class StringCharFromCodeGenerator {
1742 StringCharFromCodeGenerator(Register code,
1746 DCHECK(!code_.is(result_));
1749 // Generates the fast case code. On the fallthrough path |result|
1750 // register contains the result.
1751 void GenerateFast(MacroAssembler* masm);
1753 // Generates the slow case code. Must not be naturally
1754 // reachable. Expected to be put after a ret instruction (e.g., in
1755 // deferred code). Always jumps back to the fast case.
1756 void GenerateSlow(MacroAssembler* masm,
1757 const RuntimeCallHelper& call_helper);
1759 // Skip handling slow case and directly jump to bailout.
1760 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1761 masm->bind(&slow_case_);
1772 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
1776 // Generates code implementing String.prototype.charAt.
1778 // Only supports the case when the receiver is a string and the index
1779 // is a number (smi or heap number) that is a valid index into the
1780 // string. Additional index constraints are specified by the
1781 // flags. Otherwise, bails out to the provided labels.
1783 // Register usage: |object| may be changed to another string in a way
1784 // that doesn't affect charCodeAt/charAt semantics, |index| is
1785 // preserved, |scratch1|, |scratch2|, and |result| are clobbered.
1786 class StringCharAtGenerator {
1788 StringCharAtGenerator(Register object,
1792 Label* receiver_not_string,
1793 Label* index_not_number,
1794 Label* index_out_of_range,
1795 StringIndexFlags index_flags)
1796 : char_code_at_generator_(object,
1799 receiver_not_string,
1803 char_from_code_generator_(scratch, result) {}
1805 // Generates the fast case code. On the fallthrough path |result|
1806 // register contains the result.
1807 void GenerateFast(MacroAssembler* masm) {
1808 char_code_at_generator_.GenerateFast(masm);
1809 char_from_code_generator_.GenerateFast(masm);
1812 // Generates the slow case code. Must not be naturally
1813 // reachable. Expected to be put after a ret instruction (e.g., in
1814 // deferred code). Always jumps back to the fast case.
1815 void GenerateSlow(MacroAssembler* masm,
1816 const RuntimeCallHelper& call_helper) {
1817 char_code_at_generator_.GenerateSlow(masm, call_helper);
1818 char_from_code_generator_.GenerateSlow(masm, call_helper);
1821 // Skip handling slow case and directly jump to bailout.
1822 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1823 char_code_at_generator_.SkipSlow(masm, bailout);
1824 char_from_code_generator_.SkipSlow(masm, bailout);
1828 StringCharCodeAtGenerator char_code_at_generator_;
1829 StringCharFromCodeGenerator char_from_code_generator_;
1831 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
1835 class LoadDictionaryElementStub : public HydrogenCodeStub {
1837 explicit LoadDictionaryElementStub(Isolate* isolate)
1838 : HydrogenCodeStub(isolate) {}
1840 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
1842 virtual void InitializeInterfaceDescriptor(
1843 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1846 Major MajorKey() const { return LoadElement; }
1847 int NotMissMinorKey() const { return DICTIONARY_ELEMENTS; }
1849 DISALLOW_COPY_AND_ASSIGN(LoadDictionaryElementStub);
1853 class LoadDictionaryElementPlatformStub : public PlatformCodeStub {
1855 explicit LoadDictionaryElementPlatformStub(Isolate* isolate)
1856 : PlatformCodeStub(isolate) {}
1858 void Generate(MacroAssembler* masm);
1861 Major MajorKey() const { return LoadElement; }
1862 int MinorKey() const { return DICTIONARY_ELEMENTS; }
1864 DISALLOW_COPY_AND_ASSIGN(LoadDictionaryElementPlatformStub);
1868 class KeyedLoadGenericStub : public HydrogenCodeStub {
1870 explicit KeyedLoadGenericStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
1872 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
1874 virtual void InitializeInterfaceDescriptor(
1875 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1877 static void InstallDescriptors(Isolate* isolate);
1879 virtual Code::Kind GetCodeKind() const { return Code::KEYED_LOAD_IC; }
1880 virtual InlineCacheState GetICState() const { return GENERIC; }
1883 Major MajorKey() const { return KeyedLoadGeneric; }
1884 int NotMissMinorKey() const { return 0; }
1886 DISALLOW_COPY_AND_ASSIGN(KeyedLoadGenericStub);
1890 class DoubleToIStub : public PlatformCodeStub {
1892 DoubleToIStub(Isolate* isolate,
1894 Register destination,
1897 bool skip_fastpath = false)
1898 : PlatformCodeStub(isolate), bit_field_(0) {
1899 bit_field_ = SourceRegisterBits::encode(source.code()) |
1900 DestinationRegisterBits::encode(destination.code()) |
1901 OffsetBits::encode(offset) |
1902 IsTruncatingBits::encode(is_truncating) |
1903 SkipFastPathBits::encode(skip_fastpath) |
1904 SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0);
1908 return Register::from_code(SourceRegisterBits::decode(bit_field_));
1911 Register destination() {
1912 return Register::from_code(DestinationRegisterBits::decode(bit_field_));
1915 bool is_truncating() {
1916 return IsTruncatingBits::decode(bit_field_);
1919 bool skip_fastpath() {
1920 return SkipFastPathBits::decode(bit_field_);
1924 return OffsetBits::decode(bit_field_);
1927 void Generate(MacroAssembler* masm);
1929 virtual bool SometimesSetsUpAFrame() { return false; }
1932 static const int kBitsPerRegisterNumber = 6;
1933 STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
1934 class SourceRegisterBits:
1935 public BitField<int, 0, kBitsPerRegisterNumber> {}; // NOLINT
1936 class DestinationRegisterBits:
1937 public BitField<int, kBitsPerRegisterNumber,
1938 kBitsPerRegisterNumber> {}; // NOLINT
1939 class IsTruncatingBits:
1940 public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {}; // NOLINT
1942 public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {}; // NOLINT
1943 class SkipFastPathBits:
1944 public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {}; // NOLINT
1946 public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {}; // NOLINT
1948 Major MajorKey() const { return DoubleToI; }
1949 int MinorKey() const { return bit_field_; }
1953 DISALLOW_COPY_AND_ASSIGN(DoubleToIStub);
1957 class LoadFastElementStub : public HydrogenCodeStub {
1959 LoadFastElementStub(Isolate* isolate, bool is_js_array,
1960 ElementsKind elements_kind)
1961 : HydrogenCodeStub(isolate) {
1962 bit_field_ = ElementsKindBits::encode(elements_kind) |
1963 IsJSArrayBits::encode(is_js_array);
1966 bool is_js_array() const {
1967 return IsJSArrayBits::decode(bit_field_);
1970 ElementsKind elements_kind() const {
1971 return ElementsKindBits::decode(bit_field_);
1974 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
1976 virtual void InitializeInterfaceDescriptor(
1977 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1980 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
1981 class IsJSArrayBits: public BitField<bool, 8, 1> {};
1982 uint32_t bit_field_;
1984 Major MajorKey() const { return LoadElement; }
1985 int NotMissMinorKey() const { return bit_field_; }
1987 DISALLOW_COPY_AND_ASSIGN(LoadFastElementStub);
1991 class StoreFastElementStub : public HydrogenCodeStub {
1993 StoreFastElementStub(Isolate* isolate, bool is_js_array,
1994 ElementsKind elements_kind, KeyedAccessStoreMode mode)
1995 : HydrogenCodeStub(isolate) {
1996 bit_field_ = ElementsKindBits::encode(elements_kind) |
1997 IsJSArrayBits::encode(is_js_array) |
1998 StoreModeBits::encode(mode);
2001 bool is_js_array() const {
2002 return IsJSArrayBits::decode(bit_field_);
2005 ElementsKind elements_kind() const {
2006 return ElementsKindBits::decode(bit_field_);
2009 KeyedAccessStoreMode store_mode() const {
2010 return StoreModeBits::decode(bit_field_);
2013 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
2015 virtual void InitializeInterfaceDescriptor(
2016 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
2019 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2020 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
2021 class IsJSArrayBits: public BitField<bool, 12, 1> {};
2022 uint32_t bit_field_;
2024 Major MajorKey() const { return StoreElement; }
2025 int NotMissMinorKey() const { return bit_field_; }
2027 DISALLOW_COPY_AND_ASSIGN(StoreFastElementStub);
2031 class TransitionElementsKindStub : public HydrogenCodeStub {
2033 TransitionElementsKindStub(Isolate* isolate,
2034 ElementsKind from_kind,
2035 ElementsKind to_kind,
2036 bool is_js_array) : HydrogenCodeStub(isolate) {
2037 bit_field_ = FromKindBits::encode(from_kind) |
2038 ToKindBits::encode(to_kind) |
2039 IsJSArrayBits::encode(is_js_array);
2042 ElementsKind from_kind() const {
2043 return FromKindBits::decode(bit_field_);
2046 ElementsKind to_kind() const {
2047 return ToKindBits::decode(bit_field_);
2050 bool is_js_array() const {
2051 return IsJSArrayBits::decode(bit_field_);
2054 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
2056 virtual void InitializeInterfaceDescriptor(
2057 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
2060 class FromKindBits: public BitField<ElementsKind, 8, 8> {};
2061 class ToKindBits: public BitField<ElementsKind, 0, 8> {};
2062 class IsJSArrayBits: public BitField<bool, 16, 1> {};
2063 uint32_t bit_field_;
2065 Major MajorKey() const { return TransitionElementsKind; }
2066 int NotMissMinorKey() const { return bit_field_; }
2068 DISALLOW_COPY_AND_ASSIGN(TransitionElementsKindStub);
2072 class ArrayConstructorStubBase : public HydrogenCodeStub {
2074 ArrayConstructorStubBase(Isolate* isolate,
2076 AllocationSiteOverrideMode override_mode)
2077 : HydrogenCodeStub(isolate) {
2078 // It only makes sense to override local allocation site behavior
2079 // if there is a difference between the global allocation site policy
2080 // for an ElementsKind and the desired usage of the stub.
2081 DCHECK(override_mode != DISABLE_ALLOCATION_SITES ||
2082 AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
2083 bit_field_ = ElementsKindBits::encode(kind) |
2084 AllocationSiteOverrideModeBits::encode(override_mode);
2087 ElementsKind elements_kind() const {
2088 return ElementsKindBits::decode(bit_field_);
2091 AllocationSiteOverrideMode override_mode() const {
2092 return AllocationSiteOverrideModeBits::decode(bit_field_);
2095 static void GenerateStubsAheadOfTime(Isolate* isolate);
2096 static void InstallDescriptors(Isolate* isolate);
2098 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2099 static const int kConstructor = 0;
2100 static const int kAllocationSite = 1;
2103 OStream& BasePrintName(OStream& os, const char* name) const; // NOLINT
2106 int NotMissMinorKey() const { return bit_field_; }
2108 // Ensure data fits within available bits.
2109 STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
2111 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2112 class AllocationSiteOverrideModeBits: public
2113 BitField<AllocationSiteOverrideMode, 8, 1> {}; // NOLINT
2114 uint32_t bit_field_;
2116 DISALLOW_COPY_AND_ASSIGN(ArrayConstructorStubBase);
2120 class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
2122 ArrayNoArgumentConstructorStub(
2125 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2126 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2129 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
2131 virtual void InitializeInterfaceDescriptor(
2132 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
2135 Major MajorKey() const { return ArrayNoArgumentConstructor; }
2137 virtual void PrintName(OStream& os) const V8_OVERRIDE { // NOLINT
2138 BasePrintName(os, "ArrayNoArgumentConstructorStub");
2141 DISALLOW_COPY_AND_ASSIGN(ArrayNoArgumentConstructorStub);
2145 class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
2147 ArraySingleArgumentConstructorStub(
2150 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2151 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2154 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
2156 virtual void InitializeInterfaceDescriptor(
2157 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
2160 Major MajorKey() const { return ArraySingleArgumentConstructor; }
2162 virtual void PrintName(OStream& os) const { // NOLINT
2163 BasePrintName(os, "ArraySingleArgumentConstructorStub");
2166 DISALLOW_COPY_AND_ASSIGN(ArraySingleArgumentConstructorStub);
2170 class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
2172 ArrayNArgumentsConstructorStub(
2175 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2176 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2179 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
2181 virtual void InitializeInterfaceDescriptor(
2182 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
2185 Major MajorKey() const { return ArrayNArgumentsConstructor; }
2187 virtual void PrintName(OStream& os) const { // NOLINT
2188 BasePrintName(os, "ArrayNArgumentsConstructorStub");
2191 DISALLOW_COPY_AND_ASSIGN(ArrayNArgumentsConstructorStub);
2195 class InternalArrayConstructorStubBase : public HydrogenCodeStub {
2197 InternalArrayConstructorStubBase(Isolate* isolate, ElementsKind kind)
2198 : HydrogenCodeStub(isolate) {
2202 static void GenerateStubsAheadOfTime(Isolate* isolate);
2203 static void InstallDescriptors(Isolate* isolate);
2205 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2206 static const int kConstructor = 0;
2208 ElementsKind elements_kind() const { return kind_; }
2211 int NotMissMinorKey() const { return kind_; }
2215 DISALLOW_COPY_AND_ASSIGN(InternalArrayConstructorStubBase);
2219 class InternalArrayNoArgumentConstructorStub : public
2220 InternalArrayConstructorStubBase {
2222 InternalArrayNoArgumentConstructorStub(Isolate* isolate,
2224 : InternalArrayConstructorStubBase(isolate, kind) { }
2226 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
2228 virtual void InitializeInterfaceDescriptor(
2229 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
2232 Major MajorKey() const { return InternalArrayNoArgumentConstructor; }
2234 DISALLOW_COPY_AND_ASSIGN(InternalArrayNoArgumentConstructorStub);
2238 class InternalArraySingleArgumentConstructorStub : public
2239 InternalArrayConstructorStubBase {
2241 InternalArraySingleArgumentConstructorStub(Isolate* isolate,
2243 : InternalArrayConstructorStubBase(isolate, kind) { }
2245 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
2247 virtual void InitializeInterfaceDescriptor(
2248 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
2251 Major MajorKey() const { return InternalArraySingleArgumentConstructor; }
2253 DISALLOW_COPY_AND_ASSIGN(InternalArraySingleArgumentConstructorStub);
2257 class InternalArrayNArgumentsConstructorStub : public
2258 InternalArrayConstructorStubBase {
2260 InternalArrayNArgumentsConstructorStub(Isolate* isolate, ElementsKind kind)
2261 : InternalArrayConstructorStubBase(isolate, kind) { }
2263 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
2265 virtual void InitializeInterfaceDescriptor(
2266 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
2269 Major MajorKey() const { return InternalArrayNArgumentsConstructor; }
2271 DISALLOW_COPY_AND_ASSIGN(InternalArrayNArgumentsConstructorStub);
2275 class StoreElementStub : public PlatformCodeStub {
2277 StoreElementStub(Isolate* isolate, bool is_js_array,
2278 ElementsKind elements_kind, KeyedAccessStoreMode store_mode)
2279 : PlatformCodeStub(isolate),
2280 is_js_array_(is_js_array),
2281 elements_kind_(elements_kind),
2282 store_mode_(store_mode) {}
2284 Major MajorKey() const { return StoreElement; }
2285 int MinorKey() const {
2286 return ElementsKindBits::encode(elements_kind_) |
2287 IsJSArrayBits::encode(is_js_array_) |
2288 StoreModeBits::encode(store_mode_);
2291 void Generate(MacroAssembler* masm);
2294 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2295 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
2296 class IsJSArrayBits: public BitField<bool, 12, 1> {};
2299 ElementsKind elements_kind_;
2300 KeyedAccessStoreMode store_mode_;
2302 DISALLOW_COPY_AND_ASSIGN(StoreElementStub);
2306 class ToBooleanStub: public HydrogenCodeStub {
2321 RESULT_AS_SMI, // For Smi(1) on truthy value, Smi(0) otherwise.
2322 RESULT_AS_ODDBALL, // For {true} on truthy value, {false} otherwise.
2323 RESULT_AS_INVERSE_ODDBALL // For {false} on truthy value, {true} otherwise.
2326 // At most 8 different types can be distinguished, because the Code object
2327 // only has room for a single byte to hold a set of these types. :-P
2328 STATIC_ASSERT(NUMBER_OF_TYPES <= 8);
2330 class Types : public EnumSet<Type, byte> {
2332 Types() : EnumSet<Type, byte>(0) {}
2333 explicit Types(byte bits) : EnumSet<Type, byte>(bits) {}
2335 byte ToByte() const { return ToIntegral(); }
2336 bool UpdateStatus(Handle<Object> object);
2337 bool NeedsMap() const;
2338 bool CanBeUndetectable() const;
2339 bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
2341 static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
2344 ToBooleanStub(Isolate* isolate, ResultMode mode, Types types = Types())
2345 : HydrogenCodeStub(isolate), types_(types), mode_(mode) {}
2346 ToBooleanStub(Isolate* isolate, ExtraICState state)
2347 : HydrogenCodeStub(isolate),
2348 types_(static_cast<byte>(state)),
2349 mode_(RESULT_AS_SMI) {}
2351 bool UpdateStatus(Handle<Object> object);
2352 Types GetTypes() { return types_; }
2353 ResultMode GetMode() { return mode_; }
2355 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
2356 virtual void InitializeInterfaceDescriptor(
2357 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
2359 virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; }
2360 virtual void PrintState(OStream& os) const V8_OVERRIDE; // NOLINT
2362 virtual bool SometimesSetsUpAFrame() { return false; }
2364 static void InstallDescriptors(Isolate* isolate) {
2365 ToBooleanStub stub(isolate, RESULT_AS_SMI);
2366 stub.InitializeInterfaceDescriptor(
2367 isolate->code_stub_interface_descriptor(CodeStub::ToBoolean));
2370 static Handle<Code> GetUninitialized(Isolate* isolate) {
2371 return ToBooleanStub(isolate, UNINITIALIZED).GetCode();
2374 virtual ExtraICState GetExtraICState() const { return types_.ToIntegral(); }
2376 virtual InlineCacheState GetICState() const {
2377 if (types_.IsEmpty()) {
2378 return ::v8::internal::UNINITIALIZED;
2385 class TypesBits : public BitField<byte, 0, NUMBER_OF_TYPES> {};
2386 class ResultModeBits : public BitField<ResultMode, NUMBER_OF_TYPES, 2> {};
2388 Major MajorKey() const { return ToBoolean; }
2389 int NotMissMinorKey() const {
2390 return TypesBits::encode(types_.ToByte()) | ResultModeBits::encode(mode_);
2393 ToBooleanStub(Isolate* isolate, InitializationState init_state)
2394 : HydrogenCodeStub(isolate, init_state), mode_(RESULT_AS_SMI) {}
2401 OStream& operator<<(OStream& os, const ToBooleanStub::Types& t);
2404 class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
2406 ElementsTransitionAndStoreStub(Isolate* isolate,
2407 ElementsKind from_kind,
2408 ElementsKind to_kind,
2410 KeyedAccessStoreMode store_mode)
2411 : HydrogenCodeStub(isolate),
2412 from_kind_(from_kind),
2414 is_jsarray_(is_jsarray),
2415 store_mode_(store_mode) {}
2417 ElementsKind from_kind() const { return from_kind_; }
2418 ElementsKind to_kind() const { return to_kind_; }
2419 bool is_jsarray() const { return is_jsarray_; }
2420 KeyedAccessStoreMode store_mode() const { return store_mode_; }
2422 virtual Handle<Code> GenerateCode() V8_OVERRIDE;
2424 virtual void InitializeInterfaceDescriptor(
2425 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
2427 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2428 enum ParameterIndices {
2436 static const Register ValueRegister() {
2437 return KeyedStoreIC::ValueRegister();
2439 static const Register MapRegister() { return KeyedStoreIC::MapRegister(); }
2440 static const Register KeyRegister() { return KeyedStoreIC::NameRegister(); }
2441 static const Register ObjectRegister() {
2442 return KeyedStoreIC::ReceiverRegister();
2446 class FromBits: public BitField<ElementsKind, 0, 8> {};
2447 class ToBits: public BitField<ElementsKind, 8, 8> {};
2448 class IsJSArrayBits: public BitField<bool, 16, 1> {};
2449 class StoreModeBits: public BitField<KeyedAccessStoreMode, 17, 4> {};
2451 Major MajorKey() const { return ElementsTransitionAndStore; }
2452 int NotMissMinorKey() const {
2453 return FromBits::encode(from_kind_) |
2454 ToBits::encode(to_kind_) |
2455 IsJSArrayBits::encode(is_jsarray_) |
2456 StoreModeBits::encode(store_mode_);
2459 ElementsKind from_kind_;
2460 ElementsKind to_kind_;
2462 KeyedAccessStoreMode store_mode_;
2464 DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub);
2468 class StoreArrayLiteralElementStub : public PlatformCodeStub {
2470 explicit StoreArrayLiteralElementStub(Isolate* isolate)
2471 : PlatformCodeStub(isolate) { }
2474 Major MajorKey() const { return StoreArrayLiteralElement; }
2475 int MinorKey() const { return 0; }
2477 void Generate(MacroAssembler* masm);
2479 DISALLOW_COPY_AND_ASSIGN(StoreArrayLiteralElementStub);
2483 class StubFailureTrampolineStub : public PlatformCodeStub {
2485 StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode)
2486 : PlatformCodeStub(isolate),
2487 function_mode_(function_mode) {}
2489 static void GenerateAheadOfTime(Isolate* isolate);
2492 class FunctionModeField: public BitField<StubFunctionMode, 0, 1> {};
2494 Major MajorKey() const { return StubFailureTrampoline; }
2495 int MinorKey() const { return FunctionModeField::encode(function_mode_); }
2497 void Generate(MacroAssembler* masm);
2499 StubFunctionMode function_mode_;
2501 DISALLOW_COPY_AND_ASSIGN(StubFailureTrampolineStub);
2505 class ProfileEntryHookStub : public PlatformCodeStub {
2507 explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2509 // The profile entry hook function is not allowed to cause a GC.
2510 virtual bool SometimesSetsUpAFrame() { return false; }
2512 // Generates a call to the entry hook if it's enabled.
2513 static void MaybeCallEntryHook(MacroAssembler* masm);
2516 static void EntryHookTrampoline(intptr_t function,
2517 intptr_t stack_pointer,
2520 Major MajorKey() const { return ProfileEntryHook; }
2521 int MinorKey() const { return 0; }
2523 void Generate(MacroAssembler* masm);
2525 DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub);
2529 class CallDescriptors {
2531 static void InitializeForIsolate(Isolate* isolate);
2534 } } // namespace v8::internal
2536 #endif // V8_CODE_STUBS_H_