blob: 21e21356bb6b6407ea4ee1546a9208a1e432533e [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 */ \
24 V(ArgumentsAccess) \
25 V(ArrayConstructor) \
26 V(BinaryOpICWithAllocationSite) \
27 V(CallApiFunction) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028 V(CallApiAccessor) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000029 V(CallApiGetter) \
30 V(CallConstruct) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031 V(CallIC) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000032 V(CEntry) \
33 V(CompareIC) \
34 V(DoubleToI) \
35 V(FunctionPrototype) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000036 V(InstanceOf) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000037 V(InternalArrayConstructor) \
38 V(JSEntry) \
39 V(KeyedLoadICTrampoline) \
40 V(LoadICTrampoline) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000041 V(CallICTrampoline) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000042 V(LoadIndexedInterceptor) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040043 V(LoadIndexedString) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044 V(MathPow) \
45 V(ProfileEntryHook) \
46 V(RecordWrite) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000047 V(RestParamAccess) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000048 V(RegExpExec) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000049 V(StoreBufferOverflow) \
50 V(StoreElement) \
51 V(StringCompare) \
52 V(StubFailureTrampoline) \
53 V(SubString) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040054 V(ToNumber) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000055 V(ToLength) \
56 V(ToString) \
57 V(ToObject) \
58 V(VectorStoreICTrampoline) \
59 V(VectorKeyedStoreICTrampoline) \
60 V(VectorStoreIC) \
61 V(VectorKeyedStoreIC) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000062 /* HydrogenCodeStubs */ \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040063 V(AllocateHeapNumber) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064 V(AllocateMutableHeapNumber) \
65 V(AllocateInNewSpace) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000066 V(ArrayNArgumentsConstructor) \
67 V(ArrayNoArgumentConstructor) \
68 V(ArraySingleArgumentConstructor) \
69 V(BinaryOpIC) \
70 V(BinaryOpWithAllocationSite) \
71 V(CompareNilIC) \
72 V(CreateAllocationSite) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000073 V(CreateWeakCell) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000074 V(ElementsTransitionAndStore) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075 V(FastCloneRegExp) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000076 V(FastCloneShallowArray) \
77 V(FastCloneShallowObject) \
78 V(FastNewClosure) \
79 V(FastNewContext) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000080 V(GrowArrayElements) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000081 V(InternalArrayNArgumentsConstructor) \
82 V(InternalArrayNoArgumentConstructor) \
83 V(InternalArraySingleArgumentConstructor) \
84 V(KeyedLoadGeneric) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000085 V(LoadGlobalViaContext) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040086 V(LoadScriptContextField) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000087 V(LoadDictionaryElement) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000088 V(NameDictionaryLookup) \
89 V(NumberToString) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000090 V(Typeof) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000091 V(RegExpConstructResult) \
92 V(StoreFastElement) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000093 V(StoreGlobalViaContext) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040094 V(StoreScriptContextField) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000095 V(StringAdd) \
96 V(ToBoolean) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000097 V(TransitionElementsKind) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000098 V(KeyedLoadIC) \
99 V(LoadIC) \
100 /* TurboFanCodeStubs */ \
101 V(StringLength) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000102 /* IC Handler stubs */ \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000103 V(ArrayBufferViewLoadField) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000104 V(LoadConstant) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000105 V(LoadFastElement) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000106 V(LoadField) \
107 V(KeyedLoadSloppyArguments) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000108 V(KeyedStoreSloppyArguments) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000109 V(StoreField) \
110 V(StoreGlobal) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000111 V(StoreTransition)
Steve Blockd0582a62009-12-15 09:54:21 +0000112
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000113// List of code stubs only used on ARM 32 bits platforms.
114#if V8_TARGET_ARCH_ARM
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400115#define CODE_STUB_LIST_ARM(V) V(DirectCEntry)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000116
Steve Blockd0582a62009-12-15 09:54:21 +0000117#else
118#define CODE_STUB_LIST_ARM(V)
119#endif
120
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000121// List of code stubs only used on ARM 64 bits platforms.
122#if V8_TARGET_ARCH_ARM64
123#define CODE_STUB_LIST_ARM64(V) \
124 V(DirectCEntry) \
125 V(RestoreRegistersState) \
126 V(StoreRegistersState)
127
128#else
129#define CODE_STUB_LIST_ARM64(V)
130#endif
131
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000132// List of code stubs only used on PPC platforms.
133#ifdef V8_TARGET_ARCH_PPC
134#define CODE_STUB_LIST_PPC(V) \
135 V(DirectCEntry) \
136 V(StoreRegistersState) \
137 V(RestoreRegistersState)
138#else
139#define CODE_STUB_LIST_PPC(V)
140#endif
141
Steve Block44f0eee2011-05-26 01:26:41 +0100142// List of code stubs only used on MIPS platforms.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000143#if V8_TARGET_ARCH_MIPS
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400144#define CODE_STUB_LIST_MIPS(V) \
145 V(DirectCEntry) \
146 V(RestoreRegistersState) \
147 V(StoreRegistersState)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000148#elif V8_TARGET_ARCH_MIPS64
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400149#define CODE_STUB_LIST_MIPS(V) \
150 V(DirectCEntry) \
151 V(RestoreRegistersState) \
152 V(StoreRegistersState)
Steve Block44f0eee2011-05-26 01:26:41 +0100153#else
154#define CODE_STUB_LIST_MIPS(V)
155#endif
156
Steve Blockd0582a62009-12-15 09:54:21 +0000157// Combined list of code stubs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000158#define CODE_STUB_LIST(V) \
159 CODE_STUB_LIST_ALL_PLATFORMS(V) \
160 CODE_STUB_LIST_ARM(V) \
161 CODE_STUB_LIST_ARM64(V) \
162 CODE_STUB_LIST_PPC(V) \
Steve Block44f0eee2011-05-26 01:26:41 +0100163 CODE_STUB_LIST_MIPS(V)
Steve Blocka7e24c12009-10-30 11:49:00 +0000164
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000165static const int kHasReturnedMinusZeroSentinel = 1;
166
Steve Blocka7e24c12009-10-30 11:49:00 +0000167// Stub is base classes of all stubs.
168class CodeStub BASE_EMBEDDED {
169 public:
170 enum Major {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400171 // TODO(mvstanton): eliminate the NoCache key by getting rid
172 // of the non-monomorphic-cache.
173 NoCache = 0, // marker for stubs that do custom caching]
Steve Blockd0582a62009-12-15 09:54:21 +0000174#define DEF_ENUM(name) name,
175 CODE_STUB_LIST(DEF_ENUM)
176#undef DEF_ENUM
Steve Blocka7e24c12009-10-30 11:49:00 +0000177 NUMBER_OF_IDS
178 };
179
180 // Retrieve the code for the stub. Generate the code if needed.
181 Handle<Code> GetCode();
182
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000183 // Retrieve the code for the stub, make and return a copy of the code.
184 Handle<Code> GetCodeCopy(const Code::FindAndReplacePattern& pattern);
185
Steve Blocka7e24c12009-10-30 11:49:00 +0000186 static Major MajorKeyFromKey(uint32_t key) {
187 return static_cast<Major>(MajorKeyBits::decode(key));
Iain Merrick9ac36c92010-09-13 15:29:50 +0100188 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189 static uint32_t MinorKeyFromKey(uint32_t key) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000190 return MinorKeyBits::decode(key);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100191 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100192
193 // Gets the major key from a code object that is a code stub or binary op IC.
194 static Major GetMajorKey(Code* code_stub) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000195 return MajorKeyFromKey(code_stub->stub_key());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100196 }
197
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000198 static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }
199
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200 static const char* MajorName(Major major_key);
Steve Blocka7e24c12009-10-30 11:49:00 +0000201
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000202 explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000203 virtual ~CodeStub() {}
204
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000205 static void GenerateStubsAheadOfTime(Isolate* isolate);
206 static void GenerateFPStubs(Isolate* isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100207
208 // Some stubs put untagged junk on the stack that cannot be scanned by the
209 // GC. This means that we must be statically sure that no GC can occur while
210 // they are running. If that is the case they should override this to return
211 // true, which will cause an assertion if we try to call something that can
212 // GC or if we try to put a stack frame on top of the junk, which would not
213 // result in a traversable stack.
214 virtual bool SometimesSetsUpAFrame() { return true; }
215
216 // Lookup the code in the (possibly custom) cache.
217 bool FindCodeInCache(Code** code_out);
218
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000219 virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() const = 0;
220
221 virtual int GetStackParameterCount() const {
222 return GetCallInterfaceDescriptor().GetStackParameterCount();
223 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000224
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000225 virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {}
226
227 static void InitializeDescriptor(Isolate* isolate, uint32_t key,
228 CodeStubDescriptor* desc);
229
230 static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key);
231
232 // Returns information for computing the number key.
233 virtual Major MajorKey() const = 0;
234 uint32_t MinorKey() const { return minor_key_; }
235
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000236 // BinaryOpStub needs to override this.
237 virtual Code::Kind GetCodeKind() const;
238
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000239 virtual InlineCacheState GetICState() const { return UNINITIALIZED; }
240 virtual ExtraICState GetExtraICState() const { return kNoExtraICState; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000241 virtual Code::StubType GetStubType() const { return Code::NORMAL; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400243 friend std::ostream& operator<<(std::ostream& os, const CodeStub& s) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000244 s.PrintName(os);
245 return os;
246 }
247
248 Isolate* isolate() const { return isolate_; }
249
250 protected:
251 CodeStub(uint32_t key, Isolate* isolate)
252 : minor_key_(MinorKeyFromKey(key)), isolate_(isolate) {}
Leon Clarkee46be812010-01-19 14:06:41 +0000253
Steve Blocka7e24c12009-10-30 11:49:00 +0000254 // Generates the assembler code for the stub.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000255 virtual Handle<Code> GenerateCode() = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000256
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000257 // Returns whether the code generated for this stub needs to be allocated as
258 // a fixed (non-moveable) code object.
259 virtual bool NeedsImmovableCode() { return false; }
260
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400261 virtual void PrintName(std::ostream& os) const; // NOLINT
262 virtual void PrintBaseName(std::ostream& os) const; // NOLINT
263 virtual void PrintState(std::ostream& os) const { ; } // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000264
265 // Computes the key based on major and minor.
266 uint32_t GetKey() {
267 DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
268 return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey());
269 }
270
271 uint32_t minor_key_;
272
273 private:
Leon Clarkee46be812010-01-19 14:06:41 +0000274 // Perform bookkeeping required after code generation when stub code is
275 // initially generated.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000276 void RecordCodeGeneration(Handle<Code> code);
Leon Clarkee46be812010-01-19 14:06:41 +0000277
Ben Murdochb0fe1622011-05-05 13:52:32 +0100278 // Finish the code object after it has been generated.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100279 virtual void FinishCode(Handle<Code> code) { }
280
281 // Activate newly generated stub. Is called after
282 // registering stub in the stub cache.
283 virtual void Activate(Code* code) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100284
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100285 // Add the code to a specialized cache, specific to an individual
286 // stub type. Please note, this method must add the code object to a
287 // roots object, otherwise we will remove the code during GC.
288 virtual void AddToSpecialCache(Handle<Code> new_object) { }
289
290 // Find code in a specialized cache, work is delegated to the specific stub.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000291 virtual bool FindCodeInSpecialCache(Code** code_out) {
292 return false;
293 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100294
295 // If a stub uses a special cache override this.
296 virtual bool UseSpecialCache() { return false; }
297
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000298 // We use this dispatch to statically instantiate the correct code stub for
299 // the given stub key and call the passed function with that code stub.
300 typedef void (*DispatchedCall)(CodeStub* stub, void** value_out);
301 static void Dispatch(Isolate* isolate, uint32_t key, void** value_out,
302 DispatchedCall call);
Steve Blocka7e24c12009-10-30 11:49:00 +0000303
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000304 static void GetCodeDispatchCall(CodeStub* stub, void** value_out);
Steve Block44f0eee2011-05-26 01:26:41 +0100305
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000306 STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
307 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
308 class MinorKeyBits: public BitField<uint32_t,
309 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT
Steve Blocka7e24c12009-10-30 11:49:00 +0000310
311 friend class BreakPointIterator;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000312
313 Isolate* isolate_;
314};
315
316
317#define DEFINE_CODE_STUB_BASE(NAME, SUPER) \
318 public: \
319 NAME(uint32_t key, Isolate* isolate) : SUPER(key, isolate) {} \
320 \
321 private: \
322 DISALLOW_COPY_AND_ASSIGN(NAME)
323
324
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400325#define DEFINE_CODE_STUB(NAME, SUPER) \
326 protected: \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000327 inline Major MajorKey() const override { return NAME; }; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000328 DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER)
329
330
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400331#define DEFINE_PLATFORM_CODE_STUB(NAME, SUPER) \
332 private: \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000333 void Generate(MacroAssembler* masm) override; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000334 DEFINE_CODE_STUB(NAME, SUPER)
335
336
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400337#define DEFINE_HYDROGEN_CODE_STUB(NAME, SUPER) \
338 public: \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000339 void InitializeDescriptor(CodeStubDescriptor* descriptor) override; \
340 Handle<Code> GenerateCode() override; \
341 DEFINE_CODE_STUB(NAME, SUPER)
342
343#define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER) \
344 public: \
345 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
346 return DESC##Descriptor(isolate()); \
347 }; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000348 DEFINE_CODE_STUB(NAME, SUPER)
349
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400350#define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \
351 public: \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000352 Handle<Code> GenerateCode() override; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000353 DEFINE_CODE_STUB(NAME, SUPER)
354
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000355#define DEFINE_CALL_INTERFACE_DESCRIPTOR(NAME) \
356 public: \
357 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
358 return NAME##Descriptor(isolate()); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000359 }
360
361// There are some code stubs we just can't describe right now with a
362// CallInterfaceDescriptor. Isolate behavior for those cases with this macro.
363// An attempt to retrieve a descriptor will fail.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000364#define DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR() \
365 public: \
366 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
367 UNREACHABLE(); \
368 return CallInterfaceDescriptor(); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000369 }
370
371
372class PlatformCodeStub : public CodeStub {
373 public:
374 // Retrieve the code for the stub. Generate the code if needed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000375 Handle<Code> GenerateCode() override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000376
377 protected:
378 explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {}
379
380 // Generates the assembler code for the stub.
381 virtual void Generate(MacroAssembler* masm) = 0;
382
383 DEFINE_CODE_STUB_BASE(PlatformCodeStub, CodeStub);
384};
385
386
387enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000388
389
390class CodeStubDescriptor {
391 public:
392 explicit CodeStubDescriptor(CodeStub* stub);
393
394 CodeStubDescriptor(Isolate* isolate, uint32_t stub_key);
395
396 void Initialize(Address deoptimization_handler = NULL,
397 int hint_stack_parameter_count = -1,
398 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
399 void Initialize(Register stack_parameter_count,
400 Address deoptimization_handler = NULL,
401 int hint_stack_parameter_count = -1,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000402 StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000403
404 void SetMissHandler(ExternalReference handler) {
405 miss_handler_ = handler;
406 has_miss_handler_ = true;
407 // Our miss handler infrastructure doesn't currently support
408 // variable stack parameter counts.
409 DCHECK(!stack_parameter_count_.is_valid());
410 }
411
412 void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; }
413 CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; }
414
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000415 int GetRegisterParameterCount() const {
416 return call_descriptor().GetRegisterParameterCount();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000417 }
418
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000419 int GetStackParameterCount() const {
420 return call_descriptor().GetStackParameterCount();
421 }
422
423 int GetParameterCount() const {
424 return call_descriptor().GetParameterCount();
425 }
426
427 Register GetRegisterParameter(int index) const {
428 return call_descriptor().GetRegisterParameter(index);
429 }
430
431 Type* GetParameterType(int index) const {
432 return call_descriptor().GetParameterType(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000433 }
434
435 ExternalReference miss_handler() const {
436 DCHECK(has_miss_handler_);
437 return miss_handler_;
438 }
439
440 bool has_miss_handler() const {
441 return has_miss_handler_;
442 }
443
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000444 int GetHandlerParameterCount() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000445 int params = GetParameterCount();
446 if (PassesArgumentsToDeoptimizationHandler()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000447 params += 1;
448 }
449 return params;
450 }
451
452 int hint_stack_parameter_count() const { return hint_stack_parameter_count_; }
453 Register stack_parameter_count() const { return stack_parameter_count_; }
454 StubFunctionMode function_mode() const { return function_mode_; }
455 Address deoptimization_handler() const { return deoptimization_handler_; }
456
457 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000458 bool PassesArgumentsToDeoptimizationHandler() const {
459 return stack_parameter_count_.is_valid();
460 }
461
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000462 CallInterfaceDescriptor call_descriptor_;
463 Register stack_parameter_count_;
464 // If hint_stack_parameter_count_ > 0, the code stub can optimize the
465 // return sequence. Default value is -1, which means it is ignored.
466 int hint_stack_parameter_count_;
467 StubFunctionMode function_mode_;
468
469 Address deoptimization_handler_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000470
471 ExternalReference miss_handler_;
472 bool has_miss_handler_;
473};
474
475
476class HydrogenCodeStub : public CodeStub {
477 public:
478 enum InitializationState {
479 UNINITIALIZED,
480 INITIALIZED
481 };
482
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000483 template<class SubClass>
484 static Handle<Code> GetUninitialized(Isolate* isolate) {
485 SubClass::GenerateAheadOfTime(isolate);
486 return SubClass().GetCode(isolate);
487 }
488
489 // Retrieve the code for the stub. Generate the code if needed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000490 Handle<Code> GenerateCode() override = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000491
492 bool IsUninitialized() const { return IsMissBits::decode(minor_key_); }
493
494 Handle<Code> GenerateLightweightMissCode(ExternalReference miss);
495
496 template<class StateType>
497 void TraceTransition(StateType from, StateType to);
498
499 protected:
500 explicit HydrogenCodeStub(Isolate* isolate,
501 InitializationState state = INITIALIZED)
502 : CodeStub(isolate) {
503 minor_key_ = IsMissBits::encode(state == UNINITIALIZED);
504 }
505
506 void set_sub_minor_key(uint32_t key) {
507 minor_key_ = SubMinorKeyBits::update(minor_key_, key);
508 }
509
510 uint32_t sub_minor_key() const { return SubMinorKeyBits::decode(minor_key_); }
511
512 static const int kSubMinorKeyBits = kStubMinorKeyBits - 1;
513
514 private:
515 class IsMissBits : public BitField<bool, kSubMinorKeyBits, 1> {};
516 class SubMinorKeyBits : public BitField<int, 0, kSubMinorKeyBits> {};
517
518 void GenerateLightweightMiss(MacroAssembler* masm, ExternalReference miss);
519
520 DEFINE_CODE_STUB_BASE(HydrogenCodeStub, CodeStub);
Steve Blocka7e24c12009-10-30 11:49:00 +0000521};
522
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100523
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000524class TurboFanCodeStub : public CodeStub {
525 public:
526 // Retrieve the code for the stub. Generate the code if needed.
527 Handle<Code> GenerateCode() override;
528
529 int GetStackParameterCount() const override {
530 return GetCallInterfaceDescriptor().GetStackParameterCount();
531 }
532
533 Code::StubType GetStubType() const override { return Code::FAST; }
534
535 protected:
536 explicit TurboFanCodeStub(Isolate* isolate) : CodeStub(isolate) {}
537
538 virtual void GenerateAssembly(
539 compiler::CodeStubAssembler* assembler) const = 0;
540
541 private:
542 DEFINE_CODE_STUB_BASE(TurboFanCodeStub, CodeStub);
543};
544
545
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100546// Helper interface to prepare to/restore after making runtime calls.
547class RuntimeCallHelper {
548 public:
549 virtual ~RuntimeCallHelper() {}
550
551 virtual void BeforeCall(MacroAssembler* masm) const = 0;
552
553 virtual void AfterCall(MacroAssembler* masm) const = 0;
554
555 protected:
556 RuntimeCallHelper() {}
557
558 private:
559 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
560};
561
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000562
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000563} // namespace internal
564} // namespace v8
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100565
566#if V8_TARGET_ARCH_IA32
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000567#include "src/ia32/code-stubs-ia32.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100568#elif V8_TARGET_ARCH_X64
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000569#include "src/x64/code-stubs-x64.h"
570#elif V8_TARGET_ARCH_ARM64
571#include "src/arm64/code-stubs-arm64.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100572#elif V8_TARGET_ARCH_ARM
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000573#include "src/arm/code-stubs-arm.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000574#elif V8_TARGET_ARCH_PPC
575#include "src/ppc/code-stubs-ppc.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100576#elif V8_TARGET_ARCH_MIPS
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000577#include "src/mips/code-stubs-mips.h"
578#elif V8_TARGET_ARCH_MIPS64
579#include "src/mips64/code-stubs-mips64.h"
580#elif V8_TARGET_ARCH_X87
581#include "src/x87/code-stubs-x87.h"
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100582#else
583#error Unsupported target architecture.
584#endif
585
586namespace v8 {
587namespace internal {
588
589
Ben Murdochb0fe1622011-05-05 13:52:32 +0100590// RuntimeCallHelper implementation used in stubs: enters/leaves a
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100591// newly created internal frame before/after the runtime call.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100592class StubRuntimeCallHelper : public RuntimeCallHelper {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100593 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100594 StubRuntimeCallHelper() {}
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100595
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000596 void BeforeCall(MacroAssembler* masm) const override;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100597
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000598 void AfterCall(MacroAssembler* masm) const override;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100599};
600
601
602// Trivial RuntimeCallHelper implementation.
603class NopRuntimeCallHelper : public RuntimeCallHelper {
604 public:
605 NopRuntimeCallHelper() {}
606
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000607 void BeforeCall(MacroAssembler* masm) const override {}
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100608
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000609 void AfterCall(MacroAssembler* masm) const override {}
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100610};
611
612
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000613class StringLengthStub : public TurboFanCodeStub {
614 public:
615 explicit StringLengthStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
616
617 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
618 InlineCacheState GetICState() const override { return MONOMORPHIC; }
619 ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
620
621 void GenerateAssembly(compiler::CodeStubAssembler* assembler) const override;
622
623 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
624 DEFINE_CODE_STUB(StringLength, TurboFanCodeStub);
625};
626
627
628enum StringAddFlags {
629 // Omit both parameter checks.
630 STRING_ADD_CHECK_NONE = 0,
631 // Check left parameter.
632 STRING_ADD_CHECK_LEFT = 1 << 0,
633 // Check right parameter.
634 STRING_ADD_CHECK_RIGHT = 1 << 1,
635 // Check both parameters.
636 STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT,
637 // Convert parameters when check fails (instead of throwing an exception).
638 STRING_ADD_CONVERT = 1 << 2,
639 STRING_ADD_CONVERT_LEFT = STRING_ADD_CHECK_LEFT | STRING_ADD_CONVERT,
640 STRING_ADD_CONVERT_RIGHT = STRING_ADD_CHECK_RIGHT | STRING_ADD_CONVERT
641};
642
643
644std::ostream& operator<<(std::ostream& os, const StringAddFlags& flags);
645
646
647class NumberToStringStub final : public HydrogenCodeStub {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100648 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000649 explicit NumberToStringStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100650
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000651 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
652 static const int kNumber = 0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100653
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000654 DEFINE_CALL_INTERFACE_DESCRIPTOR(NumberToString);
655 DEFINE_HYDROGEN_CODE_STUB(NumberToString, HydrogenCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100656};
657
658
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000659class TypeofStub final : public HydrogenCodeStub {
660 public:
661 explicit TypeofStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
662
663 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
664 static const int kObject = 0;
665
666 static void GenerateAheadOfTime(Isolate* isolate);
667
668 DEFINE_CALL_INTERFACE_DESCRIPTOR(Typeof);
669 DEFINE_HYDROGEN_CODE_STUB(Typeof, HydrogenCodeStub);
670};
671
672
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000673class FastNewClosureStub : public HydrogenCodeStub {
Steve Block1e0659c2011-05-24 12:43:12 +0100674 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000675 FastNewClosureStub(Isolate* isolate, LanguageMode language_mode,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000676 FunctionKind kind)
677 : HydrogenCodeStub(isolate) {
678 DCHECK(IsValidFunctionKind(kind));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000679 set_sub_minor_key(LanguageModeBits::encode(language_mode) |
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000680 FunctionKindBits::encode(kind));
681 }
Steve Block1e0659c2011-05-24 12:43:12 +0100682
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000683 LanguageMode language_mode() const {
684 return LanguageModeBits::decode(sub_minor_key());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000685 }
686
687 FunctionKind kind() const {
688 return FunctionKindBits::decode(sub_minor_key());
689 }
Steve Block1e0659c2011-05-24 12:43:12 +0100690
691 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000692 STATIC_ASSERT(LANGUAGE_END == 3);
693 class LanguageModeBits : public BitField<LanguageMode, 0, 2> {};
694 class FunctionKindBits : public BitField<FunctionKind, 2, 8> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000695
696 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure);
697 DEFINE_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub);
Steve Block1e0659c2011-05-24 12:43:12 +0100698};
699
700
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000701class FastNewContextStub final : public HydrogenCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100702 public:
703 static const int kMaximumSlots = 64;
704
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000705 FastNewContextStub(Isolate* isolate, int slots) : HydrogenCodeStub(isolate) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000706 DCHECK(slots >= 0 && slots <= kMaximumSlots);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000707 set_sub_minor_key(SlotsBits::encode(slots));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100708 }
709
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000710 int slots() const { return SlotsBits::decode(sub_minor_key()); }
711
712 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
713 static const int kFunction = 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100714
715 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000716 class SlotsBits : public BitField<int, 0, 8> {};
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100717
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000718 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewContext);
719 DEFINE_HYDROGEN_CODE_STUB(FastNewContext, HydrogenCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100720};
721
722
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000723class FastCloneRegExpStub final : public HydrogenCodeStub {
724 public:
725 explicit FastCloneRegExpStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
726
727 private:
728 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneRegExp);
729 DEFINE_HYDROGEN_CODE_STUB(FastCloneRegExp, HydrogenCodeStub);
730};
731
732
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000733class FastCloneShallowArrayStub : public HydrogenCodeStub {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100734 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000735 FastCloneShallowArrayStub(Isolate* isolate,
736 AllocationSiteMode allocation_site_mode)
737 : HydrogenCodeStub(isolate) {
738 set_sub_minor_key(AllocationSiteModeBits::encode(allocation_site_mode));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100739 }
740
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000741 AllocationSiteMode allocation_site_mode() const {
742 return AllocationSiteModeBits::decode(sub_minor_key());
743 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100744
745 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000746 class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100747
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000748 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowArray);
749 DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowArray, HydrogenCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100750};
751
752
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000753class FastCloneShallowObjectStub : public HydrogenCodeStub {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100754 public:
755 // Maximum number of properties in copied object.
756 static const int kMaximumClonedProperties = 6;
757
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000758 FastCloneShallowObjectStub(Isolate* isolate, int length)
759 : HydrogenCodeStub(isolate) {
760 DCHECK_GE(length, 0);
761 DCHECK_LE(length, kMaximumClonedProperties);
762 set_sub_minor_key(LengthBits::encode(length));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100763 }
764
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000765 int length() const { return LengthBits::decode(sub_minor_key()); }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100766
767 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000768 class LengthBits : public BitField<int, 0, 4> {};
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100769
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000770 DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowObject);
771 DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowObject, HydrogenCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100772};
773
774
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000775class CreateAllocationSiteStub : public HydrogenCodeStub {
776 public:
777 explicit CreateAllocationSiteStub(Isolate* isolate)
778 : HydrogenCodeStub(isolate) { }
779
780 static void GenerateAheadOfTime(Isolate* isolate);
781
782 DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateAllocationSite);
783 DEFINE_HYDROGEN_CODE_STUB(CreateAllocationSite, HydrogenCodeStub);
784};
785
786
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000787class CreateWeakCellStub : public HydrogenCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100788 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000789 explicit CreateWeakCellStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
Ben Murdochb0fe1622011-05-05 13:52:32 +0100790
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000791 static void GenerateAheadOfTime(Isolate* isolate);
792
793 DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateWeakCell);
794 DEFINE_HYDROGEN_CODE_STUB(CreateWeakCell, HydrogenCodeStub);
795};
796
797
798class GrowArrayElementsStub : public HydrogenCodeStub {
799 public:
800 GrowArrayElementsStub(Isolate* isolate, bool is_js_array, ElementsKind kind)
801 : HydrogenCodeStub(isolate) {
802 set_sub_minor_key(ElementsKindBits::encode(kind) |
803 IsJsArrayBits::encode(is_js_array));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100804 }
805
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000806 ElementsKind elements_kind() const {
807 return ElementsKindBits::decode(sub_minor_key());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000808 }
809
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000810 bool is_js_array() const { return IsJsArrayBits::decode(sub_minor_key()); }
811
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000812 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000813 class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
814 class IsJsArrayBits : public BitField<bool, ElementsKindBits::kNext, 1> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000815
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000816 DEFINE_CALL_INTERFACE_DESCRIPTOR(GrowArrayElements);
817 DEFINE_HYDROGEN_CODE_STUB(GrowArrayElements, HydrogenCodeStub);
818};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000819
Ben Murdoch086aeea2011-05-13 15:57:08 +0100820
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000821class InstanceOfStub final : public PlatformCodeStub {
822 public:
823 explicit InstanceOfStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
Ben Murdoch086aeea2011-05-13 15:57:08 +0100824
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000825 private:
826 DEFINE_CALL_INTERFACE_DESCRIPTOR(InstanceOf);
827 DEFINE_PLATFORM_CODE_STUB(InstanceOf, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100828};
829
830
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000831enum AllocationSiteOverrideMode {
832 DONT_OVERRIDE,
833 DISABLE_ALLOCATION_SITES,
834 LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
835};
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100836
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000837
838class ArrayConstructorStub: public PlatformCodeStub {
839 public:
840 enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
841
842 ArrayConstructorStub(Isolate* isolate, int argument_count);
843
844 explicit ArrayConstructorStub(Isolate* isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100845
846 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000847 ArgumentCountKey argument_count() const {
848 return ArgumentCountBits::decode(minor_key_);
849 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100850
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000851 void GenerateDispatchToArrayStub(MacroAssembler* masm,
852 AllocationSiteOverrideMode mode);
853
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000854 void PrintName(std::ostream& os) const override; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000855
856 class ArgumentCountBits : public BitField<ArgumentCountKey, 0, 2> {};
857
858 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
859 DEFINE_PLATFORM_CODE_STUB(ArrayConstructor, PlatformCodeStub);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100860};
861
862
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000863class InternalArrayConstructorStub: public PlatformCodeStub {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100864 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000865 explicit InternalArrayConstructorStub(Isolate* isolate);
866
867 private:
868 void GenerateCase(MacroAssembler* masm, ElementsKind kind);
869
870 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
871 DEFINE_PLATFORM_CODE_STUB(InternalArrayConstructor, PlatformCodeStub);
872};
873
874
875class MathPowStub: public PlatformCodeStub {
876 public:
877 enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK };
878
879 MathPowStub(Isolate* isolate, ExponentType exponent_type)
880 : PlatformCodeStub(isolate) {
881 minor_key_ = ExponentTypeBits::encode(exponent_type);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100882 }
883
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000884 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000885 if (exponent_type() == TAGGED) {
886 return MathPowTaggedDescriptor(isolate());
887 } else if (exponent_type() == INTEGER) {
888 return MathPowIntegerDescriptor(isolate());
889 }
890 // A CallInterfaceDescriptor doesn't specify double registers (yet).
891 return ContextOnlyDescriptor(isolate());
892 }
893
894 private:
895 ExponentType exponent_type() const {
896 return ExponentTypeBits::decode(minor_key_);
897 }
898
899 class ExponentTypeBits : public BitField<ExponentType, 0, 2> {};
900
901 DEFINE_PLATFORM_CODE_STUB(MathPow, PlatformCodeStub);
902};
903
904
905class CallICStub: public PlatformCodeStub {
906 public:
907 CallICStub(Isolate* isolate, const CallICState& state)
908 : PlatformCodeStub(isolate) {
909 minor_key_ = state.GetExtraICState();
910 }
911
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000912 Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000913
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000914 InlineCacheState GetICState() const override { return GENERIC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000915
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000916 ExtraICState GetExtraICState() const final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000917 return static_cast<ExtraICState>(minor_key_);
918 }
919
920 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000921 int arg_count() const { return state().argc(); }
922 ConvertReceiverMode convert_mode() const { return state().convert_mode(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000923
924 CallICState state() const {
925 return CallICState(static_cast<ExtraICState>(minor_key_));
926 }
927
928 // Code generation helpers.
929 void GenerateMiss(MacroAssembler* masm);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000930 void HandleArrayCase(MacroAssembler* masm, Label* miss);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000931
932 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000933 void PrintState(std::ostream& os) const override; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000934
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000935 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedbackAndVector);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000936 DEFINE_PLATFORM_CODE_STUB(CallIC, PlatformCodeStub);
937};
938
939
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000940// TODO(verwaest): Translate to hydrogen code stub.
941class FunctionPrototypeStub : public PlatformCodeStub {
942 public:
943 explicit FunctionPrototypeStub(Isolate* isolate)
944 : PlatformCodeStub(isolate) {}
945
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000946 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000947
948 // TODO(mvstanton): only the receiver register is accessed. When this is
949 // translated to a hydrogen code stub, a new CallInterfaceDescriptor
950 // should be created that just uses that register for more efficient code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000951 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
952 return LoadWithVectorDescriptor(isolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400953 }
954
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000955 DEFINE_PLATFORM_CODE_STUB(FunctionPrototype, PlatformCodeStub);
956};
957
958
959// TODO(mvstanton): Translate to hydrogen code stub.
960class LoadIndexedInterceptorStub : public PlatformCodeStub {
961 public:
962 explicit LoadIndexedInterceptorStub(Isolate* isolate)
963 : PlatformCodeStub(isolate) {}
964
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000965 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
966 Code::StubType GetStubType() const override { return Code::FAST; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000967
968 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
969 DEFINE_PLATFORM_CODE_STUB(LoadIndexedInterceptor, PlatformCodeStub);
970};
971
972
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400973class LoadIndexedStringStub : public PlatformCodeStub {
974 public:
975 explicit LoadIndexedStringStub(Isolate* isolate)
976 : PlatformCodeStub(isolate) {}
977
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000978 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
979 Code::StubType GetStubType() const override { return Code::FAST; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400980
981 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
982 DEFINE_PLATFORM_CODE_STUB(LoadIndexedString, PlatformCodeStub);
983};
984
985
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000986class HandlerStub : public HydrogenCodeStub {
987 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000988 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
989 ExtraICState GetExtraICState() const override { return kind(); }
990 InlineCacheState GetICState() const override { return MONOMORPHIC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000991
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000992 void InitializeDescriptor(CodeStubDescriptor* descriptor) override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000993
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000994 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000995
996 protected:
997 explicit HandlerStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
998
999 virtual Code::Kind kind() const = 0;
1000
1001 DEFINE_CODE_STUB_BASE(HandlerStub, HydrogenCodeStub);
1002};
1003
1004
1005class LoadFieldStub: public HandlerStub {
1006 public:
1007 LoadFieldStub(Isolate* isolate, FieldIndex index) : HandlerStub(isolate) {
1008 int property_index_key = index.GetFieldAccessStubKey();
1009 set_sub_minor_key(LoadFieldByIndexBits::encode(property_index_key));
1010 }
1011
1012 FieldIndex index() const {
1013 int property_index_key = LoadFieldByIndexBits::decode(sub_minor_key());
1014 return FieldIndex::FromFieldAccessStubKey(property_index_key);
1015 }
1016
1017 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001018 Code::Kind kind() const override { return Code::LOAD_IC; }
1019 Code::StubType GetStubType() const override { return Code::FAST; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001020
1021 private:
1022 class LoadFieldByIndexBits : public BitField<int, 0, 13> {};
1023
1024 DEFINE_HANDLER_CODE_STUB(LoadField, HandlerStub);
1025};
1026
1027
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001028class ArrayBufferViewLoadFieldStub : public HandlerStub {
1029 public:
1030 ArrayBufferViewLoadFieldStub(Isolate* isolate, FieldIndex index)
1031 : HandlerStub(isolate) {
1032 int property_index_key = index.GetFieldAccessStubKey();
1033 set_sub_minor_key(
1034 ArrayBufferViewLoadFieldByIndexBits::encode(property_index_key));
1035 }
1036
1037 FieldIndex index() const {
1038 int property_index_key =
1039 ArrayBufferViewLoadFieldByIndexBits::decode(sub_minor_key());
1040 return FieldIndex::FromFieldAccessStubKey(property_index_key);
1041 }
1042
1043 protected:
1044 Code::Kind kind() const override { return Code::LOAD_IC; }
1045 Code::StubType GetStubType() const override { return Code::FAST; }
1046
1047 private:
1048 class ArrayBufferViewLoadFieldByIndexBits : public BitField<int, 0, 13> {};
1049
1050 DEFINE_HANDLER_CODE_STUB(ArrayBufferViewLoadField, HandlerStub);
1051};
1052
1053
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001054class KeyedLoadSloppyArgumentsStub : public HandlerStub {
1055 public:
1056 explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate)
1057 : HandlerStub(isolate) {}
1058
1059 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001060 Code::Kind kind() const override { return Code::KEYED_LOAD_IC; }
1061 Code::StubType GetStubType() const override { return Code::FAST; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001062
1063 private:
1064 DEFINE_HANDLER_CODE_STUB(KeyedLoadSloppyArguments, HandlerStub);
1065};
1066
1067
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001068class CommonStoreModeBits : public BitField<KeyedAccessStoreMode, 0, 3> {};
1069
1070class KeyedStoreSloppyArgumentsStub : public HandlerStub {
1071 public:
1072 explicit KeyedStoreSloppyArgumentsStub(Isolate* isolate,
1073 KeyedAccessStoreMode mode)
1074 : HandlerStub(isolate) {
1075 set_sub_minor_key(CommonStoreModeBits::encode(mode));
1076 }
1077
1078 protected:
1079 Code::Kind kind() const override { return Code::KEYED_STORE_IC; }
1080 Code::StubType GetStubType() const override { return Code::FAST; }
1081
1082 private:
1083 DEFINE_HANDLER_CODE_STUB(KeyedStoreSloppyArguments, HandlerStub);
1084};
1085
1086
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001087class LoadConstantStub : public HandlerStub {
1088 public:
1089 LoadConstantStub(Isolate* isolate, int constant_index)
1090 : HandlerStub(isolate) {
1091 set_sub_minor_key(ConstantIndexBits::encode(constant_index));
1092 }
1093
1094 int constant_index() const {
1095 return ConstantIndexBits::decode(sub_minor_key());
1096 }
1097
1098 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001099 Code::Kind kind() const override { return Code::LOAD_IC; }
1100 Code::StubType GetStubType() const override { return Code::FAST; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001101
1102 private:
1103 class ConstantIndexBits : public BitField<int, 0, kSubMinorKeyBits> {};
1104
1105 DEFINE_HANDLER_CODE_STUB(LoadConstant, HandlerStub);
1106};
1107
1108
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001109class StoreFieldStub : public HandlerStub {
1110 public:
1111 StoreFieldStub(Isolate* isolate, FieldIndex index,
1112 Representation representation)
1113 : HandlerStub(isolate) {
1114 int property_index_key = index.GetFieldAccessStubKey();
1115 uint8_t repr = PropertyDetails::EncodeRepresentation(representation);
1116 set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) |
1117 RepresentationBits::encode(repr));
1118 }
1119
1120 FieldIndex index() const {
1121 int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key());
1122 return FieldIndex::FromFieldAccessStubKey(property_index_key);
1123 }
1124
1125 Representation representation() {
1126 uint8_t repr = RepresentationBits::decode(sub_minor_key());
1127 return PropertyDetails::DecodeRepresentation(repr);
1128 }
1129
1130 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001131 Code::Kind kind() const override { return Code::STORE_IC; }
1132 Code::StubType GetStubType() const override { return Code::FAST; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001133
1134 private:
1135 class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
1136 class RepresentationBits : public BitField<uint8_t, 13, 4> {};
1137
1138 DEFINE_HANDLER_CODE_STUB(StoreField, HandlerStub);
1139};
1140
1141
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001142// Register and parameter access methods are specified here instead of in
1143// the CallInterfaceDescriptor because the stub uses a different descriptor
1144// if FLAG_vector_stores is on.
1145class StoreTransitionHelper {
1146 public:
1147 static Register ReceiverRegister() {
1148 return StoreTransitionDescriptor::ReceiverRegister();
1149 }
1150
1151 static Register NameRegister() {
1152 return StoreTransitionDescriptor::NameRegister();
1153 }
1154
1155 static Register ValueRegister() {
1156 return StoreTransitionDescriptor::ValueRegister();
1157 }
1158
1159 static Register SlotRegister() {
1160 return VectorStoreTransitionDescriptor::SlotRegister();
1161 }
1162
1163 static Register VectorRegister() {
1164 return VectorStoreTransitionDescriptor::VectorRegister();
1165 }
1166
1167 static Register MapRegister() {
1168 return VectorStoreTransitionDescriptor::MapRegister();
1169 }
1170
1171 static int ReceiverIndex() {
1172 return StoreTransitionDescriptor::kReceiverIndex;
1173 }
1174
1175 static int NameIndex() { return StoreTransitionDescriptor::kReceiverIndex; }
1176
1177 static int ValueIndex() { return StoreTransitionDescriptor::kValueIndex; }
1178
1179 static int MapIndex() {
1180 DCHECK(static_cast<int>(VectorStoreTransitionDescriptor::kMapIndex) ==
1181 static_cast<int>(StoreTransitionDescriptor::kMapIndex));
1182 return StoreTransitionDescriptor::kMapIndex;
1183 }
1184
1185 static int VectorIndex() {
1186 if (HasVirtualSlotArg()) {
1187 return VectorStoreTransitionDescriptor::kVirtualSlotVectorIndex;
1188 }
1189 return VectorStoreTransitionDescriptor::kVectorIndex;
1190 }
1191
1192 // Some platforms don't have a slot arg.
1193 static bool HasVirtualSlotArg() {
1194 return SlotRegister().is(no_reg);
1195 }
1196};
1197
1198
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001199class StoreTransitionStub : public HandlerStub {
1200 public:
1201 enum StoreMode {
1202 StoreMapOnly,
1203 StoreMapAndValue,
1204 ExtendStorageAndStoreMapAndValue
1205 };
1206
1207 explicit StoreTransitionStub(Isolate* isolate) : HandlerStub(isolate) {
1208 set_sub_minor_key(StoreModeBits::encode(StoreMapOnly));
1209 }
1210
1211 StoreTransitionStub(Isolate* isolate, FieldIndex index,
1212 Representation representation, StoreMode store_mode)
1213 : HandlerStub(isolate) {
1214 DCHECK(store_mode != StoreMapOnly);
1215 int property_index_key = index.GetFieldAccessStubKey();
1216 uint8_t repr = PropertyDetails::EncodeRepresentation(representation);
1217 set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) |
1218 RepresentationBits::encode(repr) |
1219 StoreModeBits::encode(store_mode));
1220 }
1221
1222 FieldIndex index() const {
1223 DCHECK(store_mode() != StoreMapOnly);
1224 int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key());
1225 return FieldIndex::FromFieldAccessStubKey(property_index_key);
1226 }
1227
1228 Representation representation() {
1229 DCHECK(store_mode() != StoreMapOnly);
1230 uint8_t repr = RepresentationBits::decode(sub_minor_key());
1231 return PropertyDetails::DecodeRepresentation(repr);
1232 }
1233
1234 StoreMode store_mode() const {
1235 return StoreModeBits::decode(sub_minor_key());
1236 }
1237
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001238 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001239
1240 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001241 Code::Kind kind() const override { return Code::STORE_IC; }
1242 Code::StubType GetStubType() const override { return Code::FAST; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001243
1244 private:
1245 class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
1246 class RepresentationBits : public BitField<uint8_t, 13, 4> {};
1247 class StoreModeBits : public BitField<StoreMode, 17, 2> {};
1248
1249 DEFINE_HANDLER_CODE_STUB(StoreTransition, HandlerStub);
1250};
1251
1252
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001253class StoreGlobalStub : public HandlerStub {
1254 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001255 StoreGlobalStub(Isolate* isolate, PropertyCellType type,
1256 Maybe<PropertyCellConstantType> constant_type,
1257 bool check_global)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001258 : HandlerStub(isolate) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001259 PropertyCellConstantType encoded_constant_type =
1260 constant_type.FromMaybe(PropertyCellConstantType::kSmi);
1261 set_sub_minor_key(CellTypeBits::encode(type) |
1262 ConstantTypeBits::encode(encoded_constant_type) |
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001263 CheckGlobalBits::encode(check_global));
1264 }
1265
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001266 static Handle<HeapObject> property_cell_placeholder(Isolate* isolate) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001267 return isolate->factory()->uninitialized_value();
1268 }
1269
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001270 static Handle<HeapObject> global_map_placeholder(Isolate* isolate) {
1271 return isolate->factory()->termination_exception();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001272 }
1273
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001274 Handle<Code> GetCodeCopyFromTemplate(Handle<JSGlobalObject> global,
1275 Handle<PropertyCell> cell) {
1276 Code::FindAndReplacePattern pattern;
1277 if (check_global()) {
1278 pattern.Add(handle(global_map_placeholder(isolate())->map()),
1279 Map::WeakCellForMap(Handle<Map>(global->map())));
1280 }
1281 pattern.Add(handle(property_cell_placeholder(isolate())->map()),
1282 isolate()->factory()->NewWeakCell(cell));
1283 return CodeStub::GetCodeCopy(pattern);
1284 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001285
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001286 Code::Kind kind() const override { return Code::STORE_IC; }
1287
1288 PropertyCellType cell_type() const {
1289 return CellTypeBits::decode(sub_minor_key());
1290 }
1291
1292 PropertyCellConstantType constant_type() const {
1293 DCHECK(PropertyCellType::kConstantType == cell_type());
1294 return ConstantTypeBits::decode(sub_minor_key());
1295 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001296
1297 bool check_global() const { return CheckGlobalBits::decode(sub_minor_key()); }
1298
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001299 Representation representation() {
1300 return Representation::FromKind(
1301 RepresentationBits::decode(sub_minor_key()));
1302 }
1303
1304 void set_representation(Representation r) {
1305 set_sub_minor_key(RepresentationBits::update(sub_minor_key(), r.kind()));
1306 }
1307
1308 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001309 class CellTypeBits : public BitField<PropertyCellType, 0, 2> {};
1310 class ConstantTypeBits : public BitField<PropertyCellConstantType, 2, 2> {};
1311 class RepresentationBits : public BitField<Representation::Kind, 4, 8> {};
1312 class CheckGlobalBits : public BitField<bool, 12, 1> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001313
1314 DEFINE_HANDLER_CODE_STUB(StoreGlobal, HandlerStub);
1315};
1316
1317
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001318class LoadGlobalViaContextStub final : public PlatformCodeStub {
1319 public:
1320 static const int kMaximumDepth = 15;
1321
1322 LoadGlobalViaContextStub(Isolate* isolate, int depth)
1323 : PlatformCodeStub(isolate) {
1324 minor_key_ = DepthBits::encode(depth);
1325 }
1326
1327 int depth() const { return DepthBits::decode(minor_key_); }
1328
1329 private:
1330 class DepthBits : public BitField<int, 0, 4> {};
1331 STATIC_ASSERT(DepthBits::kMax == kMaximumDepth);
1332
1333 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadGlobalViaContext);
1334 DEFINE_PLATFORM_CODE_STUB(LoadGlobalViaContext, PlatformCodeStub);
1335};
1336
1337
1338class StoreGlobalViaContextStub final : public PlatformCodeStub {
1339 public:
1340 static const int kMaximumDepth = 15;
1341
1342 StoreGlobalViaContextStub(Isolate* isolate, int depth,
1343 LanguageMode language_mode)
1344 : PlatformCodeStub(isolate) {
1345 minor_key_ =
1346 DepthBits::encode(depth) | LanguageModeBits::encode(language_mode);
1347 }
1348
1349 int depth() const { return DepthBits::decode(minor_key_); }
1350 LanguageMode language_mode() const {
1351 return LanguageModeBits::decode(minor_key_);
1352 }
1353
1354 private:
1355 class DepthBits : public BitField<int, 0, 4> {};
1356 STATIC_ASSERT(DepthBits::kMax == kMaximumDepth);
1357 class LanguageModeBits : public BitField<LanguageMode, 4, 2> {};
1358 STATIC_ASSERT(LANGUAGE_END == 3);
1359
1360 DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreGlobalViaContext);
1361 DEFINE_PLATFORM_CODE_STUB(StoreGlobalViaContext, PlatformCodeStub);
1362};
1363
1364
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001365class CallApiFunctionStub : public PlatformCodeStub {
1366 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001367 explicit CallApiFunctionStub(Isolate* isolate, bool call_data_undefined)
1368 : PlatformCodeStub(isolate) {
1369 minor_key_ = CallDataUndefinedBits::encode(call_data_undefined);
1370 }
1371
1372 private:
1373 bool call_data_undefined() const {
1374 return CallDataUndefinedBits::decode(minor_key_);
1375 }
1376
1377 class CallDataUndefinedBits : public BitField<bool, 0, 1> {};
1378
1379 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiFunction);
1380 DEFINE_PLATFORM_CODE_STUB(CallApiFunction, PlatformCodeStub);
1381};
1382
1383
1384class CallApiAccessorStub : public PlatformCodeStub {
1385 public:
1386 CallApiAccessorStub(Isolate* isolate, bool is_store, bool call_data_undefined)
1387 : PlatformCodeStub(isolate) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001388 minor_key_ = IsStoreBits::encode(is_store) |
1389 CallDataUndefinedBits::encode(call_data_undefined) |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001390 ArgumentBits::encode(is_store ? 1 : 0);
1391 }
1392
1393 protected:
1394 // For CallApiFunctionWithFixedArgsStub, see below.
1395 static const int kArgBits = 3;
1396 CallApiAccessorStub(Isolate* isolate, int argc, bool call_data_undefined)
1397 : PlatformCodeStub(isolate) {
1398 minor_key_ = IsStoreBits::encode(false) |
1399 CallDataUndefinedBits::encode(call_data_undefined) |
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001400 ArgumentBits::encode(argc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001401 }
1402
1403 private:
1404 bool is_store() const { return IsStoreBits::decode(minor_key_); }
1405 bool call_data_undefined() const {
1406 return CallDataUndefinedBits::decode(minor_key_);
1407 }
1408 int argc() const { return ArgumentBits::decode(minor_key_); }
1409
1410 class IsStoreBits: public BitField<bool, 0, 1> {};
1411 class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001412 class ArgumentBits : public BitField<int, 2, kArgBits> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001413
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001414 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiAccessor);
1415 DEFINE_PLATFORM_CODE_STUB(CallApiAccessor, PlatformCodeStub);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001416};
1417
1418
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001419// TODO(dcarney): see if it's possible to remove this later without performance
1420// degradation.
1421// This is not a real stub, but a way of generating the CallApiAccessorStub
1422// (which has the same abi) which makes it clear that it is not an accessor.
1423class CallApiFunctionWithFixedArgsStub : public CallApiAccessorStub {
1424 public:
1425 static const int kMaxFixedArgs = (1 << kArgBits) - 1;
1426 CallApiFunctionWithFixedArgsStub(Isolate* isolate, int argc,
1427 bool call_data_undefined)
1428 : CallApiAccessorStub(isolate, argc, call_data_undefined) {
1429 DCHECK(0 <= argc && argc <= kMaxFixedArgs);
1430 }
1431};
1432
1433
1434typedef ApiAccessorDescriptor ApiFunctionWithFixedArgsDescriptor;
1435
1436
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001437class CallApiGetterStub : public PlatformCodeStub {
1438 public:
1439 explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1440
1441 DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiGetter);
1442 DEFINE_PLATFORM_CODE_STUB(CallApiGetter, PlatformCodeStub);
1443};
1444
1445
1446class BinaryOpICStub : public HydrogenCodeStub {
1447 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001448 BinaryOpICStub(Isolate* isolate, Token::Value op, Strength strength)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001449 : HydrogenCodeStub(isolate, UNINITIALIZED) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001450 BinaryOpICState state(isolate, op, strength);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001451 set_sub_minor_key(state.GetExtraICState());
1452 }
1453
1454 BinaryOpICStub(Isolate* isolate, const BinaryOpICState& state)
1455 : HydrogenCodeStub(isolate) {
1456 set_sub_minor_key(state.GetExtraICState());
1457 }
1458
1459 static void GenerateAheadOfTime(Isolate* isolate);
1460
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001461 Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001462
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001463 InlineCacheState GetICState() const final { return state().GetICState(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001464
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001465 ExtraICState GetExtraICState() const final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001466 return static_cast<ExtraICState>(sub_minor_key());
1467 }
1468
1469 BinaryOpICState state() const {
1470 return BinaryOpICState(isolate(), GetExtraICState());
1471 }
1472
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001473 void PrintState(std::ostream& os) const final; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001474
1475 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1476 static const int kLeft = 0;
1477 static const int kRight = 1;
1478
1479 private:
1480 static void GenerateAheadOfTime(Isolate* isolate,
1481 const BinaryOpICState& state);
1482
1483 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1484 DEFINE_HYDROGEN_CODE_STUB(BinaryOpIC, HydrogenCodeStub);
1485};
1486
1487
1488// TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
1489// call support for stubs in Hydrogen.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001490class BinaryOpICWithAllocationSiteStub final : public PlatformCodeStub {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001491 public:
1492 BinaryOpICWithAllocationSiteStub(Isolate* isolate,
1493 const BinaryOpICState& state)
1494 : PlatformCodeStub(isolate) {
1495 minor_key_ = state.GetExtraICState();
1496 }
1497
1498 static void GenerateAheadOfTime(Isolate* isolate);
1499
1500 Handle<Code> GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site) {
1501 Code::FindAndReplacePattern pattern;
1502 pattern.Add(isolate()->factory()->undefined_map(), allocation_site);
1503 return CodeStub::GetCodeCopy(pattern);
1504 }
1505
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001506 Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001507
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001508 InlineCacheState GetICState() const override { return state().GetICState(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001509
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001510 ExtraICState GetExtraICState() const override {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001511 return static_cast<ExtraICState>(minor_key_);
1512 }
1513
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001514 void PrintState(std::ostream& os) const override; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001515
1516 private:
1517 BinaryOpICState state() const {
1518 return BinaryOpICState(isolate(), static_cast<ExtraICState>(minor_key_));
1519 }
1520
1521 static void GenerateAheadOfTime(Isolate* isolate,
1522 const BinaryOpICState& state);
1523
1524 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1525 DEFINE_PLATFORM_CODE_STUB(BinaryOpICWithAllocationSite, PlatformCodeStub);
1526};
1527
1528
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001529class BinaryOpWithAllocationSiteStub final : public BinaryOpICStub {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001530 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001531 BinaryOpWithAllocationSiteStub(Isolate* isolate, Token::Value op,
1532 Strength strength)
1533 : BinaryOpICStub(isolate, op, strength) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001534
1535 BinaryOpWithAllocationSiteStub(Isolate* isolate, const BinaryOpICState& state)
1536 : BinaryOpICStub(isolate, state) {}
1537
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001538 Code::Kind GetCodeKind() const final { return Code::STUB; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001539
1540 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1541 static const int kAllocationSite = 0;
1542 static const int kLeft = 1;
1543 static const int kRight = 2;
1544
1545 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1546 DEFINE_HYDROGEN_CODE_STUB(BinaryOpWithAllocationSite, BinaryOpICStub);
1547};
1548
1549
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001550class StringAddStub final : public HydrogenCodeStub {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001551 public:
1552 StringAddStub(Isolate* isolate, StringAddFlags flags,
1553 PretenureFlag pretenure_flag)
1554 : HydrogenCodeStub(isolate) {
1555 set_sub_minor_key(StringAddFlagsBits::encode(flags) |
1556 PretenureFlagBits::encode(pretenure_flag));
1557 }
1558
1559 StringAddFlags flags() const {
1560 return StringAddFlagsBits::decode(sub_minor_key());
1561 }
1562
1563 PretenureFlag pretenure_flag() const {
1564 return PretenureFlagBits::decode(sub_minor_key());
1565 }
1566
1567 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1568 static const int kLeft = 0;
1569 static const int kRight = 1;
1570
1571 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001572 class StringAddFlagsBits : public BitField<StringAddFlags, 0, 3> {};
1573 class PretenureFlagBits : public BitField<PretenureFlag, 3, 1> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001574
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001575 void PrintBaseName(std::ostream& os) const override; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001576
1577 DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd);
1578 DEFINE_HYDROGEN_CODE_STUB(StringAdd, HydrogenCodeStub);
1579};
1580
1581
1582class CompareICStub : public PlatformCodeStub {
1583 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001584 CompareICStub(Isolate* isolate, Token::Value op, Strength strength,
1585 CompareICState::State left, CompareICState::State right,
1586 CompareICState::State state)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001587 : PlatformCodeStub(isolate) {
1588 DCHECK(Token::IsCompareOp(op));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001589 minor_key_ = OpBits::encode(op - Token::EQ) |
1590 StrengthBits::encode(is_strong(strength)) |
1591 LeftStateBits::encode(left) | RightStateBits::encode(right) |
1592 StateBits::encode(state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001593 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001594
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001595 void set_known_map(Handle<Map> map) { known_map_ = map; }
1596
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001597 InlineCacheState GetICState() const override;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001598
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001599 Token::Value op() const {
1600 return static_cast<Token::Value>(Token::EQ + OpBits::decode(minor_key_));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001601 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001602
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001603 Strength strength() const {
1604 return StrengthBits::decode(minor_key_) ? Strength::STRONG : Strength::WEAK;
1605 }
1606
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001607 CompareICState::State left() const {
1608 return LeftStateBits::decode(minor_key_);
1609 }
1610 CompareICState::State right() const {
1611 return RightStateBits::decode(minor_key_);
1612 }
1613 CompareICState::State state() const { return StateBits::decode(minor_key_); }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001614
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001615 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001616 Code::Kind GetCodeKind() const override { return Code::COMPARE_IC; }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001617
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001618 void GenerateBooleans(MacroAssembler* masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001619 void GenerateSmis(MacroAssembler* masm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001620 void GenerateNumbers(MacroAssembler* masm);
1621 void GenerateInternalizedStrings(MacroAssembler* masm);
Ben Murdoch257744e2011-11-30 15:57:28 +00001622 void GenerateStrings(MacroAssembler* masm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001623 void GenerateUniqueNames(MacroAssembler* masm);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001624 void GenerateReceivers(MacroAssembler* masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001625 void GenerateMiss(MacroAssembler* masm);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001626 void GenerateKnownReceivers(MacroAssembler* masm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001627 void GenerateGeneric(MacroAssembler* masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001628
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001629 bool strict() const { return op() == Token::EQ_STRICT; }
1630 Condition GetCondition() const;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001631
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001632 void AddToSpecialCache(Handle<Code> new_object) override;
1633 bool FindCodeInSpecialCache(Code** code_out) override;
1634 bool UseSpecialCache() override {
1635 return state() == CompareICState::KNOWN_RECEIVER;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001636 }
1637
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001638 class OpBits : public BitField<int, 0, 3> {};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001639 class StrengthBits : public BitField<bool, 3, 1> {};
1640 class LeftStateBits : public BitField<CompareICState::State, 4, 4> {};
1641 class RightStateBits : public BitField<CompareICState::State, 8, 4> {};
1642 class StateBits : public BitField<CompareICState::State, 12, 4> {};
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001643
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001644 Handle<Map> known_map_;
1645
1646 DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1647 DEFINE_PLATFORM_CODE_STUB(CompareIC, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001648};
1649
1650
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001651class CompareNilICStub : public HydrogenCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001652 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001653 Type* GetType(Zone* zone, Handle<Map> map = Handle<Map>());
1654 Type* GetInputType(Zone* zone, Handle<Map> map);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001655
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001656 CompareNilICStub(Isolate* isolate, NilValue nil) : HydrogenCodeStub(isolate) {
1657 set_sub_minor_key(NilValueBits::encode(nil));
1658 }
1659
1660 CompareNilICStub(Isolate* isolate, ExtraICState ic_state,
1661 InitializationState init_state = INITIALIZED)
1662 : HydrogenCodeStub(isolate, init_state) {
1663 set_sub_minor_key(ic_state);
1664 }
1665
1666 static Handle<Code> GetUninitialized(Isolate* isolate,
1667 NilValue nil) {
1668 return CompareNilICStub(isolate, nil, UNINITIALIZED).GetCode();
1669 }
1670
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001671 InlineCacheState GetICState() const override {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001672 State state = this->state();
1673 if (state.Contains(GENERIC)) {
1674 return MEGAMORPHIC;
1675 } else if (state.Contains(MONOMORPHIC_MAP)) {
1676 return MONOMORPHIC;
1677 } else {
1678 return PREMONOMORPHIC;
1679 }
1680 }
1681
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001682 Code::Kind GetCodeKind() const override { return Code::COMPARE_NIL_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001683
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001684 ExtraICState GetExtraICState() const override { return sub_minor_key(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001685
1686 void UpdateStatus(Handle<Object> object);
1687
1688 bool IsMonomorphic() const { return state().Contains(MONOMORPHIC_MAP); }
1689
1690 NilValue nil_value() const { return NilValueBits::decode(sub_minor_key()); }
1691
1692 void ClearState() {
1693 set_sub_minor_key(TypesBits::update(sub_minor_key(), 0));
1694 }
1695
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001696 void PrintState(std::ostream& os) const override; // NOLINT
1697 void PrintBaseName(std::ostream& os) const override; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001698
1699 private:
1700 CompareNilICStub(Isolate* isolate, NilValue nil,
1701 InitializationState init_state)
1702 : HydrogenCodeStub(isolate, init_state) {
1703 set_sub_minor_key(NilValueBits::encode(nil));
1704 }
1705
1706 enum CompareNilType {
1707 UNDEFINED,
1708 NULL_TYPE,
1709 MONOMORPHIC_MAP,
1710 GENERIC,
1711 NUMBER_OF_TYPES
1712 };
1713
1714 // At most 6 different types can be distinguished, because the Code object
1715 // only has room for a single byte to hold a set and there are two more
1716 // boolean flags we need to store. :-P
1717 STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
1718
1719 class State : public EnumSet<CompareNilType, byte> {
1720 public:
1721 State() : EnumSet<CompareNilType, byte>(0) { }
1722 explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
1723 };
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001724 friend std::ostream& operator<<(std::ostream& os, const State& s);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001725
1726 State state() const { return State(TypesBits::decode(sub_minor_key())); }
1727
1728 class NilValueBits : public BitField<NilValue, 0, 1> {};
1729 class TypesBits : public BitField<byte, 1, NUMBER_OF_TYPES> {};
1730
1731 friend class CompareNilIC;
1732
1733 DEFINE_CALL_INTERFACE_DESCRIPTOR(CompareNil);
1734 DEFINE_HYDROGEN_CODE_STUB(CompareNilIC, HydrogenCodeStub);
1735};
1736
1737
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001738std::ostream& operator<<(std::ostream& os, const CompareNilICStub::State& s);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001739
1740
1741class CEntryStub : public PlatformCodeStub {
1742 public:
1743 CEntryStub(Isolate* isolate, int result_size,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001744 SaveFPRegsMode save_doubles = kDontSaveFPRegs,
1745 ArgvMode argv_mode = kArgvOnStack)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001746 : PlatformCodeStub(isolate) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001747 minor_key_ = SaveDoublesBits::encode(save_doubles == kSaveFPRegs) |
1748 ArgvMode::encode(argv_mode == kArgvInRegister);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001749 DCHECK(result_size == 1 || result_size == 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001750#if _WIN64 || V8_TARGET_ARCH_PPC
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001751 minor_key_ = ResultSizeBits::update(minor_key_, result_size);
1752#endif // _WIN64
1753 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001754
1755 // The version of this stub that doesn't save doubles is generated ahead of
1756 // time, so it's OK to call it from other stubs that can't cope with GC during
1757 // their code generation. On machines that always have gp registers (x64) we
1758 // can generate both variants ahead of time.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001759 static void GenerateAheadOfTime(Isolate* isolate);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001760
1761 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001762 bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001763 bool argv_in_register() const { return ArgvMode::decode(minor_key_); }
1764#if _WIN64 || V8_TARGET_ARCH_PPC
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001765 int result_size() const { return ResultSizeBits::decode(minor_key_); }
1766#endif // _WIN64
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001767
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001768 bool NeedsImmovableCode() override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001769
1770 class SaveDoublesBits : public BitField<bool, 0, 1> {};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001771 class ArgvMode : public BitField<bool, 1, 1> {};
1772 class ResultSizeBits : public BitField<int, 2, 3> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001773
1774 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1775 DEFINE_PLATFORM_CODE_STUB(CEntry, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001776};
1777
1778
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001779class JSEntryStub : public PlatformCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001780 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001781 JSEntryStub(Isolate* isolate, StackFrame::Type type)
1782 : PlatformCodeStub(isolate) {
1783 DCHECK(type == StackFrame::ENTRY || type == StackFrame::ENTRY_CONSTRUCT);
1784 minor_key_ = StackFrameTypeBits::encode(type);
1785 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001786
1787 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001788 void FinishCode(Handle<Code> code) override;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001789
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001790 void PrintName(std::ostream& os) const override { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001791 os << (type() == StackFrame::ENTRY ? "JSEntryStub"
1792 : "JSConstructEntryStub");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001793 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001794
1795 StackFrame::Type type() const {
1796 return StackFrameTypeBits::decode(minor_key_);
1797 }
1798
1799 class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {};
1800
1801 int handler_offset_;
1802
1803 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1804 DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001805};
1806
1807
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001808class ArgumentsAccessStub: public PlatformCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001809 public:
1810 enum Type {
1811 READ_ELEMENT,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001812 NEW_SLOPPY_FAST,
1813 NEW_SLOPPY_SLOW,
Steve Block44f0eee2011-05-26 01:26:41 +01001814 NEW_STRICT
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001815 };
1816
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001817 ArgumentsAccessStub(Isolate* isolate, Type type) : PlatformCodeStub(isolate) {
1818 minor_key_ = TypeBits::encode(type);
1819 }
1820
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001821 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001822 if (type() == READ_ELEMENT) {
1823 return ArgumentsAccessReadDescriptor(isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001824 } else {
1825 return ArgumentsAccessNewDescriptor(isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001826 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001827 }
1828
1829 static Type ComputeType(bool is_unmapped, bool has_duplicate_parameters) {
1830 if (is_unmapped) {
1831 return Type::NEW_STRICT;
1832 } else if (has_duplicate_parameters) {
1833 return Type::NEW_SLOPPY_SLOW;
1834 } else {
1835 return Type::NEW_SLOPPY_FAST;
1836 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001837 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001838
1839 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001840 Type type() const { return TypeBits::decode(minor_key_); }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001841
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001842 void GenerateReadElement(MacroAssembler* masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001843 void GenerateNewStrict(MacroAssembler* masm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001844 void GenerateNewSloppyFast(MacroAssembler* masm);
1845 void GenerateNewSloppySlow(MacroAssembler* masm);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001846
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001847 void PrintName(std::ostream& os) const override; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001848
1849 class TypeBits : public BitField<Type, 0, 2> {};
1850
1851 DEFINE_PLATFORM_CODE_STUB(ArgumentsAccess, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001852};
1853
1854
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001855class RestParamAccessStub : public PlatformCodeStub {
1856 public:
1857 explicit RestParamAccessStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1858
1859 private:
1860 void GenerateNew(MacroAssembler* masm);
1861
1862 void PrintName(std::ostream& os) const override; // NOLINT
1863
1864 DEFINE_CALL_INTERFACE_DESCRIPTOR(RestParamAccess);
1865 DEFINE_PLATFORM_CODE_STUB(RestParamAccess, PlatformCodeStub);
1866};
1867
1868
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001869class RegExpExecStub: public PlatformCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001870 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001871 explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001872
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001873 DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
1874 DEFINE_PLATFORM_CODE_STUB(RegExpExec, PlatformCodeStub);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001875};
1876
1877
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001878class RegExpConstructResultStub final : public HydrogenCodeStub {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001879 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001880 explicit RegExpConstructResultStub(Isolate* isolate)
1881 : HydrogenCodeStub(isolate) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001882
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001883 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1884 static const int kLength = 0;
1885 static const int kIndex = 1;
1886 static const int kInput = 2;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001887
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001888 DEFINE_CALL_INTERFACE_DESCRIPTOR(RegExpConstructResult);
1889 DEFINE_HYDROGEN_CODE_STUB(RegExpConstructResult, HydrogenCodeStub);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001890};
1891
1892
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001893// TODO(bmeurer/mvstanton): Turn CallConstructStub into ConstructICStub.
1894class CallConstructStub final : public PlatformCodeStub {
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001895 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001896 explicit CallConstructStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001897
1898 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallConstruct);
1899 DEFINE_PLATFORM_CODE_STUB(CallConstruct, PlatformCodeStub);
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01001900};
1901
1902
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001903enum StringIndexFlags {
1904 // Accepts smis or heap numbers.
1905 STRING_INDEX_IS_NUMBER,
1906
1907 // Accepts smis or heap numbers that are valid array indices
1908 // (ECMA-262 15.4). Invalid indices are reported as being out of
1909 // range.
1910 STRING_INDEX_IS_ARRAY_INDEX
1911};
1912
1913
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001914enum ReceiverCheckMode {
1915 // We don't know anything about the receiver.
1916 RECEIVER_IS_UNKNOWN,
1917
1918 // We know the receiver is a string.
1919 RECEIVER_IS_STRING
1920};
1921
1922
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001923enum EmbedMode {
1924 // The code being generated is part of an IC handler, which may MISS
1925 // to an IC in failure cases.
1926 PART_OF_IC_HANDLER,
1927
1928 NOT_PART_OF_IC_HANDLER
1929};
1930
1931
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001932// Generates code implementing String.prototype.charCodeAt.
1933//
1934// Only supports the case when the receiver is a string and the index
1935// is a number (smi or heap number) that is a valid index into the
1936// string. Additional index constraints are specified by the
1937// flags. Otherwise, bails out to the provided labels.
1938//
1939// Register usage: |object| may be changed to another string in a way
1940// that doesn't affect charCodeAt/charAt semantics, |index| is
1941// preserved, |scratch| and |result| are clobbered.
1942class StringCharCodeAtGenerator {
1943 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001944 StringCharCodeAtGenerator(Register object, Register index, Register result,
1945 Label* receiver_not_string, Label* index_not_number,
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001946 Label* index_out_of_range,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001947 StringIndexFlags index_flags,
1948 ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001949 : object_(object),
1950 index_(index),
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001951 result_(result),
1952 receiver_not_string_(receiver_not_string),
1953 index_not_number_(index_not_number),
1954 index_out_of_range_(index_out_of_range),
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001955 index_flags_(index_flags),
1956 check_mode_(check_mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001957 DCHECK(!result_.is(object_));
1958 DCHECK(!result_.is(index_));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001959 }
1960
1961 // Generates the fast case code. On the fallthrough path |result|
1962 // register contains the result.
1963 void GenerateFast(MacroAssembler* masm);
1964
1965 // Generates the slow case code. Must not be naturally
1966 // reachable. Expected to be put after a ret instruction (e.g., in
1967 // deferred code). Always jumps back to the fast case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001968 void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001969 const RuntimeCallHelper& call_helper);
1970
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001971 // Skip handling slow case and directly jump to bailout.
1972 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1973 masm->bind(&index_not_smi_);
1974 masm->bind(&call_runtime_);
1975 masm->jmp(bailout);
1976 }
1977
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001978 private:
1979 Register object_;
1980 Register index_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001981 Register result_;
1982
1983 Label* receiver_not_string_;
1984 Label* index_not_number_;
1985 Label* index_out_of_range_;
1986
1987 StringIndexFlags index_flags_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001988 ReceiverCheckMode check_mode_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001989
1990 Label call_runtime_;
1991 Label index_not_smi_;
1992 Label got_smi_index_;
1993 Label exit_;
1994
1995 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
1996};
1997
1998
1999// Generates code for creating a one-char string from a char code.
2000class StringCharFromCodeGenerator {
2001 public:
2002 StringCharFromCodeGenerator(Register code,
2003 Register result)
2004 : code_(code),
2005 result_(result) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002006 DCHECK(!code_.is(result_));
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002007 }
2008
2009 // Generates the fast case code. On the fallthrough path |result|
2010 // register contains the result.
2011 void GenerateFast(MacroAssembler* masm);
2012
2013 // Generates the slow case code. Must not be naturally
2014 // reachable. Expected to be put after a ret instruction (e.g., in
2015 // deferred code). Always jumps back to the fast case.
2016 void GenerateSlow(MacroAssembler* masm,
2017 const RuntimeCallHelper& call_helper);
2018
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002019 // Skip handling slow case and directly jump to bailout.
2020 void SkipSlow(MacroAssembler* masm, Label* bailout) {
2021 masm->bind(&slow_case_);
2022 masm->jmp(bailout);
2023 }
2024
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002025 private:
2026 Register code_;
2027 Register result_;
2028
2029 Label slow_case_;
2030 Label exit_;
2031
2032 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
2033};
2034
2035
2036// Generates code implementing String.prototype.charAt.
2037//
2038// Only supports the case when the receiver is a string and the index
2039// is a number (smi or heap number) that is a valid index into the
2040// string. Additional index constraints are specified by the
2041// flags. Otherwise, bails out to the provided labels.
2042//
2043// Register usage: |object| may be changed to another string in a way
2044// that doesn't affect charCodeAt/charAt semantics, |index| is
2045// preserved, |scratch1|, |scratch2|, and |result| are clobbered.
2046class StringCharAtGenerator {
2047 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002048 StringCharAtGenerator(Register object, Register index, Register scratch,
2049 Register result, Label* receiver_not_string,
2050 Label* index_not_number, Label* index_out_of_range,
2051 StringIndexFlags index_flags,
2052 ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
2053 : char_code_at_generator_(object, index, scratch, receiver_not_string,
2054 index_not_number, index_out_of_range,
2055 index_flags, check_mode),
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002056 char_from_code_generator_(scratch, result) {}
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002057
2058 // Generates the fast case code. On the fallthrough path |result|
2059 // register contains the result.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002060 void GenerateFast(MacroAssembler* masm) {
2061 char_code_at_generator_.GenerateFast(masm);
2062 char_from_code_generator_.GenerateFast(masm);
2063 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002064
2065 // Generates the slow case code. Must not be naturally
2066 // reachable. Expected to be put after a ret instruction (e.g., in
2067 // deferred code). Always jumps back to the fast case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002068 void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002069 const RuntimeCallHelper& call_helper) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002070 char_code_at_generator_.GenerateSlow(masm, embed_mode, call_helper);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002071 char_from_code_generator_.GenerateSlow(masm, call_helper);
2072 }
2073
2074 // Skip handling slow case and directly jump to bailout.
2075 void SkipSlow(MacroAssembler* masm, Label* bailout) {
2076 char_code_at_generator_.SkipSlow(masm, bailout);
2077 char_from_code_generator_.SkipSlow(masm, bailout);
2078 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002079
2080 private:
2081 StringCharCodeAtGenerator char_code_at_generator_;
2082 StringCharFromCodeGenerator char_from_code_generator_;
2083
2084 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
2085};
2086
Ben Murdoch086aeea2011-05-13 15:57:08 +01002087
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002088class LoadDictionaryElementStub : public HydrogenCodeStub {
Ben Murdoch086aeea2011-05-13 15:57:08 +01002089 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002090 explicit LoadDictionaryElementStub(Isolate* isolate, const LoadICState& state)
2091 : HydrogenCodeStub(isolate) {
2092 minor_key_ = state.GetExtraICState();
2093 }
Ben Murdoch086aeea2011-05-13 15:57:08 +01002094
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002095 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
2096 return LoadWithVectorDescriptor(isolate());
2097 }
2098
2099 LanguageMode language_mode() const {
2100 return LoadICState::GetLanguageMode(MinorKey());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002101 }
2102
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002103 DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub);
Ben Murdoch086aeea2011-05-13 15:57:08 +01002104};
2105
Ben Murdoch257744e2011-11-30 15:57:28 +00002106
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002107class KeyedLoadGenericStub : public HydrogenCodeStub {
Ben Murdoch257744e2011-11-30 15:57:28 +00002108 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002109 explicit KeyedLoadGenericStub(Isolate* isolate, const LoadICState& state)
2110 : HydrogenCodeStub(isolate) {
2111 minor_key_ = state.GetExtraICState();
2112 }
Ben Murdoch257744e2011-11-30 15:57:28 +00002113
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002114 Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2115 InlineCacheState GetICState() const override { return GENERIC; }
Ben Murdoch257744e2011-11-30 15:57:28 +00002116
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002117 LanguageMode language_mode() const {
2118 return LoadICState::GetLanguageMode(MinorKey());
2119 }
2120
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002121 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002122
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002123 DEFINE_HYDROGEN_CODE_STUB(KeyedLoadGeneric, HydrogenCodeStub);
Ben Murdoch257744e2011-11-30 15:57:28 +00002124};
2125
2126
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002127class LoadICTrampolineStub : public PlatformCodeStub {
Ben Murdoch257744e2011-11-30 15:57:28 +00002128 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002129 LoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
2130 : PlatformCodeStub(isolate) {
2131 minor_key_ = state.GetExtraICState();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002132 }
Ben Murdoch257744e2011-11-30 15:57:28 +00002133
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002134 Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002135
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002136 InlineCacheState GetICState() const final { return GENERIC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002137
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002138 ExtraICState GetExtraICState() const final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002139 return static_cast<ExtraICState>(minor_key_);
2140 }
Ben Murdoch257744e2011-11-30 15:57:28 +00002141
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002142 protected:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002143 LoadICState state() const {
2144 return LoadICState(static_cast<ExtraICState>(minor_key_));
2145 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002146
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002147 DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002148 DEFINE_PLATFORM_CODE_STUB(LoadICTrampoline, PlatformCodeStub);
Ben Murdoch257744e2011-11-30 15:57:28 +00002149};
2150
2151
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002152class KeyedLoadICTrampolineStub : public LoadICTrampolineStub {
2153 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002154 explicit KeyedLoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
2155 : LoadICTrampolineStub(isolate, state) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002156
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002157 Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002158
2159 DEFINE_PLATFORM_CODE_STUB(KeyedLoadICTrampoline, LoadICTrampolineStub);
2160};
2161
2162
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002163class VectorStoreICTrampolineStub : public PlatformCodeStub {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002164 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002165 VectorStoreICTrampolineStub(Isolate* isolate, const StoreICState& state)
2166 : PlatformCodeStub(isolate) {
2167 minor_key_ = state.GetExtraICState();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002168 }
2169
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002170 Code::Kind GetCodeKind() const override { return Code::STORE_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002171
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002172 InlineCacheState GetICState() const final { return GENERIC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002173
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002174 ExtraICState GetExtraICState() const final {
2175 return static_cast<ExtraICState>(minor_key_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002176 }
2177
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002178 protected:
2179 StoreICState state() const {
2180 return StoreICState(static_cast<ExtraICState>(minor_key_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002181 }
2182
2183 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002184 DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreICTrampoline);
2185 DEFINE_PLATFORM_CODE_STUB(VectorStoreICTrampoline, PlatformCodeStub);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002186};
2187
2188
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002189class VectorKeyedStoreICTrampolineStub : public VectorStoreICTrampolineStub {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002190 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002191 VectorKeyedStoreICTrampolineStub(Isolate* isolate, const StoreICState& state)
2192 : VectorStoreICTrampolineStub(isolate, state) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002193
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002194 Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002195
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002196 DEFINE_PLATFORM_CODE_STUB(VectorKeyedStoreICTrampoline,
2197 VectorStoreICTrampolineStub);
2198};
2199
2200
2201class CallICTrampolineStub : public PlatformCodeStub {
2202 public:
2203 CallICTrampolineStub(Isolate* isolate, const CallICState& state)
2204 : PlatformCodeStub(isolate) {
2205 minor_key_ = state.GetExtraICState();
2206 }
2207
2208 Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
2209
2210 InlineCacheState GetICState() const final { return GENERIC; }
2211
2212 ExtraICState GetExtraICState() const final {
2213 return static_cast<ExtraICState>(minor_key_);
2214 }
2215
2216 protected:
2217 CallICState state() const {
2218 return CallICState(static_cast<ExtraICState>(minor_key_));
2219 }
2220
2221 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedback);
2222 DEFINE_PLATFORM_CODE_STUB(CallICTrampoline, PlatformCodeStub);
2223};
2224
2225
2226class LoadICStub : public PlatformCodeStub {
2227 public:
2228 explicit LoadICStub(Isolate* isolate, const LoadICState& state)
2229 : PlatformCodeStub(isolate) {
2230 minor_key_ = state.GetExtraICState();
2231 }
2232
2233 void GenerateForTrampoline(MacroAssembler* masm);
2234
2235 Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
2236 InlineCacheState GetICState() const final { return GENERIC; }
2237 ExtraICState GetExtraICState() const final {
2238 return static_cast<ExtraICState>(minor_key_);
2239 }
2240
2241 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
2242 DEFINE_PLATFORM_CODE_STUB(LoadIC, PlatformCodeStub);
2243
2244 protected:
2245 void GenerateImpl(MacroAssembler* masm, bool in_frame);
2246};
2247
2248
2249class KeyedLoadICStub : public PlatformCodeStub {
2250 public:
2251 explicit KeyedLoadICStub(Isolate* isolate, const LoadICState& state)
2252 : PlatformCodeStub(isolate) {
2253 minor_key_ = state.GetExtraICState();
2254 }
2255
2256 void GenerateForTrampoline(MacroAssembler* masm);
2257
2258 Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2259 InlineCacheState GetICState() const final { return GENERIC; }
2260 ExtraICState GetExtraICState() const final {
2261 return static_cast<ExtraICState>(minor_key_);
2262 }
2263
2264 DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
2265 DEFINE_PLATFORM_CODE_STUB(KeyedLoadIC, PlatformCodeStub);
2266
2267 protected:
2268 void GenerateImpl(MacroAssembler* masm, bool in_frame);
2269};
2270
2271
2272class VectorStoreICStub : public PlatformCodeStub {
2273 public:
2274 VectorStoreICStub(Isolate* isolate, const StoreICState& state)
2275 : PlatformCodeStub(isolate) {
2276 minor_key_ = state.GetExtraICState();
2277 }
2278
2279 void GenerateForTrampoline(MacroAssembler* masm);
2280
2281 Code::Kind GetCodeKind() const final { return Code::STORE_IC; }
2282 InlineCacheState GetICState() const final { return GENERIC; }
2283 ExtraICState GetExtraICState() const final {
2284 return static_cast<ExtraICState>(minor_key_);
2285 }
2286
2287 DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreIC);
2288 DEFINE_PLATFORM_CODE_STUB(VectorStoreIC, PlatformCodeStub);
2289
2290 protected:
2291 void GenerateImpl(MacroAssembler* masm, bool in_frame);
2292};
2293
2294
2295class VectorKeyedStoreICStub : public PlatformCodeStub {
2296 public:
2297 VectorKeyedStoreICStub(Isolate* isolate, const StoreICState& state)
2298 : PlatformCodeStub(isolate) {
2299 minor_key_ = state.GetExtraICState();
2300 }
2301
2302 void GenerateForTrampoline(MacroAssembler* masm);
2303
2304 Code::Kind GetCodeKind() const final { return Code::KEYED_STORE_IC; }
2305 InlineCacheState GetICState() const final { return GENERIC; }
2306 ExtraICState GetExtraICState() const final {
2307 return static_cast<ExtraICState>(minor_key_);
2308 }
2309
2310 DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreIC);
2311 DEFINE_PLATFORM_CODE_STUB(VectorKeyedStoreIC, PlatformCodeStub);
2312
2313 protected:
2314 void GenerateImpl(MacroAssembler* masm, bool in_frame);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002315};
2316
2317
2318class DoubleToIStub : public PlatformCodeStub {
2319 public:
2320 DoubleToIStub(Isolate* isolate, Register source, Register destination,
2321 int offset, bool is_truncating, bool skip_fastpath = false)
2322 : PlatformCodeStub(isolate) {
2323 minor_key_ = SourceRegisterBits::encode(source.code()) |
2324 DestinationRegisterBits::encode(destination.code()) |
2325 OffsetBits::encode(offset) |
2326 IsTruncatingBits::encode(is_truncating) |
2327 SkipFastPathBits::encode(skip_fastpath) |
2328 SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0);
2329 }
2330
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002331 bool SometimesSetsUpAFrame() override { return false; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002332
2333 private:
2334 Register source() const {
2335 return Register::from_code(SourceRegisterBits::decode(minor_key_));
2336 }
2337 Register destination() const {
2338 return Register::from_code(DestinationRegisterBits::decode(minor_key_));
2339 }
2340 bool is_truncating() const { return IsTruncatingBits::decode(minor_key_); }
2341 bool skip_fastpath() const { return SkipFastPathBits::decode(minor_key_); }
2342 int offset() const { return OffsetBits::decode(minor_key_); }
2343
2344 static const int kBitsPerRegisterNumber = 6;
2345 STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
2346 class SourceRegisterBits:
2347 public BitField<int, 0, kBitsPerRegisterNumber> {}; // NOLINT
2348 class DestinationRegisterBits:
2349 public BitField<int, kBitsPerRegisterNumber,
2350 kBitsPerRegisterNumber> {}; // NOLINT
2351 class IsTruncatingBits:
2352 public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {}; // NOLINT
2353 class OffsetBits:
2354 public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {}; // NOLINT
2355 class SkipFastPathBits:
2356 public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {}; // NOLINT
2357 class SSE3Bits:
2358 public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {}; // NOLINT
2359
2360 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2361 DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub);
2362};
2363
2364
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002365class ScriptContextFieldStub : public HandlerStub {
2366 public:
2367 ScriptContextFieldStub(Isolate* isolate,
2368 const ScriptContextTable::LookupResult* lookup_result)
2369 : HandlerStub(isolate) {
2370 DCHECK(Accepted(lookup_result));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002371 STATIC_ASSERT(kContextIndexBits + kSlotIndexBits <= kSubMinorKeyBits);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002372 set_sub_minor_key(ContextIndexBits::encode(lookup_result->context_index) |
2373 SlotIndexBits::encode(lookup_result->slot_index));
2374 }
2375
2376 int context_index() const {
2377 return ContextIndexBits::decode(sub_minor_key());
2378 }
2379
2380 int slot_index() const { return SlotIndexBits::decode(sub_minor_key()); }
2381
2382 static bool Accepted(const ScriptContextTable::LookupResult* lookup_result) {
2383 return ContextIndexBits::is_valid(lookup_result->context_index) &&
2384 SlotIndexBits::is_valid(lookup_result->slot_index);
2385 }
2386
2387 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002388 static const int kContextIndexBits = 9;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002389 static const int kSlotIndexBits = 13;
2390 class ContextIndexBits : public BitField<int, 0, kContextIndexBits> {};
2391 class SlotIndexBits
2392 : public BitField<int, kContextIndexBits, kSlotIndexBits> {};
2393
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002394 Code::StubType GetStubType() const override { return Code::FAST; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002395
2396 DEFINE_CODE_STUB_BASE(ScriptContextFieldStub, HandlerStub);
2397};
2398
2399
2400class LoadScriptContextFieldStub : public ScriptContextFieldStub {
2401 public:
2402 LoadScriptContextFieldStub(
2403 Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
2404 : ScriptContextFieldStub(isolate, lookup_result) {}
2405
2406 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002407 Code::Kind kind() const override { return Code::LOAD_IC; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002408
2409 DEFINE_HANDLER_CODE_STUB(LoadScriptContextField, ScriptContextFieldStub);
2410};
2411
2412
2413class StoreScriptContextFieldStub : public ScriptContextFieldStub {
2414 public:
2415 StoreScriptContextFieldStub(
2416 Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
2417 : ScriptContextFieldStub(isolate, lookup_result) {}
2418
2419 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002420 Code::Kind kind() const override { return Code::STORE_IC; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002421
2422 DEFINE_HANDLER_CODE_STUB(StoreScriptContextField, ScriptContextFieldStub);
2423};
2424
2425
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002426class LoadFastElementStub : public HandlerStub {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002427 public:
2428 LoadFastElementStub(Isolate* isolate, bool is_js_array,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002429 ElementsKind elements_kind,
2430 bool convert_hole_to_undefined = false)
2431 : HandlerStub(isolate) {
2432 set_sub_minor_key(
2433 ElementsKindBits::encode(elements_kind) |
2434 IsJSArrayBits::encode(is_js_array) |
2435 CanConvertHoleToUndefined::encode(convert_hole_to_undefined));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002436 }
2437
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002438 Code::Kind kind() const override { return Code::KEYED_LOAD_IC; }
2439
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002440 bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002441 bool convert_hole_to_undefined() const {
2442 return CanConvertHoleToUndefined::decode(sub_minor_key());
2443 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002444
2445 ElementsKind elements_kind() const {
2446 return ElementsKindBits::decode(sub_minor_key());
2447 }
2448
2449 private:
2450 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2451 class IsJSArrayBits: public BitField<bool, 8, 1> {};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002452 class CanConvertHoleToUndefined : public BitField<bool, 9, 1> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002453
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002454 DEFINE_HANDLER_CODE_STUB(LoadFastElement, HandlerStub);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002455};
2456
2457
2458class StoreFastElementStub : public HydrogenCodeStub {
2459 public:
2460 StoreFastElementStub(Isolate* isolate, bool is_js_array,
2461 ElementsKind elements_kind, KeyedAccessStoreMode mode)
2462 : HydrogenCodeStub(isolate) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002463 set_sub_minor_key(CommonStoreModeBits::encode(mode) |
2464 ElementsKindBits::encode(elements_kind) |
2465 IsJSArrayBits::encode(is_js_array));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002466 }
2467
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002468 static void GenerateAheadOfTime(Isolate* isolate);
2469
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002470 bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2471
2472 ElementsKind elements_kind() const {
2473 return ElementsKindBits::decode(sub_minor_key());
2474 }
2475
2476 KeyedAccessStoreMode store_mode() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002477 return CommonStoreModeBits::decode(sub_minor_key());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002478 }
2479
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002480 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
2481 return VectorStoreICDescriptor(isolate());
2482 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002483
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002484 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
2485
2486 private:
2487 class ElementsKindBits : public BitField<ElementsKind, 3, 8> {};
2488 class IsJSArrayBits : public BitField<bool, 11, 1> {};
2489
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002490 DEFINE_HYDROGEN_CODE_STUB(StoreFastElement, HydrogenCodeStub);
2491};
2492
2493
2494class TransitionElementsKindStub : public HydrogenCodeStub {
2495 public:
2496 TransitionElementsKindStub(Isolate* isolate,
2497 ElementsKind from_kind,
2498 ElementsKind to_kind,
2499 bool is_js_array) : HydrogenCodeStub(isolate) {
2500 set_sub_minor_key(FromKindBits::encode(from_kind) |
2501 ToKindBits::encode(to_kind) |
2502 IsJSArrayBits::encode(is_js_array));
2503 }
2504
2505 ElementsKind from_kind() const {
2506 return FromKindBits::decode(sub_minor_key());
2507 }
2508
2509 ElementsKind to_kind() const { return ToKindBits::decode(sub_minor_key()); }
2510
2511 bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2512
2513 private:
2514 class FromKindBits: public BitField<ElementsKind, 8, 8> {};
2515 class ToKindBits: public BitField<ElementsKind, 0, 8> {};
2516 class IsJSArrayBits: public BitField<bool, 16, 1> {};
2517
2518 DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind);
2519 DEFINE_HYDROGEN_CODE_STUB(TransitionElementsKind, HydrogenCodeStub);
2520};
2521
2522
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002523class AllocateHeapNumberStub final : public HydrogenCodeStub {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002524 public:
2525 explicit AllocateHeapNumberStub(Isolate* isolate)
2526 : HydrogenCodeStub(isolate) {}
2527
2528 private:
2529 DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateHeapNumber);
2530 DEFINE_HYDROGEN_CODE_STUB(AllocateHeapNumber, HydrogenCodeStub);
2531};
2532
2533
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002534class AllocateMutableHeapNumberStub final : public HydrogenCodeStub {
2535 public:
2536 explicit AllocateMutableHeapNumberStub(Isolate* isolate)
2537 : HydrogenCodeStub(isolate) {}
2538
2539 private:
2540 DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateMutableHeapNumber);
2541 DEFINE_HYDROGEN_CODE_STUB(AllocateMutableHeapNumber, HydrogenCodeStub);
2542};
2543
2544
2545class AllocateInNewSpaceStub final : public HydrogenCodeStub {
2546 public:
2547 explicit AllocateInNewSpaceStub(Isolate* isolate)
2548 : HydrogenCodeStub(isolate) {}
2549
2550 private:
2551 DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateInNewSpace);
2552 DEFINE_HYDROGEN_CODE_STUB(AllocateInNewSpace, HydrogenCodeStub);
2553};
2554
2555
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002556class ArrayConstructorStubBase : public HydrogenCodeStub {
2557 public:
2558 ArrayConstructorStubBase(Isolate* isolate,
2559 ElementsKind kind,
2560 AllocationSiteOverrideMode override_mode)
2561 : HydrogenCodeStub(isolate) {
2562 // It only makes sense to override local allocation site behavior
2563 // if there is a difference between the global allocation site policy
2564 // for an ElementsKind and the desired usage of the stub.
2565 DCHECK(override_mode != DISABLE_ALLOCATION_SITES ||
2566 AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
2567 set_sub_minor_key(ElementsKindBits::encode(kind) |
2568 AllocationSiteOverrideModeBits::encode(override_mode));
2569 }
2570
2571 ElementsKind elements_kind() const {
2572 return ElementsKindBits::decode(sub_minor_key());
2573 }
2574
2575 AllocationSiteOverrideMode override_mode() const {
2576 return AllocationSiteOverrideModeBits::decode(sub_minor_key());
2577 }
2578
2579 static void GenerateStubsAheadOfTime(Isolate* isolate);
2580
2581 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2582 static const int kConstructor = 0;
2583 static const int kAllocationSite = 1;
2584
2585 protected:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002586 std::ostream& BasePrintName(std::ostream& os,
2587 const char* name) const; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002588
2589 private:
2590 // Ensure data fits within available bits.
2591 STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
2592
2593 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2594 class AllocationSiteOverrideModeBits: public
2595 BitField<AllocationSiteOverrideMode, 8, 1> {}; // NOLINT
2596
2597 DEFINE_CODE_STUB_BASE(ArrayConstructorStubBase, HydrogenCodeStub);
2598};
2599
2600
2601class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
2602 public:
2603 ArrayNoArgumentConstructorStub(
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, "ArrayNoArgumentConstructorStub");
2613 }
2614
2615 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructorConstantArgCount);
2616 DEFINE_HYDROGEN_CODE_STUB(ArrayNoArgumentConstructor,
2617 ArrayConstructorStubBase);
2618};
2619
2620
2621class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
2622 public:
2623 ArraySingleArgumentConstructorStub(
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, "ArraySingleArgumentConstructorStub");
2633 }
2634
2635 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2636 DEFINE_HYDROGEN_CODE_STUB(ArraySingleArgumentConstructor,
2637 ArrayConstructorStubBase);
2638};
2639
2640
2641class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
2642 public:
2643 ArrayNArgumentsConstructorStub(
2644 Isolate* isolate,
2645 ElementsKind kind,
2646 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2647 : ArrayConstructorStubBase(isolate, kind, override_mode) {
2648 }
2649
2650 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002651 void PrintName(std::ostream& os) const override { // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002652 BasePrintName(os, "ArrayNArgumentsConstructorStub");
2653 }
2654
2655 DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2656 DEFINE_HYDROGEN_CODE_STUB(ArrayNArgumentsConstructor,
2657 ArrayConstructorStubBase);
2658};
2659
2660
2661class InternalArrayConstructorStubBase : public HydrogenCodeStub {
2662 public:
2663 InternalArrayConstructorStubBase(Isolate* isolate, ElementsKind kind)
2664 : HydrogenCodeStub(isolate) {
2665 set_sub_minor_key(ElementsKindBits::encode(kind));
2666 }
2667
2668 static void GenerateStubsAheadOfTime(Isolate* isolate);
2669
2670 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2671 static const int kConstructor = 0;
2672
2673 ElementsKind elements_kind() const {
2674 return ElementsKindBits::decode(sub_minor_key());
2675 }
2676
2677 private:
2678 class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2679
2680 DEFINE_CODE_STUB_BASE(InternalArrayConstructorStubBase, HydrogenCodeStub);
2681};
2682
2683
2684class InternalArrayNoArgumentConstructorStub : public
2685 InternalArrayConstructorStubBase {
2686 public:
2687 InternalArrayNoArgumentConstructorStub(Isolate* isolate,
2688 ElementsKind kind)
2689 : InternalArrayConstructorStubBase(isolate, kind) { }
2690
2691 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructorConstantArgCount);
2692 DEFINE_HYDROGEN_CODE_STUB(InternalArrayNoArgumentConstructor,
2693 InternalArrayConstructorStubBase);
2694};
2695
2696
2697class InternalArraySingleArgumentConstructorStub : public
2698 InternalArrayConstructorStubBase {
2699 public:
2700 InternalArraySingleArgumentConstructorStub(Isolate* isolate,
2701 ElementsKind kind)
2702 : InternalArrayConstructorStubBase(isolate, kind) { }
2703
2704 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2705 DEFINE_HYDROGEN_CODE_STUB(InternalArraySingleArgumentConstructor,
2706 InternalArrayConstructorStubBase);
2707};
2708
2709
2710class InternalArrayNArgumentsConstructorStub : public
2711 InternalArrayConstructorStubBase {
2712 public:
2713 InternalArrayNArgumentsConstructorStub(Isolate* isolate, ElementsKind kind)
2714 : InternalArrayConstructorStubBase(isolate, kind) { }
2715
2716 DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2717 DEFINE_HYDROGEN_CODE_STUB(InternalArrayNArgumentsConstructor,
2718 InternalArrayConstructorStubBase);
2719};
2720
2721
2722class StoreElementStub : public PlatformCodeStub {
2723 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002724 StoreElementStub(Isolate* isolate, ElementsKind elements_kind,
2725 KeyedAccessStoreMode mode)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002726 : PlatformCodeStub(isolate) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002727 minor_key_ = ElementsKindBits::encode(elements_kind) |
2728 CommonStoreModeBits::encode(mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002729 }
2730
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002731 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
2732 return VectorStoreICDescriptor(isolate());
2733 }
2734
2735 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
2736
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002737 private:
2738 ElementsKind elements_kind() const {
2739 return ElementsKindBits::decode(minor_key_);
2740 }
2741
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002742 class ElementsKindBits : public BitField<ElementsKind, 3, 8> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002743
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002744 DEFINE_PLATFORM_CODE_STUB(StoreElement, PlatformCodeStub);
2745};
2746
2747
2748class ToBooleanStub: public HydrogenCodeStub {
Ben Murdoch257744e2011-11-30 15:57:28 +00002749 public:
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002750 enum Type {
2751 UNDEFINED,
2752 BOOLEAN,
2753 NULL_TYPE,
2754 SMI,
2755 SPEC_OBJECT,
2756 STRING,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002757 SYMBOL,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002758 HEAP_NUMBER,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002759 SIMD_VALUE,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002760 NUMBER_OF_TYPES
2761 };
2762
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002763 // At most 16 different types can be distinguished, because the Code object
2764 // only has room for two bytes to hold a set of these types. :-P
2765 STATIC_ASSERT(NUMBER_OF_TYPES <= 16);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002766
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002767 class Types : public EnumSet<Type, uint16_t> {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002768 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002769 Types() : EnumSet<Type, uint16_t>(0) {}
2770 explicit Types(uint16_t bits) : EnumSet<Type, uint16_t>(bits) {}
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002771
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002772 bool UpdateStatus(Handle<Object> object);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002773 bool NeedsMap() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002774 bool CanBeUndetectable() const {
2775 return Contains(ToBooleanStub::SPEC_OBJECT);
2776 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002777 bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002778
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002779 static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002780 };
2781
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002782 ToBooleanStub(Isolate* isolate, ExtraICState state)
2783 : HydrogenCodeStub(isolate) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002784 set_sub_minor_key(TypesBits::encode(static_cast<uint16_t>(state)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002785 }
Ben Murdoch257744e2011-11-30 15:57:28 +00002786
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002787 bool UpdateStatus(Handle<Object> object);
2788 Types types() const { return Types(TypesBits::decode(sub_minor_key())); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002789
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002790 Code::Kind GetCodeKind() const override { return Code::TO_BOOLEAN_IC; }
2791 void PrintState(std::ostream& os) const override; // NOLINT
Ben Murdoch257744e2011-11-30 15:57:28 +00002792
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002793 bool SometimesSetsUpAFrame() override { return false; }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002794
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002795 static Handle<Code> GetUninitialized(Isolate* isolate) {
2796 return ToBooleanStub(isolate, UNINITIALIZED).GetCode();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002797 }
2798
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002799 ExtraICState GetExtraICState() const override { return types().ToIntegral(); }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002800
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002801 InlineCacheState GetICState() const override {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002802 if (types().IsEmpty()) {
2803 return ::v8::internal::UNINITIALIZED;
2804 } else {
2805 return MONOMORPHIC;
2806 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002807 }
2808
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002809 private:
2810 ToBooleanStub(Isolate* isolate, InitializationState init_state)
2811 : HydrogenCodeStub(isolate, init_state) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002812 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002813
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002814 class TypesBits : public BitField<uint16_t, 0, NUMBER_OF_TYPES> {};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002815
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002816 DEFINE_CALL_INTERFACE_DESCRIPTOR(ToBoolean);
2817 DEFINE_HYDROGEN_CODE_STUB(ToBoolean, HydrogenCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002818};
2819
2820
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002821std::ostream& operator<<(std::ostream& os, const ToBooleanStub::Types& t);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002822
2823
2824class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002825 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002826 ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind,
2827 ElementsKind to_kind, bool is_jsarray,
2828 KeyedAccessStoreMode store_mode)
2829 : HydrogenCodeStub(isolate) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002830 set_sub_minor_key(CommonStoreModeBits::encode(store_mode) |
2831 FromBits::encode(from_kind) | ToBits::encode(to_kind) |
2832 IsJSArrayBits::encode(is_jsarray));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002833 }
2834
2835 ElementsKind from_kind() const { return FromBits::decode(sub_minor_key()); }
2836 ElementsKind to_kind() const { return ToBits::decode(sub_minor_key()); }
2837 bool is_jsarray() const { return IsJSArrayBits::decode(sub_minor_key()); }
2838 KeyedAccessStoreMode store_mode() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002839 return CommonStoreModeBits::decode(sub_minor_key());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002840 }
2841
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002842 CallInterfaceDescriptor GetCallInterfaceDescriptor() const override;
2843 Code::Kind GetCodeKind() const override { return Code::HANDLER; }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002844
2845 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002846 class FromBits : public BitField<ElementsKind, 3, 8> {};
2847 class ToBits : public BitField<ElementsKind, 11, 8> {};
2848 class IsJSArrayBits : public BitField<bool, 19, 1> {};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002849
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002850 DEFINE_HYDROGEN_CODE_STUB(ElementsTransitionAndStore, HydrogenCodeStub);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002851};
2852
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002853
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002854class StubFailureTrampolineStub : public PlatformCodeStub {
2855 public:
2856 StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode)
2857 : PlatformCodeStub(isolate) {
2858 minor_key_ = FunctionModeField::encode(function_mode);
2859 }
2860
2861 static void GenerateAheadOfTime(Isolate* isolate);
2862
2863 private:
2864 StubFunctionMode function_mode() const {
2865 return FunctionModeField::decode(minor_key_);
2866 }
2867
2868 class FunctionModeField : public BitField<StubFunctionMode, 0, 1> {};
2869
2870 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2871 DEFINE_PLATFORM_CODE_STUB(StubFailureTrampoline, PlatformCodeStub);
2872};
2873
2874
2875class ProfileEntryHookStub : public PlatformCodeStub {
2876 public:
2877 explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2878
2879 // The profile entry hook function is not allowed to cause a GC.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002880 bool SometimesSetsUpAFrame() override { return false; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002881
2882 // Generates a call to the entry hook if it's enabled.
2883 static void MaybeCallEntryHook(MacroAssembler* masm);
2884
2885 private:
2886 static void EntryHookTrampoline(intptr_t function,
2887 intptr_t stack_pointer,
2888 Isolate* isolate);
2889
2890 // ProfileEntryHookStub is called at the start of a function, so it has the
2891 // same register set.
2892 DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction)
2893 DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub);
2894};
2895
2896
2897class StoreBufferOverflowStub : public PlatformCodeStub {
2898 public:
2899 StoreBufferOverflowStub(Isolate* isolate, SaveFPRegsMode save_fp)
2900 : PlatformCodeStub(isolate) {
2901 minor_key_ = SaveDoublesBits::encode(save_fp == kSaveFPRegs);
2902 }
2903
2904 static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002905 bool SometimesSetsUpAFrame() override { return false; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002906
2907 private:
2908 bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
2909
2910 class SaveDoublesBits : public BitField<bool, 0, 1> {};
2911
2912 DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2913 DEFINE_PLATFORM_CODE_STUB(StoreBufferOverflow, PlatformCodeStub);
2914};
2915
2916
2917class SubStringStub : public PlatformCodeStub {
2918 public:
2919 explicit SubStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2920
2921 DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
2922 DEFINE_PLATFORM_CODE_STUB(SubString, PlatformCodeStub);
2923};
2924
2925
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002926class ToNumberStub final : public PlatformCodeStub {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002927 public:
2928 explicit ToNumberStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2929
2930 DEFINE_CALL_INTERFACE_DESCRIPTOR(ToNumber);
2931 DEFINE_PLATFORM_CODE_STUB(ToNumber, PlatformCodeStub);
2932};
2933
2934
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002935class ToLengthStub final : public PlatformCodeStub {
2936 public:
2937 explicit ToLengthStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2938
2939 DEFINE_CALL_INTERFACE_DESCRIPTOR(ToLength);
2940 DEFINE_PLATFORM_CODE_STUB(ToLength, PlatformCodeStub);
2941};
2942
2943
2944class ToStringStub final : public PlatformCodeStub {
2945 public:
2946 explicit ToStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2947
2948 DEFINE_CALL_INTERFACE_DESCRIPTOR(ToString);
2949 DEFINE_PLATFORM_CODE_STUB(ToString, PlatformCodeStub);
2950};
2951
2952
2953class ToObjectStub final : public HydrogenCodeStub {
2954 public:
2955 explicit ToObjectStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
2956
2957 DEFINE_CALL_INTERFACE_DESCRIPTOR(ToObject);
2958 DEFINE_HYDROGEN_CODE_STUB(ToObject, HydrogenCodeStub);
2959};
2960
2961
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002962class StringCompareStub : public PlatformCodeStub {
2963 public:
2964 explicit StringCompareStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2965
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002966 DEFINE_CALL_INTERFACE_DESCRIPTOR(StringCompare);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002967 DEFINE_PLATFORM_CODE_STUB(StringCompare, PlatformCodeStub);
2968};
2969
2970
2971#undef DEFINE_CALL_INTERFACE_DESCRIPTOR
2972#undef DEFINE_PLATFORM_CODE_STUB
2973#undef DEFINE_HANDLER_CODE_STUB
2974#undef DEFINE_HYDROGEN_CODE_STUB
2975#undef DEFINE_CODE_STUB
2976#undef DEFINE_CODE_STUB_BASE
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002977
2978extern Representation RepresentationFromType(Type* type);
2979
2980} // namespace internal
2981} // namespace v8
Steve Blocka7e24c12009-10-30 11:49:00 +00002982
2983#endif // V8_CODE_STUBS_H_