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-state.h"
13 #include "src/interface-descriptors.h"
14 #include "src/macro-assembler.h"
15 #include "src/ostreams.h"
20 // List of code stubs used on all platforms.
21 #define CODE_STUB_LIST_ALL_PLATFORMS(V) \
22 /* PlatformCodeStubs */ \
25 V(BinaryOpICWithAllocationSite) \
35 V(FunctionPrototype) \
37 V(InternalArrayConstructor) \
39 V(KeyedLoadICTrampoline) \
41 V(LoadIndexedInterceptor) \
46 V(StoreArrayLiteralElement) \
47 V(StoreBufferOverflow) \
50 V(StubFailureTrampoline) \
52 /* HydrogenCodeStubs */ \
53 V(ArrayNArgumentsConstructor) \
54 V(ArrayNoArgumentConstructor) \
55 V(ArraySingleArgumentConstructor) \
57 V(BinaryOpWithAllocationSite) \
59 V(CreateAllocationSite) \
60 V(ElementsTransitionAndStore) \
61 V(FastCloneShallowArray) \
62 V(FastCloneShallowObject) \
65 V(InternalArrayNArgumentsConstructor) \
66 V(InternalArrayNoArgumentConstructor) \
67 V(InternalArraySingleArgumentConstructor) \
69 V(LoadDictionaryElement) \
72 V(NameDictionaryLookup) \
74 V(RegExpConstructResult) \
79 V(TransitionElementsKind) \
82 /* IC Handler stubs */ \
85 V(KeyedLoadSloppyArguments) \
90 // List of code stubs only used on ARM 32 bits platforms.
91 #if V8_TARGET_ARCH_ARM
92 #define CODE_STUB_LIST_ARM(V) \
94 V(WriteInt32ToHeapNumber)
97 #define CODE_STUB_LIST_ARM(V)
100 // List of code stubs only used on ARM 64 bits platforms.
101 #if V8_TARGET_ARCH_ARM64
102 #define CODE_STUB_LIST_ARM64(V) \
104 V(RestoreRegistersState) \
105 V(StoreRegistersState)
108 #define CODE_STUB_LIST_ARM64(V)
111 // List of code stubs only used on MIPS platforms.
112 #if V8_TARGET_ARCH_MIPS
113 #define CODE_STUB_LIST_MIPS(V) \
115 V(RestoreRegistersState) \
116 V(StoreRegistersState) \
117 V(WriteInt32ToHeapNumber)
118 #elif V8_TARGET_ARCH_MIPS64
119 #define CODE_STUB_LIST_MIPS(V) \
121 V(RestoreRegistersState) \
122 V(StoreRegistersState) \
123 V(WriteInt32ToHeapNumber)
125 #define CODE_STUB_LIST_MIPS(V)
128 // Combined list of code stubs.
129 #define CODE_STUB_LIST(V) \
130 CODE_STUB_LIST_ALL_PLATFORMS(V) \
131 CODE_STUB_LIST_ARM(V) \
132 CODE_STUB_LIST_ARM64(V) \
133 CODE_STUB_LIST_MIPS(V)
135 // Stub is base classes of all stubs.
136 class CodeStub BASE_EMBEDDED {
139 #define DEF_ENUM(name) name,
140 CODE_STUB_LIST(DEF_ENUM)
142 NoCache, // marker for stubs that do custom caching
146 // Retrieve the code for the stub. Generate the code if needed.
147 Handle<Code> GetCode();
149 // Retrieve the code for the stub, make and return a copy of the code.
150 Handle<Code> GetCodeCopy(const Code::FindAndReplacePattern& pattern);
152 static Major MajorKeyFromKey(uint32_t key) {
153 return static_cast<Major>(MajorKeyBits::decode(key));
155 static uint32_t MinorKeyFromKey(uint32_t key) {
156 return MinorKeyBits::decode(key);
159 // Gets the major key from a code object that is a code stub or binary op IC.
160 static Major GetMajorKey(Code* code_stub) {
161 return MajorKeyFromKey(code_stub->stub_key());
164 static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }
166 static const char* MajorName(Major major_key, bool allow_unknown_keys);
168 explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {}
169 virtual ~CodeStub() {}
171 static void GenerateStubsAheadOfTime(Isolate* isolate);
172 static void GenerateFPStubs(Isolate* isolate);
174 // Some stubs put untagged junk on the stack that cannot be scanned by the
175 // GC. This means that we must be statically sure that no GC can occur while
176 // they are running. If that is the case they should override this to return
177 // true, which will cause an assertion if we try to call something that can
178 // GC or if we try to put a stack frame on top of the junk, which would not
179 // result in a traversable stack.
180 virtual bool SometimesSetsUpAFrame() { return true; }
182 // Lookup the code in the (possibly custom) cache.
183 bool FindCodeInCache(Code** code_out);
185 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() = 0;
187 virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {}
189 static void InitializeDescriptor(Isolate* isolate, uint32_t key,
190 CodeStubDescriptor* desc);
192 static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key);
194 // Returns information for computing the number key.
195 virtual Major MajorKey() const = 0;
196 uint32_t MinorKey() const { return minor_key_; }
198 virtual InlineCacheState GetICState() const { return UNINITIALIZED; }
199 virtual ExtraICState GetExtraICState() const { return kNoExtraICState; }
200 virtual Code::StubType GetStubType() {
204 friend OStream& operator<<(OStream& os, const CodeStub& s) {
209 Isolate* isolate() const { return isolate_; }
212 CodeStub(uint32_t key, Isolate* isolate)
213 : minor_key_(MinorKeyFromKey(key)), isolate_(isolate) {}
215 // Generates the assembler code for the stub.
216 virtual Handle<Code> GenerateCode() = 0;
218 // Returns whether the code generated for this stub needs to be allocated as
219 // a fixed (non-moveable) code object.
220 virtual bool NeedsImmovableCode() { return false; }
222 virtual void PrintName(OStream& os) const; // NOLINT
223 virtual void PrintBaseName(OStream& os) const; // NOLINT
224 virtual void PrintState(OStream& os) const { ; } // NOLINT
226 // Computes the key based on major and minor.
228 DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
229 return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey());
235 // Perform bookkeeping required after code generation when stub code is
236 // initially generated.
237 void RecordCodeGeneration(Handle<Code> code);
239 // Finish the code object after it has been generated.
240 virtual void FinishCode(Handle<Code> code) { }
242 // Activate newly generated stub. Is called after
243 // registering stub in the stub cache.
244 virtual void Activate(Code* code) { }
246 // BinaryOpStub needs to override this.
247 virtual Code::Kind GetCodeKind() const;
249 // Add the code to a specialized cache, specific to an individual
250 // stub type. Please note, this method must add the code object to a
251 // roots object, otherwise we will remove the code during GC.
252 virtual void AddToSpecialCache(Handle<Code> new_object) { }
254 // Find code in a specialized cache, work is delegated to the specific stub.
255 virtual bool FindCodeInSpecialCache(Code** code_out) {
259 // If a stub uses a special cache override this.
260 virtual bool UseSpecialCache() { return false; }
262 // We use this dispatch to statically instantiate the correct code stub for
263 // the given stub key and call the passed function with that code stub.
264 typedef void (*DispatchedCall)(CodeStub* stub, void** value_out);
265 static void Dispatch(Isolate* isolate, uint32_t key, void** value_out,
266 DispatchedCall call);
268 static void GetCodeDispatchCall(CodeStub* stub, void** value_out);
270 STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
271 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
272 class MinorKeyBits: public BitField<uint32_t,
273 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT
275 friend class BreakPointIterator;
281 #define DEFINE_CODE_STUB_BASE(NAME, SUPER) \
283 NAME(uint32_t key, Isolate* isolate) : SUPER(key, isolate) {} \
286 DISALLOW_COPY_AND_ASSIGN(NAME)
289 #define DEFINE_CODE_STUB(NAME, SUPER) \
291 virtual inline Major MajorKey() const OVERRIDE { \
294 DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER)
297 #define DEFINE_PLATFORM_CODE_STUB(NAME, SUPER) \
299 virtual void Generate(MacroAssembler* masm) OVERRIDE; \
300 DEFINE_CODE_STUB(NAME, SUPER)
303 #define DEFINE_HYDROGEN_CODE_STUB(NAME, SUPER) \
305 virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) OVERRIDE; \
306 virtual Handle<Code> GenerateCode() OVERRIDE; \
307 DEFINE_CODE_STUB(NAME, SUPER)
309 #define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \
311 virtual Handle<Code> GenerateCode() OVERRIDE; \
312 DEFINE_CODE_STUB(NAME, SUPER)
314 #define DEFINE_CALL_INTERFACE_DESCRIPTOR(NAME) \
316 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE { \
317 return NAME##Descriptor(isolate()); \
320 // There are some code stubs we just can't describe right now with a
321 // CallInterfaceDescriptor. Isolate behavior for those cases with this macro.
322 // An attempt to retrieve a descriptor will fail.
323 #define DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR() \
325 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE { \
327 return CallInterfaceDescriptor(); \
331 class PlatformCodeStub : public CodeStub {
333 // Retrieve the code for the stub. Generate the code if needed.
334 virtual Handle<Code> GenerateCode() OVERRIDE;
336 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
339 explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {}
341 // Generates the assembler code for the stub.
342 virtual void Generate(MacroAssembler* masm) = 0;
344 DEFINE_CODE_STUB_BASE(PlatformCodeStub, CodeStub);
348 enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
349 enum HandlerArgumentsMode { DONT_PASS_ARGUMENTS, PASS_ARGUMENTS };
352 class CodeStubDescriptor {
354 explicit CodeStubDescriptor(CodeStub* stub);
356 CodeStubDescriptor(Isolate* isolate, uint32_t stub_key);
358 void Initialize(Address deoptimization_handler = NULL,
359 int hint_stack_parameter_count = -1,
360 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
361 void Initialize(Register stack_parameter_count,
362 Address deoptimization_handler = NULL,
363 int hint_stack_parameter_count = -1,
364 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE,
365 HandlerArgumentsMode handler_mode = DONT_PASS_ARGUMENTS);
367 void SetMissHandler(ExternalReference handler) {
368 miss_handler_ = handler;
369 has_miss_handler_ = true;
370 // Our miss handler infrastructure doesn't currently support
371 // variable stack parameter counts.
372 DCHECK(!stack_parameter_count_.is_valid());
375 void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; }
376 CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; }
378 int GetEnvironmentParameterCount() const {
379 return call_descriptor().GetEnvironmentParameterCount();
382 Representation GetEnvironmentParameterRepresentation(int index) const {
383 return call_descriptor().GetEnvironmentParameterRepresentation(index);
386 ExternalReference miss_handler() const {
387 DCHECK(has_miss_handler_);
388 return miss_handler_;
391 bool has_miss_handler() const {
392 return has_miss_handler_;
395 bool IsEnvironmentParameterCountRegister(int index) const {
396 return call_descriptor().GetEnvironmentParameterRegister(index).is(
397 stack_parameter_count_);
400 int GetHandlerParameterCount() const {
401 int params = call_descriptor().GetEnvironmentParameterCount();
402 if (handler_arguments_mode_ == PASS_ARGUMENTS) {
408 int hint_stack_parameter_count() const { return hint_stack_parameter_count_; }
409 Register stack_parameter_count() const { return stack_parameter_count_; }
410 StubFunctionMode function_mode() const { return function_mode_; }
411 Address deoptimization_handler() const { return deoptimization_handler_; }
414 CallInterfaceDescriptor call_descriptor_;
415 Register stack_parameter_count_;
416 // If hint_stack_parameter_count_ > 0, the code stub can optimize the
417 // return sequence. Default value is -1, which means it is ignored.
418 int hint_stack_parameter_count_;
419 StubFunctionMode function_mode_;
421 Address deoptimization_handler_;
422 HandlerArgumentsMode handler_arguments_mode_;
424 ExternalReference miss_handler_;
425 bool has_miss_handler_;
429 class HydrogenCodeStub : public CodeStub {
431 enum InitializationState {
436 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
438 template<class SubClass>
439 static Handle<Code> GetUninitialized(Isolate* isolate) {
440 SubClass::GenerateAheadOfTime(isolate);
441 return SubClass().GetCode(isolate);
444 // Retrieve the code for the stub. Generate the code if needed.
445 virtual Handle<Code> GenerateCode() = 0;
447 bool IsUninitialized() const { return IsMissBits::decode(minor_key_); }
449 Handle<Code> GenerateLightweightMissCode(ExternalReference miss);
451 template<class StateType>
452 void TraceTransition(StateType from, StateType to);
455 explicit HydrogenCodeStub(Isolate* isolate,
456 InitializationState state = INITIALIZED)
457 : CodeStub(isolate) {
458 minor_key_ = IsMissBits::encode(state == UNINITIALIZED);
461 void set_sub_minor_key(uint32_t key) {
462 minor_key_ = SubMinorKeyBits::update(minor_key_, key);
465 uint32_t sub_minor_key() const { return SubMinorKeyBits::decode(minor_key_); }
467 static const int kSubMinorKeyBits = kStubMinorKeyBits - 1;
470 class IsMissBits : public BitField<bool, kSubMinorKeyBits, 1> {};
471 class SubMinorKeyBits : public BitField<int, 0, kSubMinorKeyBits> {};
473 void GenerateLightweightMiss(MacroAssembler* masm, ExternalReference miss);
475 DEFINE_CODE_STUB_BASE(HydrogenCodeStub, CodeStub);
479 // Helper interface to prepare to/restore after making runtime calls.
480 class RuntimeCallHelper {
482 virtual ~RuntimeCallHelper() {}
484 virtual void BeforeCall(MacroAssembler* masm) const = 0;
486 virtual void AfterCall(MacroAssembler* masm) const = 0;
489 RuntimeCallHelper() {}
492 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
496 } } // namespace v8::internal
498 #if V8_TARGET_ARCH_IA32
499 #include "src/ia32/code-stubs-ia32.h"
500 #elif V8_TARGET_ARCH_X64
501 #include "src/x64/code-stubs-x64.h"
502 #elif V8_TARGET_ARCH_ARM64
503 #include "src/arm64/code-stubs-arm64.h"
504 #elif V8_TARGET_ARCH_ARM
505 #include "src/arm/code-stubs-arm.h"
506 #elif V8_TARGET_ARCH_MIPS
507 #include "src/mips/code-stubs-mips.h"
508 #elif V8_TARGET_ARCH_MIPS64
509 #include "src/mips64/code-stubs-mips64.h"
510 #elif V8_TARGET_ARCH_X87
511 #include "src/x87/code-stubs-x87.h"
513 #error Unsupported target architecture.
520 // RuntimeCallHelper implementation used in stubs: enters/leaves a
521 // newly created internal frame before/after the runtime call.
522 class StubRuntimeCallHelper : public RuntimeCallHelper {
524 StubRuntimeCallHelper() {}
526 virtual void BeforeCall(MacroAssembler* masm) const;
528 virtual void AfterCall(MacroAssembler* masm) const;
532 // Trivial RuntimeCallHelper implementation.
533 class NopRuntimeCallHelper : public RuntimeCallHelper {
535 NopRuntimeCallHelper() {}
537 virtual void BeforeCall(MacroAssembler* masm) const {}
539 virtual void AfterCall(MacroAssembler* masm) const {}
543 class ToNumberStub: public HydrogenCodeStub {
545 explicit ToNumberStub(Isolate* isolate) : HydrogenCodeStub(isolate) { }
547 DEFINE_CALL_INTERFACE_DESCRIPTOR(ToNumber);
548 DEFINE_HYDROGEN_CODE_STUB(ToNumber, HydrogenCodeStub);
552 class NumberToStringStub FINAL : public HydrogenCodeStub {
554 explicit NumberToStringStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
556 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
557 static const int kNumber = 0;
559 DEFINE_CALL_INTERFACE_DESCRIPTOR(NumberToString);
560 DEFINE_HYDROGEN_CODE_STUB(NumberToString, HydrogenCodeStub);
564 class FastNewClosureStub : public HydrogenCodeStub {
566 FastNewClosureStub(Isolate* isolate, StrictMode strict_mode,
568 : HydrogenCodeStub(isolate) {
569 DCHECK(IsValidFunctionKind(kind));
570 set_sub_minor_key(StrictModeBits::encode(strict_mode) |
571 FunctionKindBits::encode(kind));
574 StrictMode strict_mode() const {
575 return StrictModeBits::decode(sub_minor_key());
578 FunctionKind kind() const {
579 return FunctionKindBits::decode(sub_minor_key());
581 bool is_arrow() const { return IsArrowFunction(kind()); }
582 bool is_generator() const { return IsGeneratorFunction(kind()); }
583 bool is_concise_method() const { return IsConciseMethod(kind()); }
586 class StrictModeBits : public BitField<StrictMode, 0, 1> {};
587 class FunctionKindBits : public BitField<FunctionKind, 1, 3> {};
589 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure);
590 DEFINE_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub);
594 class FastNewContextStub FINAL : public HydrogenCodeStub {
596 static const int kMaximumSlots = 64;
598 FastNewContextStub(Isolate* isolate, int slots) : HydrogenCodeStub(isolate) {
599 DCHECK(slots > 0 && slots <= kMaximumSlots);
600 set_sub_minor_key(SlotsBits::encode(slots));
603 int slots() const { return SlotsBits::decode(sub_minor_key()); }
605 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
606 static const int kFunction = 0;
609 class SlotsBits : public BitField<int, 0, 8> {};
611 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewContext);
612 DEFINE_HYDROGEN_CODE_STUB(FastNewContext, HydrogenCodeStub);
616 class FastCloneShallowArrayStub : public HydrogenCodeStub {
618 FastCloneShallowArrayStub(Isolate* isolate,
619 AllocationSiteMode allocation_site_mode)
620 : HydrogenCodeStub(isolate) {
621 set_sub_minor_key(AllocationSiteModeBits::encode(allocation_site_mode));
624 AllocationSiteMode allocation_site_mode() const {
625 return AllocationSiteModeBits::decode(sub_minor_key());
629 class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
631 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowArray);
632 DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowArray, HydrogenCodeStub);
636 class FastCloneShallowObjectStub : public HydrogenCodeStub {
638 // Maximum number of properties in copied object.
639 static const int kMaximumClonedProperties = 6;
641 FastCloneShallowObjectStub(Isolate* isolate, int length)
642 : HydrogenCodeStub(isolate) {
643 DCHECK_GE(length, 0);
644 DCHECK_LE(length, kMaximumClonedProperties);
645 set_sub_minor_key(LengthBits::encode(length));
648 int length() const { return LengthBits::decode(sub_minor_key()); }
651 class LengthBits : public BitField<int, 0, 4> {};
653 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowObject);
654 DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowObject, HydrogenCodeStub);
658 class CreateAllocationSiteStub : public HydrogenCodeStub {
660 explicit CreateAllocationSiteStub(Isolate* isolate)
661 : HydrogenCodeStub(isolate) { }
663 static void GenerateAheadOfTime(Isolate* isolate);
665 DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateAllocationSite);
666 DEFINE_HYDROGEN_CODE_STUB(CreateAllocationSite, HydrogenCodeStub);
670 class InstanceofStub: public PlatformCodeStub {
674 kArgsInRegisters = 1 << 0,
675 kCallSiteInlineCheck = 1 << 1,
676 kReturnTrueFalseObject = 1 << 2
679 InstanceofStub(Isolate* isolate, Flags flags) : PlatformCodeStub(isolate) {
680 minor_key_ = FlagBits::encode(flags);
683 static Register left() { return InstanceofDescriptor::left(); }
684 static Register right() { return InstanceofDescriptor::right(); }
686 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
687 if (HasArgsInRegisters()) {
688 return InstanceofDescriptor(isolate());
690 return ContextOnlyDescriptor(isolate());
694 Flags flags() const { return FlagBits::decode(minor_key_); }
696 bool HasArgsInRegisters() const { return (flags() & kArgsInRegisters) != 0; }
698 bool HasCallSiteInlineCheck() const {
699 return (flags() & kCallSiteInlineCheck) != 0;
702 bool ReturnTrueFalseObject() const {
703 return (flags() & kReturnTrueFalseObject) != 0;
706 virtual void PrintName(OStream& os) const OVERRIDE; // NOLINT
708 class FlagBits : public BitField<Flags, 0, 3> {};
710 DEFINE_PLATFORM_CODE_STUB(Instanceof, PlatformCodeStub);
714 enum AllocationSiteOverrideMode {
716 DISABLE_ALLOCATION_SITES,
717 LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
721 class ArrayConstructorStub: public PlatformCodeStub {
723 enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
725 ArrayConstructorStub(Isolate* isolate, int argument_count);
727 explicit ArrayConstructorStub(Isolate* isolate);
730 ArgumentCountKey argument_count() const {
731 return ArgumentCountBits::decode(minor_key_);
734 void GenerateDispatchToArrayStub(MacroAssembler* masm,
735 AllocationSiteOverrideMode mode);
737 virtual void PrintName(OStream& os) const OVERRIDE; // NOLINT
739 class ArgumentCountBits : public BitField<ArgumentCountKey, 0, 2> {};
741 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
742 DEFINE_PLATFORM_CODE_STUB(ArrayConstructor, PlatformCodeStub);
746 class InternalArrayConstructorStub: public PlatformCodeStub {
748 explicit InternalArrayConstructorStub(Isolate* isolate);
751 void GenerateCase(MacroAssembler* masm, ElementsKind kind);
753 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
754 DEFINE_PLATFORM_CODE_STUB(InternalArrayConstructor, PlatformCodeStub);
758 class MathPowStub: public PlatformCodeStub {
760 enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK };
762 MathPowStub(Isolate* isolate, ExponentType exponent_type)
763 : PlatformCodeStub(isolate) {
764 minor_key_ = ExponentTypeBits::encode(exponent_type);
767 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
768 if (exponent_type() == TAGGED) {
769 return MathPowTaggedDescriptor(isolate());
770 } else if (exponent_type() == INTEGER) {
771 return MathPowIntegerDescriptor(isolate());
773 // A CallInterfaceDescriptor doesn't specify double registers (yet).
774 return ContextOnlyDescriptor(isolate());
778 ExponentType exponent_type() const {
779 return ExponentTypeBits::decode(minor_key_);
782 class ExponentTypeBits : public BitField<ExponentType, 0, 2> {};
784 DEFINE_PLATFORM_CODE_STUB(MathPow, PlatformCodeStub);
788 class CallICStub: public PlatformCodeStub {
790 CallICStub(Isolate* isolate, const CallICState& state)
791 : PlatformCodeStub(isolate) {
792 minor_key_ = state.GetExtraICState();
795 static int ExtractArgcFromMinorKey(int minor_key) {
796 CallICState state(static_cast<ExtraICState>(minor_key));
797 return state.arg_count();
800 virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::CALL_IC; }
802 virtual InlineCacheState GetICState() const OVERRIDE { return DEFAULT; }
804 virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
805 return static_cast<ExtraICState>(minor_key_);
809 bool CallAsMethod() const {
810 return state().call_type() == CallICState::METHOD;
813 int arg_count() const { return state().arg_count(); }
815 CallICState state() const {
816 return CallICState(static_cast<ExtraICState>(minor_key_));
819 // Code generation helpers.
820 void GenerateMiss(MacroAssembler* masm);
823 virtual void PrintState(OStream& os) const OVERRIDE; // NOLINT
825 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedback);
826 DEFINE_PLATFORM_CODE_STUB(CallIC, PlatformCodeStub);
830 class CallIC_ArrayStub: public CallICStub {
832 CallIC_ArrayStub(Isolate* isolate, const CallICState& state_in)
833 : CallICStub(isolate, state_in) {}
835 virtual InlineCacheState GetICState() const FINAL OVERRIDE {
840 virtual void PrintState(OStream& os) const OVERRIDE; // NOLINT
842 DEFINE_PLATFORM_CODE_STUB(CallIC_Array, CallICStub);
846 // TODO(verwaest): Translate to hydrogen code stub.
847 class FunctionPrototypeStub : public PlatformCodeStub {
849 explicit FunctionPrototypeStub(Isolate* isolate)
850 : PlatformCodeStub(isolate) {}
852 virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
854 // TODO(mvstanton): only the receiver register is accessed. When this is
855 // translated to a hydrogen code stub, a new CallInterfaceDescriptor
856 // should be created that just uses that register for more efficient code.
857 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
858 DEFINE_PLATFORM_CODE_STUB(FunctionPrototype, PlatformCodeStub);
862 // TODO(mvstanton): Translate to hydrogen code stub.
863 class LoadIndexedInterceptorStub : public PlatformCodeStub {
865 explicit LoadIndexedInterceptorStub(Isolate* isolate)
866 : PlatformCodeStub(isolate) {}
868 virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
869 virtual Code::StubType GetStubType() { return Code::FAST; }
871 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
872 DEFINE_PLATFORM_CODE_STUB(LoadIndexedInterceptor, PlatformCodeStub);
876 class HandlerStub : public HydrogenCodeStub {
878 virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
879 virtual ExtraICState GetExtraICState() const { return kind(); }
880 virtual InlineCacheState GetICState() const { return MONOMORPHIC; }
882 virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) OVERRIDE;
884 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE;
887 explicit HandlerStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
889 virtual Code::Kind kind() const = 0;
891 DEFINE_CODE_STUB_BASE(HandlerStub, HydrogenCodeStub);
895 class LoadFieldStub: public HandlerStub {
897 LoadFieldStub(Isolate* isolate, FieldIndex index) : HandlerStub(isolate) {
898 int property_index_key = index.GetFieldAccessStubKey();
899 set_sub_minor_key(LoadFieldByIndexBits::encode(property_index_key));
902 FieldIndex index() const {
903 int property_index_key = LoadFieldByIndexBits::decode(sub_minor_key());
904 return FieldIndex::FromFieldAccessStubKey(property_index_key);
908 virtual Code::Kind kind() const { return Code::LOAD_IC; }
909 virtual Code::StubType GetStubType() { return Code::FAST; }
912 class LoadFieldByIndexBits : public BitField<int, 0, 13> {};
914 DEFINE_HANDLER_CODE_STUB(LoadField, HandlerStub);
918 class KeyedLoadSloppyArgumentsStub : public HandlerStub {
920 explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate)
921 : HandlerStub(isolate) {}
924 virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
925 virtual Code::StubType GetStubType() { return Code::FAST; }
928 DEFINE_HANDLER_CODE_STUB(KeyedLoadSloppyArguments, HandlerStub);
932 class LoadConstantStub : public HandlerStub {
934 LoadConstantStub(Isolate* isolate, int constant_index)
935 : HandlerStub(isolate) {
936 set_sub_minor_key(ConstantIndexBits::encode(constant_index));
939 int constant_index() const {
940 return ConstantIndexBits::decode(sub_minor_key());
944 virtual Code::Kind kind() const { return Code::LOAD_IC; }
945 virtual Code::StubType GetStubType() { return Code::FAST; }
948 class ConstantIndexBits : public BitField<int, 0, kSubMinorKeyBits> {};
950 DEFINE_HANDLER_CODE_STUB(LoadConstant, HandlerStub);
954 class StringLengthStub: public HandlerStub {
956 explicit StringLengthStub(Isolate* isolate) : HandlerStub(isolate) {}
959 virtual Code::Kind kind() const { return Code::LOAD_IC; }
960 virtual Code::StubType GetStubType() { return Code::FAST; }
962 DEFINE_HANDLER_CODE_STUB(StringLength, HandlerStub);
966 class StoreFieldStub : public HandlerStub {
968 StoreFieldStub(Isolate* isolate, FieldIndex index,
969 Representation representation)
970 : HandlerStub(isolate) {
971 int property_index_key = index.GetFieldAccessStubKey();
972 uint8_t repr = PropertyDetails::EncodeRepresentation(representation);
973 set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) |
974 RepresentationBits::encode(repr));
977 FieldIndex index() const {
978 int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key());
979 return FieldIndex::FromFieldAccessStubKey(property_index_key);
982 Representation representation() {
983 uint8_t repr = RepresentationBits::decode(sub_minor_key());
984 return PropertyDetails::DecodeRepresentation(repr);
988 virtual Code::Kind kind() const { return Code::STORE_IC; }
989 virtual Code::StubType GetStubType() { return Code::FAST; }
992 class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
993 class RepresentationBits : public BitField<uint8_t, 13, 4> {};
995 DEFINE_HANDLER_CODE_STUB(StoreField, HandlerStub);
999 class StoreGlobalStub : public HandlerStub {
1001 StoreGlobalStub(Isolate* isolate, bool is_constant, bool check_global)
1002 : HandlerStub(isolate) {
1003 set_sub_minor_key(IsConstantBits::encode(is_constant) |
1004 CheckGlobalBits::encode(check_global));
1007 static Handle<HeapObject> global_placeholder(Isolate* isolate) {
1008 return isolate->factory()->uninitialized_value();
1011 Handle<Code> GetCodeCopyFromTemplate(Handle<GlobalObject> global,
1012 Handle<PropertyCell> cell) {
1013 if (check_global()) {
1014 Code::FindAndReplacePattern pattern;
1015 pattern.Add(Handle<Map>(global_placeholder(isolate())->map()), global);
1016 pattern.Add(isolate()->factory()->meta_map(), Handle<Map>(global->map()));
1017 pattern.Add(isolate()->factory()->global_property_cell_map(), cell);
1018 return CodeStub::GetCodeCopy(pattern);
1020 Code::FindAndReplacePattern pattern;
1021 pattern.Add(isolate()->factory()->global_property_cell_map(), cell);
1022 return CodeStub::GetCodeCopy(pattern);
1026 virtual Code::Kind kind() const { return Code::STORE_IC; }
1028 bool is_constant() const { return IsConstantBits::decode(sub_minor_key()); }
1030 bool check_global() const { return CheckGlobalBits::decode(sub_minor_key()); }
1032 void set_is_constant(bool value) {
1033 set_sub_minor_key(IsConstantBits::update(sub_minor_key(), value));
1036 Representation representation() {
1037 return Representation::FromKind(
1038 RepresentationBits::decode(sub_minor_key()));
1041 void set_representation(Representation r) {
1042 set_sub_minor_key(RepresentationBits::update(sub_minor_key(), r.kind()));
1046 class IsConstantBits: public BitField<bool, 0, 1> {};
1047 class RepresentationBits: public BitField<Representation::Kind, 1, 8> {};
1048 class CheckGlobalBits: public BitField<bool, 9, 1> {};
1050 DEFINE_HANDLER_CODE_STUB(StoreGlobal, HandlerStub);
1054 class CallApiFunctionStub : public PlatformCodeStub {
1056 CallApiFunctionStub(Isolate* isolate,
1058 bool call_data_undefined,
1059 int argc) : PlatformCodeStub(isolate) {
1060 minor_key_ = IsStoreBits::encode(is_store) |
1061 CallDataUndefinedBits::encode(call_data_undefined) |
1062 ArgumentBits::encode(argc);
1063 DCHECK(!is_store || argc == 1);
1067 bool is_store() const { return IsStoreBits::decode(minor_key_); }
1068 bool call_data_undefined() const {
1069 return CallDataUndefinedBits::decode(minor_key_);
1071 int argc() const { return ArgumentBits::decode(minor_key_); }
1073 class IsStoreBits: public BitField<bool, 0, 1> {};
1074 class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
1075 class ArgumentBits: public BitField<int, 2, Code::kArgumentsBits> {};
1076 STATIC_ASSERT(Code::kArgumentsBits + 2 <= kStubMinorKeyBits);
1078 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiFunction);
1079 DEFINE_PLATFORM_CODE_STUB(CallApiFunction, PlatformCodeStub);
1083 class CallApiGetterStub : public PlatformCodeStub {
1085 explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1087 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiGetter);
1088 DEFINE_PLATFORM_CODE_STUB(CallApiGetter, PlatformCodeStub);
1092 class BinaryOpICStub : public HydrogenCodeStub {
1094 BinaryOpICStub(Isolate* isolate, Token::Value op,
1095 OverwriteMode mode = NO_OVERWRITE)
1096 : HydrogenCodeStub(isolate, UNINITIALIZED) {
1097 BinaryOpICState state(isolate, op, mode);
1098 set_sub_minor_key(state.GetExtraICState());
1101 BinaryOpICStub(Isolate* isolate, const BinaryOpICState& state)
1102 : HydrogenCodeStub(isolate) {
1103 set_sub_minor_key(state.GetExtraICState());
1106 static void GenerateAheadOfTime(Isolate* isolate);
1108 virtual Code::Kind GetCodeKind() const OVERRIDE {
1109 return Code::BINARY_OP_IC;
1112 virtual InlineCacheState GetICState() const FINAL OVERRIDE {
1113 return state().GetICState();
1116 virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
1117 return static_cast<ExtraICState>(sub_minor_key());
1120 BinaryOpICState state() const {
1121 return BinaryOpICState(isolate(), GetExtraICState());
1124 virtual void PrintState(OStream& os) const FINAL OVERRIDE; // NOLINT
1126 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1127 static const int kLeft = 0;
1128 static const int kRight = 1;
1131 static void GenerateAheadOfTime(Isolate* isolate,
1132 const BinaryOpICState& state);
1134 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1135 DEFINE_HYDROGEN_CODE_STUB(BinaryOpIC, HydrogenCodeStub);
1139 // TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
1140 // call support for stubs in Hydrogen.
1141 class BinaryOpICWithAllocationSiteStub FINAL : public PlatformCodeStub {
1143 BinaryOpICWithAllocationSiteStub(Isolate* isolate,
1144 const BinaryOpICState& state)
1145 : PlatformCodeStub(isolate) {
1146 minor_key_ = state.GetExtraICState();
1149 static void GenerateAheadOfTime(Isolate* isolate);
1151 Handle<Code> GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site) {
1152 Code::FindAndReplacePattern pattern;
1153 pattern.Add(isolate()->factory()->undefined_map(), allocation_site);
1154 return CodeStub::GetCodeCopy(pattern);
1157 virtual Code::Kind GetCodeKind() const OVERRIDE {
1158 return Code::BINARY_OP_IC;
1161 virtual InlineCacheState GetICState() const OVERRIDE {
1162 return state().GetICState();
1165 virtual ExtraICState GetExtraICState() const OVERRIDE {
1166 return static_cast<ExtraICState>(minor_key_);
1169 virtual void PrintState(OStream& os) const OVERRIDE; // NOLINT
1172 BinaryOpICState state() const {
1173 return BinaryOpICState(isolate(), static_cast<ExtraICState>(minor_key_));
1176 static void GenerateAheadOfTime(Isolate* isolate,
1177 const BinaryOpICState& state);
1179 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1180 DEFINE_PLATFORM_CODE_STUB(BinaryOpICWithAllocationSite, PlatformCodeStub);
1184 class BinaryOpWithAllocationSiteStub FINAL : public BinaryOpICStub {
1186 BinaryOpWithAllocationSiteStub(Isolate* isolate,
1189 : BinaryOpICStub(isolate, op, mode) {}
1191 BinaryOpWithAllocationSiteStub(Isolate* isolate, const BinaryOpICState& state)
1192 : BinaryOpICStub(isolate, state) {}
1194 virtual Code::Kind GetCodeKind() const FINAL OVERRIDE {
1198 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1199 static const int kAllocationSite = 0;
1200 static const int kLeft = 1;
1201 static const int kRight = 2;
1203 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1204 DEFINE_HYDROGEN_CODE_STUB(BinaryOpWithAllocationSite, BinaryOpICStub);
1208 enum StringAddFlags {
1209 // Omit both parameter checks.
1210 STRING_ADD_CHECK_NONE = 0,
1211 // Check left parameter.
1212 STRING_ADD_CHECK_LEFT = 1 << 0,
1213 // Check right parameter.
1214 STRING_ADD_CHECK_RIGHT = 1 << 1,
1215 // Check both parameters.
1216 STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT
1220 class StringAddStub FINAL : public HydrogenCodeStub {
1222 StringAddStub(Isolate* isolate, StringAddFlags flags,
1223 PretenureFlag pretenure_flag)
1224 : HydrogenCodeStub(isolate) {
1225 set_sub_minor_key(StringAddFlagsBits::encode(flags) |
1226 PretenureFlagBits::encode(pretenure_flag));
1229 StringAddFlags flags() const {
1230 return StringAddFlagsBits::decode(sub_minor_key());
1233 PretenureFlag pretenure_flag() const {
1234 return PretenureFlagBits::decode(sub_minor_key());
1237 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1238 static const int kLeft = 0;
1239 static const int kRight = 1;
1242 class StringAddFlagsBits: public BitField<StringAddFlags, 0, 2> {};
1243 class PretenureFlagBits: public BitField<PretenureFlag, 2, 1> {};
1245 virtual void PrintBaseName(OStream& os) const OVERRIDE; // NOLINT
1247 DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd);
1248 DEFINE_HYDROGEN_CODE_STUB(StringAdd, HydrogenCodeStub);
1252 class CompareICStub : public PlatformCodeStub {
1254 CompareICStub(Isolate* isolate, Token::Value op, CompareICState::State left,
1255 CompareICState::State right, CompareICState::State state)
1256 : PlatformCodeStub(isolate) {
1257 DCHECK(Token::IsCompareOp(op));
1258 minor_key_ = OpBits::encode(op - Token::EQ) | LeftStateBits::encode(left) |
1259 RightStateBits::encode(right) | StateBits::encode(state);
1262 void set_known_map(Handle<Map> map) { known_map_ = map; }
1264 virtual InlineCacheState GetICState() const;
1266 Token::Value op() const {
1267 return static_cast<Token::Value>(Token::EQ + OpBits::decode(minor_key_));
1270 CompareICState::State left() const {
1271 return LeftStateBits::decode(minor_key_);
1273 CompareICState::State right() const {
1274 return RightStateBits::decode(minor_key_);
1276 CompareICState::State state() const { return StateBits::decode(minor_key_); }
1279 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_IC; }
1281 void GenerateSmis(MacroAssembler* masm);
1282 void GenerateNumbers(MacroAssembler* masm);
1283 void GenerateInternalizedStrings(MacroAssembler* masm);
1284 void GenerateStrings(MacroAssembler* masm);
1285 void GenerateUniqueNames(MacroAssembler* masm);
1286 void GenerateObjects(MacroAssembler* masm);
1287 void GenerateMiss(MacroAssembler* masm);
1288 void GenerateKnownObjects(MacroAssembler* masm);
1289 void GenerateGeneric(MacroAssembler* masm);
1291 bool strict() const { return op() == Token::EQ_STRICT; }
1292 Condition GetCondition() const;
1294 virtual void AddToSpecialCache(Handle<Code> new_object);
1295 virtual bool FindCodeInSpecialCache(Code** code_out);
1296 virtual bool UseSpecialCache() {
1297 return state() == CompareICState::KNOWN_OBJECT;
1300 class OpBits : public BitField<int, 0, 3> {};
1301 class LeftStateBits : public BitField<CompareICState::State, 3, 4> {};
1302 class RightStateBits : public BitField<CompareICState::State, 7, 4> {};
1303 class StateBits : public BitField<CompareICState::State, 11, 4> {};
1305 Handle<Map> known_map_;
1307 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1308 DEFINE_PLATFORM_CODE_STUB(CompareIC, PlatformCodeStub);
1312 class CompareNilICStub : public HydrogenCodeStub {
1314 Type* GetType(Zone* zone, Handle<Map> map = Handle<Map>());
1315 Type* GetInputType(Zone* zone, Handle<Map> map);
1317 CompareNilICStub(Isolate* isolate, NilValue nil) : HydrogenCodeStub(isolate) {
1318 set_sub_minor_key(NilValueBits::encode(nil));
1321 CompareNilICStub(Isolate* isolate, ExtraICState ic_state,
1322 InitializationState init_state = INITIALIZED)
1323 : HydrogenCodeStub(isolate, init_state) {
1324 set_sub_minor_key(ic_state);
1327 static Handle<Code> GetUninitialized(Isolate* isolate,
1329 return CompareNilICStub(isolate, nil, UNINITIALIZED).GetCode();
1332 virtual InlineCacheState GetICState() const {
1333 State state = this->state();
1334 if (state.Contains(GENERIC)) {
1336 } else if (state.Contains(MONOMORPHIC_MAP)) {
1339 return PREMONOMORPHIC;
1343 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_NIL_IC; }
1345 virtual ExtraICState GetExtraICState() const { return sub_minor_key(); }
1347 void UpdateStatus(Handle<Object> object);
1349 bool IsMonomorphic() const { return state().Contains(MONOMORPHIC_MAP); }
1351 NilValue nil_value() const { return NilValueBits::decode(sub_minor_key()); }
1354 set_sub_minor_key(TypesBits::update(sub_minor_key(), 0));
1357 virtual void PrintState(OStream& os) const OVERRIDE; // NOLINT
1358 virtual void PrintBaseName(OStream& os) const OVERRIDE; // NOLINT
1361 CompareNilICStub(Isolate* isolate, NilValue nil,
1362 InitializationState init_state)
1363 : HydrogenCodeStub(isolate, init_state) {
1364 set_sub_minor_key(NilValueBits::encode(nil));
1367 enum CompareNilType {
1375 // At most 6 different types can be distinguished, because the Code object
1376 // only has room for a single byte to hold a set and there are two more
1377 // boolean flags we need to store. :-P
1378 STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
1380 class State : public EnumSet<CompareNilType, byte> {
1382 State() : EnumSet<CompareNilType, byte>(0) { }
1383 explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
1385 friend OStream& operator<<(OStream& os, const State& s);
1387 State state() const { return State(TypesBits::decode(sub_minor_key())); }
1389 class NilValueBits : public BitField<NilValue, 0, 1> {};
1390 class TypesBits : public BitField<byte, 1, NUMBER_OF_TYPES> {};
1392 friend class CompareNilIC;
1394 DEFINE_CALL_INTERFACE_DESCRIPTOR(CompareNil);
1395 DEFINE_HYDROGEN_CODE_STUB(CompareNilIC, HydrogenCodeStub);
1399 OStream& operator<<(OStream& os, const CompareNilICStub::State& s);
1402 class CEntryStub : public PlatformCodeStub {
1404 CEntryStub(Isolate* isolate, int result_size,
1405 SaveFPRegsMode save_doubles = kDontSaveFPRegs)
1406 : PlatformCodeStub(isolate) {
1407 minor_key_ = SaveDoublesBits::encode(save_doubles == kSaveFPRegs);
1408 DCHECK(result_size == 1 || result_size == 2);
1410 minor_key_ = ResultSizeBits::update(minor_key_, result_size);
1414 // The version of this stub that doesn't save doubles is generated ahead of
1415 // time, so it's OK to call it from other stubs that can't cope with GC during
1416 // their code generation. On machines that always have gp registers (x64) we
1417 // can generate both variants ahead of time.
1418 static void GenerateAheadOfTime(Isolate* isolate);
1421 bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
1423 int result_size() const { return ResultSizeBits::decode(minor_key_); }
1426 bool NeedsImmovableCode();
1428 class SaveDoublesBits : public BitField<bool, 0, 1> {};
1429 class ResultSizeBits : public BitField<int, 1, 3> {};
1431 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1432 DEFINE_PLATFORM_CODE_STUB(CEntry, PlatformCodeStub);
1436 class JSEntryStub : public PlatformCodeStub {
1438 JSEntryStub(Isolate* isolate, StackFrame::Type type)
1439 : PlatformCodeStub(isolate) {
1440 DCHECK(type == StackFrame::ENTRY || type == StackFrame::ENTRY_CONSTRUCT);
1441 minor_key_ = StackFrameTypeBits::encode(type);
1445 virtual void FinishCode(Handle<Code> code);
1447 virtual void PrintName(OStream& os) const OVERRIDE { // NOLINT
1448 os << (type() == StackFrame::ENTRY ? "JSEntryStub"
1449 : "JSConstructEntryStub");
1452 StackFrame::Type type() const {
1453 return StackFrameTypeBits::decode(minor_key_);
1456 class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {};
1458 int handler_offset_;
1460 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1461 DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub);
1465 class ArgumentsAccessStub: public PlatformCodeStub {
1474 ArgumentsAccessStub(Isolate* isolate, Type type) : PlatformCodeStub(isolate) {
1475 minor_key_ = TypeBits::encode(type);
1478 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
1479 if (type() == READ_ELEMENT) {
1480 return ArgumentsAccessReadDescriptor(isolate());
1482 return ContextOnlyDescriptor(isolate());
1486 Type type() const { return TypeBits::decode(minor_key_); }
1488 void GenerateReadElement(MacroAssembler* masm);
1489 void GenerateNewStrict(MacroAssembler* masm);
1490 void GenerateNewSloppyFast(MacroAssembler* masm);
1491 void GenerateNewSloppySlow(MacroAssembler* masm);
1493 virtual void PrintName(OStream& os) const OVERRIDE; // NOLINT
1495 class TypeBits : public BitField<Type, 0, 2> {};
1497 DEFINE_PLATFORM_CODE_STUB(ArgumentsAccess, PlatformCodeStub);
1501 class RegExpExecStub: public PlatformCodeStub {
1503 explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
1505 DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
1506 DEFINE_PLATFORM_CODE_STUB(RegExpExec, PlatformCodeStub);
1510 class RegExpConstructResultStub FINAL : public HydrogenCodeStub {
1512 explicit RegExpConstructResultStub(Isolate* isolate)
1513 : HydrogenCodeStub(isolate) { }
1515 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1516 static const int kLength = 0;
1517 static const int kIndex = 1;
1518 static const int kInput = 2;
1520 DEFINE_CALL_INTERFACE_DESCRIPTOR(RegExpConstructResult);
1521 DEFINE_HYDROGEN_CODE_STUB(RegExpConstructResult, HydrogenCodeStub);
1525 class CallFunctionStub: public PlatformCodeStub {
1527 CallFunctionStub(Isolate* isolate, int argc, CallFunctionFlags flags)
1528 : PlatformCodeStub(isolate) {
1529 DCHECK(argc >= 0 && argc <= Code::kMaxArguments);
1530 minor_key_ = ArgcBits::encode(argc) | FlagBits::encode(flags);
1533 static int ExtractArgcFromMinorKey(int minor_key) {
1534 return ArgcBits::decode(minor_key);
1538 int argc() const { return ArgcBits::decode(minor_key_); }
1539 int flags() const { return FlagBits::decode(minor_key_); }
1541 bool CallAsMethod() const {
1542 return flags() == CALL_AS_METHOD || flags() == WRAP_AND_CALL;
1545 bool NeedsChecks() const { return flags() != WRAP_AND_CALL; }
1547 virtual void PrintName(OStream& os) const OVERRIDE; // NOLINT
1549 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
1550 class FlagBits : public BitField<CallFunctionFlags, 0, 2> {};
1551 class ArgcBits : public BitField<unsigned, 2, Code::kArgumentsBits> {};
1552 STATIC_ASSERT(Code::kArgumentsBits + 2 <= kStubMinorKeyBits);
1554 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction);
1555 DEFINE_PLATFORM_CODE_STUB(CallFunction, PlatformCodeStub);
1559 class CallConstructStub: public PlatformCodeStub {
1561 CallConstructStub(Isolate* isolate, CallConstructorFlags flags)
1562 : PlatformCodeStub(isolate) {
1563 minor_key_ = FlagBits::encode(flags);
1566 virtual void FinishCode(Handle<Code> code) {
1567 code->set_has_function_cache(RecordCallTarget());
1571 CallConstructorFlags flags() const { return FlagBits::decode(minor_key_); }
1573 bool RecordCallTarget() const {
1574 return (flags() & RECORD_CONSTRUCTOR_TARGET) != 0;
1577 virtual void PrintName(OStream& os) const OVERRIDE; // NOLINT
1579 class FlagBits : public BitField<CallConstructorFlags, 0, 1> {};
1581 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallConstruct);
1582 DEFINE_PLATFORM_CODE_STUB(CallConstruct, PlatformCodeStub);
1586 enum StringIndexFlags {
1587 // Accepts smis or heap numbers.
1588 STRING_INDEX_IS_NUMBER,
1590 // Accepts smis or heap numbers that are valid array indices
1591 // (ECMA-262 15.4). Invalid indices are reported as being out of
1593 STRING_INDEX_IS_ARRAY_INDEX
1597 // Generates code implementing String.prototype.charCodeAt.
1599 // Only supports the case when the receiver is a string and the index
1600 // is a number (smi or heap number) that is a valid index into the
1601 // string. Additional index constraints are specified by the
1602 // flags. Otherwise, bails out to the provided labels.
1604 // Register usage: |object| may be changed to another string in a way
1605 // that doesn't affect charCodeAt/charAt semantics, |index| is
1606 // preserved, |scratch| and |result| are clobbered.
1607 class StringCharCodeAtGenerator {
1609 StringCharCodeAtGenerator(Register object,
1612 Label* receiver_not_string,
1613 Label* index_not_number,
1614 Label* index_out_of_range,
1615 StringIndexFlags index_flags)
1619 receiver_not_string_(receiver_not_string),
1620 index_not_number_(index_not_number),
1621 index_out_of_range_(index_out_of_range),
1622 index_flags_(index_flags) {
1623 DCHECK(!result_.is(object_));
1624 DCHECK(!result_.is(index_));
1627 // Generates the fast case code. On the fallthrough path |result|
1628 // register contains the result.
1629 void GenerateFast(MacroAssembler* masm);
1631 // Generates the slow case code. Must not be naturally
1632 // reachable. Expected to be put after a ret instruction (e.g., in
1633 // deferred code). Always jumps back to the fast case.
1634 void GenerateSlow(MacroAssembler* masm,
1635 const RuntimeCallHelper& call_helper);
1637 // Skip handling slow case and directly jump to bailout.
1638 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1639 masm->bind(&index_not_smi_);
1640 masm->bind(&call_runtime_);
1649 Label* receiver_not_string_;
1650 Label* index_not_number_;
1651 Label* index_out_of_range_;
1653 StringIndexFlags index_flags_;
1655 Label call_runtime_;
1656 Label index_not_smi_;
1657 Label got_smi_index_;
1660 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
1664 // Generates code for creating a one-char string from a char code.
1665 class StringCharFromCodeGenerator {
1667 StringCharFromCodeGenerator(Register code,
1671 DCHECK(!code_.is(result_));
1674 // Generates the fast case code. On the fallthrough path |result|
1675 // register contains the result.
1676 void GenerateFast(MacroAssembler* masm);
1678 // Generates the slow case code. Must not be naturally
1679 // reachable. Expected to be put after a ret instruction (e.g., in
1680 // deferred code). Always jumps back to the fast case.
1681 void GenerateSlow(MacroAssembler* masm,
1682 const RuntimeCallHelper& call_helper);
1684 // Skip handling slow case and directly jump to bailout.
1685 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1686 masm->bind(&slow_case_);
1697 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
1701 // Generates code implementing String.prototype.charAt.
1703 // Only supports the case when the receiver is a string and the index
1704 // is a number (smi or heap number) that is a valid index into the
1705 // string. Additional index constraints are specified by the
1706 // flags. Otherwise, bails out to the provided labels.
1708 // Register usage: |object| may be changed to another string in a way
1709 // that doesn't affect charCodeAt/charAt semantics, |index| is
1710 // preserved, |scratch1|, |scratch2|, and |result| are clobbered.
1711 class StringCharAtGenerator {
1713 StringCharAtGenerator(Register object,
1717 Label* receiver_not_string,
1718 Label* index_not_number,
1719 Label* index_out_of_range,
1720 StringIndexFlags index_flags)
1721 : char_code_at_generator_(object,
1724 receiver_not_string,
1728 char_from_code_generator_(scratch, result) {}
1730 // Generates the fast case code. On the fallthrough path |result|
1731 // register contains the result.
1732 void GenerateFast(MacroAssembler* masm) {
1733 char_code_at_generator_.GenerateFast(masm);
1734 char_from_code_generator_.GenerateFast(masm);
1737 // Generates the slow case code. Must not be naturally
1738 // reachable. Expected to be put after a ret instruction (e.g., in
1739 // deferred code). Always jumps back to the fast case.
1740 void GenerateSlow(MacroAssembler* masm,
1741 const RuntimeCallHelper& call_helper) {
1742 char_code_at_generator_.GenerateSlow(masm, call_helper);
1743 char_from_code_generator_.GenerateSlow(masm, call_helper);
1746 // Skip handling slow case and directly jump to bailout.
1747 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1748 char_code_at_generator_.SkipSlow(masm, bailout);
1749 char_from_code_generator_.SkipSlow(masm, bailout);
1753 StringCharCodeAtGenerator char_code_at_generator_;
1754 StringCharFromCodeGenerator char_from_code_generator_;
1756 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
1760 class LoadDictionaryElementStub : public HydrogenCodeStub {
1762 explicit LoadDictionaryElementStub(Isolate* isolate)
1763 : HydrogenCodeStub(isolate) {}
1765 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1766 DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub);
1770 class KeyedLoadGenericStub : public HydrogenCodeStub {
1772 explicit KeyedLoadGenericStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
1774 virtual Code::Kind GetCodeKind() const { return Code::KEYED_LOAD_IC; }
1775 virtual InlineCacheState GetICState() const { return GENERIC; }
1777 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1778 DEFINE_HYDROGEN_CODE_STUB(KeyedLoadGeneric, HydrogenCodeStub);
1782 class LoadICTrampolineStub : public PlatformCodeStub {
1784 LoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
1785 : PlatformCodeStub(isolate) {
1786 minor_key_ = state.GetExtraICState();
1789 virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; }
1791 virtual InlineCacheState GetICState() const FINAL OVERRIDE {
1795 virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
1796 return static_cast<ExtraICState>(minor_key_);
1800 LoadICState state() const {
1801 return LoadICState(static_cast<ExtraICState>(minor_key_));
1804 DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorLoadICTrampoline);
1805 DEFINE_PLATFORM_CODE_STUB(LoadICTrampoline, PlatformCodeStub);
1809 class KeyedLoadICTrampolineStub : public LoadICTrampolineStub {
1811 explicit KeyedLoadICTrampolineStub(Isolate* isolate)
1812 : LoadICTrampolineStub(isolate, LoadICState(0)) {}
1814 virtual Code::Kind GetCodeKind() const OVERRIDE {
1815 return Code::KEYED_LOAD_IC;
1818 DEFINE_PLATFORM_CODE_STUB(KeyedLoadICTrampoline, LoadICTrampolineStub);
1822 class MegamorphicLoadStub : public HydrogenCodeStub {
1824 MegamorphicLoadStub(Isolate* isolate, const LoadICState& state)
1825 : HydrogenCodeStub(isolate) {
1826 set_sub_minor_key(state.GetExtraICState());
1829 virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; }
1831 virtual InlineCacheState GetICState() const FINAL OVERRIDE {
1835 virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
1836 return static_cast<ExtraICState>(sub_minor_key());
1839 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1840 DEFINE_HYDROGEN_CODE_STUB(MegamorphicLoad, HydrogenCodeStub);
1844 class VectorLoadStub : public HydrogenCodeStub {
1846 explicit VectorLoadStub(Isolate* isolate, const LoadICState& state)
1847 : HydrogenCodeStub(isolate) {
1848 set_sub_minor_key(state.GetExtraICState());
1851 virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; }
1853 virtual InlineCacheState GetICState() const FINAL OVERRIDE {
1857 virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
1858 return static_cast<ExtraICState>(sub_minor_key());
1862 LoadICState state() const { return LoadICState(GetExtraICState()); }
1864 DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorLoadIC);
1865 DEFINE_HYDROGEN_CODE_STUB(VectorLoad, HydrogenCodeStub);
1869 class VectorKeyedLoadStub : public VectorLoadStub {
1871 explicit VectorKeyedLoadStub(Isolate* isolate)
1872 : VectorLoadStub(isolate, LoadICState(0)) {}
1874 virtual Code::Kind GetCodeKind() const OVERRIDE {
1875 return Code::KEYED_LOAD_IC;
1878 DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorLoadIC);
1879 DEFINE_HYDROGEN_CODE_STUB(VectorKeyedLoad, VectorLoadStub);
1883 class DoubleToIStub : public PlatformCodeStub {
1885 DoubleToIStub(Isolate* isolate, Register source, Register destination,
1886 int offset, bool is_truncating, bool skip_fastpath = false)
1887 : PlatformCodeStub(isolate) {
1888 minor_key_ = SourceRegisterBits::encode(source.code()) |
1889 DestinationRegisterBits::encode(destination.code()) |
1890 OffsetBits::encode(offset) |
1891 IsTruncatingBits::encode(is_truncating) |
1892 SkipFastPathBits::encode(skip_fastpath) |
1893 SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0);
1896 virtual bool SometimesSetsUpAFrame() { return false; }
1899 Register source() const {
1900 return Register::from_code(SourceRegisterBits::decode(minor_key_));
1902 Register destination() const {
1903 return Register::from_code(DestinationRegisterBits::decode(minor_key_));
1905 bool is_truncating() const { return IsTruncatingBits::decode(minor_key_); }
1906 bool skip_fastpath() const { return SkipFastPathBits::decode(minor_key_); }
1907 int offset() const { return OffsetBits::decode(minor_key_); }
1909 static const int kBitsPerRegisterNumber = 6;
1910 STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
1911 class SourceRegisterBits:
1912 public BitField<int, 0, kBitsPerRegisterNumber> {}; // NOLINT
1913 class DestinationRegisterBits:
1914 public BitField<int, kBitsPerRegisterNumber,
1915 kBitsPerRegisterNumber> {}; // NOLINT
1916 class IsTruncatingBits:
1917 public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {}; // NOLINT
1919 public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {}; // NOLINT
1920 class SkipFastPathBits:
1921 public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {}; // NOLINT
1923 public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {}; // NOLINT
1925 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1926 DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub);
1930 class LoadFastElementStub : public HydrogenCodeStub {
1932 LoadFastElementStub(Isolate* isolate, bool is_js_array,
1933 ElementsKind elements_kind)
1934 : HydrogenCodeStub(isolate) {
1935 set_sub_minor_key(ElementsKindBits::encode(elements_kind) |
1936 IsJSArrayBits::encode(is_js_array));
1939 bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
1941 ElementsKind elements_kind() const {
1942 return ElementsKindBits::decode(sub_minor_key());
1946 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
1947 class IsJSArrayBits: public BitField<bool, 8, 1> {};
1949 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1950 DEFINE_HYDROGEN_CODE_STUB(LoadFastElement, HydrogenCodeStub);
1954 class StoreFastElementStub : public HydrogenCodeStub {
1956 StoreFastElementStub(Isolate* isolate, bool is_js_array,
1957 ElementsKind elements_kind, KeyedAccessStoreMode mode)
1958 : HydrogenCodeStub(isolate) {
1959 set_sub_minor_key(ElementsKindBits::encode(elements_kind) |
1960 IsJSArrayBits::encode(is_js_array) |
1961 StoreModeBits::encode(mode));
1964 bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
1966 ElementsKind elements_kind() const {
1967 return ElementsKindBits::decode(sub_minor_key());
1970 KeyedAccessStoreMode store_mode() const {
1971 return StoreModeBits::decode(sub_minor_key());
1975 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
1976 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
1977 class IsJSArrayBits: public BitField<bool, 12, 1> {};
1979 DEFINE_CALL_INTERFACE_DESCRIPTOR(Store);
1980 DEFINE_HYDROGEN_CODE_STUB(StoreFastElement, HydrogenCodeStub);
1984 class TransitionElementsKindStub : public HydrogenCodeStub {
1986 TransitionElementsKindStub(Isolate* isolate,
1987 ElementsKind from_kind,
1988 ElementsKind to_kind,
1989 bool is_js_array) : HydrogenCodeStub(isolate) {
1990 set_sub_minor_key(FromKindBits::encode(from_kind) |
1991 ToKindBits::encode(to_kind) |
1992 IsJSArrayBits::encode(is_js_array));
1995 ElementsKind from_kind() const {
1996 return FromKindBits::decode(sub_minor_key());
1999 ElementsKind to_kind() const { return ToKindBits::decode(sub_minor_key()); }
2001 bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2004 class FromKindBits: public BitField<ElementsKind, 8, 8> {};
2005 class ToKindBits: public BitField<ElementsKind, 0, 8> {};
2006 class IsJSArrayBits: public BitField<bool, 16, 1> {};
2008 DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind);
2009 DEFINE_HYDROGEN_CODE_STUB(TransitionElementsKind, HydrogenCodeStub);
2013 class ArrayConstructorStubBase : public HydrogenCodeStub {
2015 ArrayConstructorStubBase(Isolate* isolate,
2017 AllocationSiteOverrideMode override_mode)
2018 : HydrogenCodeStub(isolate) {
2019 // It only makes sense to override local allocation site behavior
2020 // if there is a difference between the global allocation site policy
2021 // for an ElementsKind and the desired usage of the stub.
2022 DCHECK(override_mode != DISABLE_ALLOCATION_SITES ||
2023 AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
2024 set_sub_minor_key(ElementsKindBits::encode(kind) |
2025 AllocationSiteOverrideModeBits::encode(override_mode));
2028 ElementsKind elements_kind() const {
2029 return ElementsKindBits::decode(sub_minor_key());
2032 AllocationSiteOverrideMode override_mode() const {
2033 return AllocationSiteOverrideModeBits::decode(sub_minor_key());
2036 static void GenerateStubsAheadOfTime(Isolate* isolate);
2038 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2039 static const int kConstructor = 0;
2040 static const int kAllocationSite = 1;
2043 OStream& BasePrintName(OStream& os, const char* name) const; // NOLINT
2046 // Ensure data fits within available bits.
2047 STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
2049 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2050 class AllocationSiteOverrideModeBits: public
2051 BitField<AllocationSiteOverrideMode, 8, 1> {}; // NOLINT
2053 DEFINE_CODE_STUB_BASE(ArrayConstructorStubBase, HydrogenCodeStub);
2057 class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
2059 ArrayNoArgumentConstructorStub(
2062 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2063 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2067 virtual void PrintName(OStream& os) const OVERRIDE { // NOLINT
2068 BasePrintName(os, "ArrayNoArgumentConstructorStub");
2071 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructorConstantArgCount);
2072 DEFINE_HYDROGEN_CODE_STUB(ArrayNoArgumentConstructor,
2073 ArrayConstructorStubBase);
2077 class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
2079 ArraySingleArgumentConstructorStub(
2082 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2083 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2087 virtual void PrintName(OStream& os) const { // NOLINT
2088 BasePrintName(os, "ArraySingleArgumentConstructorStub");
2091 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2092 DEFINE_HYDROGEN_CODE_STUB(ArraySingleArgumentConstructor,
2093 ArrayConstructorStubBase);
2097 class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
2099 ArrayNArgumentsConstructorStub(
2102 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2103 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2107 virtual void PrintName(OStream& os) const { // NOLINT
2108 BasePrintName(os, "ArrayNArgumentsConstructorStub");
2111 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2112 DEFINE_HYDROGEN_CODE_STUB(ArrayNArgumentsConstructor,
2113 ArrayConstructorStubBase);
2117 class InternalArrayConstructorStubBase : public HydrogenCodeStub {
2119 InternalArrayConstructorStubBase(Isolate* isolate, ElementsKind kind)
2120 : HydrogenCodeStub(isolate) {
2121 set_sub_minor_key(ElementsKindBits::encode(kind));
2124 static void GenerateStubsAheadOfTime(Isolate* isolate);
2126 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2127 static const int kConstructor = 0;
2129 ElementsKind elements_kind() const {
2130 return ElementsKindBits::decode(sub_minor_key());
2134 class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2136 DEFINE_CODE_STUB_BASE(InternalArrayConstructorStubBase, HydrogenCodeStub);
2140 class InternalArrayNoArgumentConstructorStub : public
2141 InternalArrayConstructorStubBase {
2143 InternalArrayNoArgumentConstructorStub(Isolate* isolate,
2145 : InternalArrayConstructorStubBase(isolate, kind) { }
2147 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructorConstantArgCount);
2148 DEFINE_HYDROGEN_CODE_STUB(InternalArrayNoArgumentConstructor,
2149 InternalArrayConstructorStubBase);
2153 class InternalArraySingleArgumentConstructorStub : public
2154 InternalArrayConstructorStubBase {
2156 InternalArraySingleArgumentConstructorStub(Isolate* isolate,
2158 : InternalArrayConstructorStubBase(isolate, kind) { }
2160 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2161 DEFINE_HYDROGEN_CODE_STUB(InternalArraySingleArgumentConstructor,
2162 InternalArrayConstructorStubBase);
2166 class InternalArrayNArgumentsConstructorStub : public
2167 InternalArrayConstructorStubBase {
2169 InternalArrayNArgumentsConstructorStub(Isolate* isolate, ElementsKind kind)
2170 : InternalArrayConstructorStubBase(isolate, kind) { }
2172 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2173 DEFINE_HYDROGEN_CODE_STUB(InternalArrayNArgumentsConstructor,
2174 InternalArrayConstructorStubBase);
2178 class StoreElementStub : public PlatformCodeStub {
2180 StoreElementStub(Isolate* isolate, ElementsKind elements_kind)
2181 : PlatformCodeStub(isolate) {
2182 minor_key_ = ElementsKindBits::encode(elements_kind);
2186 ElementsKind elements_kind() const {
2187 return ElementsKindBits::decode(minor_key_);
2190 class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2192 DEFINE_CALL_INTERFACE_DESCRIPTOR(Store);
2193 DEFINE_PLATFORM_CODE_STUB(StoreElement, PlatformCodeStub);
2197 class ToBooleanStub: public HydrogenCodeStub {
2212 RESULT_AS_SMI, // For Smi(1) on truthy value, Smi(0) otherwise.
2213 RESULT_AS_ODDBALL, // For {true} on truthy value, {false} otherwise.
2214 RESULT_AS_INVERSE_ODDBALL // For {false} on truthy value, {true} otherwise.
2217 // At most 8 different types can be distinguished, because the Code object
2218 // only has room for a single byte to hold a set of these types. :-P
2219 STATIC_ASSERT(NUMBER_OF_TYPES <= 8);
2221 class Types : public EnumSet<Type, byte> {
2223 Types() : EnumSet<Type, byte>(0) {}
2224 explicit Types(byte bits) : EnumSet<Type, byte>(bits) {}
2226 byte ToByte() const { return ToIntegral(); }
2227 bool UpdateStatus(Handle<Object> object);
2228 bool NeedsMap() const;
2229 bool CanBeUndetectable() const;
2230 bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
2232 static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
2235 ToBooleanStub(Isolate* isolate, ResultMode mode, Types types = Types())
2236 : HydrogenCodeStub(isolate) {
2237 set_sub_minor_key(TypesBits::encode(types.ToByte()) |
2238 ResultModeBits::encode(mode));
2241 ToBooleanStub(Isolate* isolate, ExtraICState state)
2242 : HydrogenCodeStub(isolate) {
2243 set_sub_minor_key(TypesBits::encode(static_cast<byte>(state)) |
2244 ResultModeBits::encode(RESULT_AS_SMI));
2247 bool UpdateStatus(Handle<Object> object);
2248 Types types() const { return Types(TypesBits::decode(sub_minor_key())); }
2249 ResultMode mode() const { return ResultModeBits::decode(sub_minor_key()); }
2251 virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; }
2252 virtual void PrintState(OStream& os) const OVERRIDE; // NOLINT
2254 virtual bool SometimesSetsUpAFrame() { return false; }
2256 static Handle<Code> GetUninitialized(Isolate* isolate) {
2257 return ToBooleanStub(isolate, UNINITIALIZED).GetCode();
2260 virtual ExtraICState GetExtraICState() const { return types().ToIntegral(); }
2262 virtual InlineCacheState GetICState() const {
2263 if (types().IsEmpty()) {
2264 return ::v8::internal::UNINITIALIZED;
2271 ToBooleanStub(Isolate* isolate, InitializationState init_state)
2272 : HydrogenCodeStub(isolate, init_state) {
2273 set_sub_minor_key(ResultModeBits::encode(RESULT_AS_SMI));
2276 class TypesBits : public BitField<byte, 0, NUMBER_OF_TYPES> {};
2277 class ResultModeBits : public BitField<ResultMode, NUMBER_OF_TYPES, 2> {};
2279 DEFINE_CALL_INTERFACE_DESCRIPTOR(ToBoolean);
2280 DEFINE_HYDROGEN_CODE_STUB(ToBoolean, HydrogenCodeStub);
2284 OStream& operator<<(OStream& os, const ToBooleanStub::Types& t);
2287 class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
2289 ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind,
2290 ElementsKind to_kind, bool is_jsarray,
2291 KeyedAccessStoreMode store_mode)
2292 : HydrogenCodeStub(isolate) {
2293 set_sub_minor_key(FromBits::encode(from_kind) | ToBits::encode(to_kind) |
2294 IsJSArrayBits::encode(is_jsarray) |
2295 StoreModeBits::encode(store_mode));
2298 ElementsKind from_kind() const { return FromBits::decode(sub_minor_key()); }
2299 ElementsKind to_kind() const { return ToBits::decode(sub_minor_key()); }
2300 bool is_jsarray() const { return IsJSArrayBits::decode(sub_minor_key()); }
2301 KeyedAccessStoreMode store_mode() const {
2302 return StoreModeBits::decode(sub_minor_key());
2305 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2306 enum ParameterIndices {
2314 static const Register ValueRegister() {
2315 return ElementTransitionAndStoreDescriptor::ValueRegister();
2317 static const Register MapRegister() {
2318 return ElementTransitionAndStoreDescriptor::MapRegister();
2320 static const Register KeyRegister() {
2321 return ElementTransitionAndStoreDescriptor::NameRegister();
2323 static const Register ObjectRegister() {
2324 return ElementTransitionAndStoreDescriptor::ReceiverRegister();
2328 class FromBits : public BitField<ElementsKind, 0, 8> {};
2329 class ToBits : public BitField<ElementsKind, 8, 8> {};
2330 class IsJSArrayBits : public BitField<bool, 16, 1> {};
2331 class StoreModeBits : public BitField<KeyedAccessStoreMode, 17, 4> {};
2333 DEFINE_CALL_INTERFACE_DESCRIPTOR(ElementTransitionAndStore);
2334 DEFINE_HYDROGEN_CODE_STUB(ElementsTransitionAndStore, HydrogenCodeStub);
2338 class StoreArrayLiteralElementStub : public PlatformCodeStub {
2340 explicit StoreArrayLiteralElementStub(Isolate* isolate)
2341 : PlatformCodeStub(isolate) { }
2343 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreArrayLiteralElement);
2344 DEFINE_PLATFORM_CODE_STUB(StoreArrayLiteralElement, PlatformCodeStub);
2348 class StubFailureTrampolineStub : public PlatformCodeStub {
2350 StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode)
2351 : PlatformCodeStub(isolate) {
2352 minor_key_ = FunctionModeField::encode(function_mode);
2355 static void GenerateAheadOfTime(Isolate* isolate);
2358 StubFunctionMode function_mode() const {
2359 return FunctionModeField::decode(minor_key_);
2362 class FunctionModeField : public BitField<StubFunctionMode, 0, 1> {};
2364 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2365 DEFINE_PLATFORM_CODE_STUB(StubFailureTrampoline, PlatformCodeStub);
2369 class ProfileEntryHookStub : public PlatformCodeStub {
2371 explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2373 // The profile entry hook function is not allowed to cause a GC.
2374 virtual bool SometimesSetsUpAFrame() { return false; }
2376 // Generates a call to the entry hook if it's enabled.
2377 static void MaybeCallEntryHook(MacroAssembler* masm);
2380 static void EntryHookTrampoline(intptr_t function,
2381 intptr_t stack_pointer,
2384 // ProfileEntryHookStub is called at the start of a function, so it has the
2385 // same register set.
2386 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction)
2387 DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub);
2391 class StoreBufferOverflowStub : public PlatformCodeStub {
2393 StoreBufferOverflowStub(Isolate* isolate, SaveFPRegsMode save_fp)
2394 : PlatformCodeStub(isolate) {
2395 minor_key_ = SaveDoublesBits::encode(save_fp == kSaveFPRegs);
2398 static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
2399 virtual bool SometimesSetsUpAFrame() { return false; }
2402 bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
2404 class SaveDoublesBits : public BitField<bool, 0, 1> {};
2406 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2407 DEFINE_PLATFORM_CODE_STUB(StoreBufferOverflow, PlatformCodeStub);
2411 class SubStringStub : public PlatformCodeStub {
2413 explicit SubStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2415 DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
2416 DEFINE_PLATFORM_CODE_STUB(SubString, PlatformCodeStub);
2420 class StringCompareStub : public PlatformCodeStub {
2422 explicit StringCompareStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2424 DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
2425 DEFINE_PLATFORM_CODE_STUB(StringCompare, PlatformCodeStub);
2429 #undef DEFINE_CALL_INTERFACE_DESCRIPTOR
2430 #undef DEFINE_PLATFORM_CODE_STUB
2431 #undef DEFINE_HANDLER_CODE_STUB
2432 #undef DEFINE_HYDROGEN_CODE_STUB
2433 #undef DEFINE_CODE_STUB
2434 #undef DEFINE_CODE_STUB_BASE
2435 } } // namespace v8::internal
2437 #endif // V8_CODE_STUBS_H_