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) \
36 V(FunctionPrototype) \
38 V(InternalArrayConstructor) \
40 V(KeyedLoadICTrampoline) \
43 V(CallIC_ArrayTrampoline) \
44 V(LoadIndexedInterceptor) \
45 V(LoadIndexedString) \
50 V(StoreArrayLiteralElement) \
51 V(StoreBufferOverflow) \
54 V(StubFailureTrampoline) \
57 V(VectorStoreICTrampoline) \
58 V(VectorKeyedStoreICTrampoline) \
60 V(VectorKeyedStoreIC) \
61 /* HydrogenCodeStubs */ \
62 V(AllocateHeapNumber) \
63 V(ArrayNArgumentsConstructor) \
64 V(ArrayNoArgumentConstructor) \
65 V(ArraySingleArgumentConstructor) \
67 V(BinaryOpWithAllocationSite) \
69 V(CreateAllocationSite) \
71 V(ElementsTransitionAndStore) \
72 V(FastCloneShallowArray) \
73 V(FastCloneShallowObject) \
76 V(GrowArrayElements) \
77 V(InternalArrayNArgumentsConstructor) \
78 V(InternalArrayNoArgumentConstructor) \
79 V(InternalArraySingleArgumentConstructor) \
81 V(LoadScriptContextField) \
82 V(LoadDictionaryElement) \
83 V(NameDictionaryLookup) \
86 V(RegExpConstructResult) \
88 V(StoreScriptContextField) \
91 V(TransitionElementsKind) \
94 /* TurboFanCodeStubs */ \
98 /* IC Handler stubs */ \
99 V(ArrayBufferViewLoadField) \
103 V(KeyedLoadSloppyArguments) \
104 V(KeyedStoreSloppyArguments) \
111 // List of code stubs only used on ARM 32 bits platforms.
112 #if V8_TARGET_ARCH_ARM
113 #define CODE_STUB_LIST_ARM(V) V(DirectCEntry)
116 #define CODE_STUB_LIST_ARM(V)
119 // List of code stubs only used on ARM 64 bits platforms.
120 #if V8_TARGET_ARCH_ARM64
121 #define CODE_STUB_LIST_ARM64(V) \
123 V(RestoreRegistersState) \
124 V(StoreRegistersState)
127 #define CODE_STUB_LIST_ARM64(V)
130 // List of code stubs only used on PPC platforms.
131 #ifdef V8_TARGET_ARCH_PPC
132 #define CODE_STUB_LIST_PPC(V) \
134 V(StoreRegistersState) \
135 V(RestoreRegistersState)
137 #define CODE_STUB_LIST_PPC(V)
140 // List of code stubs only used on MIPS platforms.
141 #if V8_TARGET_ARCH_MIPS
142 #define CODE_STUB_LIST_MIPS(V) \
144 V(RestoreRegistersState) \
145 V(StoreRegistersState)
146 #elif V8_TARGET_ARCH_MIPS64
147 #define CODE_STUB_LIST_MIPS(V) \
149 V(RestoreRegistersState) \
150 V(StoreRegistersState)
152 #define CODE_STUB_LIST_MIPS(V)
155 // Combined list of code stubs.
156 #define CODE_STUB_LIST(V) \
157 CODE_STUB_LIST_ALL_PLATFORMS(V) \
158 CODE_STUB_LIST_ARM(V) \
159 CODE_STUB_LIST_ARM64(V) \
160 CODE_STUB_LIST_PPC(V) \
161 CODE_STUB_LIST_MIPS(V)
163 static const int kHasReturnedMinusZeroSentinel = 1;
165 // Stub is base classes of all stubs.
166 class CodeStub BASE_EMBEDDED {
169 // TODO(mvstanton): eliminate the NoCache key by getting rid
170 // of the non-monomorphic-cache.
171 NoCache = 0, // marker for stubs that do custom caching]
172 #define DEF_ENUM(name) name,
173 CODE_STUB_LIST(DEF_ENUM)
178 // Retrieve the code for the stub. Generate the code if needed.
179 Handle<Code> GetCode();
181 // Retrieve the code for the stub, make and return a copy of the code.
182 Handle<Code> GetCodeCopy(const Code::FindAndReplacePattern& pattern);
184 static Major MajorKeyFromKey(uint32_t key) {
185 return static_cast<Major>(MajorKeyBits::decode(key));
187 static uint32_t MinorKeyFromKey(uint32_t key) {
188 return MinorKeyBits::decode(key);
191 // Gets the major key from a code object that is a code stub or binary op IC.
192 static Major GetMajorKey(Code* code_stub) {
193 return MajorKeyFromKey(code_stub->stub_key());
196 static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }
198 static const char* MajorName(Major major_key, bool allow_unknown_keys);
200 explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {}
201 virtual ~CodeStub() {}
203 static void GenerateStubsAheadOfTime(Isolate* isolate);
204 static void GenerateFPStubs(Isolate* isolate);
206 // Some stubs put untagged junk on the stack that cannot be scanned by the
207 // GC. This means that we must be statically sure that no GC can occur while
208 // they are running. If that is the case they should override this to return
209 // true, which will cause an assertion if we try to call something that can
210 // GC or if we try to put a stack frame on top of the junk, which would not
211 // result in a traversable stack.
212 virtual bool SometimesSetsUpAFrame() { return true; }
214 // Lookup the code in the (possibly custom) cache.
215 bool FindCodeInCache(Code** code_out);
217 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() = 0;
219 virtual int GetStackParameterCount() const { return 0; }
221 virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {}
223 static void InitializeDescriptor(Isolate* isolate, uint32_t key,
224 CodeStubDescriptor* desc);
226 static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key);
228 // Returns information for computing the number key.
229 virtual Major MajorKey() const = 0;
230 uint32_t MinorKey() const { return minor_key_; }
232 // BinaryOpStub needs to override this.
233 virtual Code::Kind GetCodeKind() const;
235 virtual InlineCacheState GetICState() const { return UNINITIALIZED; }
236 virtual ExtraICState GetExtraICState() const { return kNoExtraICState; }
237 virtual Code::StubType GetStubType() const { return Code::NORMAL; }
239 friend std::ostream& operator<<(std::ostream& os, const CodeStub& s) {
244 Isolate* isolate() const { return isolate_; }
247 CodeStub(uint32_t key, Isolate* isolate)
248 : minor_key_(MinorKeyFromKey(key)), isolate_(isolate) {}
250 // Generates the assembler code for the stub.
251 virtual Handle<Code> GenerateCode() = 0;
253 // Returns whether the code generated for this stub needs to be allocated as
254 // a fixed (non-moveable) code object.
255 virtual bool NeedsImmovableCode() { return false; }
257 virtual void PrintName(std::ostream& os) const; // NOLINT
258 virtual void PrintBaseName(std::ostream& os) const; // NOLINT
259 virtual void PrintState(std::ostream& os) const { ; } // NOLINT
261 // Computes the key based on major and minor.
263 DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
264 return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey());
270 // Perform bookkeeping required after code generation when stub code is
271 // initially generated.
272 void RecordCodeGeneration(Handle<Code> code);
274 // Finish the code object after it has been generated.
275 virtual void FinishCode(Handle<Code> code) { }
277 // Activate newly generated stub. Is called after
278 // registering stub in the stub cache.
279 virtual void Activate(Code* code) { }
281 // Add the code to a specialized cache, specific to an individual
282 // stub type. Please note, this method must add the code object to a
283 // roots object, otherwise we will remove the code during GC.
284 virtual void AddToSpecialCache(Handle<Code> new_object) { }
286 // Find code in a specialized cache, work is delegated to the specific stub.
287 virtual bool FindCodeInSpecialCache(Code** code_out) {
291 // If a stub uses a special cache override this.
292 virtual bool UseSpecialCache() { return false; }
294 // We use this dispatch to statically instantiate the correct code stub for
295 // the given stub key and call the passed function with that code stub.
296 typedef void (*DispatchedCall)(CodeStub* stub, void** value_out);
297 static void Dispatch(Isolate* isolate, uint32_t key, void** value_out,
298 DispatchedCall call);
300 static void GetCodeDispatchCall(CodeStub* stub, void** value_out);
302 STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
303 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
304 class MinorKeyBits: public BitField<uint32_t,
305 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT
307 friend class BreakPointIterator;
313 // TODO(svenpanne) This class is only used to construct a more or less sensible
314 // CompilationInfo for testing purposes, basically pretending that we are
315 // currently compiling some kind of code stub. Remove this when the pipeline and
316 // testing machinery is restructured in such a way that we don't have to come up
317 // with a CompilationInfo out of thin air, although we only need a few parts of
319 struct FakeStubForTesting : public CodeStub {
320 explicit FakeStubForTesting(Isolate* isolate) : CodeStub(isolate) {}
322 // Only used by pipeline.cc's GetDebugName in DEBUG mode.
323 Major MajorKey() const override { return CodeStub::NoCache; }
325 CallInterfaceDescriptor GetCallInterfaceDescriptor() override {
327 return CallInterfaceDescriptor();
330 Handle<Code> GenerateCode() override {
332 return Handle<Code>();
337 #define DEFINE_CODE_STUB_BASE(NAME, SUPER) \
339 NAME(uint32_t key, Isolate* isolate) : SUPER(key, isolate) {} \
342 DISALLOW_COPY_AND_ASSIGN(NAME)
345 #define DEFINE_CODE_STUB(NAME, SUPER) \
347 inline Major MajorKey() const override { return NAME; }; \
348 DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER)
351 #define DEFINE_PLATFORM_CODE_STUB(NAME, SUPER) \
353 void Generate(MacroAssembler* masm) override; \
354 DEFINE_CODE_STUB(NAME, SUPER)
357 #define DEFINE_HYDROGEN_CODE_STUB(NAME, SUPER) \
359 void InitializeDescriptor(CodeStubDescriptor* descriptor) override; \
360 Handle<Code> GenerateCode() override; \
361 DEFINE_CODE_STUB(NAME, SUPER)
363 #define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \
365 Handle<Code> GenerateCode() override; \
366 DEFINE_CODE_STUB(NAME, SUPER)
368 #define DEFINE_CALL_INTERFACE_DESCRIPTOR(NAME) \
370 CallInterfaceDescriptor GetCallInterfaceDescriptor() override { \
371 return NAME##Descriptor(isolate()); \
374 // There are some code stubs we just can't describe right now with a
375 // CallInterfaceDescriptor. Isolate behavior for those cases with this macro.
376 // An attempt to retrieve a descriptor will fail.
377 #define DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR() \
379 CallInterfaceDescriptor GetCallInterfaceDescriptor() override { \
381 return CallInterfaceDescriptor(); \
385 class PlatformCodeStub : public CodeStub {
387 // Retrieve the code for the stub. Generate the code if needed.
388 Handle<Code> GenerateCode() override;
391 explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {}
393 // Generates the assembler code for the stub.
394 virtual void Generate(MacroAssembler* masm) = 0;
396 DEFINE_CODE_STUB_BASE(PlatformCodeStub, CodeStub);
400 enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
401 enum HandlerArgumentsMode { DONT_PASS_ARGUMENTS, PASS_ARGUMENTS };
404 class CodeStubDescriptor {
406 explicit CodeStubDescriptor(CodeStub* stub);
408 CodeStubDescriptor(Isolate* isolate, uint32_t stub_key);
410 void Initialize(Address deoptimization_handler = NULL,
411 int hint_stack_parameter_count = -1,
412 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
413 void Initialize(Register stack_parameter_count,
414 Address deoptimization_handler = NULL,
415 int hint_stack_parameter_count = -1,
416 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE,
417 HandlerArgumentsMode handler_mode = DONT_PASS_ARGUMENTS);
419 void SetMissHandler(ExternalReference handler) {
420 miss_handler_ = handler;
421 has_miss_handler_ = true;
422 // Our miss handler infrastructure doesn't currently support
423 // variable stack parameter counts.
424 DCHECK(!stack_parameter_count_.is_valid());
427 void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; }
428 CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; }
430 int GetEnvironmentParameterCount() const {
431 return call_descriptor().GetEnvironmentParameterCount();
434 Representation GetEnvironmentParameterRepresentation(int index) const {
435 return call_descriptor().GetEnvironmentParameterRepresentation(index);
438 ExternalReference miss_handler() const {
439 DCHECK(has_miss_handler_);
440 return miss_handler_;
443 bool has_miss_handler() const {
444 return has_miss_handler_;
447 bool IsEnvironmentParameterCountRegister(int index) const {
448 return call_descriptor().GetEnvironmentParameterRegister(index).is(
449 stack_parameter_count_);
452 int GetHandlerParameterCount() const {
453 int params = call_descriptor().GetEnvironmentParameterCount();
454 if (handler_arguments_mode_ == PASS_ARGUMENTS) {
460 int hint_stack_parameter_count() const { return hint_stack_parameter_count_; }
461 Register stack_parameter_count() const { return stack_parameter_count_; }
462 StubFunctionMode function_mode() const { return function_mode_; }
463 Address deoptimization_handler() const { return deoptimization_handler_; }
466 CallInterfaceDescriptor call_descriptor_;
467 Register stack_parameter_count_;
468 // If hint_stack_parameter_count_ > 0, the code stub can optimize the
469 // return sequence. Default value is -1, which means it is ignored.
470 int hint_stack_parameter_count_;
471 StubFunctionMode function_mode_;
473 Address deoptimization_handler_;
474 HandlerArgumentsMode handler_arguments_mode_;
476 ExternalReference miss_handler_;
477 bool has_miss_handler_;
481 class HydrogenCodeStub : public CodeStub {
483 enum InitializationState {
488 template<class SubClass>
489 static Handle<Code> GetUninitialized(Isolate* isolate) {
490 SubClass::GenerateAheadOfTime(isolate);
491 return SubClass().GetCode(isolate);
494 // Retrieve the code for the stub. Generate the code if needed.
495 Handle<Code> GenerateCode() override = 0;
497 bool IsUninitialized() const { return IsMissBits::decode(minor_key_); }
499 Handle<Code> GenerateLightweightMissCode(ExternalReference miss);
501 template<class StateType>
502 void TraceTransition(StateType from, StateType to);
505 explicit HydrogenCodeStub(Isolate* isolate,
506 InitializationState state = INITIALIZED)
507 : CodeStub(isolate) {
508 minor_key_ = IsMissBits::encode(state == UNINITIALIZED);
511 void set_sub_minor_key(uint32_t key) {
512 minor_key_ = SubMinorKeyBits::update(minor_key_, key);
515 uint32_t sub_minor_key() const { return SubMinorKeyBits::decode(minor_key_); }
517 static const int kSubMinorKeyBits = kStubMinorKeyBits - 1;
520 class IsMissBits : public BitField<bool, kSubMinorKeyBits, 1> {};
521 class SubMinorKeyBits : public BitField<int, 0, kSubMinorKeyBits> {};
523 void GenerateLightweightMiss(MacroAssembler* masm, ExternalReference miss);
525 DEFINE_CODE_STUB_BASE(HydrogenCodeStub, CodeStub);
529 class TurboFanCodeStub : public CodeStub {
531 // Retrieve the code for the stub. Generate the code if needed.
532 Handle<Code> GenerateCode() override;
534 Code::StubType GetStubType() const override { return Code::FAST; }
537 explicit TurboFanCodeStub(Isolate* isolate) : CodeStub(isolate) {}
540 DEFINE_CODE_STUB_BASE(TurboFanCodeStub, CodeStub);
544 // Helper interface to prepare to/restore after making runtime calls.
545 class RuntimeCallHelper {
547 virtual ~RuntimeCallHelper() {}
549 virtual void BeforeCall(MacroAssembler* masm) const = 0;
551 virtual void AfterCall(MacroAssembler* masm) const = 0;
554 RuntimeCallHelper() {}
557 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
561 } } // namespace v8::internal
563 #if V8_TARGET_ARCH_IA32
564 #include "src/ia32/code-stubs-ia32.h"
565 #elif V8_TARGET_ARCH_X64
566 #include "src/x64/code-stubs-x64.h"
567 #elif V8_TARGET_ARCH_ARM64
568 #include "src/arm64/code-stubs-arm64.h"
569 #elif V8_TARGET_ARCH_ARM
570 #include "src/arm/code-stubs-arm.h"
571 #elif V8_TARGET_ARCH_PPC
572 #include "src/ppc/code-stubs-ppc.h"
573 #elif V8_TARGET_ARCH_MIPS
574 #include "src/mips/code-stubs-mips.h"
575 #elif V8_TARGET_ARCH_MIPS64
576 #include "src/mips64/code-stubs-mips64.h"
577 #elif V8_TARGET_ARCH_X87
578 #include "src/x87/code-stubs-x87.h"
580 #error Unsupported target architecture.
587 // RuntimeCallHelper implementation used in stubs: enters/leaves a
588 // newly created internal frame before/after the runtime call.
589 class StubRuntimeCallHelper : public RuntimeCallHelper {
591 StubRuntimeCallHelper() {}
593 virtual void BeforeCall(MacroAssembler* masm) const;
595 virtual void AfterCall(MacroAssembler* masm) const;
599 // Trivial RuntimeCallHelper implementation.
600 class NopRuntimeCallHelper : public RuntimeCallHelper {
602 NopRuntimeCallHelper() {}
604 virtual void BeforeCall(MacroAssembler* masm) const {}
606 virtual void AfterCall(MacroAssembler* masm) const {}
610 class MathFloorStub : public TurboFanCodeStub {
612 explicit MathFloorStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
613 int GetStackParameterCount() const override { return 1; }
615 DEFINE_CALL_INTERFACE_DESCRIPTOR(MathRoundVariant);
616 DEFINE_CODE_STUB(MathFloor, TurboFanCodeStub);
620 class StringLengthTFStub : public TurboFanCodeStub {
622 explicit StringLengthTFStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
624 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
625 InlineCacheState GetICState() const override { return MONOMORPHIC; }
626 ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
628 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
629 DEFINE_CODE_STUB(StringLengthTF, TurboFanCodeStub);
633 enum StringAddFlags {
634 // Omit both parameter checks.
635 STRING_ADD_CHECK_NONE = 0,
636 // Check left parameter.
637 STRING_ADD_CHECK_LEFT = 1 << 0,
638 // Check right parameter.
639 STRING_ADD_CHECK_RIGHT = 1 << 1,
640 // Check both parameters.
641 STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT
645 std::ostream& operator<<(std::ostream& os, const StringAddFlags& flags);
648 class StringAddTFStub : public TurboFanCodeStub {
650 StringAddTFStub(Isolate* isolate, StringAddFlags flags,
651 PretenureFlag pretenure_flag)
652 : TurboFanCodeStub(isolate) {
653 minor_key_ = StringAddFlagsBits::encode(flags) |
654 PretenureFlagBits::encode(pretenure_flag);
657 StringAddFlags flags() const {
658 return StringAddFlagsBits::decode(MinorKey());
661 PretenureFlag pretenure_flag() const {
662 return PretenureFlagBits::decode(MinorKey());
666 class StringAddFlagsBits : public BitField<StringAddFlags, 0, 2> {};
667 class PretenureFlagBits : public BitField<PretenureFlag, 2, 1> {};
669 void PrintBaseName(std::ostream& os) const override; // NOLINT
671 DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd);
672 DEFINE_CODE_STUB(StringAddTF, TurboFanCodeStub);
676 class NumberToStringStub final : public HydrogenCodeStub {
678 explicit NumberToStringStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
680 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
681 static const int kNumber = 0;
683 DEFINE_CALL_INTERFACE_DESCRIPTOR(NumberToString);
684 DEFINE_HYDROGEN_CODE_STUB(NumberToString, HydrogenCodeStub);
688 class TypeofStub final : public HydrogenCodeStub {
690 explicit TypeofStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
692 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
693 static const int kObject = 0;
695 static void GenerateAheadOfTime(Isolate* isolate);
697 DEFINE_CALL_INTERFACE_DESCRIPTOR(Typeof);
698 DEFINE_HYDROGEN_CODE_STUB(Typeof, HydrogenCodeStub);
702 class FastNewClosureStub : public HydrogenCodeStub {
704 FastNewClosureStub(Isolate* isolate, LanguageMode language_mode,
706 : HydrogenCodeStub(isolate) {
707 DCHECK(IsValidFunctionKind(kind));
708 set_sub_minor_key(LanguageModeBits::encode(language_mode) |
709 FunctionKindBits::encode(kind));
712 LanguageMode language_mode() const {
713 return LanguageModeBits::decode(sub_minor_key());
716 FunctionKind kind() const {
717 return FunctionKindBits::decode(sub_minor_key());
721 STATIC_ASSERT(LANGUAGE_END == 3);
722 class LanguageModeBits : public BitField<LanguageMode, 0, 2> {};
723 class FunctionKindBits : public BitField<FunctionKind, 2, 8> {};
725 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure);
726 DEFINE_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub);
730 class FastNewContextStub final : public HydrogenCodeStub {
732 static const int kMaximumSlots = 64;
734 FastNewContextStub(Isolate* isolate, int slots) : HydrogenCodeStub(isolate) {
735 DCHECK(slots >= 0 && slots <= kMaximumSlots);
736 set_sub_minor_key(SlotsBits::encode(slots));
739 int slots() const { return SlotsBits::decode(sub_minor_key()); }
741 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
742 static const int kFunction = 0;
745 class SlotsBits : public BitField<int, 0, 8> {};
747 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewContext);
748 DEFINE_HYDROGEN_CODE_STUB(FastNewContext, HydrogenCodeStub);
752 class FastCloneShallowArrayStub : public HydrogenCodeStub {
754 FastCloneShallowArrayStub(Isolate* isolate,
755 AllocationSiteMode allocation_site_mode)
756 : HydrogenCodeStub(isolate) {
757 set_sub_minor_key(AllocationSiteModeBits::encode(allocation_site_mode));
760 AllocationSiteMode allocation_site_mode() const {
761 return AllocationSiteModeBits::decode(sub_minor_key());
765 class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
767 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowArray);
768 DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowArray, HydrogenCodeStub);
772 class FastCloneShallowObjectStub : public HydrogenCodeStub {
774 // Maximum number of properties in copied object.
775 static const int kMaximumClonedProperties = 6;
777 FastCloneShallowObjectStub(Isolate* isolate, int length)
778 : HydrogenCodeStub(isolate) {
779 DCHECK_GE(length, 0);
780 DCHECK_LE(length, kMaximumClonedProperties);
781 set_sub_minor_key(LengthBits::encode(length));
784 int length() const { return LengthBits::decode(sub_minor_key()); }
787 class LengthBits : public BitField<int, 0, 4> {};
789 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowObject);
790 DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowObject, HydrogenCodeStub);
794 class CreateAllocationSiteStub : public HydrogenCodeStub {
796 explicit CreateAllocationSiteStub(Isolate* isolate)
797 : HydrogenCodeStub(isolate) { }
799 static void GenerateAheadOfTime(Isolate* isolate);
801 DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateAllocationSite);
802 DEFINE_HYDROGEN_CODE_STUB(CreateAllocationSite, HydrogenCodeStub);
806 class CreateWeakCellStub : public HydrogenCodeStub {
808 explicit CreateWeakCellStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
810 static void GenerateAheadOfTime(Isolate* isolate);
812 DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateWeakCell);
813 DEFINE_HYDROGEN_CODE_STUB(CreateWeakCell, HydrogenCodeStub);
817 class GrowArrayElementsStub : public HydrogenCodeStub {
819 GrowArrayElementsStub(Isolate* isolate, bool is_js_array, ElementsKind kind)
820 : HydrogenCodeStub(isolate) {
821 set_sub_minor_key(ElementsKindBits::encode(kind) |
822 IsJsArrayBits::encode(is_js_array));
825 ElementsKind elements_kind() const {
826 return ElementsKindBits::decode(sub_minor_key());
829 bool is_js_array() const { return IsJsArrayBits::decode(sub_minor_key()); }
832 class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
833 class IsJsArrayBits : public BitField<bool, ElementsKindBits::kNext, 1> {};
835 DEFINE_CALL_INTERFACE_DESCRIPTOR(GrowArrayElements);
836 DEFINE_HYDROGEN_CODE_STUB(GrowArrayElements, HydrogenCodeStub);
839 class InstanceofStub: public PlatformCodeStub {
843 kArgsInRegisters = 1 << 0,
844 kCallSiteInlineCheck = 1 << 1,
845 kReturnTrueFalseObject = 1 << 2
848 InstanceofStub(Isolate* isolate, Flags flags) : PlatformCodeStub(isolate) {
849 minor_key_ = FlagBits::encode(flags);
852 static Register left() { return InstanceofDescriptor::left(); }
853 static Register right() { return InstanceofDescriptor::right(); }
855 CallInterfaceDescriptor GetCallInterfaceDescriptor() override {
856 if (HasArgsInRegisters()) {
857 return InstanceofDescriptor(isolate());
859 return ContextOnlyDescriptor(isolate());
863 Flags flags() const { return FlagBits::decode(minor_key_); }
865 bool HasArgsInRegisters() const { return (flags() & kArgsInRegisters) != 0; }
867 bool HasCallSiteInlineCheck() const {
868 return (flags() & kCallSiteInlineCheck) != 0;
871 bool ReturnTrueFalseObject() const {
872 return (flags() & kReturnTrueFalseObject) != 0;
875 void PrintName(std::ostream& os) const override; // NOLINT
877 class FlagBits : public BitField<Flags, 0, 3> {};
879 DEFINE_PLATFORM_CODE_STUB(Instanceof, PlatformCodeStub);
883 enum AllocationSiteOverrideMode {
885 DISABLE_ALLOCATION_SITES,
886 LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
890 class ArrayConstructorStub: public PlatformCodeStub {
892 enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
894 ArrayConstructorStub(Isolate* isolate, int argument_count);
896 explicit ArrayConstructorStub(Isolate* isolate);
899 ArgumentCountKey argument_count() const {
900 return ArgumentCountBits::decode(minor_key_);
903 void GenerateDispatchToArrayStub(MacroAssembler* masm,
904 AllocationSiteOverrideMode mode);
906 void PrintName(std::ostream& os) const override; // NOLINT
908 class ArgumentCountBits : public BitField<ArgumentCountKey, 0, 2> {};
910 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
911 DEFINE_PLATFORM_CODE_STUB(ArrayConstructor, PlatformCodeStub);
915 class InternalArrayConstructorStub: public PlatformCodeStub {
917 explicit InternalArrayConstructorStub(Isolate* isolate);
920 void GenerateCase(MacroAssembler* masm, ElementsKind kind);
922 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
923 DEFINE_PLATFORM_CODE_STUB(InternalArrayConstructor, PlatformCodeStub);
927 class MathPowStub: public PlatformCodeStub {
929 enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK };
931 MathPowStub(Isolate* isolate, ExponentType exponent_type)
932 : PlatformCodeStub(isolate) {
933 minor_key_ = ExponentTypeBits::encode(exponent_type);
936 CallInterfaceDescriptor GetCallInterfaceDescriptor() override {
937 if (exponent_type() == TAGGED) {
938 return MathPowTaggedDescriptor(isolate());
939 } else if (exponent_type() == INTEGER) {
940 return MathPowIntegerDescriptor(isolate());
942 // A CallInterfaceDescriptor doesn't specify double registers (yet).
943 return ContextOnlyDescriptor(isolate());
947 ExponentType exponent_type() const {
948 return ExponentTypeBits::decode(minor_key_);
951 class ExponentTypeBits : public BitField<ExponentType, 0, 2> {};
953 DEFINE_PLATFORM_CODE_STUB(MathPow, PlatformCodeStub);
957 class CallICStub: public PlatformCodeStub {
959 CallICStub(Isolate* isolate, const CallICState& state)
960 : PlatformCodeStub(isolate) {
961 minor_key_ = state.GetExtraICState();
964 static int ExtractArgcFromMinorKey(int minor_key) {
965 CallICState state(static_cast<ExtraICState>(minor_key));
966 return state.arg_count();
969 Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
971 InlineCacheState GetICState() const override { return DEFAULT; }
973 ExtraICState GetExtraICState() const final {
974 return static_cast<ExtraICState>(minor_key_);
978 bool CallAsMethod() const {
979 return state().call_type() == CallICState::METHOD;
982 int arg_count() const { return state().arg_count(); }
984 CallICState state() const {
985 return CallICState(static_cast<ExtraICState>(minor_key_));
988 // Code generation helpers.
989 void GenerateMiss(MacroAssembler* masm);
992 void PrintState(std::ostream& os) const override; // NOLINT
994 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedbackAndVector);
995 DEFINE_PLATFORM_CODE_STUB(CallIC, PlatformCodeStub);
999 class CallIC_ArrayStub: public CallICStub {
1001 CallIC_ArrayStub(Isolate* isolate, const CallICState& state_in)
1002 : CallICStub(isolate, state_in) {}
1004 InlineCacheState GetICState() const final { return MONOMORPHIC; }
1007 void PrintState(std::ostream& os) const override; // NOLINT
1009 DEFINE_PLATFORM_CODE_STUB(CallIC_Array, CallICStub);
1013 // TODO(verwaest): Translate to hydrogen code stub.
1014 class FunctionPrototypeStub : public PlatformCodeStub {
1016 explicit FunctionPrototypeStub(Isolate* isolate)
1017 : PlatformCodeStub(isolate) {}
1019 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
1021 // TODO(mvstanton): only the receiver register is accessed. When this is
1022 // translated to a hydrogen code stub, a new CallInterfaceDescriptor
1023 // should be created that just uses that register for more efficient code.
1024 CallInterfaceDescriptor GetCallInterfaceDescriptor() override {
1025 return LoadWithVectorDescriptor(isolate());
1028 DEFINE_PLATFORM_CODE_STUB(FunctionPrototype, PlatformCodeStub);
1032 // TODO(mvstanton): Translate to hydrogen code stub.
1033 class LoadIndexedInterceptorStub : public PlatformCodeStub {
1035 explicit LoadIndexedInterceptorStub(Isolate* isolate)
1036 : PlatformCodeStub(isolate) {}
1038 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
1039 Code::StubType GetStubType() const override { return Code::FAST; }
1041 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1042 DEFINE_PLATFORM_CODE_STUB(LoadIndexedInterceptor, PlatformCodeStub);
1046 class LoadIndexedStringStub : public PlatformCodeStub {
1048 explicit LoadIndexedStringStub(Isolate* isolate)
1049 : PlatformCodeStub(isolate) {}
1051 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
1052 Code::StubType GetStubType() const override { return Code::FAST; }
1054 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1055 DEFINE_PLATFORM_CODE_STUB(LoadIndexedString, PlatformCodeStub);
1059 class HandlerStub : public HydrogenCodeStub {
1061 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
1062 ExtraICState GetExtraICState() const override { return kind(); }
1063 InlineCacheState GetICState() const override { return MONOMORPHIC; }
1065 void InitializeDescriptor(CodeStubDescriptor* descriptor) override;
1067 CallInterfaceDescriptor GetCallInterfaceDescriptor() override;
1070 explicit HandlerStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
1072 virtual Code::Kind kind() const = 0;
1074 DEFINE_CODE_STUB_BASE(HandlerStub, HydrogenCodeStub);
1078 class LoadFieldStub: public HandlerStub {
1080 LoadFieldStub(Isolate* isolate, FieldIndex index) : HandlerStub(isolate) {
1081 int property_index_key = index.GetFieldAccessStubKey();
1082 set_sub_minor_key(LoadFieldByIndexBits::encode(property_index_key));
1085 FieldIndex index() const {
1086 int property_index_key = LoadFieldByIndexBits::decode(sub_minor_key());
1087 return FieldIndex::FromFieldAccessStubKey(property_index_key);
1091 Code::Kind kind() const override { return Code::LOAD_IC; }
1092 Code::StubType GetStubType() const override { return Code::FAST; }
1095 class LoadFieldByIndexBits : public BitField<int, 0, 13> {};
1097 DEFINE_HANDLER_CODE_STUB(LoadField, HandlerStub);
1101 class ArrayBufferViewLoadFieldStub : public HandlerStub {
1103 ArrayBufferViewLoadFieldStub(Isolate* isolate, FieldIndex index)
1104 : HandlerStub(isolate) {
1105 int property_index_key = index.GetFieldAccessStubKey();
1107 ArrayBufferViewLoadFieldByIndexBits::encode(property_index_key));
1110 FieldIndex index() const {
1111 int property_index_key =
1112 ArrayBufferViewLoadFieldByIndexBits::decode(sub_minor_key());
1113 return FieldIndex::FromFieldAccessStubKey(property_index_key);
1117 Code::Kind kind() const override { return Code::LOAD_IC; }
1118 Code::StubType GetStubType() const override { return Code::FAST; }
1121 class ArrayBufferViewLoadFieldByIndexBits : public BitField<int, 0, 13> {};
1123 DEFINE_HANDLER_CODE_STUB(ArrayBufferViewLoadField, HandlerStub);
1127 class KeyedLoadSloppyArgumentsStub : public HandlerStub {
1129 explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate)
1130 : HandlerStub(isolate) {}
1133 Code::Kind kind() const override { return Code::KEYED_LOAD_IC; }
1134 Code::StubType GetStubType() const override { return Code::FAST; }
1137 DEFINE_HANDLER_CODE_STUB(KeyedLoadSloppyArguments, HandlerStub);
1141 class KeyedStoreSloppyArgumentsStub : public HandlerStub {
1143 explicit KeyedStoreSloppyArgumentsStub(Isolate* isolate)
1144 : HandlerStub(isolate) {}
1147 Code::Kind kind() const override { return Code::KEYED_STORE_IC; }
1148 Code::StubType GetStubType() const override { return Code::FAST; }
1151 DEFINE_HANDLER_CODE_STUB(KeyedStoreSloppyArguments, HandlerStub);
1155 class LoadConstantStub : public HandlerStub {
1157 LoadConstantStub(Isolate* isolate, int constant_index)
1158 : HandlerStub(isolate) {
1159 set_sub_minor_key(ConstantIndexBits::encode(constant_index));
1162 int constant_index() const {
1163 return ConstantIndexBits::decode(sub_minor_key());
1167 Code::Kind kind() const override { return Code::LOAD_IC; }
1168 Code::StubType GetStubType() const override { return Code::FAST; }
1171 class ConstantIndexBits : public BitField<int, 0, kSubMinorKeyBits> {};
1173 DEFINE_HANDLER_CODE_STUB(LoadConstant, HandlerStub);
1177 class StringLengthStub: public HandlerStub {
1179 explicit StringLengthStub(Isolate* isolate) : HandlerStub(isolate) {}
1182 Code::Kind kind() const override { return Code::LOAD_IC; }
1183 Code::StubType GetStubType() const override { return Code::FAST; }
1185 DEFINE_HANDLER_CODE_STUB(StringLength, HandlerStub);
1189 class StoreFieldStub : public HandlerStub {
1191 StoreFieldStub(Isolate* isolate, FieldIndex index,
1192 Representation representation)
1193 : HandlerStub(isolate) {
1194 int property_index_key = index.GetFieldAccessStubKey();
1195 uint8_t repr = PropertyDetails::EncodeRepresentation(representation);
1196 set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) |
1197 RepresentationBits::encode(repr));
1200 FieldIndex index() const {
1201 int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key());
1202 return FieldIndex::FromFieldAccessStubKey(property_index_key);
1205 Representation representation() {
1206 uint8_t repr = RepresentationBits::decode(sub_minor_key());
1207 return PropertyDetails::DecodeRepresentation(repr);
1211 Code::Kind kind() const override { return Code::STORE_IC; }
1212 Code::StubType GetStubType() const override { return Code::FAST; }
1215 class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
1216 class RepresentationBits : public BitField<uint8_t, 13, 4> {};
1218 DEFINE_HANDLER_CODE_STUB(StoreField, HandlerStub);
1222 class StoreTransitionStub : public HandlerStub {
1227 ExtendStorageAndStoreMapAndValue
1230 explicit StoreTransitionStub(Isolate* isolate) : HandlerStub(isolate) {
1231 set_sub_minor_key(StoreModeBits::encode(StoreMapOnly));
1234 StoreTransitionStub(Isolate* isolate, FieldIndex index,
1235 Representation representation, StoreMode store_mode)
1236 : HandlerStub(isolate) {
1237 DCHECK(store_mode != StoreMapOnly);
1238 int property_index_key = index.GetFieldAccessStubKey();
1239 uint8_t repr = PropertyDetails::EncodeRepresentation(representation);
1240 set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) |
1241 RepresentationBits::encode(repr) |
1242 StoreModeBits::encode(store_mode));
1245 FieldIndex index() const {
1246 DCHECK(store_mode() != StoreMapOnly);
1247 int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key());
1248 return FieldIndex::FromFieldAccessStubKey(property_index_key);
1251 Representation representation() {
1252 DCHECK(store_mode() != StoreMapOnly);
1253 uint8_t repr = RepresentationBits::decode(sub_minor_key());
1254 return PropertyDetails::DecodeRepresentation(repr);
1257 StoreMode store_mode() const {
1258 return StoreModeBits::decode(sub_minor_key());
1261 CallInterfaceDescriptor GetCallInterfaceDescriptor() override;
1264 Code::Kind kind() const override { return Code::STORE_IC; }
1265 Code::StubType GetStubType() const override { return Code::FAST; }
1268 class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
1269 class RepresentationBits : public BitField<uint8_t, 13, 4> {};
1270 class StoreModeBits : public BitField<StoreMode, 17, 2> {};
1272 DEFINE_HANDLER_CODE_STUB(StoreTransition, HandlerStub);
1276 class StoreGlobalStub : public HandlerStub {
1278 StoreGlobalStub(Isolate* isolate, PropertyCellType type,
1279 Maybe<PropertyCellConstantType> constant_type,
1281 : HandlerStub(isolate) {
1282 PropertyCellConstantType encoded_constant_type =
1283 constant_type.FromMaybe(PropertyCellConstantType::kSmi);
1284 set_sub_minor_key(CellTypeBits::encode(type) |
1285 ConstantTypeBits::encode(encoded_constant_type) |
1286 CheckGlobalBits::encode(check_global));
1289 static Handle<HeapObject> property_cell_placeholder(Isolate* isolate) {
1290 return isolate->factory()->uninitialized_value();
1293 static Handle<HeapObject> global_map_placeholder(Isolate* isolate) {
1294 return isolate->factory()->termination_exception();
1297 Handle<Code> GetCodeCopyFromTemplate(Handle<GlobalObject> global,
1298 Handle<PropertyCell> cell) {
1299 Code::FindAndReplacePattern pattern;
1300 if (check_global()) {
1301 pattern.Add(handle(global_map_placeholder(isolate())->map()),
1302 Map::WeakCellForMap(Handle<Map>(global->map())));
1304 pattern.Add(handle(property_cell_placeholder(isolate())->map()),
1305 isolate()->factory()->NewWeakCell(cell));
1306 return CodeStub::GetCodeCopy(pattern);
1309 Code::Kind kind() const override { return Code::STORE_IC; }
1311 PropertyCellType cell_type() const {
1312 return CellTypeBits::decode(sub_minor_key());
1315 PropertyCellConstantType constant_type() const {
1316 DCHECK(PropertyCellType::kConstantType == cell_type());
1317 return ConstantTypeBits::decode(sub_minor_key());
1320 bool check_global() const { return CheckGlobalBits::decode(sub_minor_key()); }
1322 Representation representation() {
1323 return Representation::FromKind(
1324 RepresentationBits::decode(sub_minor_key()));
1327 void set_representation(Representation r) {
1328 set_sub_minor_key(RepresentationBits::update(sub_minor_key(), r.kind()));
1332 class CellTypeBits : public BitField<PropertyCellType, 0, 2> {};
1333 class ConstantTypeBits : public BitField<PropertyCellConstantType, 2, 2> {};
1334 class RepresentationBits : public BitField<Representation::Kind, 4, 8> {};
1335 class CheckGlobalBits : public BitField<bool, 12, 1> {};
1337 DEFINE_HANDLER_CODE_STUB(StoreGlobal, HandlerStub);
1341 class CallApiFunctionStub : public PlatformCodeStub {
1343 explicit CallApiFunctionStub(Isolate* isolate, bool call_data_undefined)
1344 : PlatformCodeStub(isolate) {
1345 minor_key_ = CallDataUndefinedBits::encode(call_data_undefined);
1349 bool call_data_undefined() const {
1350 return CallDataUndefinedBits::decode(minor_key_);
1353 class CallDataUndefinedBits : public BitField<bool, 0, 1> {};
1355 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiFunction);
1356 DEFINE_PLATFORM_CODE_STUB(CallApiFunction, PlatformCodeStub);
1360 class CallApiAccessorStub : public PlatformCodeStub {
1362 CallApiAccessorStub(Isolate* isolate, bool is_store, bool call_data_undefined)
1363 : PlatformCodeStub(isolate) {
1364 minor_key_ = IsStoreBits::encode(is_store) |
1365 CallDataUndefinedBits::encode(call_data_undefined) |
1366 ArgumentBits::encode(is_store ? 1 : 0);
1370 // For CallApiFunctionWithFixedArgsStub, see below.
1371 static const int kArgBits = 3;
1372 CallApiAccessorStub(Isolate* isolate, int argc, bool call_data_undefined)
1373 : PlatformCodeStub(isolate) {
1374 minor_key_ = IsStoreBits::encode(false) |
1375 CallDataUndefinedBits::encode(call_data_undefined) |
1376 ArgumentBits::encode(argc);
1380 bool is_store() const { return IsStoreBits::decode(minor_key_); }
1381 bool call_data_undefined() const {
1382 return CallDataUndefinedBits::decode(minor_key_);
1384 int argc() const { return ArgumentBits::decode(minor_key_); }
1386 class IsStoreBits: public BitField<bool, 0, 1> {};
1387 class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
1388 class ArgumentBits : public BitField<int, 2, kArgBits> {};
1390 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiAccessor);
1391 DEFINE_PLATFORM_CODE_STUB(CallApiAccessor, PlatformCodeStub);
1395 // TODO(dcarney): see if it's possible to remove this later without performance
1397 // This is not a real stub, but a way of generating the CallApiAccessorStub
1398 // (which has the same abi) which makes it clear that it is not an accessor.
1399 class CallApiFunctionWithFixedArgsStub : public CallApiAccessorStub {
1401 static const int kMaxFixedArgs = (1 << kArgBits) - 1;
1402 CallApiFunctionWithFixedArgsStub(Isolate* isolate, int argc,
1403 bool call_data_undefined)
1404 : CallApiAccessorStub(isolate, argc, call_data_undefined) {
1405 DCHECK(0 <= argc && argc <= kMaxFixedArgs);
1410 typedef ApiAccessorDescriptor ApiFunctionWithFixedArgsDescriptor;
1413 class CallApiGetterStub : public PlatformCodeStub {
1415 explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1417 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiGetter);
1418 DEFINE_PLATFORM_CODE_STUB(CallApiGetter, PlatformCodeStub);
1422 class BinaryOpICStub : public HydrogenCodeStub {
1424 BinaryOpICStub(Isolate* isolate, Token::Value op, LanguageMode language_mode)
1425 : HydrogenCodeStub(isolate, UNINITIALIZED) {
1426 BinaryOpICState state(isolate, op, language_mode);
1427 set_sub_minor_key(state.GetExtraICState());
1430 BinaryOpICStub(Isolate* isolate, const BinaryOpICState& state)
1431 : HydrogenCodeStub(isolate) {
1432 set_sub_minor_key(state.GetExtraICState());
1435 static void GenerateAheadOfTime(Isolate* isolate);
1437 Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
1439 InlineCacheState GetICState() const final { return state().GetICState(); }
1441 ExtraICState GetExtraICState() const final {
1442 return static_cast<ExtraICState>(sub_minor_key());
1445 BinaryOpICState state() const {
1446 return BinaryOpICState(isolate(), GetExtraICState());
1449 void PrintState(std::ostream& os) const final; // NOLINT
1451 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1452 static const int kLeft = 0;
1453 static const int kRight = 1;
1456 static void GenerateAheadOfTime(Isolate* isolate,
1457 const BinaryOpICState& state);
1459 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1460 DEFINE_HYDROGEN_CODE_STUB(BinaryOpIC, HydrogenCodeStub);
1464 // TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
1465 // call support for stubs in Hydrogen.
1466 class BinaryOpICWithAllocationSiteStub final : public PlatformCodeStub {
1468 BinaryOpICWithAllocationSiteStub(Isolate* isolate,
1469 const BinaryOpICState& state)
1470 : PlatformCodeStub(isolate) {
1471 minor_key_ = state.GetExtraICState();
1474 static void GenerateAheadOfTime(Isolate* isolate);
1476 Handle<Code> GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site) {
1477 Code::FindAndReplacePattern pattern;
1478 pattern.Add(isolate()->factory()->undefined_map(), allocation_site);
1479 return CodeStub::GetCodeCopy(pattern);
1482 Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
1484 InlineCacheState GetICState() const override { return state().GetICState(); }
1486 ExtraICState GetExtraICState() const override {
1487 return static_cast<ExtraICState>(minor_key_);
1490 void PrintState(std::ostream& os) const override; // NOLINT
1493 BinaryOpICState state() const {
1494 return BinaryOpICState(isolate(), static_cast<ExtraICState>(minor_key_));
1497 static void GenerateAheadOfTime(Isolate* isolate,
1498 const BinaryOpICState& state);
1500 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1501 DEFINE_PLATFORM_CODE_STUB(BinaryOpICWithAllocationSite, PlatformCodeStub);
1505 class BinaryOpWithAllocationSiteStub final : public BinaryOpICStub {
1507 BinaryOpWithAllocationSiteStub(Isolate* isolate, Token::Value op,
1508 LanguageMode language_mode)
1509 : BinaryOpICStub(isolate, op, language_mode) {}
1511 BinaryOpWithAllocationSiteStub(Isolate* isolate, const BinaryOpICState& state)
1512 : BinaryOpICStub(isolate, state) {}
1514 Code::Kind GetCodeKind() const final { return Code::STUB; }
1516 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1517 static const int kAllocationSite = 0;
1518 static const int kLeft = 1;
1519 static const int kRight = 2;
1521 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1522 DEFINE_HYDROGEN_CODE_STUB(BinaryOpWithAllocationSite, BinaryOpICStub);
1526 class StringAddStub final : public HydrogenCodeStub {
1528 StringAddStub(Isolate* isolate, StringAddFlags flags,
1529 PretenureFlag pretenure_flag)
1530 : HydrogenCodeStub(isolate) {
1531 set_sub_minor_key(StringAddFlagsBits::encode(flags) |
1532 PretenureFlagBits::encode(pretenure_flag));
1535 StringAddFlags flags() const {
1536 return StringAddFlagsBits::decode(sub_minor_key());
1539 PretenureFlag pretenure_flag() const {
1540 return PretenureFlagBits::decode(sub_minor_key());
1543 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1544 static const int kLeft = 0;
1545 static const int kRight = 1;
1548 class StringAddFlagsBits: public BitField<StringAddFlags, 0, 2> {};
1549 class PretenureFlagBits: public BitField<PretenureFlag, 2, 1> {};
1551 void PrintBaseName(std::ostream& os) const override; // NOLINT
1553 DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd);
1554 DEFINE_HYDROGEN_CODE_STUB(StringAdd, HydrogenCodeStub);
1558 class CompareICStub : public PlatformCodeStub {
1560 CompareICStub(Isolate* isolate, Token::Value op, bool strong,
1561 CompareICState::State left, CompareICState::State right,
1562 CompareICState::State state)
1563 : PlatformCodeStub(isolate) {
1564 DCHECK(Token::IsCompareOp(op));
1565 minor_key_ = OpBits::encode(op - Token::EQ) | StrongBits::encode(strong) |
1566 LeftStateBits::encode(left) | RightStateBits::encode(right) |
1567 StateBits::encode(state);
1570 void set_known_map(Handle<Map> map) { known_map_ = map; }
1572 InlineCacheState GetICState() const override;
1574 Token::Value op() const {
1575 return static_cast<Token::Value>(Token::EQ + OpBits::decode(minor_key_));
1578 bool strong() const { return StrongBits::decode(minor_key_); }
1580 CompareICState::State left() const {
1581 return LeftStateBits::decode(minor_key_);
1583 CompareICState::State right() const {
1584 return RightStateBits::decode(minor_key_);
1586 CompareICState::State state() const { return StateBits::decode(minor_key_); }
1589 Code::Kind GetCodeKind() const override { return Code::COMPARE_IC; }
1591 void GenerateSmis(MacroAssembler* masm);
1592 void GenerateNumbers(MacroAssembler* masm);
1593 void GenerateInternalizedStrings(MacroAssembler* masm);
1594 void GenerateStrings(MacroAssembler* masm);
1595 void GenerateUniqueNames(MacroAssembler* masm);
1596 void GenerateObjects(MacroAssembler* masm);
1597 void GenerateMiss(MacroAssembler* masm);
1598 void GenerateKnownObjects(MacroAssembler* masm);
1599 void GenerateGeneric(MacroAssembler* masm);
1601 bool strict() const { return op() == Token::EQ_STRICT; }
1602 Condition GetCondition() const;
1604 void AddToSpecialCache(Handle<Code> new_object) override;
1605 bool FindCodeInSpecialCache(Code** code_out) override;
1606 bool UseSpecialCache() override {
1607 return state() == CompareICState::KNOWN_OBJECT;
1610 class OpBits : public BitField<int, 0, 3> {};
1611 class StrongBits : public BitField<bool, 3, 1> {};
1612 class LeftStateBits : public BitField<CompareICState::State, 4, 4> {};
1613 class RightStateBits : public BitField<CompareICState::State, 8, 4> {};
1614 class StateBits : public BitField<CompareICState::State, 12, 4> {};
1616 Handle<Map> known_map_;
1618 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1619 DEFINE_PLATFORM_CODE_STUB(CompareIC, PlatformCodeStub);
1623 class CompareNilICStub : public HydrogenCodeStub {
1625 Type* GetType(Zone* zone, Handle<Map> map = Handle<Map>());
1626 Type* GetInputType(Zone* zone, Handle<Map> map);
1628 CompareNilICStub(Isolate* isolate, NilValue nil) : HydrogenCodeStub(isolate) {
1629 set_sub_minor_key(NilValueBits::encode(nil));
1632 CompareNilICStub(Isolate* isolate, ExtraICState ic_state,
1633 InitializationState init_state = INITIALIZED)
1634 : HydrogenCodeStub(isolate, init_state) {
1635 set_sub_minor_key(ic_state);
1638 static Handle<Code> GetUninitialized(Isolate* isolate,
1640 return CompareNilICStub(isolate, nil, UNINITIALIZED).GetCode();
1643 InlineCacheState GetICState() const override {
1644 State state = this->state();
1645 if (state.Contains(GENERIC)) {
1647 } else if (state.Contains(MONOMORPHIC_MAP)) {
1650 return PREMONOMORPHIC;
1654 Code::Kind GetCodeKind() const override { return Code::COMPARE_NIL_IC; }
1656 ExtraICState GetExtraICState() const override { return sub_minor_key(); }
1658 void UpdateStatus(Handle<Object> object);
1660 bool IsMonomorphic() const { return state().Contains(MONOMORPHIC_MAP); }
1662 NilValue nil_value() const { return NilValueBits::decode(sub_minor_key()); }
1665 set_sub_minor_key(TypesBits::update(sub_minor_key(), 0));
1668 void PrintState(std::ostream& os) const override; // NOLINT
1669 void PrintBaseName(std::ostream& os) const override; // NOLINT
1672 CompareNilICStub(Isolate* isolate, NilValue nil,
1673 InitializationState init_state)
1674 : HydrogenCodeStub(isolate, init_state) {
1675 set_sub_minor_key(NilValueBits::encode(nil));
1678 enum CompareNilType {
1686 // At most 6 different types can be distinguished, because the Code object
1687 // only has room for a single byte to hold a set and there are two more
1688 // boolean flags we need to store. :-P
1689 STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
1691 class State : public EnumSet<CompareNilType, byte> {
1693 State() : EnumSet<CompareNilType, byte>(0) { }
1694 explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
1696 friend std::ostream& operator<<(std::ostream& os, const State& s);
1698 State state() const { return State(TypesBits::decode(sub_minor_key())); }
1700 class NilValueBits : public BitField<NilValue, 0, 1> {};
1701 class TypesBits : public BitField<byte, 1, NUMBER_OF_TYPES> {};
1703 friend class CompareNilIC;
1705 DEFINE_CALL_INTERFACE_DESCRIPTOR(CompareNil);
1706 DEFINE_HYDROGEN_CODE_STUB(CompareNilIC, HydrogenCodeStub);
1710 std::ostream& operator<<(std::ostream& os, const CompareNilICStub::State& s);
1713 class CEntryStub : public PlatformCodeStub {
1715 CEntryStub(Isolate* isolate, int result_size,
1716 SaveFPRegsMode save_doubles = kDontSaveFPRegs)
1717 : PlatformCodeStub(isolate) {
1718 minor_key_ = SaveDoublesBits::encode(save_doubles == kSaveFPRegs);
1719 DCHECK(result_size == 1 || result_size == 2);
1720 #if _WIN64 || V8_TARGET_ARCH_PPC
1721 minor_key_ = ResultSizeBits::update(minor_key_, result_size);
1725 // The version of this stub that doesn't save doubles is generated ahead of
1726 // time, so it's OK to call it from other stubs that can't cope with GC during
1727 // their code generation. On machines that always have gp registers (x64) we
1728 // can generate both variants ahead of time.
1729 static void GenerateAheadOfTime(Isolate* isolate);
1732 bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
1733 #if _WIN64 || V8_TARGET_ARCH_PPC
1734 int result_size() const { return ResultSizeBits::decode(minor_key_); }
1737 bool NeedsImmovableCode() override;
1739 class SaveDoublesBits : public BitField<bool, 0, 1> {};
1740 class ResultSizeBits : public BitField<int, 1, 3> {};
1742 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1743 DEFINE_PLATFORM_CODE_STUB(CEntry, PlatformCodeStub);
1747 class JSEntryStub : public PlatformCodeStub {
1749 JSEntryStub(Isolate* isolate, StackFrame::Type type)
1750 : PlatformCodeStub(isolate) {
1751 DCHECK(type == StackFrame::ENTRY || type == StackFrame::ENTRY_CONSTRUCT);
1752 minor_key_ = StackFrameTypeBits::encode(type);
1756 void FinishCode(Handle<Code> code) override;
1758 void PrintName(std::ostream& os) const override { // NOLINT
1759 os << (type() == StackFrame::ENTRY ? "JSEntryStub"
1760 : "JSConstructEntryStub");
1763 StackFrame::Type type() const {
1764 return StackFrameTypeBits::decode(minor_key_);
1767 class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {};
1769 int handler_offset_;
1771 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1772 DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub);
1776 class ArgumentsAccessStub: public PlatformCodeStub {
1785 enum HasNewTarget { NO_NEW_TARGET, HAS_NEW_TARGET };
1787 ArgumentsAccessStub(Isolate* isolate, Type type,
1788 HasNewTarget has_new_target = NO_NEW_TARGET)
1789 : PlatformCodeStub(isolate) {
1791 TypeBits::encode(type) | HasNewTargetBits::encode(has_new_target);
1794 CallInterfaceDescriptor GetCallInterfaceDescriptor() override {
1795 if (type() == READ_ELEMENT) {
1796 return ArgumentsAccessReadDescriptor(isolate());
1798 return ContextOnlyDescriptor(isolate());
1802 Type type() const { return TypeBits::decode(minor_key_); }
1803 bool has_new_target() const {
1804 return HasNewTargetBits::decode(minor_key_) == HAS_NEW_TARGET;
1807 void GenerateReadElement(MacroAssembler* masm);
1808 void GenerateNewStrict(MacroAssembler* masm);
1809 void GenerateNewSloppyFast(MacroAssembler* masm);
1810 void GenerateNewSloppySlow(MacroAssembler* masm);
1812 void PrintName(std::ostream& os) const override; // NOLINT
1814 class TypeBits : public BitField<Type, 0, 2> {};
1815 class HasNewTargetBits : public BitField<HasNewTarget, 2, 1> {};
1817 DEFINE_PLATFORM_CODE_STUB(ArgumentsAccess, PlatformCodeStub);
1821 class RestParamAccessStub: public PlatformCodeStub {
1823 explicit RestParamAccessStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
1825 CallInterfaceDescriptor GetCallInterfaceDescriptor() override {
1826 return ContextOnlyDescriptor(isolate());
1830 void GenerateNew(MacroAssembler* masm);
1832 void PrintName(std::ostream& os) const override; // NOLINT
1834 DEFINE_PLATFORM_CODE_STUB(RestParamAccess, PlatformCodeStub);
1838 class RegExpExecStub: public PlatformCodeStub {
1840 explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
1842 DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
1843 DEFINE_PLATFORM_CODE_STUB(RegExpExec, PlatformCodeStub);
1847 class RegExpConstructResultStub final : public HydrogenCodeStub {
1849 explicit RegExpConstructResultStub(Isolate* isolate)
1850 : HydrogenCodeStub(isolate) { }
1852 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1853 static const int kLength = 0;
1854 static const int kIndex = 1;
1855 static const int kInput = 2;
1857 DEFINE_CALL_INTERFACE_DESCRIPTOR(RegExpConstructResult);
1858 DEFINE_HYDROGEN_CODE_STUB(RegExpConstructResult, HydrogenCodeStub);
1862 class CallFunctionStub: public PlatformCodeStub {
1864 CallFunctionStub(Isolate* isolate, int argc, CallFunctionFlags flags)
1865 : PlatformCodeStub(isolate) {
1866 DCHECK(argc >= 0 && argc <= Code::kMaxArguments);
1867 minor_key_ = ArgcBits::encode(argc) | FlagBits::encode(flags);
1870 static int ExtractArgcFromMinorKey(int minor_key) {
1871 return ArgcBits::decode(minor_key);
1875 int argc() const { return ArgcBits::decode(minor_key_); }
1876 int flags() const { return FlagBits::decode(minor_key_); }
1878 bool CallAsMethod() const {
1879 return flags() == CALL_AS_METHOD || flags() == WRAP_AND_CALL;
1882 bool NeedsChecks() const { return flags() != WRAP_AND_CALL; }
1884 void PrintName(std::ostream& os) const override; // NOLINT
1886 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
1887 class FlagBits : public BitField<CallFunctionFlags, 0, 2> {};
1888 class ArgcBits : public BitField<unsigned, 2, Code::kArgumentsBits> {};
1889 STATIC_ASSERT(Code::kArgumentsBits + 2 <= kStubMinorKeyBits);
1891 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction);
1892 DEFINE_PLATFORM_CODE_STUB(CallFunction, PlatformCodeStub);
1896 class CallConstructStub: public PlatformCodeStub {
1898 CallConstructStub(Isolate* isolate, CallConstructorFlags flags)
1899 : PlatformCodeStub(isolate) {
1900 minor_key_ = FlagBits::encode(flags);
1903 void FinishCode(Handle<Code> code) override {
1904 code->set_has_function_cache(RecordCallTarget());
1908 CallConstructorFlags flags() const { return FlagBits::decode(minor_key_); }
1910 bool RecordCallTarget() const {
1911 return (flags() & RECORD_CONSTRUCTOR_TARGET) != 0;
1914 bool IsSuperConstructorCall() const {
1915 return (flags() & SUPER_CONSTRUCTOR_CALL) != 0;
1918 void PrintName(std::ostream& os) const override; // NOLINT
1920 class FlagBits : public BitField<CallConstructorFlags, 0, 2> {};
1922 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallConstruct);
1923 DEFINE_PLATFORM_CODE_STUB(CallConstruct, PlatformCodeStub);
1927 enum StringIndexFlags {
1928 // Accepts smis or heap numbers.
1929 STRING_INDEX_IS_NUMBER,
1931 // Accepts smis or heap numbers that are valid array indices
1932 // (ECMA-262 15.4). Invalid indices are reported as being out of
1934 STRING_INDEX_IS_ARRAY_INDEX
1938 enum ReceiverCheckMode {
1939 // We don't know anything about the receiver.
1940 RECEIVER_IS_UNKNOWN,
1942 // We know the receiver is a string.
1948 // The code being generated is part of an IC handler, which may MISS
1949 // to an IC in failure cases.
1952 NOT_PART_OF_IC_HANDLER
1956 // Generates code implementing String.prototype.charCodeAt.
1958 // Only supports the case when the receiver is a string and the index
1959 // is a number (smi or heap number) that is a valid index into the
1960 // string. Additional index constraints are specified by the
1961 // flags. Otherwise, bails out to the provided labels.
1963 // Register usage: |object| may be changed to another string in a way
1964 // that doesn't affect charCodeAt/charAt semantics, |index| is
1965 // preserved, |scratch| and |result| are clobbered.
1966 class StringCharCodeAtGenerator {
1968 StringCharCodeAtGenerator(Register object, Register index, Register result,
1969 Label* receiver_not_string, Label* index_not_number,
1970 Label* index_out_of_range,
1971 StringIndexFlags index_flags,
1972 ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
1976 receiver_not_string_(receiver_not_string),
1977 index_not_number_(index_not_number),
1978 index_out_of_range_(index_out_of_range),
1979 index_flags_(index_flags),
1980 check_mode_(check_mode) {
1981 DCHECK(!result_.is(object_));
1982 DCHECK(!result_.is(index_));
1985 // Generates the fast case code. On the fallthrough path |result|
1986 // register contains the result.
1987 void GenerateFast(MacroAssembler* masm);
1989 // Generates the slow case code. Must not be naturally
1990 // reachable. Expected to be put after a ret instruction (e.g., in
1991 // deferred code). Always jumps back to the fast case.
1992 void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
1993 const RuntimeCallHelper& call_helper);
1995 // Skip handling slow case and directly jump to bailout.
1996 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1997 masm->bind(&index_not_smi_);
1998 masm->bind(&call_runtime_);
2007 Label* receiver_not_string_;
2008 Label* index_not_number_;
2009 Label* index_out_of_range_;
2011 StringIndexFlags index_flags_;
2012 ReceiverCheckMode check_mode_;
2014 Label call_runtime_;
2015 Label index_not_smi_;
2016 Label got_smi_index_;
2019 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
2023 // Generates code for creating a one-char string from a char code.
2024 class StringCharFromCodeGenerator {
2026 StringCharFromCodeGenerator(Register code,
2030 DCHECK(!code_.is(result_));
2033 // Generates the fast case code. On the fallthrough path |result|
2034 // register contains the result.
2035 void GenerateFast(MacroAssembler* masm);
2037 // Generates the slow case code. Must not be naturally
2038 // reachable. Expected to be put after a ret instruction (e.g., in
2039 // deferred code). Always jumps back to the fast case.
2040 void GenerateSlow(MacroAssembler* masm,
2041 const RuntimeCallHelper& call_helper);
2043 // Skip handling slow case and directly jump to bailout.
2044 void SkipSlow(MacroAssembler* masm, Label* bailout) {
2045 masm->bind(&slow_case_);
2056 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
2060 // Generates code implementing String.prototype.charAt.
2062 // Only supports the case when the receiver is a string and the index
2063 // is a number (smi or heap number) that is a valid index into the
2064 // string. Additional index constraints are specified by the
2065 // flags. Otherwise, bails out to the provided labels.
2067 // Register usage: |object| may be changed to another string in a way
2068 // that doesn't affect charCodeAt/charAt semantics, |index| is
2069 // preserved, |scratch1|, |scratch2|, and |result| are clobbered.
2070 class StringCharAtGenerator {
2072 StringCharAtGenerator(Register object, Register index, Register scratch,
2073 Register result, Label* receiver_not_string,
2074 Label* index_not_number, Label* index_out_of_range,
2075 StringIndexFlags index_flags,
2076 ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
2077 : char_code_at_generator_(object, index, scratch, receiver_not_string,
2078 index_not_number, index_out_of_range,
2079 index_flags, check_mode),
2080 char_from_code_generator_(scratch, result) {}
2082 // Generates the fast case code. On the fallthrough path |result|
2083 // register contains the result.
2084 void GenerateFast(MacroAssembler* masm) {
2085 char_code_at_generator_.GenerateFast(masm);
2086 char_from_code_generator_.GenerateFast(masm);
2089 // Generates the slow case code. Must not be naturally
2090 // reachable. Expected to be put after a ret instruction (e.g., in
2091 // deferred code). Always jumps back to the fast case.
2092 void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
2093 const RuntimeCallHelper& call_helper) {
2094 char_code_at_generator_.GenerateSlow(masm, embed_mode, call_helper);
2095 char_from_code_generator_.GenerateSlow(masm, call_helper);
2098 // Skip handling slow case and directly jump to bailout.
2099 void SkipSlow(MacroAssembler* masm, Label* bailout) {
2100 char_code_at_generator_.SkipSlow(masm, bailout);
2101 char_from_code_generator_.SkipSlow(masm, bailout);
2105 StringCharCodeAtGenerator char_code_at_generator_;
2106 StringCharFromCodeGenerator char_from_code_generator_;
2108 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
2112 class LoadDictionaryElementStub : public HydrogenCodeStub {
2114 explicit LoadDictionaryElementStub(Isolate* isolate)
2115 : HydrogenCodeStub(isolate) {}
2117 CallInterfaceDescriptor GetCallInterfaceDescriptor() override {
2118 return LoadWithVectorDescriptor(isolate());
2121 DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub);
2125 class KeyedLoadGenericStub : public HydrogenCodeStub {
2127 explicit KeyedLoadGenericStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
2129 Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2130 InlineCacheState GetICState() const override { return GENERIC; }
2132 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
2134 DEFINE_HYDROGEN_CODE_STUB(KeyedLoadGeneric, HydrogenCodeStub);
2138 class LoadICTrampolineStub : public PlatformCodeStub {
2140 LoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
2141 : PlatformCodeStub(isolate) {
2142 minor_key_ = state.GetExtraICState();
2145 Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
2147 InlineCacheState GetICState() const final { return DEFAULT; }
2149 ExtraICState GetExtraICState() const final {
2150 return static_cast<ExtraICState>(minor_key_);
2154 LoadICState state() const {
2155 return LoadICState(static_cast<ExtraICState>(minor_key_));
2158 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
2159 DEFINE_PLATFORM_CODE_STUB(LoadICTrampoline, PlatformCodeStub);
2163 class KeyedLoadICTrampolineStub : public LoadICTrampolineStub {
2165 explicit KeyedLoadICTrampolineStub(Isolate* isolate)
2166 : LoadICTrampolineStub(isolate, LoadICState(0)) {}
2168 Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2170 DEFINE_PLATFORM_CODE_STUB(KeyedLoadICTrampoline, LoadICTrampolineStub);
2174 class VectorStoreICTrampolineStub : public PlatformCodeStub {
2176 VectorStoreICTrampolineStub(Isolate* isolate, const StoreICState& state)
2177 : PlatformCodeStub(isolate) {
2178 minor_key_ = state.GetExtraICState();
2181 Code::Kind GetCodeKind() const override { return Code::STORE_IC; }
2183 InlineCacheState GetICState() const final { return DEFAULT; }
2185 ExtraICState GetExtraICState() const final {
2186 return static_cast<ExtraICState>(minor_key_);
2190 StoreICState state() const {
2191 return StoreICState(static_cast<ExtraICState>(minor_key_));
2195 DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreICTrampoline);
2196 DEFINE_PLATFORM_CODE_STUB(VectorStoreICTrampoline, PlatformCodeStub);
2200 class VectorKeyedStoreICTrampolineStub : public VectorStoreICTrampolineStub {
2202 VectorKeyedStoreICTrampolineStub(Isolate* isolate, const StoreICState& state)
2203 : VectorStoreICTrampolineStub(isolate, state) {}
2205 Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; }
2207 DEFINE_PLATFORM_CODE_STUB(VectorKeyedStoreICTrampoline,
2208 VectorStoreICTrampolineStub);
2212 class CallICTrampolineStub : public PlatformCodeStub {
2214 CallICTrampolineStub(Isolate* isolate, const CallICState& state)
2215 : PlatformCodeStub(isolate) {
2216 minor_key_ = state.GetExtraICState();
2219 Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
2221 InlineCacheState GetICState() const final { return DEFAULT; }
2223 ExtraICState GetExtraICState() const final {
2224 return static_cast<ExtraICState>(minor_key_);
2228 CallICState state() const {
2229 return CallICState(static_cast<ExtraICState>(minor_key_));
2232 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedback);
2233 DEFINE_PLATFORM_CODE_STUB(CallICTrampoline, PlatformCodeStub);
2237 class CallIC_ArrayTrampolineStub : public CallICTrampolineStub {
2239 CallIC_ArrayTrampolineStub(Isolate* isolate, const CallICState& state)
2240 : CallICTrampolineStub(isolate, state) {}
2243 DEFINE_PLATFORM_CODE_STUB(CallIC_ArrayTrampoline, CallICTrampolineStub);
2247 class LoadICStub : public PlatformCodeStub {
2249 explicit LoadICStub(Isolate* isolate, const LoadICState& state)
2250 : PlatformCodeStub(isolate) {
2251 minor_key_ = state.GetExtraICState();
2254 void GenerateForTrampoline(MacroAssembler* masm);
2256 Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
2257 InlineCacheState GetICState() const final { return DEFAULT; }
2258 ExtraICState GetExtraICState() const final {
2259 return static_cast<ExtraICState>(minor_key_);
2262 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
2263 DEFINE_PLATFORM_CODE_STUB(LoadIC, PlatformCodeStub);
2266 void GenerateImpl(MacroAssembler* masm, bool in_frame);
2270 class KeyedLoadICStub : public PlatformCodeStub {
2272 explicit KeyedLoadICStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2274 void GenerateForTrampoline(MacroAssembler* masm);
2276 Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2277 InlineCacheState GetICState() const final { return DEFAULT; }
2279 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
2280 DEFINE_PLATFORM_CODE_STUB(KeyedLoadIC, PlatformCodeStub);
2283 void GenerateImpl(MacroAssembler* masm, bool in_frame);
2287 class VectorStoreICStub : public PlatformCodeStub {
2289 VectorStoreICStub(Isolate* isolate, const StoreICState& state)
2290 : PlatformCodeStub(isolate) {
2291 minor_key_ = state.GetExtraICState();
2294 void GenerateForTrampoline(MacroAssembler* masm);
2296 Code::Kind GetCodeKind() const final { return Code::STORE_IC; }
2297 InlineCacheState GetICState() const final { return DEFAULT; }
2298 ExtraICState GetExtraICState() const final {
2299 return static_cast<ExtraICState>(minor_key_);
2302 DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreIC);
2303 DEFINE_PLATFORM_CODE_STUB(VectorStoreIC, PlatformCodeStub);
2306 void GenerateImpl(MacroAssembler* masm, bool in_frame);
2310 class VectorKeyedStoreICStub : public PlatformCodeStub {
2312 VectorKeyedStoreICStub(Isolate* isolate, const StoreICState& state)
2313 : PlatformCodeStub(isolate) {
2314 minor_key_ = state.GetExtraICState();
2317 void GenerateForTrampoline(MacroAssembler* masm);
2319 Code::Kind GetCodeKind() const final { return Code::KEYED_STORE_IC; }
2320 InlineCacheState GetICState() const final { return DEFAULT; }
2322 DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreIC);
2323 DEFINE_PLATFORM_CODE_STUB(VectorKeyedStoreIC, PlatformCodeStub);
2326 void GenerateImpl(MacroAssembler* masm, bool in_frame);
2330 class DoubleToIStub : public PlatformCodeStub {
2332 DoubleToIStub(Isolate* isolate, Register source, Register destination,
2333 int offset, bool is_truncating, bool skip_fastpath = false)
2334 : PlatformCodeStub(isolate) {
2335 minor_key_ = SourceRegisterBits::encode(source.code()) |
2336 DestinationRegisterBits::encode(destination.code()) |
2337 OffsetBits::encode(offset) |
2338 IsTruncatingBits::encode(is_truncating) |
2339 SkipFastPathBits::encode(skip_fastpath) |
2340 SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0);
2343 bool SometimesSetsUpAFrame() override { return false; }
2346 Register source() const {
2347 return Register::from_code(SourceRegisterBits::decode(minor_key_));
2349 Register destination() const {
2350 return Register::from_code(DestinationRegisterBits::decode(minor_key_));
2352 bool is_truncating() const { return IsTruncatingBits::decode(minor_key_); }
2353 bool skip_fastpath() const { return SkipFastPathBits::decode(minor_key_); }
2354 int offset() const { return OffsetBits::decode(minor_key_); }
2356 static const int kBitsPerRegisterNumber = 6;
2357 STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
2358 class SourceRegisterBits:
2359 public BitField<int, 0, kBitsPerRegisterNumber> {}; // NOLINT
2360 class DestinationRegisterBits:
2361 public BitField<int, kBitsPerRegisterNumber,
2362 kBitsPerRegisterNumber> {}; // NOLINT
2363 class IsTruncatingBits:
2364 public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {}; // NOLINT
2366 public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {}; // NOLINT
2367 class SkipFastPathBits:
2368 public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {}; // NOLINT
2370 public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {}; // NOLINT
2372 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2373 DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub);
2377 class ScriptContextFieldStub : public HandlerStub {
2379 ScriptContextFieldStub(Isolate* isolate,
2380 const ScriptContextTable::LookupResult* lookup_result)
2381 : HandlerStub(isolate) {
2382 DCHECK(Accepted(lookup_result));
2383 set_sub_minor_key(ContextIndexBits::encode(lookup_result->context_index) |
2384 SlotIndexBits::encode(lookup_result->slot_index));
2387 int context_index() const {
2388 return ContextIndexBits::decode(sub_minor_key());
2391 int slot_index() const { return SlotIndexBits::decode(sub_minor_key()); }
2393 static bool Accepted(const ScriptContextTable::LookupResult* lookup_result) {
2394 return ContextIndexBits::is_valid(lookup_result->context_index) &&
2395 SlotIndexBits::is_valid(lookup_result->slot_index);
2399 static const int kContextIndexBits = 13;
2400 static const int kSlotIndexBits = 13;
2401 class ContextIndexBits : public BitField<int, 0, kContextIndexBits> {};
2403 : public BitField<int, kContextIndexBits, kSlotIndexBits> {};
2405 Code::StubType GetStubType() const override { return Code::FAST; }
2407 DEFINE_CODE_STUB_BASE(ScriptContextFieldStub, HandlerStub);
2411 class LoadScriptContextFieldStub : public ScriptContextFieldStub {
2413 LoadScriptContextFieldStub(
2414 Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
2415 : ScriptContextFieldStub(isolate, lookup_result) {}
2418 Code::Kind kind() const override { return Code::LOAD_IC; }
2420 DEFINE_HANDLER_CODE_STUB(LoadScriptContextField, ScriptContextFieldStub);
2424 class StoreScriptContextFieldStub : public ScriptContextFieldStub {
2426 StoreScriptContextFieldStub(
2427 Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
2428 : ScriptContextFieldStub(isolate, lookup_result) {}
2431 Code::Kind kind() const override { return Code::STORE_IC; }
2433 DEFINE_HANDLER_CODE_STUB(StoreScriptContextField, ScriptContextFieldStub);
2437 class LoadFastElementStub : public HandlerStub {
2439 LoadFastElementStub(Isolate* isolate, bool is_js_array,
2440 ElementsKind elements_kind,
2441 bool convert_hole_to_undefined = false)
2442 : HandlerStub(isolate) {
2444 ElementsKindBits::encode(elements_kind) |
2445 IsJSArrayBits::encode(is_js_array) |
2446 CanConvertHoleToUndefined::encode(convert_hole_to_undefined));
2449 Code::Kind kind() const override { return Code::KEYED_LOAD_IC; }
2451 bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2452 bool convert_hole_to_undefined() const {
2453 return CanConvertHoleToUndefined::decode(sub_minor_key());
2456 ElementsKind elements_kind() const {
2457 return ElementsKindBits::decode(sub_minor_key());
2461 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2462 class IsJSArrayBits: public BitField<bool, 8, 1> {};
2463 class CanConvertHoleToUndefined : public BitField<bool, 9, 1> {};
2465 DEFINE_HANDLER_CODE_STUB(LoadFastElement, HandlerStub);
2469 class StoreFastElementStub : public HydrogenCodeStub {
2471 StoreFastElementStub(Isolate* isolate, bool is_js_array,
2472 ElementsKind elements_kind, KeyedAccessStoreMode mode)
2473 : HydrogenCodeStub(isolate) {
2474 set_sub_minor_key(ElementsKindBits::encode(elements_kind) |
2475 IsJSArrayBits::encode(is_js_array) |
2476 StoreModeBits::encode(mode));
2479 static void GenerateAheadOfTime(Isolate* isolate);
2481 bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2483 ElementsKind elements_kind() const {
2484 return ElementsKindBits::decode(sub_minor_key());
2487 KeyedAccessStoreMode store_mode() const {
2488 return StoreModeBits::decode(sub_minor_key());
2492 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2493 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
2494 class IsJSArrayBits: public BitField<bool, 12, 1> {};
2496 DEFINE_CALL_INTERFACE_DESCRIPTOR(Store);
2497 DEFINE_HYDROGEN_CODE_STUB(StoreFastElement, HydrogenCodeStub);
2501 class TransitionElementsKindStub : public HydrogenCodeStub {
2503 TransitionElementsKindStub(Isolate* isolate,
2504 ElementsKind from_kind,
2505 ElementsKind to_kind,
2506 bool is_js_array) : HydrogenCodeStub(isolate) {
2507 set_sub_minor_key(FromKindBits::encode(from_kind) |
2508 ToKindBits::encode(to_kind) |
2509 IsJSArrayBits::encode(is_js_array));
2512 ElementsKind from_kind() const {
2513 return FromKindBits::decode(sub_minor_key());
2516 ElementsKind to_kind() const { return ToKindBits::decode(sub_minor_key()); }
2518 bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2521 class FromKindBits: public BitField<ElementsKind, 8, 8> {};
2522 class ToKindBits: public BitField<ElementsKind, 0, 8> {};
2523 class IsJSArrayBits: public BitField<bool, 16, 1> {};
2525 DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind);
2526 DEFINE_HYDROGEN_CODE_STUB(TransitionElementsKind, HydrogenCodeStub);
2530 class AllocateHeapNumberStub final : public HydrogenCodeStub {
2532 explicit AllocateHeapNumberStub(Isolate* isolate)
2533 : HydrogenCodeStub(isolate) {}
2536 DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateHeapNumber);
2537 DEFINE_HYDROGEN_CODE_STUB(AllocateHeapNumber, HydrogenCodeStub);
2541 class ArrayConstructorStubBase : public HydrogenCodeStub {
2543 ArrayConstructorStubBase(Isolate* isolate,
2545 AllocationSiteOverrideMode override_mode)
2546 : HydrogenCodeStub(isolate) {
2547 // It only makes sense to override local allocation site behavior
2548 // if there is a difference between the global allocation site policy
2549 // for an ElementsKind and the desired usage of the stub.
2550 DCHECK(override_mode != DISABLE_ALLOCATION_SITES ||
2551 AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
2552 set_sub_minor_key(ElementsKindBits::encode(kind) |
2553 AllocationSiteOverrideModeBits::encode(override_mode));
2556 ElementsKind elements_kind() const {
2557 return ElementsKindBits::decode(sub_minor_key());
2560 AllocationSiteOverrideMode override_mode() const {
2561 return AllocationSiteOverrideModeBits::decode(sub_minor_key());
2564 static void GenerateStubsAheadOfTime(Isolate* isolate);
2566 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2567 static const int kConstructor = 0;
2568 static const int kAllocationSite = 1;
2571 std::ostream& BasePrintName(std::ostream& os,
2572 const char* name) const; // NOLINT
2575 // Ensure data fits within available bits.
2576 STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
2578 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2579 class AllocationSiteOverrideModeBits: public
2580 BitField<AllocationSiteOverrideMode, 8, 1> {}; // NOLINT
2582 DEFINE_CODE_STUB_BASE(ArrayConstructorStubBase, HydrogenCodeStub);
2586 class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
2588 ArrayNoArgumentConstructorStub(
2591 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2592 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2596 void PrintName(std::ostream& os) const override { // NOLINT
2597 BasePrintName(os, "ArrayNoArgumentConstructorStub");
2600 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructorConstantArgCount);
2601 DEFINE_HYDROGEN_CODE_STUB(ArrayNoArgumentConstructor,
2602 ArrayConstructorStubBase);
2606 class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
2608 ArraySingleArgumentConstructorStub(
2611 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2612 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2616 void PrintName(std::ostream& os) const override { // NOLINT
2617 BasePrintName(os, "ArraySingleArgumentConstructorStub");
2620 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2621 DEFINE_HYDROGEN_CODE_STUB(ArraySingleArgumentConstructor,
2622 ArrayConstructorStubBase);
2626 class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
2628 ArrayNArgumentsConstructorStub(
2631 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2632 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2636 void PrintName(std::ostream& os) const override { // NOLINT
2637 BasePrintName(os, "ArrayNArgumentsConstructorStub");
2640 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2641 DEFINE_HYDROGEN_CODE_STUB(ArrayNArgumentsConstructor,
2642 ArrayConstructorStubBase);
2646 class InternalArrayConstructorStubBase : public HydrogenCodeStub {
2648 InternalArrayConstructorStubBase(Isolate* isolate, ElementsKind kind)
2649 : HydrogenCodeStub(isolate) {
2650 set_sub_minor_key(ElementsKindBits::encode(kind));
2653 static void GenerateStubsAheadOfTime(Isolate* isolate);
2655 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2656 static const int kConstructor = 0;
2658 ElementsKind elements_kind() const {
2659 return ElementsKindBits::decode(sub_minor_key());
2663 class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2665 DEFINE_CODE_STUB_BASE(InternalArrayConstructorStubBase, HydrogenCodeStub);
2669 class InternalArrayNoArgumentConstructorStub : public
2670 InternalArrayConstructorStubBase {
2672 InternalArrayNoArgumentConstructorStub(Isolate* isolate,
2674 : InternalArrayConstructorStubBase(isolate, kind) { }
2676 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructorConstantArgCount);
2677 DEFINE_HYDROGEN_CODE_STUB(InternalArrayNoArgumentConstructor,
2678 InternalArrayConstructorStubBase);
2682 class InternalArraySingleArgumentConstructorStub : public
2683 InternalArrayConstructorStubBase {
2685 InternalArraySingleArgumentConstructorStub(Isolate* isolate,
2687 : InternalArrayConstructorStubBase(isolate, kind) { }
2689 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2690 DEFINE_HYDROGEN_CODE_STUB(InternalArraySingleArgumentConstructor,
2691 InternalArrayConstructorStubBase);
2695 class InternalArrayNArgumentsConstructorStub : public
2696 InternalArrayConstructorStubBase {
2698 InternalArrayNArgumentsConstructorStub(Isolate* isolate, ElementsKind kind)
2699 : InternalArrayConstructorStubBase(isolate, kind) { }
2701 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2702 DEFINE_HYDROGEN_CODE_STUB(InternalArrayNArgumentsConstructor,
2703 InternalArrayConstructorStubBase);
2707 class StoreElementStub : public PlatformCodeStub {
2709 StoreElementStub(Isolate* isolate, ElementsKind elements_kind)
2710 : PlatformCodeStub(isolate) {
2711 minor_key_ = ElementsKindBits::encode(elements_kind);
2715 ElementsKind elements_kind() const {
2716 return ElementsKindBits::decode(minor_key_);
2719 class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2721 DEFINE_CALL_INTERFACE_DESCRIPTOR(Store);
2722 DEFINE_PLATFORM_CODE_STUB(StoreElement, PlatformCodeStub);
2726 class ToBooleanStub: public HydrogenCodeStub {
2741 RESULT_AS_SMI, // For Smi(1) on truthy value, Smi(0) otherwise.
2742 RESULT_AS_ODDBALL, // For {true} on truthy value, {false} otherwise.
2743 RESULT_AS_INVERSE_ODDBALL // For {false} on truthy value, {true} otherwise.
2746 // At most 8 different types can be distinguished, because the Code object
2747 // only has room for a single byte to hold a set of these types. :-P
2748 STATIC_ASSERT(NUMBER_OF_TYPES <= 8);
2750 class Types : public EnumSet<Type, byte> {
2752 Types() : EnumSet<Type, byte>(0) {}
2753 explicit Types(byte bits) : EnumSet<Type, byte>(bits) {}
2755 byte ToByte() const { return ToIntegral(); }
2756 bool UpdateStatus(Handle<Object> object);
2757 bool NeedsMap() const;
2758 bool CanBeUndetectable() const;
2759 bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
2761 static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
2764 ToBooleanStub(Isolate* isolate, ResultMode mode, Types types = Types())
2765 : HydrogenCodeStub(isolate) {
2766 set_sub_minor_key(TypesBits::encode(types.ToByte()) |
2767 ResultModeBits::encode(mode));
2770 ToBooleanStub(Isolate* isolate, ExtraICState state)
2771 : HydrogenCodeStub(isolate) {
2772 set_sub_minor_key(TypesBits::encode(static_cast<byte>(state)) |
2773 ResultModeBits::encode(RESULT_AS_SMI));
2776 bool UpdateStatus(Handle<Object> object);
2777 Types types() const { return Types(TypesBits::decode(sub_minor_key())); }
2778 ResultMode mode() const { return ResultModeBits::decode(sub_minor_key()); }
2780 Code::Kind GetCodeKind() const override { return Code::TO_BOOLEAN_IC; }
2781 void PrintState(std::ostream& os) const override; // NOLINT
2783 bool SometimesSetsUpAFrame() override { return false; }
2785 static Handle<Code> GetUninitialized(Isolate* isolate) {
2786 return ToBooleanStub(isolate, UNINITIALIZED).GetCode();
2789 ExtraICState GetExtraICState() const override { return types().ToIntegral(); }
2791 InlineCacheState GetICState() const override {
2792 if (types().IsEmpty()) {
2793 return ::v8::internal::UNINITIALIZED;
2800 ToBooleanStub(Isolate* isolate, InitializationState init_state)
2801 : HydrogenCodeStub(isolate, init_state) {
2802 set_sub_minor_key(ResultModeBits::encode(RESULT_AS_SMI));
2805 class TypesBits : public BitField<byte, 0, NUMBER_OF_TYPES> {};
2806 class ResultModeBits : public BitField<ResultMode, NUMBER_OF_TYPES, 2> {};
2808 DEFINE_CALL_INTERFACE_DESCRIPTOR(ToBoolean);
2809 DEFINE_HYDROGEN_CODE_STUB(ToBoolean, HydrogenCodeStub);
2813 std::ostream& operator<<(std::ostream& os, const ToBooleanStub::Types& t);
2816 class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
2818 ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind,
2819 ElementsKind to_kind, bool is_jsarray,
2820 KeyedAccessStoreMode store_mode)
2821 : HydrogenCodeStub(isolate) {
2822 set_sub_minor_key(FromBits::encode(from_kind) | ToBits::encode(to_kind) |
2823 IsJSArrayBits::encode(is_jsarray) |
2824 StoreModeBits::encode(store_mode));
2827 ElementsKind from_kind() const { return FromBits::decode(sub_minor_key()); }
2828 ElementsKind to_kind() const { return ToBits::decode(sub_minor_key()); }
2829 bool is_jsarray() const { return IsJSArrayBits::decode(sub_minor_key()); }
2830 KeyedAccessStoreMode store_mode() const {
2831 return StoreModeBits::decode(sub_minor_key());
2834 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2835 enum ParameterIndices {
2843 static const Register ValueRegister() {
2844 return ElementTransitionAndStoreDescriptor::ValueRegister();
2846 static const Register MapRegister() {
2847 return ElementTransitionAndStoreDescriptor::MapRegister();
2849 static const Register KeyRegister() {
2850 return ElementTransitionAndStoreDescriptor::NameRegister();
2852 static const Register ObjectRegister() {
2853 return ElementTransitionAndStoreDescriptor::ReceiverRegister();
2857 class FromBits : public BitField<ElementsKind, 0, 8> {};
2858 class ToBits : public BitField<ElementsKind, 8, 8> {};
2859 class IsJSArrayBits : public BitField<bool, 16, 1> {};
2860 class StoreModeBits : public BitField<KeyedAccessStoreMode, 17, 4> {};
2862 DEFINE_CALL_INTERFACE_DESCRIPTOR(ElementTransitionAndStore);
2863 DEFINE_HYDROGEN_CODE_STUB(ElementsTransitionAndStore, HydrogenCodeStub);
2867 class StoreArrayLiteralElementStub : public PlatformCodeStub {
2869 explicit StoreArrayLiteralElementStub(Isolate* isolate)
2870 : PlatformCodeStub(isolate) { }
2872 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreArrayLiteralElement);
2873 DEFINE_PLATFORM_CODE_STUB(StoreArrayLiteralElement, PlatformCodeStub);
2877 class StubFailureTrampolineStub : public PlatformCodeStub {
2879 StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode)
2880 : PlatformCodeStub(isolate) {
2881 minor_key_ = FunctionModeField::encode(function_mode);
2884 static void GenerateAheadOfTime(Isolate* isolate);
2887 StubFunctionMode function_mode() const {
2888 return FunctionModeField::decode(minor_key_);
2891 class FunctionModeField : public BitField<StubFunctionMode, 0, 1> {};
2893 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2894 DEFINE_PLATFORM_CODE_STUB(StubFailureTrampoline, PlatformCodeStub);
2898 class ProfileEntryHookStub : public PlatformCodeStub {
2900 explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2902 // The profile entry hook function is not allowed to cause a GC.
2903 bool SometimesSetsUpAFrame() override { return false; }
2905 // Generates a call to the entry hook if it's enabled.
2906 static void MaybeCallEntryHook(MacroAssembler* masm);
2909 static void EntryHookTrampoline(intptr_t function,
2910 intptr_t stack_pointer,
2913 // ProfileEntryHookStub is called at the start of a function, so it has the
2914 // same register set.
2915 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction)
2916 DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub);
2920 class StoreBufferOverflowStub : public PlatformCodeStub {
2922 StoreBufferOverflowStub(Isolate* isolate, SaveFPRegsMode save_fp)
2923 : PlatformCodeStub(isolate) {
2924 minor_key_ = SaveDoublesBits::encode(save_fp == kSaveFPRegs);
2927 static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
2928 bool SometimesSetsUpAFrame() override { return false; }
2931 bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
2933 class SaveDoublesBits : public BitField<bool, 0, 1> {};
2935 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2936 DEFINE_PLATFORM_CODE_STUB(StoreBufferOverflow, PlatformCodeStub);
2940 class SubStringStub : public PlatformCodeStub {
2942 explicit SubStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2944 DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
2945 DEFINE_PLATFORM_CODE_STUB(SubString, PlatformCodeStub);
2949 class ToNumberStub final : public PlatformCodeStub {
2951 explicit ToNumberStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2953 DEFINE_CALL_INTERFACE_DESCRIPTOR(ToNumber);
2954 DEFINE_PLATFORM_CODE_STUB(ToNumber, PlatformCodeStub);
2958 class StringCompareStub : public PlatformCodeStub {
2960 explicit StringCompareStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2962 DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
2963 DEFINE_PLATFORM_CODE_STUB(StringCompare, PlatformCodeStub);
2967 #undef DEFINE_CALL_INTERFACE_DESCRIPTOR
2968 #undef DEFINE_PLATFORM_CODE_STUB
2969 #undef DEFINE_HANDLER_CODE_STUB
2970 #undef DEFINE_HYDROGEN_CODE_STUB
2971 #undef DEFINE_CODE_STUB
2972 #undef DEFINE_CODE_STUB_BASE
2973 } } // namespace v8::internal
2975 #endif // V8_CODE_STUBS_H_