blob: f370ce64735e994c84591d0316967d45c1cd9cd8 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
5#ifndef V8_CODE_STUBS_H_
6#define V8_CODE_STUBS_H_
7
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/allocation.h"
9#include "src/assembler.h"
10#include "src/codegen.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011#include "src/compiler/code-stub-assembler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012#include "src/globals.h"
13#include "src/ic/ic-state.h"
14#include "src/interface-descriptors.h"
15#include "src/macro-assembler.h"
16#include "src/ostreams.h"
Steve Block6ded16b2010-05-10 14:33:55 +010017
Steve Blocka7e24c12009-10-30 11:49:00 +000018namespace v8 {
19namespace internal {
20
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000021// List of code stubs used on all platforms.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022#define CODE_STUB_LIST_ALL_PLATFORMS(V) \
23 /* PlatformCodeStubs */ \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024 V(ArrayConstructor) \
25 V(BinaryOpICWithAllocationSite) \
26 V(CallApiFunction) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000027 V(CallApiAccessor) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000028 V(CallApiGetter) \
29 V(CallConstruct) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030 V(CallIC) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031 V(CEntry) \
32 V(CompareIC) \
33 V(DoubleToI) \
34 V(FunctionPrototype) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000035 V(InstanceOf) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000036 V(InternalArrayConstructor) \
37 V(JSEntry) \
38 V(KeyedLoadICTrampoline) \
39 V(LoadICTrampoline) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000040 V(CallICTrampoline) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000041 V(LoadIndexedInterceptor) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040042 V(LoadIndexedString) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000043 V(MathPow) \
44 V(ProfileEntryHook) \
45 V(RecordWrite) \
46 V(RegExpExec) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000047 V(StoreBufferOverflow) \
48 V(StoreElement) \
49 V(StringCompare) \
50 V(StubFailureTrampoline) \
51 V(SubString) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040052 V(ToNumber) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000053 V(ToLength) \
54 V(ToString) \
Ben Murdoch097c5b22016-05-18 11:27:45 +010055 V(ToName) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000056 V(ToObject) \
57 V(VectorStoreICTrampoline) \
58 V(VectorKeyedStoreICTrampoline) \
59 V(VectorStoreIC) \
60 V(VectorKeyedStoreIC) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000061 /* HydrogenCodeStubs */ \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040062 V(AllocateHeapNumber) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000063 V(AllocateMutableHeapNumber) \
64 V(AllocateInNewSpace) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000065 V(ArrayNArgumentsConstructor) \
66 V(ArrayNoArgumentConstructor) \
67 V(ArraySingleArgumentConstructor) \
68 V(BinaryOpIC) \
69 V(BinaryOpWithAllocationSite) \
70 V(CompareNilIC) \
71 V(CreateAllocationSite) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000072 V(CreateWeakCell) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000073 V(ElementsTransitionAndStore) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000074 V(FastCloneRegExp) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000075 V(FastCloneShallowArray) \
76 V(FastCloneShallowObject) \
77 V(FastNewClosure) \
78 V(FastNewContext) \
Ben Murdoch097c5b22016-05-18 11:27:45 +010079 V(FastNewObject) \
80 V(FastNewRestParameter) \
81 V(FastNewSloppyArguments) \
82 V(FastNewStrictArguments) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083 V(GrowArrayElements) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000084 V(InternalArrayNArgumentsConstructor) \
85 V(InternalArrayNoArgumentConstructor) \
86 V(InternalArraySingleArgumentConstructor) \
87 V(KeyedLoadGeneric) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000088 V(LoadGlobalViaContext) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040089 V(LoadScriptContextField) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000090 V(LoadDictionaryElement) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000091 V(NameDictionaryLookup) \
92 V(NumberToString) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000093 V(Typeof) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000094 V(RegExpConstructResult) \
95 V(StoreFastElement) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000096 V(StoreGlobalViaContext) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040097 V(StoreScriptContextField) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000098 V(StringAdd) \
99 V(ToBoolean) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000100 V(TransitionElementsKind) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000101 V(KeyedLoadIC) \
102 V(LoadIC) \
103 /* TurboFanCodeStubs */ \
104 V(StringLength) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000105 /* IC Handler stubs */ \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000106 V(ArrayBufferViewLoadField) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107 V(LoadConstant) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000108 V(LoadFastElement) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000109 V(LoadField) \
110 V(KeyedLoadSloppyArguments) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000111 V(KeyedStoreSloppyArguments) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000112 V(StoreField) \
113 V(StoreGlobal) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000114 V(StoreTransition)
Steve Blockd0582a62009-12-15 09:54:21 +0000115
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000116// List of code stubs only used on ARM 32 bits platforms.
117#if V8_TARGET_ARCH_ARM
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400118#define CODE_STUB_LIST_ARM(V) V(DirectCEntry)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000119
Steve Blockd0582a62009-12-15 09:54:21 +0000120#else
121#define CODE_STUB_LIST_ARM(V)
122#endif
123
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000124// List of code stubs only used on ARM 64 bits platforms.
125#if V8_TARGET_ARCH_ARM64
126#define CODE_STUB_LIST_ARM64(V) \
127 V(DirectCEntry) \
128 V(RestoreRegistersState) \
129 V(StoreRegistersState)
130
131#else
132#define CODE_STUB_LIST_ARM64(V)
133#endif
134
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000135// List of code stubs only used on PPC platforms.
136#ifdef V8_TARGET_ARCH_PPC
137#define CODE_STUB_LIST_PPC(V) \
138 V(DirectCEntry) \
139 V(StoreRegistersState) \
140 V(RestoreRegistersState)
141#else
142#define CODE_STUB_LIST_PPC(V)
143#endif
144
Steve Block44f0eee2011-05-26 01:26:41 +0100145// List of code stubs only used on MIPS platforms.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000146#if V8_TARGET_ARCH_MIPS
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400147#define CODE_STUB_LIST_MIPS(V) \
148 V(DirectCEntry) \
149 V(RestoreRegistersState) \
150 V(StoreRegistersState)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000151#elif V8_TARGET_ARCH_MIPS64
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400152#define CODE_STUB_LIST_MIPS(V) \
153 V(DirectCEntry) \
154 V(RestoreRegistersState) \
155 V(StoreRegistersState)
Steve Block44f0eee2011-05-26 01:26:41 +0100156#else
157#define CODE_STUB_LIST_MIPS(V)
158#endif
159
Steve Blockd0582a62009-12-15 09:54:21 +0000160// Combined list of code stubs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000161#define CODE_STUB_LIST(V) \
162 CODE_STUB_LIST_ALL_PLATFORMS(V) \
163 CODE_STUB_LIST_ARM(V) \
164 CODE_STUB_LIST_ARM64(V) \
165 CODE_STUB_LIST_PPC(V) \
Steve Block44f0eee2011-05-26 01:26:41 +0100166 CODE_STUB_LIST_MIPS(V)
Steve Blocka7e24c12009-10-30 11:49:00 +0000167
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000168static const int kHasReturnedMinusZeroSentinel = 1;
169
Steve Blocka7e24c12009-10-30 11:49:00 +0000170// Stub is base classes of all stubs.
171class CodeStub BASE_EMBEDDED {
172 public:
173 enum Major {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400174 // TODO(mvstanton): eliminate the NoCache key by getting rid
175 // of the non-monomorphic-cache.
176 NoCache = 0, // marker for stubs that do custom caching]
Steve Blockd0582a62009-12-15 09:54:21 +0000177#define DEF_ENUM(name) name,
178 CODE_STUB_LIST(DEF_ENUM)
179#undef DEF_ENUM
Steve Blocka7e24c12009-10-30 11:49:00 +0000180 NUMBER_OF_IDS
181 };
182
183 // Retrieve the code for the stub. Generate the code if needed.
184 Handle<Code> GetCode();
185
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000186 // Retrieve the code for the stub, make and return a copy of the code.
187 Handle<Code> GetCodeCopy(const Code::FindAndReplacePattern& pattern);
188
Steve Blocka7e24c12009-10-30 11:49:00 +0000189 static Major MajorKeyFromKey(uint32_t key) {
190 return static_cast<Major>(MajorKeyBits::decode(key));
Iain Merrick9ac36c92010-09-13 15:29:50 +0100191 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192 static uint32_t MinorKeyFromKey(uint32_t key) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000193 return MinorKeyBits::decode(key);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100194 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100195
196 // Gets the major key from a code object that is a code stub or binary op IC.
197 static Major GetMajorKey(Code* code_stub) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000198 return MajorKeyFromKey(code_stub->stub_key());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100199 }
200
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000201 static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }
202
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203 static const char* MajorName(Major major_key);
Steve Blocka7e24c12009-10-30 11:49:00 +0000204
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000205 explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000206 virtual ~CodeStub() {}
207
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000208 static void GenerateStubsAheadOfTime(Isolate* isolate);
209 static void GenerateFPStubs(Isolate* isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100210
211 // Some stubs put untagged junk on the stack that cannot be scanned by the
212 // GC. This means that we must be statically sure that no GC can occur while
213 // they are running. If that is the case they should override this to return
214 // true, which will cause an assertion if we try to call something that can
215 // GC or if we try to put a stack frame on top of the junk, which would not
216 // result in a traversable stack.
217 virtual bool SometimesSetsUpAFrame() { return true; }
218
219 // Lookup the code in the (possibly custom) cache.
220 bool FindCodeInCache(Code** code_out);
221
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000222 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() const = 0;
223
224 virtual int GetStackParameterCount() const {
225 return GetCallInterfaceDescriptor().GetStackParameterCount();
226 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000227
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000228 virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {}
229
230 static void InitializeDescriptor(Isolate* isolate, uint32_t key,
231 CodeStubDescriptor* desc);
232
233 static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key);
234
235 // Returns information for computing the number key.
236 virtual Major MajorKey() const = 0;
237 uint32_t MinorKey() const { return minor_key_; }
238
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000239 // BinaryOpStub needs to override this.
240 virtual Code::Kind GetCodeKind() const;
241
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242 virtual InlineCacheState GetICState() const { return UNINITIALIZED; }
243 virtual ExtraICState GetExtraICState() const { return kNoExtraICState; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000244 virtual Code::StubType GetStubType() const { return Code::NORMAL; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000245
Ben Murdoch097c5b22016-05-18 11:27:45 +0100246 Code::Flags GetCodeFlags() const;
247
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400248 friend std::ostream& operator<<(std::ostream& os, const CodeStub& s) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000249 s.PrintName(os);
250 return os;
251 }
252
253 Isolate* isolate() const { return isolate_; }
254
255 protected:
256 CodeStub(uint32_t key, Isolate* isolate)
257 : minor_key_(MinorKeyFromKey(key)), isolate_(isolate) {}
Leon Clarkee46be812010-01-19 14:06:41 +0000258
Steve Blocka7e24c12009-10-30 11:49:00 +0000259 // Generates the assembler code for the stub.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000260 virtual Handle<Code> GenerateCode() = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000261
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000262 // Returns whether the code generated for this stub needs to be allocated as
263 // a fixed (non-moveable) code object.
264 virtual bool NeedsImmovableCode() { return false; }
265
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400266 virtual void PrintName(std::ostream& os) const; // NOLINT
267 virtual void PrintBaseName(std::ostream& os) const; // NOLINT
268 virtual void PrintState(std::ostream& os) const { ; } // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000269
270 // Computes the key based on major and minor.
271 uint32_t GetKey() {
272 DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
273 return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey());
274 }
275
276 uint32_t minor_key_;
277
278 private:
Leon Clarkee46be812010-01-19 14:06:41 +0000279 // Perform bookkeeping required after code generation when stub code is
280 // initially generated.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000281 void RecordCodeGeneration(Handle<Code> code);
Leon Clarkee46be812010-01-19 14:06:41 +0000282
Ben Murdochb0fe1622011-05-05 13:52:32 +0100283 // Finish the code object after it has been generated.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100284 virtual void FinishCode(Handle<Code> code) { }
285
286 // Activate newly generated stub. Is called after
287 // registering stub in the stub cache.
288 virtual void Activate(Code* code) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100289
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100290 // Add the code to a specialized cache, specific to an individual
291 // stub type. Please note, this method must add the code object to a
292 // roots object, otherwise we will remove the code during GC.
293 virtual void AddToSpecialCache(Handle<Code> new_object) { }
294
295 // Find code in a specialized cache, work is delegated to the specific stub.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000296 virtual bool FindCodeInSpecialCache(Code** code_out) {
297 return false;
298 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100299
300 // If a stub uses a special cache override this.
301 virtual bool UseSpecialCache() { return false; }
302
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000303 // We use this dispatch to statically instantiate the correct code stub for
304 // the given stub key and call the passed function with that code stub.
305 typedef void (*DispatchedCall)(CodeStub* stub, void** value_out);
306 static void Dispatch(Isolate* isolate, uint32_t key, void** value_out,
307 DispatchedCall call);
Steve Blocka7e24c12009-10-30 11:49:00 +0000308
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000309 static void GetCodeDispatchCall(CodeStub* stub, void** value_out);
Steve Block44f0eee2011-05-26 01:26:41 +0100310
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000311 STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
312 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
313 class MinorKeyBits: public BitField<uint32_t,
314 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT
Steve Blocka7e24c12009-10-30 11:49:00 +0000315
316 friend class BreakPointIterator;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000317
318 Isolate* isolate_;
319};
320
321
322#define DEFINE_CODE_STUB_BASE(NAME, SUPER) \
323 public: \
324 NAME(uint32_t key, Isolate* isolate) : SUPER(key, isolate) {} \
325 \
326 private: \
327 DISALLOW_COPY_AND_ASSIGN(NAME)
328
329
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400330#define DEFINE_CODE_STUB(NAME, SUPER) \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100331 public: \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000332 inline Major MajorKey() const override { return NAME; }; \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100333 \
334 protected: \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000335 DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER)
336
337
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400338#define DEFINE_PLATFORM_CODE_STUB(NAME, SUPER) \
339 private: \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000340 void Generate(MacroAssembler* masm) override; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000341 DEFINE_CODE_STUB(NAME, SUPER)
342
343
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400344#define DEFINE_HYDROGEN_CODE_STUB(NAME, SUPER) \
345 public: \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000346 void InitializeDescriptor(CodeStubDescriptor* descriptor) override; \
347 Handle<Code> GenerateCode() override; \
348 DEFINE_CODE_STUB(NAME, SUPER)
349
350#define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER) \
351 public: \
352 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
353 return DESC##Descriptor(isolate()); \
354 }; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000355 DEFINE_CODE_STUB(NAME, SUPER)
356
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400357#define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \
358 public: \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000359 Handle<Code> GenerateCode() override; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000360 DEFINE_CODE_STUB(NAME, SUPER)
361
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000362#define DEFINE_CALL_INTERFACE_DESCRIPTOR(NAME) \
363 public: \
364 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
365 return NAME##Descriptor(isolate()); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000366 }
367
368// There are some code stubs we just can't describe right now with a
369// CallInterfaceDescriptor. Isolate behavior for those cases with this macro.
370// An attempt to retrieve a descriptor will fail.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000371#define DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR() \
372 public: \
373 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
374 UNREACHABLE(); \
375 return CallInterfaceDescriptor(); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000376 }
377
378
379class PlatformCodeStub : public CodeStub {
380 public:
381 // Retrieve the code for the stub. Generate the code if needed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000382 Handle<Code> GenerateCode() override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000383
384 protected:
385 explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {}
386
387 // Generates the assembler code for the stub.
388 virtual void Generate(MacroAssembler* masm) = 0;
389
390 DEFINE_CODE_STUB_BASE(PlatformCodeStub, CodeStub);
391};
392
393
394enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000395
396
397class CodeStubDescriptor {
398 public:
399 explicit CodeStubDescriptor(CodeStub* stub);
400
401 CodeStubDescriptor(Isolate* isolate, uint32_t stub_key);
402
403 void Initialize(Address deoptimization_handler = NULL,
404 int hint_stack_parameter_count = -1,
405 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
406 void Initialize(Register stack_parameter_count,
407 Address deoptimization_handler = NULL,
408 int hint_stack_parameter_count = -1,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000409 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000410
411 void SetMissHandler(ExternalReference handler) {
412 miss_handler_ = handler;
413 has_miss_handler_ = true;
414 // Our miss handler infrastructure doesn't currently support
415 // variable stack parameter counts.
416 DCHECK(!stack_parameter_count_.is_valid());
417 }
418
419 void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; }
420 CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; }
421
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000422 int GetRegisterParameterCount() const {
423 return call_descriptor().GetRegisterParameterCount();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000424 }
425
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000426 int GetStackParameterCount() const {
427 return call_descriptor().GetStackParameterCount();
428 }
429
430 int GetParameterCount() const {
431 return call_descriptor().GetParameterCount();
432 }
433
434 Register GetRegisterParameter(int index) const {
435 return call_descriptor().GetRegisterParameter(index);
436 }
437
438 Type* GetParameterType(int index) const {
439 return call_descriptor().GetParameterType(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000440 }
441
442 ExternalReference miss_handler() const {
443 DCHECK(has_miss_handler_);
444 return miss_handler_;
445 }
446
447 bool has_miss_handler() const {
448 return has_miss_handler_;
449 }
450
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000451 int GetHandlerParameterCount() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000452 int params = GetParameterCount();
453 if (PassesArgumentsToDeoptimizationHandler()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000454 params += 1;
455 }
456 return params;
457 }
458
459 int hint_stack_parameter_count() const { return hint_stack_parameter_count_; }
460 Register stack_parameter_count() const { return stack_parameter_count_; }
461 StubFunctionMode function_mode() const { return function_mode_; }
462 Address deoptimization_handler() const { return deoptimization_handler_; }
463
464 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000465 bool PassesArgumentsToDeoptimizationHandler() const {
466 return stack_parameter_count_.is_valid();
467 }
468
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000469 CallInterfaceDescriptor call_descriptor_;
470 Register stack_parameter_count_;
471 // If hint_stack_parameter_count_ > 0, the code stub can optimize the
472 // return sequence. Default value is -1, which means it is ignored.
473 int hint_stack_parameter_count_;
474 StubFunctionMode function_mode_;
475
476 Address deoptimization_handler_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000477
478 ExternalReference miss_handler_;
479 bool has_miss_handler_;
480};
481
482
483class HydrogenCodeStub : public CodeStub {
484 public:
485 enum InitializationState {
486 UNINITIALIZED,
487 INITIALIZED
488 };
489
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000490 template<class SubClass>
491 static Handle<Code> GetUninitialized(Isolate* isolate) {
492 SubClass::GenerateAheadOfTime(isolate);
493 return SubClass().GetCode(isolate);
494 }
495
496 // Retrieve the code for the stub. Generate the code if needed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000497 Handle<Code> GenerateCode() override = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000498
499 bool IsUninitialized() const { return IsMissBits::decode(minor_key_); }
500
501 Handle<Code> GenerateLightweightMissCode(ExternalReference miss);
502
503 template<class StateType>
504 void TraceTransition(StateType from, StateType to);
505
506 protected:
507 explicit HydrogenCodeStub(Isolate* isolate,
508 InitializationState state = INITIALIZED)
509 : CodeStub(isolate) {
510 minor_key_ = IsMissBits::encode(state == UNINITIALIZED);
511 }
512
513 void set_sub_minor_key(uint32_t key) {
514 minor_key_ = SubMinorKeyBits::update(minor_key_, key);
515 }
516
517 uint32_t sub_minor_key() const { return SubMinorKeyBits::decode(minor_key_); }
518
519 static const int kSubMinorKeyBits = kStubMinorKeyBits - 1;
520
521 private:
522 class IsMissBits : public BitField<bool, kSubMinorKeyBits, 1> {};
523 class SubMinorKeyBits : public BitField<int, 0, kSubMinorKeyBits> {};
524
525 void GenerateLightweightMiss(MacroAssembler* masm, ExternalReference miss);
526
527 DEFINE_CODE_STUB_BASE(HydrogenCodeStub, CodeStub);
Steve Blocka7e24c12009-10-30 11:49:00 +0000528};
529
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100530
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000531class TurboFanCodeStub : public CodeStub {
532 public:
533 // Retrieve the code for the stub. Generate the code if needed.
534 Handle<Code> GenerateCode() override;
535
536 int GetStackParameterCount() const override {
537 return GetCallInterfaceDescriptor().GetStackParameterCount();
538 }
539
540 Code::StubType GetStubType() const override { return Code::FAST; }
541
542 protected:
543 explicit TurboFanCodeStub(Isolate* isolate) : CodeStub(isolate) {}
544
545 virtual void GenerateAssembly(
546 compiler::CodeStubAssembler* assembler) const = 0;
547
548 private:
549 DEFINE_CODE_STUB_BASE(TurboFanCodeStub, CodeStub);
550};
551
552
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100553// Helper interface to prepare to/restore after making runtime calls.
554class RuntimeCallHelper {
555 public:
556 virtual ~RuntimeCallHelper() {}
557
558 virtual void BeforeCall(MacroAssembler* masm) const = 0;
559
560 virtual void AfterCall(MacroAssembler* masm) const = 0;
561
562 protected:
563 RuntimeCallHelper() {}
564
565 private:
566 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
567};
568
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000569
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000570} // namespace internal
571} // namespace v8
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100572
573#if V8_TARGET_ARCH_IA32
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000574#include "src/ia32/code-stubs-ia32.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100575#elif V8_TARGET_ARCH_X64
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000576#include "src/x64/code-stubs-x64.h"
577#elif V8_TARGET_ARCH_ARM64
578#include "src/arm64/code-stubs-arm64.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100579#elif V8_TARGET_ARCH_ARM
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000580#include "src/arm/code-stubs-arm.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000581#elif V8_TARGET_ARCH_PPC
582#include "src/ppc/code-stubs-ppc.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100583#elif V8_TARGET_ARCH_MIPS
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000584#include "src/mips/code-stubs-mips.h"
585#elif V8_TARGET_ARCH_MIPS64
586#include "src/mips64/code-stubs-mips64.h"
587#elif V8_TARGET_ARCH_X87
588#include "src/x87/code-stubs-x87.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100589#else
590#error Unsupported target architecture.
591#endif
592
593namespace v8 {
594namespace internal {
595
596
Ben Murdochb0fe1622011-05-05 13:52:32 +0100597// RuntimeCallHelper implementation used in stubs: enters/leaves a
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100598// newly created internal frame before/after the runtime call.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100599class StubRuntimeCallHelper : public RuntimeCallHelper {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100600 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100601 StubRuntimeCallHelper() {}
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100602
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000603 void BeforeCall(MacroAssembler* masm) const override;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100604
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000605 void AfterCall(MacroAssembler* masm) const override;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100606};
607
608
609// Trivial RuntimeCallHelper implementation.
610class NopRuntimeCallHelper : public RuntimeCallHelper {
611 public:
612 NopRuntimeCallHelper() {}
613
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000614 void BeforeCall(MacroAssembler* masm) const override {}
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100615
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000616 void AfterCall(MacroAssembler* masm) const override {}
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100617};
618
619
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000620class StringLengthStub : public TurboFanCodeStub {
621 public:
622 explicit StringLengthStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
623
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; }
627
628 void GenerateAssembly(compiler::CodeStubAssembler* assembler) const override;
629
630 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
631 DEFINE_CODE_STUB(StringLength, TurboFanCodeStub);
632};
633
634
635enum StringAddFlags {
636 // Omit both parameter checks.
637 STRING_ADD_CHECK_NONE = 0,
638 // Check left parameter.
639 STRING_ADD_CHECK_LEFT = 1 << 0,
640 // Check right parameter.
641 STRING_ADD_CHECK_RIGHT = 1 << 1,
642 // Check both parameters.
643 STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT,
644 // Convert parameters when check fails (instead of throwing an exception).
645 STRING_ADD_CONVERT = 1 << 2,
646 STRING_ADD_CONVERT_LEFT = STRING_ADD_CHECK_LEFT | STRING_ADD_CONVERT,
647 STRING_ADD_CONVERT_RIGHT = STRING_ADD_CHECK_RIGHT | STRING_ADD_CONVERT
648};
649
650
651std::ostream& operator<<(std::ostream& os, const StringAddFlags& flags);
652
653
654class NumberToStringStub final : public HydrogenCodeStub {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100655 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000656 explicit NumberToStringStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100657
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000658 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
659 static const int kNumber = 0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100660
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000661 DEFINE_CALL_INTERFACE_DESCRIPTOR(NumberToString);
662 DEFINE_HYDROGEN_CODE_STUB(NumberToString, HydrogenCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100663};
664
665
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000666class TypeofStub final : public HydrogenCodeStub {
667 public:
668 explicit TypeofStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
669
670 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
671 static const int kObject = 0;
672
673 static void GenerateAheadOfTime(Isolate* isolate);
674
675 DEFINE_CALL_INTERFACE_DESCRIPTOR(Typeof);
676 DEFINE_HYDROGEN_CODE_STUB(Typeof, HydrogenCodeStub);
677};
678
679
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000680class FastNewClosureStub : public HydrogenCodeStub {
Steve Block1e0659c2011-05-24 12:43:12 +0100681 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000682 FastNewClosureStub(Isolate* isolate, LanguageMode language_mode,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000683 FunctionKind kind)
684 : HydrogenCodeStub(isolate) {
685 DCHECK(IsValidFunctionKind(kind));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000686 set_sub_minor_key(LanguageModeBits::encode(language_mode) |
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000687 FunctionKindBits::encode(kind));
688 }
Steve Block1e0659c2011-05-24 12:43:12 +0100689
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000690 LanguageMode language_mode() const {
691 return LanguageModeBits::decode(sub_minor_key());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000692 }
693
694 FunctionKind kind() const {
695 return FunctionKindBits::decode(sub_minor_key());
696 }
Steve Block1e0659c2011-05-24 12:43:12 +0100697
698 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000699 STATIC_ASSERT(LANGUAGE_END == 3);
700 class LanguageModeBits : public BitField<LanguageMode, 0, 2> {};
701 class FunctionKindBits : public BitField<FunctionKind, 2, 8> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000702
703 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure);
704 DEFINE_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub);
Steve Block1e0659c2011-05-24 12:43:12 +0100705};
706
707
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000708class FastNewContextStub final : public HydrogenCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100709 public:
710 static const int kMaximumSlots = 64;
711
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000712 FastNewContextStub(Isolate* isolate, int slots) : HydrogenCodeStub(isolate) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000713 DCHECK(slots >= 0 && slots <= kMaximumSlots);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000714 set_sub_minor_key(SlotsBits::encode(slots));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100715 }
716
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000717 int slots() const { return SlotsBits::decode(sub_minor_key()); }
718
719 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
720 static const int kFunction = 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100721
722 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000723 class SlotsBits : public BitField<int, 0, 8> {};
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100724
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000725 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewContext);
726 DEFINE_HYDROGEN_CODE_STUB(FastNewContext, HydrogenCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100727};
728
729
Ben Murdoch097c5b22016-05-18 11:27:45 +0100730class FastNewObjectStub final : public PlatformCodeStub {
731 public:
732 explicit FastNewObjectStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
733
734 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewObject);
735 DEFINE_PLATFORM_CODE_STUB(FastNewObject, PlatformCodeStub);
736};
737
738
739// TODO(turbofan): This stub should be possible to write in TurboFan
740// using the CodeStubAssembler very soon in a way that is as efficient
741// and easy as the current handwritten version, which is partly a copy
742// of the strict arguments object materialization code.
743class FastNewRestParameterStub final : public PlatformCodeStub {
744 public:
745 explicit FastNewRestParameterStub(Isolate* isolate)
746 : PlatformCodeStub(isolate) {}
747
748 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewRestParameter);
749 DEFINE_PLATFORM_CODE_STUB(FastNewRestParameter, PlatformCodeStub);
750};
751
752
753// TODO(turbofan): This stub should be possible to write in TurboFan
754// using the CodeStubAssembler very soon in a way that is as efficient
755// and easy as the current handwritten version.
756class FastNewSloppyArgumentsStub final : public PlatformCodeStub {
757 public:
758 explicit FastNewSloppyArgumentsStub(Isolate* isolate)
759 : PlatformCodeStub(isolate) {}
760
761 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewSloppyArguments);
762 DEFINE_PLATFORM_CODE_STUB(FastNewSloppyArguments, PlatformCodeStub);
763};
764
765
766// TODO(turbofan): This stub should be possible to write in TurboFan
767// using the CodeStubAssembler very soon in a way that is as efficient
768// and easy as the current handwritten version.
769class FastNewStrictArgumentsStub final : public PlatformCodeStub {
770 public:
771 explicit FastNewStrictArgumentsStub(Isolate* isolate)
772 : PlatformCodeStub(isolate) {}
773
774 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewStrictArguments);
775 DEFINE_PLATFORM_CODE_STUB(FastNewStrictArguments, PlatformCodeStub);
776};
777
778
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000779class FastCloneRegExpStub final : public HydrogenCodeStub {
780 public:
781 explicit FastCloneRegExpStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
782
783 private:
784 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneRegExp);
785 DEFINE_HYDROGEN_CODE_STUB(FastCloneRegExp, HydrogenCodeStub);
786};
787
788
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000789class FastCloneShallowArrayStub : public HydrogenCodeStub {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100790 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000791 FastCloneShallowArrayStub(Isolate* isolate,
792 AllocationSiteMode allocation_site_mode)
793 : HydrogenCodeStub(isolate) {
794 set_sub_minor_key(AllocationSiteModeBits::encode(allocation_site_mode));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100795 }
796
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000797 AllocationSiteMode allocation_site_mode() const {
798 return AllocationSiteModeBits::decode(sub_minor_key());
799 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100800
801 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000802 class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100803
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000804 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowArray);
805 DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowArray, HydrogenCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100806};
807
808
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000809class FastCloneShallowObjectStub : public HydrogenCodeStub {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100810 public:
811 // Maximum number of properties in copied object.
812 static const int kMaximumClonedProperties = 6;
813
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000814 FastCloneShallowObjectStub(Isolate* isolate, int length)
815 : HydrogenCodeStub(isolate) {
816 DCHECK_GE(length, 0);
817 DCHECK_LE(length, kMaximumClonedProperties);
818 set_sub_minor_key(LengthBits::encode(length));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100819 }
820
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000821 int length() const { return LengthBits::decode(sub_minor_key()); }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100822
823 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000824 class LengthBits : public BitField<int, 0, 4> {};
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100825
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000826 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowObject);
827 DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowObject, HydrogenCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100828};
829
830
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000831class CreateAllocationSiteStub : public HydrogenCodeStub {
832 public:
833 explicit CreateAllocationSiteStub(Isolate* isolate)
834 : HydrogenCodeStub(isolate) { }
835
836 static void GenerateAheadOfTime(Isolate* isolate);
837
838 DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateAllocationSite);
839 DEFINE_HYDROGEN_CODE_STUB(CreateAllocationSite, HydrogenCodeStub);
840};
841
842
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000843class CreateWeakCellStub : public HydrogenCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100844 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000845 explicit CreateWeakCellStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
Ben Murdochb0fe1622011-05-05 13:52:32 +0100846
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000847 static void GenerateAheadOfTime(Isolate* isolate);
848
849 DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateWeakCell);
850 DEFINE_HYDROGEN_CODE_STUB(CreateWeakCell, HydrogenCodeStub);
851};
852
853
854class GrowArrayElementsStub : public HydrogenCodeStub {
855 public:
856 GrowArrayElementsStub(Isolate* isolate, bool is_js_array, ElementsKind kind)
857 : HydrogenCodeStub(isolate) {
858 set_sub_minor_key(ElementsKindBits::encode(kind) |
859 IsJsArrayBits::encode(is_js_array));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100860 }
861
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000862 ElementsKind elements_kind() const {
863 return ElementsKindBits::decode(sub_minor_key());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000864 }
865
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000866 bool is_js_array() const { return IsJsArrayBits::decode(sub_minor_key()); }
867
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000868 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000869 class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
870 class IsJsArrayBits : public BitField<bool, ElementsKindBits::kNext, 1> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000871
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000872 DEFINE_CALL_INTERFACE_DESCRIPTOR(GrowArrayElements);
873 DEFINE_HYDROGEN_CODE_STUB(GrowArrayElements, HydrogenCodeStub);
874};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000875
Ben Murdoch086aeea2011-05-13 15:57:08 +0100876
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000877class InstanceOfStub final : public PlatformCodeStub {
878 public:
879 explicit InstanceOfStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
Ben Murdoch086aeea2011-05-13 15:57:08 +0100880
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000881 private:
882 DEFINE_CALL_INTERFACE_DESCRIPTOR(InstanceOf);
883 DEFINE_PLATFORM_CODE_STUB(InstanceOf, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100884};
885
886
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000887enum AllocationSiteOverrideMode {
888 DONT_OVERRIDE,
889 DISABLE_ALLOCATION_SITES,
890 LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
891};
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100892
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000893
894class ArrayConstructorStub: public PlatformCodeStub {
895 public:
896 enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
897
898 ArrayConstructorStub(Isolate* isolate, int argument_count);
899
900 explicit ArrayConstructorStub(Isolate* isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100901
902 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000903 ArgumentCountKey argument_count() const {
904 return ArgumentCountBits::decode(minor_key_);
905 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100906
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000907 void GenerateDispatchToArrayStub(MacroAssembler* masm,
908 AllocationSiteOverrideMode mode);
909
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000910 void PrintName(std::ostream& os) const override; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000911
912 class ArgumentCountBits : public BitField<ArgumentCountKey, 0, 2> {};
913
914 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
915 DEFINE_PLATFORM_CODE_STUB(ArrayConstructor, PlatformCodeStub);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100916};
917
918
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000919class InternalArrayConstructorStub: public PlatformCodeStub {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100920 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000921 explicit InternalArrayConstructorStub(Isolate* isolate);
922
923 private:
924 void GenerateCase(MacroAssembler* masm, ElementsKind kind);
925
926 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
927 DEFINE_PLATFORM_CODE_STUB(InternalArrayConstructor, PlatformCodeStub);
928};
929
930
931class MathPowStub: public PlatformCodeStub {
932 public:
933 enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK };
934
935 MathPowStub(Isolate* isolate, ExponentType exponent_type)
936 : PlatformCodeStub(isolate) {
937 minor_key_ = ExponentTypeBits::encode(exponent_type);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100938 }
939
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000940 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000941 if (exponent_type() == TAGGED) {
942 return MathPowTaggedDescriptor(isolate());
943 } else if (exponent_type() == INTEGER) {
944 return MathPowIntegerDescriptor(isolate());
945 }
946 // A CallInterfaceDescriptor doesn't specify double registers (yet).
947 return ContextOnlyDescriptor(isolate());
948 }
949
950 private:
951 ExponentType exponent_type() const {
952 return ExponentTypeBits::decode(minor_key_);
953 }
954
955 class ExponentTypeBits : public BitField<ExponentType, 0, 2> {};
956
957 DEFINE_PLATFORM_CODE_STUB(MathPow, PlatformCodeStub);
958};
959
960
961class CallICStub: public PlatformCodeStub {
962 public:
963 CallICStub(Isolate* isolate, const CallICState& state)
964 : PlatformCodeStub(isolate) {
965 minor_key_ = state.GetExtraICState();
966 }
967
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000968 Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000969
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000970 InlineCacheState GetICState() const override { return GENERIC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000971
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000972 ExtraICState GetExtraICState() const final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000973 return static_cast<ExtraICState>(minor_key_);
974 }
975
976 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000977 int arg_count() const { return state().argc(); }
978 ConvertReceiverMode convert_mode() const { return state().convert_mode(); }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100979 TailCallMode tail_call_mode() const { return state().tail_call_mode(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000980
981 CallICState state() const {
982 return CallICState(static_cast<ExtraICState>(minor_key_));
983 }
984
985 // Code generation helpers.
986 void GenerateMiss(MacroAssembler* masm);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000987 void HandleArrayCase(MacroAssembler* masm, Label* miss);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000988
989 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000990 void PrintState(std::ostream& os) const override; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000991
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000992 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedbackAndVector);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000993 DEFINE_PLATFORM_CODE_STUB(CallIC, PlatformCodeStub);
994};
995
996
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000997// TODO(verwaest): Translate to hydrogen code stub.
998class FunctionPrototypeStub : public PlatformCodeStub {
999 public:
1000 explicit FunctionPrototypeStub(Isolate* isolate)
1001 : PlatformCodeStub(isolate) {}
1002
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001003 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001004
1005 // TODO(mvstanton): only the receiver register is accessed. When this is
1006 // translated to a hydrogen code stub, a new CallInterfaceDescriptor
1007 // should be created that just uses that register for more efficient code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001008 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
1009 return LoadWithVectorDescriptor(isolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001010 }
1011
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001012 DEFINE_PLATFORM_CODE_STUB(FunctionPrototype, PlatformCodeStub);
1013};
1014
1015
1016// TODO(mvstanton): Translate to hydrogen code stub.
1017class LoadIndexedInterceptorStub : public PlatformCodeStub {
1018 public:
1019 explicit LoadIndexedInterceptorStub(Isolate* isolate)
1020 : PlatformCodeStub(isolate) {}
1021
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001022 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
1023 Code::StubType GetStubType() const override { return Code::FAST; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001024
1025 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1026 DEFINE_PLATFORM_CODE_STUB(LoadIndexedInterceptor, PlatformCodeStub);
1027};
1028
1029
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001030class LoadIndexedStringStub : public PlatformCodeStub {
1031 public:
1032 explicit LoadIndexedStringStub(Isolate* isolate)
1033 : PlatformCodeStub(isolate) {}
1034
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001035 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
1036 Code::StubType GetStubType() const override { return Code::FAST; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001037
1038 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1039 DEFINE_PLATFORM_CODE_STUB(LoadIndexedString, PlatformCodeStub);
1040};
1041
1042
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001043class HandlerStub : public HydrogenCodeStub {
1044 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001045 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
1046 ExtraICState GetExtraICState() const override { return kind(); }
1047 InlineCacheState GetICState() const override { return MONOMORPHIC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001048
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001049 void InitializeDescriptor(CodeStubDescriptor* descriptor) override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001050
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001051 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001052
1053 protected:
1054 explicit HandlerStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
1055
1056 virtual Code::Kind kind() const = 0;
1057
1058 DEFINE_CODE_STUB_BASE(HandlerStub, HydrogenCodeStub);
1059};
1060
1061
1062class LoadFieldStub: public HandlerStub {
1063 public:
1064 LoadFieldStub(Isolate* isolate, FieldIndex index) : HandlerStub(isolate) {
1065 int property_index_key = index.GetFieldAccessStubKey();
1066 set_sub_minor_key(LoadFieldByIndexBits::encode(property_index_key));
1067 }
1068
1069 FieldIndex index() const {
1070 int property_index_key = LoadFieldByIndexBits::decode(sub_minor_key());
1071 return FieldIndex::FromFieldAccessStubKey(property_index_key);
1072 }
1073
1074 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001075 Code::Kind kind() const override { return Code::LOAD_IC; }
1076 Code::StubType GetStubType() const override { return Code::FAST; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001077
1078 private:
1079 class LoadFieldByIndexBits : public BitField<int, 0, 13> {};
1080
1081 DEFINE_HANDLER_CODE_STUB(LoadField, HandlerStub);
1082};
1083
1084
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001085class ArrayBufferViewLoadFieldStub : public HandlerStub {
1086 public:
1087 ArrayBufferViewLoadFieldStub(Isolate* isolate, FieldIndex index)
1088 : HandlerStub(isolate) {
1089 int property_index_key = index.GetFieldAccessStubKey();
1090 set_sub_minor_key(
1091 ArrayBufferViewLoadFieldByIndexBits::encode(property_index_key));
1092 }
1093
1094 FieldIndex index() const {
1095 int property_index_key =
1096 ArrayBufferViewLoadFieldByIndexBits::decode(sub_minor_key());
1097 return FieldIndex::FromFieldAccessStubKey(property_index_key);
1098 }
1099
1100 protected:
1101 Code::Kind kind() const override { return Code::LOAD_IC; }
1102 Code::StubType GetStubType() const override { return Code::FAST; }
1103
1104 private:
1105 class ArrayBufferViewLoadFieldByIndexBits : public BitField<int, 0, 13> {};
1106
1107 DEFINE_HANDLER_CODE_STUB(ArrayBufferViewLoadField, HandlerStub);
1108};
1109
1110
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001111class KeyedLoadSloppyArgumentsStub : public HandlerStub {
1112 public:
1113 explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate)
1114 : HandlerStub(isolate) {}
1115
1116 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001117 Code::Kind kind() const override { return Code::KEYED_LOAD_IC; }
1118 Code::StubType GetStubType() const override { return Code::FAST; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001119
1120 private:
1121 DEFINE_HANDLER_CODE_STUB(KeyedLoadSloppyArguments, HandlerStub);
1122};
1123
1124
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001125class CommonStoreModeBits : public BitField<KeyedAccessStoreMode, 0, 3> {};
1126
1127class KeyedStoreSloppyArgumentsStub : public HandlerStub {
1128 public:
1129 explicit KeyedStoreSloppyArgumentsStub(Isolate* isolate,
1130 KeyedAccessStoreMode mode)
1131 : HandlerStub(isolate) {
1132 set_sub_minor_key(CommonStoreModeBits::encode(mode));
1133 }
1134
1135 protected:
1136 Code::Kind kind() const override { return Code::KEYED_STORE_IC; }
1137 Code::StubType GetStubType() const override { return Code::FAST; }
1138
1139 private:
1140 DEFINE_HANDLER_CODE_STUB(KeyedStoreSloppyArguments, HandlerStub);
1141};
1142
1143
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001144class LoadConstantStub : public HandlerStub {
1145 public:
1146 LoadConstantStub(Isolate* isolate, int constant_index)
1147 : HandlerStub(isolate) {
1148 set_sub_minor_key(ConstantIndexBits::encode(constant_index));
1149 }
1150
1151 int constant_index() const {
1152 return ConstantIndexBits::decode(sub_minor_key());
1153 }
1154
1155 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001156 Code::Kind kind() const override { return Code::LOAD_IC; }
1157 Code::StubType GetStubType() const override { return Code::FAST; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001158
1159 private:
1160 class ConstantIndexBits : public BitField<int, 0, kSubMinorKeyBits> {};
1161
1162 DEFINE_HANDLER_CODE_STUB(LoadConstant, HandlerStub);
1163};
1164
1165
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001166class StoreFieldStub : public HandlerStub {
1167 public:
1168 StoreFieldStub(Isolate* isolate, FieldIndex index,
1169 Representation representation)
1170 : HandlerStub(isolate) {
1171 int property_index_key = index.GetFieldAccessStubKey();
1172 uint8_t repr = PropertyDetails::EncodeRepresentation(representation);
1173 set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) |
1174 RepresentationBits::encode(repr));
1175 }
1176
1177 FieldIndex index() const {
1178 int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key());
1179 return FieldIndex::FromFieldAccessStubKey(property_index_key);
1180 }
1181
1182 Representation representation() {
1183 uint8_t repr = RepresentationBits::decode(sub_minor_key());
1184 return PropertyDetails::DecodeRepresentation(repr);
1185 }
1186
1187 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001188 Code::Kind kind() const override { return Code::STORE_IC; }
1189 Code::StubType GetStubType() const override { return Code::FAST; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001190
1191 private:
1192 class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
1193 class RepresentationBits : public BitField<uint8_t, 13, 4> {};
1194
1195 DEFINE_HANDLER_CODE_STUB(StoreField, HandlerStub);
1196};
1197
1198
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001199// Register and parameter access methods are specified here instead of in
1200// the CallInterfaceDescriptor because the stub uses a different descriptor
1201// if FLAG_vector_stores is on.
1202class StoreTransitionHelper {
1203 public:
1204 static Register ReceiverRegister() {
1205 return StoreTransitionDescriptor::ReceiverRegister();
1206 }
1207
1208 static Register NameRegister() {
1209 return StoreTransitionDescriptor::NameRegister();
1210 }
1211
1212 static Register ValueRegister() {
1213 return StoreTransitionDescriptor::ValueRegister();
1214 }
1215
1216 static Register SlotRegister() {
1217 return VectorStoreTransitionDescriptor::SlotRegister();
1218 }
1219
1220 static Register VectorRegister() {
1221 return VectorStoreTransitionDescriptor::VectorRegister();
1222 }
1223
1224 static Register MapRegister() {
1225 return VectorStoreTransitionDescriptor::MapRegister();
1226 }
1227
1228 static int ReceiverIndex() {
1229 return StoreTransitionDescriptor::kReceiverIndex;
1230 }
1231
1232 static int NameIndex() { return StoreTransitionDescriptor::kReceiverIndex; }
1233
1234 static int ValueIndex() { return StoreTransitionDescriptor::kValueIndex; }
1235
1236 static int MapIndex() {
1237 DCHECK(static_cast<int>(VectorStoreTransitionDescriptor::kMapIndex) ==
1238 static_cast<int>(StoreTransitionDescriptor::kMapIndex));
1239 return StoreTransitionDescriptor::kMapIndex;
1240 }
1241
1242 static int VectorIndex() {
1243 if (HasVirtualSlotArg()) {
1244 return VectorStoreTransitionDescriptor::kVirtualSlotVectorIndex;
1245 }
1246 return VectorStoreTransitionDescriptor::kVectorIndex;
1247 }
1248
1249 // Some platforms don't have a slot arg.
1250 static bool HasVirtualSlotArg() {
1251 return SlotRegister().is(no_reg);
1252 }
1253};
1254
1255
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001256class StoreTransitionStub : public HandlerStub {
1257 public:
1258 enum StoreMode {
1259 StoreMapOnly,
1260 StoreMapAndValue,
1261 ExtendStorageAndStoreMapAndValue
1262 };
1263
1264 explicit StoreTransitionStub(Isolate* isolate) : HandlerStub(isolate) {
1265 set_sub_minor_key(StoreModeBits::encode(StoreMapOnly));
1266 }
1267
1268 StoreTransitionStub(Isolate* isolate, FieldIndex index,
1269 Representation representation, StoreMode store_mode)
1270 : HandlerStub(isolate) {
1271 DCHECK(store_mode != StoreMapOnly);
1272 int property_index_key = index.GetFieldAccessStubKey();
1273 uint8_t repr = PropertyDetails::EncodeRepresentation(representation);
1274 set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) |
1275 RepresentationBits::encode(repr) |
1276 StoreModeBits::encode(store_mode));
1277 }
1278
1279 FieldIndex index() const {
1280 DCHECK(store_mode() != StoreMapOnly);
1281 int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key());
1282 return FieldIndex::FromFieldAccessStubKey(property_index_key);
1283 }
1284
1285 Representation representation() {
1286 DCHECK(store_mode() != StoreMapOnly);
1287 uint8_t repr = RepresentationBits::decode(sub_minor_key());
1288 return PropertyDetails::DecodeRepresentation(repr);
1289 }
1290
1291 StoreMode store_mode() const {
1292 return StoreModeBits::decode(sub_minor_key());
1293 }
1294
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001295 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001296
1297 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001298 Code::Kind kind() const override { return Code::STORE_IC; }
1299 Code::StubType GetStubType() const override { return Code::FAST; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001300
1301 private:
1302 class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
1303 class RepresentationBits : public BitField<uint8_t, 13, 4> {};
1304 class StoreModeBits : public BitField<StoreMode, 17, 2> {};
1305
1306 DEFINE_HANDLER_CODE_STUB(StoreTransition, HandlerStub);
1307};
1308
1309
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001310class StoreGlobalStub : public HandlerStub {
1311 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001312 StoreGlobalStub(Isolate* isolate, PropertyCellType type,
1313 Maybe<PropertyCellConstantType> constant_type,
1314 bool check_global)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001315 : HandlerStub(isolate) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001316 PropertyCellConstantType encoded_constant_type =
1317 constant_type.FromMaybe(PropertyCellConstantType::kSmi);
1318 set_sub_minor_key(CellTypeBits::encode(type) |
1319 ConstantTypeBits::encode(encoded_constant_type) |
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001320 CheckGlobalBits::encode(check_global));
1321 }
1322
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001323 static Handle<HeapObject> property_cell_placeholder(Isolate* isolate) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001324 return isolate->factory()->uninitialized_value();
1325 }
1326
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001327 static Handle<HeapObject> global_map_placeholder(Isolate* isolate) {
1328 return isolate->factory()->termination_exception();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001329 }
1330
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001331 Handle<Code> GetCodeCopyFromTemplate(Handle<JSGlobalObject> global,
1332 Handle<PropertyCell> cell) {
1333 Code::FindAndReplacePattern pattern;
1334 if (check_global()) {
1335 pattern.Add(handle(global_map_placeholder(isolate())->map()),
1336 Map::WeakCellForMap(Handle<Map>(global->map())));
1337 }
1338 pattern.Add(handle(property_cell_placeholder(isolate())->map()),
1339 isolate()->factory()->NewWeakCell(cell));
1340 return CodeStub::GetCodeCopy(pattern);
1341 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001342
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001343 Code::Kind kind() const override { return Code::STORE_IC; }
1344
1345 PropertyCellType cell_type() const {
1346 return CellTypeBits::decode(sub_minor_key());
1347 }
1348
1349 PropertyCellConstantType constant_type() const {
1350 DCHECK(PropertyCellType::kConstantType == cell_type());
1351 return ConstantTypeBits::decode(sub_minor_key());
1352 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001353
1354 bool check_global() const { return CheckGlobalBits::decode(sub_minor_key()); }
1355
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001356 Representation representation() {
1357 return Representation::FromKind(
1358 RepresentationBits::decode(sub_minor_key()));
1359 }
1360
1361 void set_representation(Representation r) {
1362 set_sub_minor_key(RepresentationBits::update(sub_minor_key(), r.kind()));
1363 }
1364
1365 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001366 class CellTypeBits : public BitField<PropertyCellType, 0, 2> {};
1367 class ConstantTypeBits : public BitField<PropertyCellConstantType, 2, 2> {};
1368 class RepresentationBits : public BitField<Representation::Kind, 4, 8> {};
1369 class CheckGlobalBits : public BitField<bool, 12, 1> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001370
1371 DEFINE_HANDLER_CODE_STUB(StoreGlobal, HandlerStub);
1372};
1373
1374
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001375class LoadGlobalViaContextStub final : public PlatformCodeStub {
1376 public:
1377 static const int kMaximumDepth = 15;
1378
1379 LoadGlobalViaContextStub(Isolate* isolate, int depth)
1380 : PlatformCodeStub(isolate) {
1381 minor_key_ = DepthBits::encode(depth);
1382 }
1383
1384 int depth() const { return DepthBits::decode(minor_key_); }
1385
1386 private:
1387 class DepthBits : public BitField<int, 0, 4> {};
1388 STATIC_ASSERT(DepthBits::kMax == kMaximumDepth);
1389
1390 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadGlobalViaContext);
1391 DEFINE_PLATFORM_CODE_STUB(LoadGlobalViaContext, PlatformCodeStub);
1392};
1393
1394
1395class StoreGlobalViaContextStub final : public PlatformCodeStub {
1396 public:
1397 static const int kMaximumDepth = 15;
1398
1399 StoreGlobalViaContextStub(Isolate* isolate, int depth,
1400 LanguageMode language_mode)
1401 : PlatformCodeStub(isolate) {
1402 minor_key_ =
1403 DepthBits::encode(depth) | LanguageModeBits::encode(language_mode);
1404 }
1405
1406 int depth() const { return DepthBits::decode(minor_key_); }
1407 LanguageMode language_mode() const {
1408 return LanguageModeBits::decode(minor_key_);
1409 }
1410
1411 private:
1412 class DepthBits : public BitField<int, 0, 4> {};
1413 STATIC_ASSERT(DepthBits::kMax == kMaximumDepth);
1414 class LanguageModeBits : public BitField<LanguageMode, 4, 2> {};
1415 STATIC_ASSERT(LANGUAGE_END == 3);
1416
1417 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreGlobalViaContext);
1418 DEFINE_PLATFORM_CODE_STUB(StoreGlobalViaContext, PlatformCodeStub);
1419};
1420
1421
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001422class CallApiFunctionStub : public PlatformCodeStub {
1423 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001424 explicit CallApiFunctionStub(Isolate* isolate, bool call_data_undefined)
1425 : PlatformCodeStub(isolate) {
1426 minor_key_ = CallDataUndefinedBits::encode(call_data_undefined);
1427 }
1428
1429 private:
1430 bool call_data_undefined() const {
1431 return CallDataUndefinedBits::decode(minor_key_);
1432 }
1433
1434 class CallDataUndefinedBits : public BitField<bool, 0, 1> {};
1435
1436 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiFunction);
1437 DEFINE_PLATFORM_CODE_STUB(CallApiFunction, PlatformCodeStub);
1438};
1439
1440
1441class CallApiAccessorStub : public PlatformCodeStub {
1442 public:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001443 CallApiAccessorStub(Isolate* isolate, bool is_store, bool call_data_undefined,
1444 bool is_lazy)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001445 : PlatformCodeStub(isolate) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001446 minor_key_ = IsStoreBits::encode(is_store) |
1447 CallDataUndefinedBits::encode(call_data_undefined) |
Ben Murdoch097c5b22016-05-18 11:27:45 +01001448 ArgumentBits::encode(is_store ? 1 : 0) |
1449 IsLazyAccessorBits::encode(is_lazy);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001450 }
1451
1452 protected:
1453 // For CallApiFunctionWithFixedArgsStub, see below.
1454 static const int kArgBits = 3;
1455 CallApiAccessorStub(Isolate* isolate, int argc, bool call_data_undefined)
1456 : PlatformCodeStub(isolate) {
1457 minor_key_ = IsStoreBits::encode(false) |
1458 CallDataUndefinedBits::encode(call_data_undefined) |
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001459 ArgumentBits::encode(argc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001460 }
1461
1462 private:
1463 bool is_store() const { return IsStoreBits::decode(minor_key_); }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001464 bool is_lazy() const { return IsLazyAccessorBits::decode(minor_key_); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001465 bool call_data_undefined() const {
1466 return CallDataUndefinedBits::decode(minor_key_);
1467 }
1468 int argc() const { return ArgumentBits::decode(minor_key_); }
1469
1470 class IsStoreBits: public BitField<bool, 0, 1> {};
1471 class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001472 class ArgumentBits : public BitField<int, 2, kArgBits> {};
Ben Murdoch097c5b22016-05-18 11:27:45 +01001473 class IsLazyAccessorBits : public BitField<bool, 3 + kArgBits, 1> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001474
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001475 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiAccessor);
1476 DEFINE_PLATFORM_CODE_STUB(CallApiAccessor, PlatformCodeStub);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001477};
1478
1479
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001480// TODO(dcarney): see if it's possible to remove this later without performance
1481// degradation.
1482// This is not a real stub, but a way of generating the CallApiAccessorStub
1483// (which has the same abi) which makes it clear that it is not an accessor.
1484class CallApiFunctionWithFixedArgsStub : public CallApiAccessorStub {
1485 public:
1486 static const int kMaxFixedArgs = (1 << kArgBits) - 1;
1487 CallApiFunctionWithFixedArgsStub(Isolate* isolate, int argc,
1488 bool call_data_undefined)
1489 : CallApiAccessorStub(isolate, argc, call_data_undefined) {
1490 DCHECK(0 <= argc && argc <= kMaxFixedArgs);
1491 }
1492};
1493
1494
1495typedef ApiAccessorDescriptor ApiFunctionWithFixedArgsDescriptor;
1496
1497
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001498class CallApiGetterStub : public PlatformCodeStub {
1499 public:
1500 explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1501
1502 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiGetter);
1503 DEFINE_PLATFORM_CODE_STUB(CallApiGetter, PlatformCodeStub);
1504};
1505
1506
1507class BinaryOpICStub : public HydrogenCodeStub {
1508 public:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001509 BinaryOpICStub(Isolate* isolate, Token::Value op)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001510 : HydrogenCodeStub(isolate, UNINITIALIZED) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001511 BinaryOpICState state(isolate, op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001512 set_sub_minor_key(state.GetExtraICState());
1513 }
1514
1515 BinaryOpICStub(Isolate* isolate, const BinaryOpICState& state)
1516 : HydrogenCodeStub(isolate) {
1517 set_sub_minor_key(state.GetExtraICState());
1518 }
1519
1520 static void GenerateAheadOfTime(Isolate* isolate);
1521
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001522 Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001523
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001524 InlineCacheState GetICState() const final { return state().GetICState(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001525
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001526 ExtraICState GetExtraICState() const final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001527 return static_cast<ExtraICState>(sub_minor_key());
1528 }
1529
1530 BinaryOpICState state() const {
1531 return BinaryOpICState(isolate(), GetExtraICState());
1532 }
1533
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001534 void PrintState(std::ostream& os) const final; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001535
1536 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1537 static const int kLeft = 0;
1538 static const int kRight = 1;
1539
1540 private:
1541 static void GenerateAheadOfTime(Isolate* isolate,
1542 const BinaryOpICState& state);
1543
1544 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1545 DEFINE_HYDROGEN_CODE_STUB(BinaryOpIC, HydrogenCodeStub);
1546};
1547
1548
1549// TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
1550// call support for stubs in Hydrogen.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001551class BinaryOpICWithAllocationSiteStub final : public PlatformCodeStub {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001552 public:
1553 BinaryOpICWithAllocationSiteStub(Isolate* isolate,
1554 const BinaryOpICState& state)
1555 : PlatformCodeStub(isolate) {
1556 minor_key_ = state.GetExtraICState();
1557 }
1558
1559 static void GenerateAheadOfTime(Isolate* isolate);
1560
1561 Handle<Code> GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site) {
1562 Code::FindAndReplacePattern pattern;
1563 pattern.Add(isolate()->factory()->undefined_map(), allocation_site);
1564 return CodeStub::GetCodeCopy(pattern);
1565 }
1566
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001567 Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001568
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001569 InlineCacheState GetICState() const override { return state().GetICState(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001570
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001571 ExtraICState GetExtraICState() const override {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001572 return static_cast<ExtraICState>(minor_key_);
1573 }
1574
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001575 void PrintState(std::ostream& os) const override; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001576
1577 private:
1578 BinaryOpICState state() const {
1579 return BinaryOpICState(isolate(), static_cast<ExtraICState>(minor_key_));
1580 }
1581
1582 static void GenerateAheadOfTime(Isolate* isolate,
1583 const BinaryOpICState& state);
1584
1585 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1586 DEFINE_PLATFORM_CODE_STUB(BinaryOpICWithAllocationSite, PlatformCodeStub);
1587};
1588
1589
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001590class BinaryOpWithAllocationSiteStub final : public BinaryOpICStub {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001591 public:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001592 BinaryOpWithAllocationSiteStub(Isolate* isolate, Token::Value op)
1593 : BinaryOpICStub(isolate, op) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001594
1595 BinaryOpWithAllocationSiteStub(Isolate* isolate, const BinaryOpICState& state)
1596 : BinaryOpICStub(isolate, state) {}
1597
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001598 Code::Kind GetCodeKind() const final { return Code::STUB; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001599
1600 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1601 static const int kAllocationSite = 0;
1602 static const int kLeft = 1;
1603 static const int kRight = 2;
1604
1605 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1606 DEFINE_HYDROGEN_CODE_STUB(BinaryOpWithAllocationSite, BinaryOpICStub);
1607};
1608
1609
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001610class StringAddStub final : public HydrogenCodeStub {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001611 public:
1612 StringAddStub(Isolate* isolate, StringAddFlags flags,
1613 PretenureFlag pretenure_flag)
1614 : HydrogenCodeStub(isolate) {
1615 set_sub_minor_key(StringAddFlagsBits::encode(flags) |
1616 PretenureFlagBits::encode(pretenure_flag));
1617 }
1618
1619 StringAddFlags flags() const {
1620 return StringAddFlagsBits::decode(sub_minor_key());
1621 }
1622
1623 PretenureFlag pretenure_flag() const {
1624 return PretenureFlagBits::decode(sub_minor_key());
1625 }
1626
1627 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1628 static const int kLeft = 0;
1629 static const int kRight = 1;
1630
1631 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001632 class StringAddFlagsBits : public BitField<StringAddFlags, 0, 3> {};
1633 class PretenureFlagBits : public BitField<PretenureFlag, 3, 1> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001634
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001635 void PrintBaseName(std::ostream& os) const override; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001636
1637 DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd);
1638 DEFINE_HYDROGEN_CODE_STUB(StringAdd, HydrogenCodeStub);
1639};
1640
1641
1642class CompareICStub : public PlatformCodeStub {
1643 public:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001644 CompareICStub(Isolate* isolate, Token::Value op, CompareICState::State left,
1645 CompareICState::State right, CompareICState::State state)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001646 : PlatformCodeStub(isolate) {
1647 DCHECK(Token::IsCompareOp(op));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001648 minor_key_ = OpBits::encode(op - Token::EQ) |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001649 LeftStateBits::encode(left) | RightStateBits::encode(right) |
1650 StateBits::encode(state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001651 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001652
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001653 void set_known_map(Handle<Map> map) { known_map_ = map; }
1654
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001655 InlineCacheState GetICState() const override;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001656
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001657 Token::Value op() const {
1658 return static_cast<Token::Value>(Token::EQ + OpBits::decode(minor_key_));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001659 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001660
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001661 CompareICState::State left() const {
1662 return LeftStateBits::decode(minor_key_);
1663 }
1664 CompareICState::State right() const {
1665 return RightStateBits::decode(minor_key_);
1666 }
1667 CompareICState::State state() const { return StateBits::decode(minor_key_); }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001668
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001669 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001670 Code::Kind GetCodeKind() const override { return Code::COMPARE_IC; }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001671
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001672 void GenerateBooleans(MacroAssembler* masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001673 void GenerateSmis(MacroAssembler* masm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001674 void GenerateNumbers(MacroAssembler* masm);
1675 void GenerateInternalizedStrings(MacroAssembler* masm);
Ben Murdoch257744e2011-11-30 15:57:28 +00001676 void GenerateStrings(MacroAssembler* masm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001677 void GenerateUniqueNames(MacroAssembler* masm);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001678 void GenerateReceivers(MacroAssembler* masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001679 void GenerateMiss(MacroAssembler* masm);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001680 void GenerateKnownReceivers(MacroAssembler* masm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001681 void GenerateGeneric(MacroAssembler* masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001682
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001683 bool strict() const { return op() == Token::EQ_STRICT; }
1684 Condition GetCondition() const;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001685
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001686 void AddToSpecialCache(Handle<Code> new_object) override;
1687 bool FindCodeInSpecialCache(Code** code_out) override;
1688 bool UseSpecialCache() override {
1689 return state() == CompareICState::KNOWN_RECEIVER;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001690 }
1691
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001692 class OpBits : public BitField<int, 0, 3> {};
Ben Murdoch097c5b22016-05-18 11:27:45 +01001693 class LeftStateBits : public BitField<CompareICState::State, 3, 4> {};
1694 class RightStateBits : public BitField<CompareICState::State, 7, 4> {};
1695 class StateBits : public BitField<CompareICState::State, 11, 4> {};
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001696
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001697 Handle<Map> known_map_;
1698
1699 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1700 DEFINE_PLATFORM_CODE_STUB(CompareIC, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001701};
1702
1703
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001704class CompareNilICStub : public HydrogenCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001705 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001706 Type* GetType(Zone* zone, Handle<Map> map = Handle<Map>());
1707 Type* GetInputType(Zone* zone, Handle<Map> map);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001708
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001709 CompareNilICStub(Isolate* isolate, NilValue nil) : HydrogenCodeStub(isolate) {
1710 set_sub_minor_key(NilValueBits::encode(nil));
1711 }
1712
1713 CompareNilICStub(Isolate* isolate, ExtraICState ic_state,
1714 InitializationState init_state = INITIALIZED)
1715 : HydrogenCodeStub(isolate, init_state) {
1716 set_sub_minor_key(ic_state);
1717 }
1718
1719 static Handle<Code> GetUninitialized(Isolate* isolate,
1720 NilValue nil) {
1721 return CompareNilICStub(isolate, nil, UNINITIALIZED).GetCode();
1722 }
1723
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001724 InlineCacheState GetICState() const override {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001725 State state = this->state();
1726 if (state.Contains(GENERIC)) {
1727 return MEGAMORPHIC;
1728 } else if (state.Contains(MONOMORPHIC_MAP)) {
1729 return MONOMORPHIC;
1730 } else {
1731 return PREMONOMORPHIC;
1732 }
1733 }
1734
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001735 Code::Kind GetCodeKind() const override { return Code::COMPARE_NIL_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001736
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001737 ExtraICState GetExtraICState() const override { return sub_minor_key(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001738
1739 void UpdateStatus(Handle<Object> object);
1740
1741 bool IsMonomorphic() const { return state().Contains(MONOMORPHIC_MAP); }
1742
1743 NilValue nil_value() const { return NilValueBits::decode(sub_minor_key()); }
1744
1745 void ClearState() {
1746 set_sub_minor_key(TypesBits::update(sub_minor_key(), 0));
1747 }
1748
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001749 void PrintState(std::ostream& os) const override; // NOLINT
1750 void PrintBaseName(std::ostream& os) const override; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001751
1752 private:
1753 CompareNilICStub(Isolate* isolate, NilValue nil,
1754 InitializationState init_state)
1755 : HydrogenCodeStub(isolate, init_state) {
1756 set_sub_minor_key(NilValueBits::encode(nil));
1757 }
1758
1759 enum CompareNilType {
1760 UNDEFINED,
1761 NULL_TYPE,
1762 MONOMORPHIC_MAP,
1763 GENERIC,
1764 NUMBER_OF_TYPES
1765 };
1766
1767 // At most 6 different types can be distinguished, because the Code object
1768 // only has room for a single byte to hold a set and there are two more
1769 // boolean flags we need to store. :-P
1770 STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
1771
1772 class State : public EnumSet<CompareNilType, byte> {
1773 public:
1774 State() : EnumSet<CompareNilType, byte>(0) { }
1775 explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
1776 };
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001777 friend std::ostream& operator<<(std::ostream& os, const State& s);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001778
1779 State state() const { return State(TypesBits::decode(sub_minor_key())); }
1780
1781 class NilValueBits : public BitField<NilValue, 0, 1> {};
1782 class TypesBits : public BitField<byte, 1, NUMBER_OF_TYPES> {};
1783
1784 friend class CompareNilIC;
1785
1786 DEFINE_CALL_INTERFACE_DESCRIPTOR(CompareNil);
1787 DEFINE_HYDROGEN_CODE_STUB(CompareNilIC, HydrogenCodeStub);
1788};
1789
1790
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001791std::ostream& operator<<(std::ostream& os, const CompareNilICStub::State& s);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001792
1793
1794class CEntryStub : public PlatformCodeStub {
1795 public:
1796 CEntryStub(Isolate* isolate, int result_size,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001797 SaveFPRegsMode save_doubles = kDontSaveFPRegs,
1798 ArgvMode argv_mode = kArgvOnStack)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001799 : PlatformCodeStub(isolate) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001800 minor_key_ = SaveDoublesBits::encode(save_doubles == kSaveFPRegs) |
1801 ArgvMode::encode(argv_mode == kArgvInRegister);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001802 DCHECK(result_size == 1 || result_size == 2 || result_size == 3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001803 minor_key_ = ResultSizeBits::update(minor_key_, result_size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001804 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001805
1806 // The version of this stub that doesn't save doubles is generated ahead of
1807 // time, so it's OK to call it from other stubs that can't cope with GC during
1808 // their code generation. On machines that always have gp registers (x64) we
1809 // can generate both variants ahead of time.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001810 static void GenerateAheadOfTime(Isolate* isolate);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001811
1812 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001813 bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001814 bool argv_in_register() const { return ArgvMode::decode(minor_key_); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001815 int result_size() const { return ResultSizeBits::decode(minor_key_); }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001816
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001817 bool NeedsImmovableCode() override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001818
1819 class SaveDoublesBits : public BitField<bool, 0, 1> {};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001820 class ArgvMode : public BitField<bool, 1, 1> {};
1821 class ResultSizeBits : public BitField<int, 2, 3> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001822
1823 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1824 DEFINE_PLATFORM_CODE_STUB(CEntry, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001825};
1826
1827
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001828class JSEntryStub : public PlatformCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001829 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001830 JSEntryStub(Isolate* isolate, StackFrame::Type type)
1831 : PlatformCodeStub(isolate) {
1832 DCHECK(type == StackFrame::ENTRY || type == StackFrame::ENTRY_CONSTRUCT);
1833 minor_key_ = StackFrameTypeBits::encode(type);
1834 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001835
1836 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001837 void FinishCode(Handle<Code> code) override;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001838
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001839 void PrintName(std::ostream& os) const override { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001840 os << (type() == StackFrame::ENTRY ? "JSEntryStub"
1841 : "JSConstructEntryStub");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001842 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001843
1844 StackFrame::Type type() const {
1845 return StackFrameTypeBits::decode(minor_key_);
1846 }
1847
1848 class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {};
1849
1850 int handler_offset_;
1851
1852 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1853 DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001854};
1855
1856
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001857class RegExpExecStub: public PlatformCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001858 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001859 explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001860
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001861 DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
1862 DEFINE_PLATFORM_CODE_STUB(RegExpExec, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001863};
1864
1865
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001866class RegExpConstructResultStub final : public HydrogenCodeStub {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001867 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001868 explicit RegExpConstructResultStub(Isolate* isolate)
1869 : HydrogenCodeStub(isolate) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001870
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001871 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1872 static const int kLength = 0;
1873 static const int kIndex = 1;
1874 static const int kInput = 2;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001875
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001876 DEFINE_CALL_INTERFACE_DESCRIPTOR(RegExpConstructResult);
1877 DEFINE_HYDROGEN_CODE_STUB(RegExpConstructResult, HydrogenCodeStub);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001878};
1879
1880
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001881// TODO(bmeurer/mvstanton): Turn CallConstructStub into ConstructICStub.
1882class CallConstructStub final : public PlatformCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001883 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001884 explicit CallConstructStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001885
1886 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallConstruct);
1887 DEFINE_PLATFORM_CODE_STUB(CallConstruct, PlatformCodeStub);
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01001888};
1889
1890
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001891enum StringIndexFlags {
1892 // Accepts smis or heap numbers.
1893 STRING_INDEX_IS_NUMBER,
1894
1895 // Accepts smis or heap numbers that are valid array indices
1896 // (ECMA-262 15.4). Invalid indices are reported as being out of
1897 // range.
1898 STRING_INDEX_IS_ARRAY_INDEX
1899};
1900
1901
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001902enum ReceiverCheckMode {
1903 // We don't know anything about the receiver.
1904 RECEIVER_IS_UNKNOWN,
1905
1906 // We know the receiver is a string.
1907 RECEIVER_IS_STRING
1908};
1909
1910
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001911enum EmbedMode {
1912 // The code being generated is part of an IC handler, which may MISS
1913 // to an IC in failure cases.
1914 PART_OF_IC_HANDLER,
1915
1916 NOT_PART_OF_IC_HANDLER
1917};
1918
1919
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001920// Generates code implementing String.prototype.charCodeAt.
1921//
1922// Only supports the case when the receiver is a string and the index
1923// is a number (smi or heap number) that is a valid index into the
1924// string. Additional index constraints are specified by the
1925// flags. Otherwise, bails out to the provided labels.
1926//
1927// Register usage: |object| may be changed to another string in a way
1928// that doesn't affect charCodeAt/charAt semantics, |index| is
1929// preserved, |scratch| and |result| are clobbered.
1930class StringCharCodeAtGenerator {
1931 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001932 StringCharCodeAtGenerator(Register object, Register index, Register result,
1933 Label* receiver_not_string, Label* index_not_number,
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001934 Label* index_out_of_range,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001935 StringIndexFlags index_flags,
1936 ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001937 : object_(object),
1938 index_(index),
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001939 result_(result),
1940 receiver_not_string_(receiver_not_string),
1941 index_not_number_(index_not_number),
1942 index_out_of_range_(index_out_of_range),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001943 index_flags_(index_flags),
1944 check_mode_(check_mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001945 DCHECK(!result_.is(object_));
1946 DCHECK(!result_.is(index_));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001947 }
1948
1949 // Generates the fast case code. On the fallthrough path |result|
1950 // register contains the result.
1951 void GenerateFast(MacroAssembler* masm);
1952
1953 // Generates the slow case code. Must not be naturally
1954 // reachable. Expected to be put after a ret instruction (e.g., in
1955 // deferred code). Always jumps back to the fast case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001956 void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001957 const RuntimeCallHelper& call_helper);
1958
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001959 // Skip handling slow case and directly jump to bailout.
1960 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1961 masm->bind(&index_not_smi_);
1962 masm->bind(&call_runtime_);
1963 masm->jmp(bailout);
1964 }
1965
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001966 private:
1967 Register object_;
1968 Register index_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001969 Register result_;
1970
1971 Label* receiver_not_string_;
1972 Label* index_not_number_;
1973 Label* index_out_of_range_;
1974
1975 StringIndexFlags index_flags_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001976 ReceiverCheckMode check_mode_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001977
1978 Label call_runtime_;
1979 Label index_not_smi_;
1980 Label got_smi_index_;
1981 Label exit_;
1982
1983 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
1984};
1985
1986
1987// Generates code for creating a one-char string from a char code.
1988class StringCharFromCodeGenerator {
1989 public:
1990 StringCharFromCodeGenerator(Register code,
1991 Register result)
1992 : code_(code),
1993 result_(result) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001994 DCHECK(!code_.is(result_));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001995 }
1996
1997 // Generates the fast case code. On the fallthrough path |result|
1998 // register contains the result.
1999 void GenerateFast(MacroAssembler* masm);
2000
2001 // Generates the slow case code. Must not be naturally
2002 // reachable. Expected to be put after a ret instruction (e.g., in
2003 // deferred code). Always jumps back to the fast case.
2004 void GenerateSlow(MacroAssembler* masm,
2005 const RuntimeCallHelper& call_helper);
2006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002007 // Skip handling slow case and directly jump to bailout.
2008 void SkipSlow(MacroAssembler* masm, Label* bailout) {
2009 masm->bind(&slow_case_);
2010 masm->jmp(bailout);
2011 }
2012
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002013 private:
2014 Register code_;
2015 Register result_;
2016
2017 Label slow_case_;
2018 Label exit_;
2019
2020 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
2021};
2022
2023
2024// Generates code implementing String.prototype.charAt.
2025//
2026// Only supports the case when the receiver is a string and the index
2027// is a number (smi or heap number) that is a valid index into the
2028// string. Additional index constraints are specified by the
2029// flags. Otherwise, bails out to the provided labels.
2030//
2031// Register usage: |object| may be changed to another string in a way
2032// that doesn't affect charCodeAt/charAt semantics, |index| is
2033// preserved, |scratch1|, |scratch2|, and |result| are clobbered.
2034class StringCharAtGenerator {
2035 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002036 StringCharAtGenerator(Register object, Register index, Register scratch,
2037 Register result, Label* receiver_not_string,
2038 Label* index_not_number, Label* index_out_of_range,
2039 StringIndexFlags index_flags,
2040 ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
2041 : char_code_at_generator_(object, index, scratch, receiver_not_string,
2042 index_not_number, index_out_of_range,
2043 index_flags, check_mode),
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002044 char_from_code_generator_(scratch, result) {}
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002045
2046 // Generates the fast case code. On the fallthrough path |result|
2047 // register contains the result.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002048 void GenerateFast(MacroAssembler* masm) {
2049 char_code_at_generator_.GenerateFast(masm);
2050 char_from_code_generator_.GenerateFast(masm);
2051 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002052
2053 // Generates the slow case code. Must not be naturally
2054 // reachable. Expected to be put after a ret instruction (e.g., in
2055 // deferred code). Always jumps back to the fast case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002056 void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002057 const RuntimeCallHelper& call_helper) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002058 char_code_at_generator_.GenerateSlow(masm, embed_mode, call_helper);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002059 char_from_code_generator_.GenerateSlow(masm, call_helper);
2060 }
2061
2062 // Skip handling slow case and directly jump to bailout.
2063 void SkipSlow(MacroAssembler* masm, Label* bailout) {
2064 char_code_at_generator_.SkipSlow(masm, bailout);
2065 char_from_code_generator_.SkipSlow(masm, bailout);
2066 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002067
2068 private:
2069 StringCharCodeAtGenerator char_code_at_generator_;
2070 StringCharFromCodeGenerator char_from_code_generator_;
2071
2072 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
2073};
2074
Ben Murdoch086aeea2011-05-13 15:57:08 +01002075
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002076class LoadDictionaryElementStub : public HydrogenCodeStub {
Ben Murdoch086aeea2011-05-13 15:57:08 +01002077 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002078 explicit LoadDictionaryElementStub(Isolate* isolate, const LoadICState& state)
2079 : HydrogenCodeStub(isolate) {
2080 minor_key_ = state.GetExtraICState();
2081 }
Ben Murdoch086aeea2011-05-13 15:57:08 +01002082
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002083 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
2084 return LoadWithVectorDescriptor(isolate());
2085 }
2086
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002087 DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub);
Ben Murdoch086aeea2011-05-13 15:57:08 +01002088};
2089
Ben Murdoch257744e2011-11-30 15:57:28 +00002090
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002091class KeyedLoadGenericStub : public HydrogenCodeStub {
Ben Murdoch257744e2011-11-30 15:57:28 +00002092 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002093 explicit KeyedLoadGenericStub(Isolate* isolate, const LoadICState& state)
2094 : HydrogenCodeStub(isolate) {
2095 minor_key_ = state.GetExtraICState();
2096 }
Ben Murdoch257744e2011-11-30 15:57:28 +00002097
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002098 Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2099 InlineCacheState GetICState() const override { return GENERIC; }
Ben Murdoch257744e2011-11-30 15:57:28 +00002100
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002101 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002102
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002103 DEFINE_HYDROGEN_CODE_STUB(KeyedLoadGeneric, HydrogenCodeStub);
Ben Murdoch257744e2011-11-30 15:57:28 +00002104};
2105
2106
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002107class LoadICTrampolineStub : public PlatformCodeStub {
Ben Murdoch257744e2011-11-30 15:57:28 +00002108 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002109 LoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
2110 : PlatformCodeStub(isolate) {
2111 minor_key_ = state.GetExtraICState();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002112 }
Ben Murdoch257744e2011-11-30 15:57:28 +00002113
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002114 Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002115
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002116 InlineCacheState GetICState() const final { return GENERIC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002117
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002118 ExtraICState GetExtraICState() const final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002119 return static_cast<ExtraICState>(minor_key_);
2120 }
Ben Murdoch257744e2011-11-30 15:57:28 +00002121
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002122 protected:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002123 LoadICState state() const {
2124 return LoadICState(static_cast<ExtraICState>(minor_key_));
2125 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002126
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002127 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002128 DEFINE_PLATFORM_CODE_STUB(LoadICTrampoline, PlatformCodeStub);
Ben Murdoch257744e2011-11-30 15:57:28 +00002129};
2130
2131
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002132class KeyedLoadICTrampolineStub : public LoadICTrampolineStub {
2133 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002134 explicit KeyedLoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
2135 : LoadICTrampolineStub(isolate, state) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002136
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002137 Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002138
2139 DEFINE_PLATFORM_CODE_STUB(KeyedLoadICTrampoline, LoadICTrampolineStub);
2140};
2141
2142
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002143class VectorStoreICTrampolineStub : public PlatformCodeStub {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002144 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002145 VectorStoreICTrampolineStub(Isolate* isolate, const StoreICState& state)
2146 : PlatformCodeStub(isolate) {
2147 minor_key_ = state.GetExtraICState();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002148 }
2149
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002150 Code::Kind GetCodeKind() const override { return Code::STORE_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002151
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002152 InlineCacheState GetICState() const final { return GENERIC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002153
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002154 ExtraICState GetExtraICState() const final {
2155 return static_cast<ExtraICState>(minor_key_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002156 }
2157
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002158 protected:
2159 StoreICState state() const {
2160 return StoreICState(static_cast<ExtraICState>(minor_key_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002161 }
2162
2163 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002164 DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreICTrampoline);
2165 DEFINE_PLATFORM_CODE_STUB(VectorStoreICTrampoline, PlatformCodeStub);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002166};
2167
2168
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002169class VectorKeyedStoreICTrampolineStub : public VectorStoreICTrampolineStub {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002170 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002171 VectorKeyedStoreICTrampolineStub(Isolate* isolate, const StoreICState& state)
2172 : VectorStoreICTrampolineStub(isolate, state) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002173
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002174 Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002175
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002176 DEFINE_PLATFORM_CODE_STUB(VectorKeyedStoreICTrampoline,
2177 VectorStoreICTrampolineStub);
2178};
2179
2180
2181class CallICTrampolineStub : public PlatformCodeStub {
2182 public:
2183 CallICTrampolineStub(Isolate* isolate, const CallICState& state)
2184 : PlatformCodeStub(isolate) {
2185 minor_key_ = state.GetExtraICState();
2186 }
2187
2188 Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
2189
2190 InlineCacheState GetICState() const final { return GENERIC; }
2191
2192 ExtraICState GetExtraICState() const final {
2193 return static_cast<ExtraICState>(minor_key_);
2194 }
2195
2196 protected:
2197 CallICState state() const {
2198 return CallICState(static_cast<ExtraICState>(minor_key_));
2199 }
2200
2201 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedback);
2202 DEFINE_PLATFORM_CODE_STUB(CallICTrampoline, PlatformCodeStub);
2203};
2204
2205
2206class LoadICStub : public PlatformCodeStub {
2207 public:
2208 explicit LoadICStub(Isolate* isolate, const LoadICState& state)
2209 : PlatformCodeStub(isolate) {
2210 minor_key_ = state.GetExtraICState();
2211 }
2212
2213 void GenerateForTrampoline(MacroAssembler* masm);
2214
2215 Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
2216 InlineCacheState GetICState() const final { return GENERIC; }
2217 ExtraICState GetExtraICState() const final {
2218 return static_cast<ExtraICState>(minor_key_);
2219 }
2220
2221 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
2222 DEFINE_PLATFORM_CODE_STUB(LoadIC, PlatformCodeStub);
2223
2224 protected:
2225 void GenerateImpl(MacroAssembler* masm, bool in_frame);
2226};
2227
2228
2229class KeyedLoadICStub : public PlatformCodeStub {
2230 public:
2231 explicit KeyedLoadICStub(Isolate* isolate, const LoadICState& state)
2232 : PlatformCodeStub(isolate) {
2233 minor_key_ = state.GetExtraICState();
2234 }
2235
2236 void GenerateForTrampoline(MacroAssembler* masm);
2237
2238 Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2239 InlineCacheState GetICState() const final { return GENERIC; }
2240 ExtraICState GetExtraICState() const final {
2241 return static_cast<ExtraICState>(minor_key_);
2242 }
2243
2244 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
2245 DEFINE_PLATFORM_CODE_STUB(KeyedLoadIC, PlatformCodeStub);
2246
2247 protected:
2248 void GenerateImpl(MacroAssembler* masm, bool in_frame);
2249};
2250
2251
2252class VectorStoreICStub : public PlatformCodeStub {
2253 public:
2254 VectorStoreICStub(Isolate* isolate, const StoreICState& state)
2255 : PlatformCodeStub(isolate) {
2256 minor_key_ = state.GetExtraICState();
2257 }
2258
2259 void GenerateForTrampoline(MacroAssembler* masm);
2260
2261 Code::Kind GetCodeKind() const final { return Code::STORE_IC; }
2262 InlineCacheState GetICState() const final { return GENERIC; }
2263 ExtraICState GetExtraICState() const final {
2264 return static_cast<ExtraICState>(minor_key_);
2265 }
2266
2267 DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreIC);
2268 DEFINE_PLATFORM_CODE_STUB(VectorStoreIC, PlatformCodeStub);
2269
2270 protected:
2271 void GenerateImpl(MacroAssembler* masm, bool in_frame);
2272};
2273
2274
2275class VectorKeyedStoreICStub : public PlatformCodeStub {
2276 public:
2277 VectorKeyedStoreICStub(Isolate* isolate, const StoreICState& state)
2278 : PlatformCodeStub(isolate) {
2279 minor_key_ = state.GetExtraICState();
2280 }
2281
2282 void GenerateForTrampoline(MacroAssembler* masm);
2283
2284 Code::Kind GetCodeKind() const final { return Code::KEYED_STORE_IC; }
2285 InlineCacheState GetICState() const final { return GENERIC; }
2286 ExtraICState GetExtraICState() const final {
2287 return static_cast<ExtraICState>(minor_key_);
2288 }
2289
2290 DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreIC);
2291 DEFINE_PLATFORM_CODE_STUB(VectorKeyedStoreIC, PlatformCodeStub);
2292
2293 protected:
2294 void GenerateImpl(MacroAssembler* masm, bool in_frame);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002295};
2296
2297
2298class DoubleToIStub : public PlatformCodeStub {
2299 public:
2300 DoubleToIStub(Isolate* isolate, Register source, Register destination,
2301 int offset, bool is_truncating, bool skip_fastpath = false)
2302 : PlatformCodeStub(isolate) {
2303 minor_key_ = SourceRegisterBits::encode(source.code()) |
2304 DestinationRegisterBits::encode(destination.code()) |
2305 OffsetBits::encode(offset) |
2306 IsTruncatingBits::encode(is_truncating) |
2307 SkipFastPathBits::encode(skip_fastpath) |
2308 SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0);
2309 }
2310
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002311 bool SometimesSetsUpAFrame() override { return false; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002312
2313 private:
2314 Register source() const {
2315 return Register::from_code(SourceRegisterBits::decode(minor_key_));
2316 }
2317 Register destination() const {
2318 return Register::from_code(DestinationRegisterBits::decode(minor_key_));
2319 }
2320 bool is_truncating() const { return IsTruncatingBits::decode(minor_key_); }
2321 bool skip_fastpath() const { return SkipFastPathBits::decode(minor_key_); }
2322 int offset() const { return OffsetBits::decode(minor_key_); }
2323
2324 static const int kBitsPerRegisterNumber = 6;
2325 STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
2326 class SourceRegisterBits:
2327 public BitField<int, 0, kBitsPerRegisterNumber> {}; // NOLINT
2328 class DestinationRegisterBits:
2329 public BitField<int, kBitsPerRegisterNumber,
2330 kBitsPerRegisterNumber> {}; // NOLINT
2331 class IsTruncatingBits:
2332 public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {}; // NOLINT
2333 class OffsetBits:
2334 public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {}; // NOLINT
2335 class SkipFastPathBits:
2336 public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {}; // NOLINT
2337 class SSE3Bits:
2338 public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {}; // NOLINT
2339
2340 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2341 DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub);
2342};
2343
2344
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002345class ScriptContextFieldStub : public HandlerStub {
2346 public:
2347 ScriptContextFieldStub(Isolate* isolate,
2348 const ScriptContextTable::LookupResult* lookup_result)
2349 : HandlerStub(isolate) {
2350 DCHECK(Accepted(lookup_result));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002351 STATIC_ASSERT(kContextIndexBits + kSlotIndexBits <= kSubMinorKeyBits);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002352 set_sub_minor_key(ContextIndexBits::encode(lookup_result->context_index) |
2353 SlotIndexBits::encode(lookup_result->slot_index));
2354 }
2355
2356 int context_index() const {
2357 return ContextIndexBits::decode(sub_minor_key());
2358 }
2359
2360 int slot_index() const { return SlotIndexBits::decode(sub_minor_key()); }
2361
2362 static bool Accepted(const ScriptContextTable::LookupResult* lookup_result) {
2363 return ContextIndexBits::is_valid(lookup_result->context_index) &&
2364 SlotIndexBits::is_valid(lookup_result->slot_index);
2365 }
2366
2367 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002368 static const int kContextIndexBits = 9;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002369 static const int kSlotIndexBits = 13;
2370 class ContextIndexBits : public BitField<int, 0, kContextIndexBits> {};
2371 class SlotIndexBits
2372 : public BitField<int, kContextIndexBits, kSlotIndexBits> {};
2373
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002374 Code::StubType GetStubType() const override { return Code::FAST; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002375
2376 DEFINE_CODE_STUB_BASE(ScriptContextFieldStub, HandlerStub);
2377};
2378
2379
2380class LoadScriptContextFieldStub : public ScriptContextFieldStub {
2381 public:
2382 LoadScriptContextFieldStub(
2383 Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
2384 : ScriptContextFieldStub(isolate, lookup_result) {}
2385
2386 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002387 Code::Kind kind() const override { return Code::LOAD_IC; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002388
2389 DEFINE_HANDLER_CODE_STUB(LoadScriptContextField, ScriptContextFieldStub);
2390};
2391
2392
2393class StoreScriptContextFieldStub : public ScriptContextFieldStub {
2394 public:
2395 StoreScriptContextFieldStub(
2396 Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
2397 : ScriptContextFieldStub(isolate, lookup_result) {}
2398
2399 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002400 Code::Kind kind() const override { return Code::STORE_IC; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002401
2402 DEFINE_HANDLER_CODE_STUB(StoreScriptContextField, ScriptContextFieldStub);
2403};
2404
2405
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002406class LoadFastElementStub : public HandlerStub {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002407 public:
2408 LoadFastElementStub(Isolate* isolate, bool is_js_array,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002409 ElementsKind elements_kind,
2410 bool convert_hole_to_undefined = false)
2411 : HandlerStub(isolate) {
2412 set_sub_minor_key(
2413 ElementsKindBits::encode(elements_kind) |
2414 IsJSArrayBits::encode(is_js_array) |
2415 CanConvertHoleToUndefined::encode(convert_hole_to_undefined));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002416 }
2417
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002418 Code::Kind kind() const override { return Code::KEYED_LOAD_IC; }
2419
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002420 bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002421 bool convert_hole_to_undefined() const {
2422 return CanConvertHoleToUndefined::decode(sub_minor_key());
2423 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002424
2425 ElementsKind elements_kind() const {
2426 return ElementsKindBits::decode(sub_minor_key());
2427 }
2428
2429 private:
2430 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2431 class IsJSArrayBits: public BitField<bool, 8, 1> {};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002432 class CanConvertHoleToUndefined : public BitField<bool, 9, 1> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002433
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002434 DEFINE_HANDLER_CODE_STUB(LoadFastElement, HandlerStub);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002435};
2436
2437
2438class StoreFastElementStub : public HydrogenCodeStub {
2439 public:
2440 StoreFastElementStub(Isolate* isolate, bool is_js_array,
2441 ElementsKind elements_kind, KeyedAccessStoreMode mode)
2442 : HydrogenCodeStub(isolate) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002443 set_sub_minor_key(CommonStoreModeBits::encode(mode) |
2444 ElementsKindBits::encode(elements_kind) |
2445 IsJSArrayBits::encode(is_js_array));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002446 }
2447
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002448 static void GenerateAheadOfTime(Isolate* isolate);
2449
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002450 bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2451
2452 ElementsKind elements_kind() const {
2453 return ElementsKindBits::decode(sub_minor_key());
2454 }
2455
2456 KeyedAccessStoreMode store_mode() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002457 return CommonStoreModeBits::decode(sub_minor_key());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002458 }
2459
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002460 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
2461 return VectorStoreICDescriptor(isolate());
2462 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002463
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002464 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
2465
2466 private:
2467 class ElementsKindBits : public BitField<ElementsKind, 3, 8> {};
2468 class IsJSArrayBits : public BitField<bool, 11, 1> {};
2469
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002470 DEFINE_HYDROGEN_CODE_STUB(StoreFastElement, HydrogenCodeStub);
2471};
2472
2473
2474class TransitionElementsKindStub : public HydrogenCodeStub {
2475 public:
2476 TransitionElementsKindStub(Isolate* isolate,
2477 ElementsKind from_kind,
2478 ElementsKind to_kind,
2479 bool is_js_array) : HydrogenCodeStub(isolate) {
2480 set_sub_minor_key(FromKindBits::encode(from_kind) |
2481 ToKindBits::encode(to_kind) |
2482 IsJSArrayBits::encode(is_js_array));
2483 }
2484
2485 ElementsKind from_kind() const {
2486 return FromKindBits::decode(sub_minor_key());
2487 }
2488
2489 ElementsKind to_kind() const { return ToKindBits::decode(sub_minor_key()); }
2490
2491 bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2492
2493 private:
2494 class FromKindBits: public BitField<ElementsKind, 8, 8> {};
2495 class ToKindBits: public BitField<ElementsKind, 0, 8> {};
2496 class IsJSArrayBits: public BitField<bool, 16, 1> {};
2497
2498 DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind);
2499 DEFINE_HYDROGEN_CODE_STUB(TransitionElementsKind, HydrogenCodeStub);
2500};
2501
2502
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002503class AllocateHeapNumberStub final : public HydrogenCodeStub {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002504 public:
2505 explicit AllocateHeapNumberStub(Isolate* isolate)
2506 : HydrogenCodeStub(isolate) {}
2507
2508 private:
2509 DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateHeapNumber);
2510 DEFINE_HYDROGEN_CODE_STUB(AllocateHeapNumber, HydrogenCodeStub);
2511};
2512
2513
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002514class AllocateMutableHeapNumberStub final : public HydrogenCodeStub {
2515 public:
2516 explicit AllocateMutableHeapNumberStub(Isolate* isolate)
2517 : HydrogenCodeStub(isolate) {}
2518
2519 private:
2520 DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateMutableHeapNumber);
2521 DEFINE_HYDROGEN_CODE_STUB(AllocateMutableHeapNumber, HydrogenCodeStub);
2522};
2523
2524
2525class AllocateInNewSpaceStub final : public HydrogenCodeStub {
2526 public:
2527 explicit AllocateInNewSpaceStub(Isolate* isolate)
2528 : HydrogenCodeStub(isolate) {}
2529
2530 private:
2531 DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateInNewSpace);
2532 DEFINE_HYDROGEN_CODE_STUB(AllocateInNewSpace, HydrogenCodeStub);
2533};
2534
2535
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002536class ArrayConstructorStubBase : public HydrogenCodeStub {
2537 public:
2538 ArrayConstructorStubBase(Isolate* isolate,
2539 ElementsKind kind,
2540 AllocationSiteOverrideMode override_mode)
2541 : HydrogenCodeStub(isolate) {
2542 // It only makes sense to override local allocation site behavior
2543 // if there is a difference between the global allocation site policy
2544 // for an ElementsKind and the desired usage of the stub.
2545 DCHECK(override_mode != DISABLE_ALLOCATION_SITES ||
2546 AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
2547 set_sub_minor_key(ElementsKindBits::encode(kind) |
2548 AllocationSiteOverrideModeBits::encode(override_mode));
2549 }
2550
2551 ElementsKind elements_kind() const {
2552 return ElementsKindBits::decode(sub_minor_key());
2553 }
2554
2555 AllocationSiteOverrideMode override_mode() const {
2556 return AllocationSiteOverrideModeBits::decode(sub_minor_key());
2557 }
2558
2559 static void GenerateStubsAheadOfTime(Isolate* isolate);
2560
2561 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2562 static const int kConstructor = 0;
2563 static const int kAllocationSite = 1;
2564
2565 protected:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002566 std::ostream& BasePrintName(std::ostream& os,
2567 const char* name) const; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002568
2569 private:
2570 // Ensure data fits within available bits.
2571 STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
2572
2573 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2574 class AllocationSiteOverrideModeBits: public
2575 BitField<AllocationSiteOverrideMode, 8, 1> {}; // NOLINT
2576
2577 DEFINE_CODE_STUB_BASE(ArrayConstructorStubBase, HydrogenCodeStub);
2578};
2579
2580
2581class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
2582 public:
2583 ArrayNoArgumentConstructorStub(
2584 Isolate* isolate,
2585 ElementsKind kind,
2586 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2587 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2588 }
2589
2590 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002591 void PrintName(std::ostream& os) const override { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002592 BasePrintName(os, "ArrayNoArgumentConstructorStub");
2593 }
2594
2595 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructorConstantArgCount);
2596 DEFINE_HYDROGEN_CODE_STUB(ArrayNoArgumentConstructor,
2597 ArrayConstructorStubBase);
2598};
2599
2600
2601class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
2602 public:
2603 ArraySingleArgumentConstructorStub(
2604 Isolate* isolate,
2605 ElementsKind kind,
2606 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2607 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2608 }
2609
2610 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002611 void PrintName(std::ostream& os) const override { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002612 BasePrintName(os, "ArraySingleArgumentConstructorStub");
2613 }
2614
2615 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2616 DEFINE_HYDROGEN_CODE_STUB(ArraySingleArgumentConstructor,
2617 ArrayConstructorStubBase);
2618};
2619
2620
2621class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
2622 public:
2623 ArrayNArgumentsConstructorStub(
2624 Isolate* isolate,
2625 ElementsKind kind,
2626 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2627 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2628 }
2629
2630 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002631 void PrintName(std::ostream& os) const override { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002632 BasePrintName(os, "ArrayNArgumentsConstructorStub");
2633 }
2634
2635 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2636 DEFINE_HYDROGEN_CODE_STUB(ArrayNArgumentsConstructor,
2637 ArrayConstructorStubBase);
2638};
2639
2640
2641class InternalArrayConstructorStubBase : public HydrogenCodeStub {
2642 public:
2643 InternalArrayConstructorStubBase(Isolate* isolate, ElementsKind kind)
2644 : HydrogenCodeStub(isolate) {
2645 set_sub_minor_key(ElementsKindBits::encode(kind));
2646 }
2647
2648 static void GenerateStubsAheadOfTime(Isolate* isolate);
2649
2650 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2651 static const int kConstructor = 0;
2652
2653 ElementsKind elements_kind() const {
2654 return ElementsKindBits::decode(sub_minor_key());
2655 }
2656
2657 private:
2658 class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2659
2660 DEFINE_CODE_STUB_BASE(InternalArrayConstructorStubBase, HydrogenCodeStub);
2661};
2662
2663
2664class InternalArrayNoArgumentConstructorStub : public
2665 InternalArrayConstructorStubBase {
2666 public:
2667 InternalArrayNoArgumentConstructorStub(Isolate* isolate,
2668 ElementsKind kind)
2669 : InternalArrayConstructorStubBase(isolate, kind) { }
2670
2671 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructorConstantArgCount);
2672 DEFINE_HYDROGEN_CODE_STUB(InternalArrayNoArgumentConstructor,
2673 InternalArrayConstructorStubBase);
2674};
2675
2676
2677class InternalArraySingleArgumentConstructorStub : public
2678 InternalArrayConstructorStubBase {
2679 public:
2680 InternalArraySingleArgumentConstructorStub(Isolate* isolate,
2681 ElementsKind kind)
2682 : InternalArrayConstructorStubBase(isolate, kind) { }
2683
2684 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2685 DEFINE_HYDROGEN_CODE_STUB(InternalArraySingleArgumentConstructor,
2686 InternalArrayConstructorStubBase);
2687};
2688
2689
2690class InternalArrayNArgumentsConstructorStub : public
2691 InternalArrayConstructorStubBase {
2692 public:
2693 InternalArrayNArgumentsConstructorStub(Isolate* isolate, ElementsKind kind)
2694 : InternalArrayConstructorStubBase(isolate, kind) { }
2695
2696 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2697 DEFINE_HYDROGEN_CODE_STUB(InternalArrayNArgumentsConstructor,
2698 InternalArrayConstructorStubBase);
2699};
2700
2701
2702class StoreElementStub : public PlatformCodeStub {
2703 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002704 StoreElementStub(Isolate* isolate, ElementsKind elements_kind,
2705 KeyedAccessStoreMode mode)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002706 : PlatformCodeStub(isolate) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002707 // TODO(jkummerow): Rename this stub to StoreSlowElementStub,
2708 // drop elements_kind parameter.
2709 DCHECK_EQ(DICTIONARY_ELEMENTS, elements_kind);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002710 minor_key_ = ElementsKindBits::encode(elements_kind) |
2711 CommonStoreModeBits::encode(mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002712 }
2713
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002714 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
2715 return VectorStoreICDescriptor(isolate());
2716 }
2717
2718 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
2719
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002720 private:
2721 ElementsKind elements_kind() const {
2722 return ElementsKindBits::decode(minor_key_);
2723 }
2724
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002725 class ElementsKindBits : public BitField<ElementsKind, 3, 8> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002726
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002727 DEFINE_PLATFORM_CODE_STUB(StoreElement, PlatformCodeStub);
2728};
2729
2730
2731class ToBooleanStub: public HydrogenCodeStub {
Ben Murdoch257744e2011-11-30 15:57:28 +00002732 public:
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002733 enum Type {
2734 UNDEFINED,
2735 BOOLEAN,
2736 NULL_TYPE,
2737 SMI,
2738 SPEC_OBJECT,
2739 STRING,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002740 SYMBOL,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002741 HEAP_NUMBER,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002742 SIMD_VALUE,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002743 NUMBER_OF_TYPES
2744 };
2745
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002746 // At most 16 different types can be distinguished, because the Code object
2747 // only has room for two bytes to hold a set of these types. :-P
2748 STATIC_ASSERT(NUMBER_OF_TYPES <= 16);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002749
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002750 class Types : public EnumSet<Type, uint16_t> {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002751 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002752 Types() : EnumSet<Type, uint16_t>(0) {}
2753 explicit Types(uint16_t bits) : EnumSet<Type, uint16_t>(bits) {}
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002754
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002755 bool UpdateStatus(Handle<Object> object);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002756 bool NeedsMap() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002757 bool CanBeUndetectable() const {
2758 return Contains(ToBooleanStub::SPEC_OBJECT);
2759 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002760 bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002761
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002762 static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002763 };
2764
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002765 ToBooleanStub(Isolate* isolate, ExtraICState state)
2766 : HydrogenCodeStub(isolate) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002767 set_sub_minor_key(TypesBits::encode(static_cast<uint16_t>(state)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002768 }
Ben Murdoch257744e2011-11-30 15:57:28 +00002769
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002770 bool UpdateStatus(Handle<Object> object);
2771 Types types() const { return Types(TypesBits::decode(sub_minor_key())); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002772
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002773 Code::Kind GetCodeKind() const override { return Code::TO_BOOLEAN_IC; }
2774 void PrintState(std::ostream& os) const override; // NOLINT
Ben Murdoch257744e2011-11-30 15:57:28 +00002775
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002776 bool SometimesSetsUpAFrame() override { return false; }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002777
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002778 static Handle<Code> GetUninitialized(Isolate* isolate) {
2779 return ToBooleanStub(isolate, UNINITIALIZED).GetCode();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002780 }
2781
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002782 ExtraICState GetExtraICState() const override { return types().ToIntegral(); }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002783
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002784 InlineCacheState GetICState() const override {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002785 if (types().IsEmpty()) {
2786 return ::v8::internal::UNINITIALIZED;
2787 } else {
2788 return MONOMORPHIC;
2789 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002790 }
2791
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002792 private:
2793 ToBooleanStub(Isolate* isolate, InitializationState init_state)
2794 : HydrogenCodeStub(isolate, init_state) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002795 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002796
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002797 class TypesBits : public BitField<uint16_t, 0, NUMBER_OF_TYPES> {};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002798
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002799 DEFINE_CALL_INTERFACE_DESCRIPTOR(ToBoolean);
2800 DEFINE_HYDROGEN_CODE_STUB(ToBoolean, HydrogenCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002801};
2802
2803
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002804std::ostream& operator<<(std::ostream& os, const ToBooleanStub::Types& t);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002805
2806
2807class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002808 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002809 ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind,
2810 ElementsKind to_kind, bool is_jsarray,
2811 KeyedAccessStoreMode store_mode)
2812 : HydrogenCodeStub(isolate) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002813 set_sub_minor_key(CommonStoreModeBits::encode(store_mode) |
2814 FromBits::encode(from_kind) | ToBits::encode(to_kind) |
2815 IsJSArrayBits::encode(is_jsarray));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002816 }
2817
2818 ElementsKind from_kind() const { return FromBits::decode(sub_minor_key()); }
2819 ElementsKind to_kind() const { return ToBits::decode(sub_minor_key()); }
2820 bool is_jsarray() const { return IsJSArrayBits::decode(sub_minor_key()); }
2821 KeyedAccessStoreMode store_mode() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002822 return CommonStoreModeBits::decode(sub_minor_key());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002823 }
2824
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002825 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override;
2826 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002827
2828 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002829 class FromBits : public BitField<ElementsKind, 3, 8> {};
2830 class ToBits : public BitField<ElementsKind, 11, 8> {};
2831 class IsJSArrayBits : public BitField<bool, 19, 1> {};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002832
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002833 DEFINE_HYDROGEN_CODE_STUB(ElementsTransitionAndStore, HydrogenCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002834};
2835
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002836
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002837class StubFailureTrampolineStub : public PlatformCodeStub {
2838 public:
2839 StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode)
2840 : PlatformCodeStub(isolate) {
2841 minor_key_ = FunctionModeField::encode(function_mode);
2842 }
2843
2844 static void GenerateAheadOfTime(Isolate* isolate);
2845
2846 private:
2847 StubFunctionMode function_mode() const {
2848 return FunctionModeField::decode(minor_key_);
2849 }
2850
2851 class FunctionModeField : public BitField<StubFunctionMode, 0, 1> {};
2852
2853 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2854 DEFINE_PLATFORM_CODE_STUB(StubFailureTrampoline, PlatformCodeStub);
2855};
2856
2857
2858class ProfileEntryHookStub : public PlatformCodeStub {
2859 public:
2860 explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2861
2862 // The profile entry hook function is not allowed to cause a GC.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002863 bool SometimesSetsUpAFrame() override { return false; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002864
2865 // Generates a call to the entry hook if it's enabled.
2866 static void MaybeCallEntryHook(MacroAssembler* masm);
2867
2868 private:
2869 static void EntryHookTrampoline(intptr_t function,
2870 intptr_t stack_pointer,
2871 Isolate* isolate);
2872
2873 // ProfileEntryHookStub is called at the start of a function, so it has the
2874 // same register set.
2875 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction)
2876 DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub);
2877};
2878
2879
2880class StoreBufferOverflowStub : public PlatformCodeStub {
2881 public:
2882 StoreBufferOverflowStub(Isolate* isolate, SaveFPRegsMode save_fp)
2883 : PlatformCodeStub(isolate) {
2884 minor_key_ = SaveDoublesBits::encode(save_fp == kSaveFPRegs);
2885 }
2886
2887 static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002888 bool SometimesSetsUpAFrame() override { return false; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002889
2890 private:
2891 bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
2892
2893 class SaveDoublesBits : public BitField<bool, 0, 1> {};
2894
2895 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2896 DEFINE_PLATFORM_CODE_STUB(StoreBufferOverflow, PlatformCodeStub);
2897};
2898
2899
2900class SubStringStub : public PlatformCodeStub {
2901 public:
2902 explicit SubStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2903
2904 DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
2905 DEFINE_PLATFORM_CODE_STUB(SubString, PlatformCodeStub);
2906};
2907
2908
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002909class ToNumberStub final : public PlatformCodeStub {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002910 public:
2911 explicit ToNumberStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2912
2913 DEFINE_CALL_INTERFACE_DESCRIPTOR(ToNumber);
2914 DEFINE_PLATFORM_CODE_STUB(ToNumber, PlatformCodeStub);
2915};
2916
2917
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002918class ToLengthStub final : public PlatformCodeStub {
2919 public:
2920 explicit ToLengthStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2921
2922 DEFINE_CALL_INTERFACE_DESCRIPTOR(ToLength);
2923 DEFINE_PLATFORM_CODE_STUB(ToLength, PlatformCodeStub);
2924};
2925
2926
2927class ToStringStub final : public PlatformCodeStub {
2928 public:
2929 explicit ToStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2930
2931 DEFINE_CALL_INTERFACE_DESCRIPTOR(ToString);
2932 DEFINE_PLATFORM_CODE_STUB(ToString, PlatformCodeStub);
2933};
2934
2935
Ben Murdoch097c5b22016-05-18 11:27:45 +01002936class ToNameStub final : public PlatformCodeStub {
2937 public:
2938 explicit ToNameStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2939
2940 DEFINE_CALL_INTERFACE_DESCRIPTOR(ToName);
2941 DEFINE_PLATFORM_CODE_STUB(ToName, PlatformCodeStub);
2942};
2943
2944
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002945class ToObjectStub final : public HydrogenCodeStub {
2946 public:
2947 explicit ToObjectStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
2948
2949 DEFINE_CALL_INTERFACE_DESCRIPTOR(ToObject);
2950 DEFINE_HYDROGEN_CODE_STUB(ToObject, HydrogenCodeStub);
2951};
2952
2953
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002954class StringCompareStub : public PlatformCodeStub {
2955 public:
2956 explicit StringCompareStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2957
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002958 DEFINE_CALL_INTERFACE_DESCRIPTOR(StringCompare);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002959 DEFINE_PLATFORM_CODE_STUB(StringCompare, PlatformCodeStub);
2960};
2961
2962
2963#undef DEFINE_CALL_INTERFACE_DESCRIPTOR
2964#undef DEFINE_PLATFORM_CODE_STUB
2965#undef DEFINE_HANDLER_CODE_STUB
2966#undef DEFINE_HYDROGEN_CODE_STUB
2967#undef DEFINE_CODE_STUB
2968#undef DEFINE_CODE_STUB_BASE
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002969
2970extern Representation RepresentationFromType(Type* type);
2971
2972} // namespace internal
2973} // namespace v8
Steve Blocka7e24c12009-10-30 11:49:00 +00002974
2975#endif // V8_CODE_STUBS_H_