blob: d2101ae293b6cee60ef3ca597bc483ab9b4d18ba [file] [log] [blame]
ulan@chromium.org65a89c22012-02-14 11:46:07 +00001// Copyright 2012 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_CODE_STUBS_H_
29#define V8_CODE_STUBS_H_
30
lrn@chromium.org1c092762011-05-09 09:42:16 +000031#include "allocation.h"
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000032#include "assembler.h"
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000033#include "globals.h"
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000034#include "codegen.h"
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000035
kasperl@chromium.org71affb52009-05-26 05:44:31 +000036namespace v8 {
37namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000038
ricow@chromium.orgc54d3652011-05-30 09:20:16 +000039// List of code stubs used on all platforms.
ager@chromium.orgc4c92722009-11-18 14:12:51 +000040#define CODE_STUB_LIST_ALL_PLATFORMS(V) \
41 V(CallFunction) \
danno@chromium.orgfa458e42012-02-01 10:48:36 +000042 V(CallConstruct) \
danno@chromium.org40cb8782011-05-25 07:58:50 +000043 V(BinaryOp) \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000044 V(StringAdd) \
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000045 V(SubString) \
46 V(StringCompare) \
ager@chromium.orgc4c92722009-11-18 14:12:51 +000047 V(Compare) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000048 V(CompareIC) \
danno@chromium.orgca29dd82013-04-26 11:59:48 +000049 V(CompareNilIC) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000050 V(MathPow) \
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +000051 V(StringLength) \
52 V(FunctionPrototype) \
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000053 V(StoreArrayLength) \
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000054 V(RecordWrite) \
55 V(StoreBufferOverflow) \
56 V(RegExpExec) \
whesse@chromium.org871db8c2010-12-21 15:17:57 +000057 V(TranscendentalCache) \
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000058 V(Instanceof) \
ager@chromium.orgc4c92722009-11-18 14:12:51 +000059 V(ConvertToDouble) \
60 V(WriteInt32ToHeapNumber) \
61 V(StackCheck) \
yangguo@chromium.org56454712012-02-16 15:33:53 +000062 V(Interrupt) \
sgjesse@chromium.org846fb742009-12-18 08:56:33 +000063 V(FastNewClosure) \
64 V(FastNewContext) \
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +000065 V(FastNewBlockContext) \
sgjesse@chromium.org846fb742009-12-18 08:56:33 +000066 V(FastCloneShallowArray) \
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +000067 V(FastCloneShallowObject) \
danno@chromium.orgbee51992013-07-10 14:57:15 +000068 V(CreateAllocationSite) \
ager@chromium.orgc4c92722009-11-18 14:12:51 +000069 V(ToBoolean) \
whesse@chromium.org7a392b32011-01-31 11:30:36 +000070 V(ToNumber) \
ager@chromium.orgc4c92722009-11-18 14:12:51 +000071 V(ArgumentsAccess) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000072 V(RegExpConstructResult) \
ager@chromium.org5c838252010-02-19 08:53:10 +000073 V(NumberToString) \
danno@chromium.org169691d2013-07-15 08:01:13 +000074 V(DoubleToI) \
ager@chromium.orgc4c92722009-11-18 14:12:51 +000075 V(CEntry) \
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000076 V(JSEntry) \
sgjesse@chromium.org6db88712011-07-11 11:41:22 +000077 V(KeyedLoadElement) \
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000078 V(ArrayNoArgumentConstructor) \
79 V(ArraySingleArgumentConstructor) \
80 V(ArrayNArgumentsConstructor) \
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000081 V(InternalArrayNoArgumentConstructor) \
82 V(InternalArraySingleArgumentConstructor) \
83 V(InternalArrayNArgumentsConstructor) \
sgjesse@chromium.org6db88712011-07-11 11:41:22 +000084 V(KeyedStoreElement) \
lrn@chromium.org1c092762011-05-09 09:42:16 +000085 V(DebuggerStatement) \
ulan@chromium.org750145a2013-03-07 15:14:13 +000086 V(NameDictionaryLookup) \
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000087 V(ElementsTransitionAndStore) \
danno@chromium.org94b0d6f2013-02-04 13:33:20 +000088 V(TransitionElementsKind) \
verwaest@chromium.org753aee42012-07-17 16:15:42 +000089 V(StoreArrayLiteralElement) \
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +000090 V(StubFailureTrampoline) \
danno@chromium.orgca29dd82013-04-26 11:59:48 +000091 V(ArrayConstructor) \
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000092 V(InternalArrayConstructor) \
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000093 V(ProfileEntryHook) \
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000094 V(StoreGlobal) \
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000095 /* IC Handler stubs */ \
ulan@chromium.org57ff8812013-05-10 08:16:55 +000096 V(LoadField) \
97 V(KeyedLoadField)
ager@chromium.org3811b432009-10-28 14:53:37 +000098
99// List of code stubs only used on ARM platforms.
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000100#if V8_TARGET_ARCH_ARM
ager@chromium.org3811b432009-10-28 14:53:37 +0000101#define CODE_STUB_LIST_ARM(V) \
102 V(GetProperty) \
103 V(SetProperty) \
104 V(InvokeBuiltin) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000105 V(DirectCEntry)
ager@chromium.org3811b432009-10-28 14:53:37 +0000106#else
107#define CODE_STUB_LIST_ARM(V)
108#endif
109
lrn@chromium.org7516f052011-03-30 08:52:27 +0000110// List of code stubs only used on MIPS platforms.
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000111#if V8_TARGET_ARCH_MIPS
lrn@chromium.org7516f052011-03-30 08:52:27 +0000112#define CODE_STUB_LIST_MIPS(V) \
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000113 V(RegExpCEntry) \
114 V(DirectCEntry)
lrn@chromium.org7516f052011-03-30 08:52:27 +0000115#else
116#define CODE_STUB_LIST_MIPS(V)
117#endif
118
ager@chromium.org3811b432009-10-28 14:53:37 +0000119// Combined list of code stubs.
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000120#define CODE_STUB_LIST(V) \
121 CODE_STUB_LIST_ALL_PLATFORMS(V) \
lrn@chromium.org7516f052011-03-30 08:52:27 +0000122 CODE_STUB_LIST_ARM(V) \
123 CODE_STUB_LIST_MIPS(V)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000124
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000125// Mode to overwrite BinaryExpression values.
126enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000127
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000128// Stub is base classes of all stubs.
129class CodeStub BASE_EMBEDDED {
130 public:
131 enum Major {
ager@chromium.org3811b432009-10-28 14:53:37 +0000132#define DEF_ENUM(name) name,
133 CODE_STUB_LIST(DEF_ENUM)
134#undef DEF_ENUM
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000135 NoCache, // marker for stubs that do custom caching
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000136 NUMBER_OF_IDS
137 };
138
139 // Retrieve the code for the stub. Generate the code if needed.
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000140 Handle<Code> GetCode(Isolate* isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000141
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000142 // Retrieve the code for the stub, make and return a copy of the code.
143 Handle<Code> GetCodeCopyFromTemplate(Isolate* isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000144 static Major MajorKeyFromKey(uint32_t key) {
145 return static_cast<Major>(MajorKeyBits::decode(key));
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000146 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000147 static int MinorKeyFromKey(uint32_t key) {
148 return MinorKeyBits::decode(key);
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000149 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000150
151 // Gets the major key from a code object that is a code stub or binary op IC.
152 static Major GetMajorKey(Code* code_stub) {
153 return static_cast<Major>(code_stub->major_key());
154 }
155
ager@chromium.org5c838252010-02-19 08:53:10 +0000156 static const char* MajorName(Major major_key, bool allow_unknown_keys);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000157
158 virtual ~CodeStub() {}
159
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000160 bool CompilingCallsToThisStubIsGCSafe(Isolate* isolate) {
dslomov@chromium.orge97852d2013-09-12 09:02:59 +0000161 bool is_pregenerated = IsPregenerated(isolate);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000162 Code* code = NULL;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000163 CHECK(!is_pregenerated || FindCodeInCache(&code, isolate));
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000164 return is_pregenerated;
165 }
166
167 // See comment above, where Instanceof is defined.
dslomov@chromium.orge97852d2013-09-12 09:02:59 +0000168 virtual bool IsPregenerated(Isolate* isolate) { return false; }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000169
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000170 static void GenerateStubsAheadOfTime(Isolate* isolate);
171 static void GenerateFPStubs(Isolate* isolate);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000172
173 // Some stubs put untagged junk on the stack that cannot be scanned by the
174 // GC. This means that we must be statically sure that no GC can occur while
175 // they are running. If that is the case they should override this to return
176 // true, which will cause an assertion if we try to call something that can
177 // GC or if we try to put a stack frame on top of the junk, which would not
178 // result in a traversable stack.
179 virtual bool SometimesSetsUpAFrame() { return true; }
180
danno@chromium.orgc612e022011-11-10 11:38:15 +0000181 // Lookup the code in the (possibly custom) cache.
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000182 bool FindCodeInCache(Code** code_out, Isolate* isolate);
danno@chromium.orgc612e022011-11-10 11:38:15 +0000183
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000184 // Returns information for computing the number key.
185 virtual Major MajorKey() = 0;
186 virtual int MinorKey() = 0;
187
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000188 virtual InlineCacheState GetICState() {
189 return UNINITIALIZED;
190 }
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000191 virtual Code::ExtraICState GetExtraICState() {
192 return Code::kNoExtraICState;
193 }
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000194 virtual Code::StubType GetStubType() {
195 return Code::NORMAL;
196 }
197 virtual int GetStubFlags() {
198 return -1;
199 }
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000200
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000201 virtual void PrintName(StringStream* stream);
202
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +0000203 // Returns a name for logging/debugging purposes.
204 SmartArrayPointer<const char> GetName();
205
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000206 protected:
207 static bool CanUseFPRegisters();
208
209 // Generates the assembler code for the stub.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000210 virtual Handle<Code> GenerateCode(Isolate* isolate) = 0;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000211
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +0000212 virtual void VerifyPlatformFeatures(Isolate* isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000213
214 // Returns whether the code generated for this stub needs to be allocated as
215 // a fixed (non-moveable) code object.
216 virtual bool NeedsImmovableCode() { return false; }
217
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000218 virtual void PrintBaseName(StringStream* stream);
219 virtual void PrintState(StringStream* stream) { }
220
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000221 private:
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000222 // Perform bookkeeping required after code generation when stub code is
223 // initially generated.
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000224 void RecordCodeGeneration(Code* code, Isolate* isolate);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000225
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000226 // Finish the code object after it has been generated.
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +0000227 virtual void FinishCode(Handle<Code> code) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000228
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000229 // Activate newly generated stub. Is called after
230 // registering stub in the stub cache.
231 virtual void Activate(Code* code) { }
232
danno@chromium.org40cb8782011-05-25 07:58:50 +0000233 // BinaryOpStub needs to override this.
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000234 virtual Code::Kind GetCodeKind() const;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000235
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000236 // Add the code to a specialized cache, specific to an individual
237 // stub type. Please note, this method must add the code object to a
238 // roots object, otherwise we will remove the code during GC.
239 virtual void AddToSpecialCache(Handle<Code> new_object) { }
240
241 // Find code in a specialized cache, work is delegated to the specific stub.
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000242 virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate) {
243 return false;
244 }
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000245
246 // If a stub uses a special cache override this.
247 virtual bool UseSpecialCache() { return false; }
248
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000249 // Computes the key based on major and minor.
250 uint32_t GetKey() {
251 ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
252 return MinorKeyBits::encode(MinorKey()) |
253 MajorKeyBits::encode(MajorKey());
254 }
255
danno@chromium.org81cac2b2012-07-10 11:28:27 +0000256 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
257 class MinorKeyBits: public BitField<uint32_t,
258 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000259
260 friend class BreakPointIterator;
261};
262
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000263
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000264class PlatformCodeStub : public CodeStub {
265 public:
266 // Retrieve the code for the stub. Generate the code if needed.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000267 virtual Handle<Code> GenerateCode(Isolate* isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000268
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000269 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000270
271 protected:
272 // Generates the assembler code for the stub.
273 virtual void Generate(MacroAssembler* masm) = 0;
274};
275
276
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000277enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
278
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000279
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000280struct CodeStubInterfaceDescriptor {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000281 CodeStubInterfaceDescriptor();
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000282 int register_param_count_;
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000283 const Register* stack_parameter_count_;
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000284 // if hint_stack_parameter_count_ > 0, the code stub can optimize the
285 // return sequence. Default value is -1, which means it is ignored.
286 int hint_stack_parameter_count_;
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000287 StubFunctionMode function_mode_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000288 Register* register_params_;
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000289 Address deoptimization_handler_;
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000290
291 int environment_length() const {
292 if (stack_parameter_count_ != NULL) {
293 return register_param_count_ + 1;
294 }
295 return register_param_count_;
296 }
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000297
298 bool initialized() const { return register_param_count_ >= 0; }
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000299
300 void SetMissHandler(ExternalReference handler) {
301 miss_handler_ = handler;
302 has_miss_handler_ = true;
303 }
304
305 ExternalReference miss_handler() {
306 ASSERT(has_miss_handler_);
307 return miss_handler_;
308 }
309
310 bool has_miss_handler() {
311 return has_miss_handler_;
312 }
313
314 private:
315 ExternalReference miss_handler_;
316 bool has_miss_handler_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000317};
318
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000319// A helper to make up for the fact that type Register is not fully
320// defined outside of the platform directories
321#define DESCRIPTOR_GET_PARAMETER_REGISTER(descriptor, index) \
322 ((index) == (descriptor)->register_param_count_) \
323 ? *((descriptor)->stack_parameter_count_) \
324 : (descriptor)->register_params_[(index)]
325
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000326
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000327class HydrogenCodeStub : public CodeStub {
328 public:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000329 enum InitializationState {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000330 UNINITIALIZED,
331 INITIALIZED
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000332 };
333
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000334 explicit HydrogenCodeStub(InitializationState state = INITIALIZED) {
335 is_uninitialized_ = (state == UNINITIALIZED);
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000336 }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000337
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000338 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000339
340 CodeStubInterfaceDescriptor* GetInterfaceDescriptor(Isolate* isolate) {
341 return isolate->code_stub_interface_descriptor(MajorKey());
342 }
343
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000344 bool IsUninitialized() { return is_uninitialized_; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000345
346 template<class SubClass>
347 static Handle<Code> GetUninitialized(Isolate* isolate) {
348 SubClass::GenerateAheadOfTime(isolate);
349 return SubClass().GetCode(isolate);
350 }
351
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000352 virtual void InitializeInterfaceDescriptor(
353 Isolate* isolate,
354 CodeStubInterfaceDescriptor* descriptor) = 0;
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000355
356 // Retrieve the code for the stub. Generate the code if needed.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000357 virtual Handle<Code> GenerateCode(Isolate* isolate) = 0;
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000358
359 virtual int NotMissMinorKey() = 0;
360
361 Handle<Code> GenerateLightweightMissCode(Isolate* isolate);
362
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000363 template<class StateType>
364 void TraceTransition(StateType from, StateType to);
365
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000366 private:
367 class MinorKeyBits: public BitField<int, 0, kStubMinorKeyBits - 1> {};
368 class IsMissBits: public BitField<bool, kStubMinorKeyBits - 1, 1> {};
369
370 void GenerateLightweightMiss(MacroAssembler* masm);
371 virtual int MinorKey() {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000372 return IsMissBits::encode(is_uninitialized_) |
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000373 MinorKeyBits::encode(NotMissMinorKey());
374 }
375
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000376 bool is_uninitialized_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000377};
378
379
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000380// Helper interface to prepare to/restore after making runtime calls.
381class RuntimeCallHelper {
382 public:
383 virtual ~RuntimeCallHelper() {}
384
385 virtual void BeforeCall(MacroAssembler* masm) const = 0;
386
387 virtual void AfterCall(MacroAssembler* masm) const = 0;
388
389 protected:
390 RuntimeCallHelper() {}
391
392 private:
393 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
394};
395
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +0000396
397// TODO(bmeurer): Move to the StringAddStub declaration once we're
398// done with the translation to a hydrogen code stub.
399enum StringAddFlags {
400 // Omit both parameter checks.
401 STRING_ADD_CHECK_NONE = 0,
402 // Check left parameter.
403 STRING_ADD_CHECK_LEFT = 1 << 0,
404 // Check right parameter.
405 STRING_ADD_CHECK_RIGHT = 1 << 1,
406 // Check both parameters.
407 STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT,
408 // Stub needs a frame before calling the runtime
409 STRING_ADD_ERECT_FRAME = 1 << 2
410};
411
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000412} } // namespace v8::internal
413
414#if V8_TARGET_ARCH_IA32
415#include "ia32/code-stubs-ia32.h"
416#elif V8_TARGET_ARCH_X64
417#include "x64/code-stubs-x64.h"
418#elif V8_TARGET_ARCH_ARM
419#include "arm/code-stubs-arm.h"
420#elif V8_TARGET_ARCH_MIPS
421#include "mips/code-stubs-mips.h"
422#else
423#error Unsupported target architecture.
424#endif
425
426namespace v8 {
427namespace internal {
428
429
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000430// RuntimeCallHelper implementation used in stubs: enters/leaves a
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000431// newly created internal frame before/after the runtime call.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000432class StubRuntimeCallHelper : public RuntimeCallHelper {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000433 public:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000434 StubRuntimeCallHelper() {}
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000435
436 virtual void BeforeCall(MacroAssembler* masm) const;
437
438 virtual void AfterCall(MacroAssembler* masm) const;
439};
440
441
442// Trivial RuntimeCallHelper implementation.
443class NopRuntimeCallHelper : public RuntimeCallHelper {
444 public:
445 NopRuntimeCallHelper() {}
446
447 virtual void BeforeCall(MacroAssembler* masm) const {}
448
449 virtual void AfterCall(MacroAssembler* masm) const {}
450};
451
452
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000453class ToNumberStub: public HydrogenCodeStub {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000454 public:
455 ToNumberStub() { }
456
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000457 virtual Handle<Code> GenerateCode(Isolate* isolate);
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000458
459 virtual void InitializeInterfaceDescriptor(
460 Isolate* isolate,
461 CodeStubInterfaceDescriptor* descriptor);
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000462
463 private:
464 Major MajorKey() { return ToNumber; }
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000465 int NotMissMinorKey() { return 0; }
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000466};
467
468
machenbach@chromium.org3d079fe2013-09-25 08:19:55 +0000469class NumberToStringStub V8_FINAL : public HydrogenCodeStub {
470 public:
471 NumberToStringStub() {}
472
473 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
474
475 virtual void InitializeInterfaceDescriptor(
476 Isolate* isolate,
477 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
478
479 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
480 static const int kNumber = 0;
481
482 private:
483 virtual Major MajorKey() V8_OVERRIDE { return NumberToString; }
484 virtual int NotMissMinorKey() V8_OVERRIDE { return 0; }
485};
486
487
verwaest@chromium.org662436e2013-08-28 08:41:27 +0000488class FastNewClosureStub : public HydrogenCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000489 public:
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000490 explicit FastNewClosureStub(LanguageMode language_mode, bool is_generator)
491 : language_mode_(language_mode),
492 is_generator_(is_generator) { }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000493
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000494 virtual Handle<Code> GenerateCode(Isolate* isolate);
verwaest@chromium.org662436e2013-08-28 08:41:27 +0000495
496 virtual void InitializeInterfaceDescriptor(
497 Isolate* isolate,
498 CodeStubInterfaceDescriptor* descriptor);
499
500 static void InstallDescriptors(Isolate* isolate);
501
502 LanguageMode language_mode() const { return language_mode_; }
503 bool is_generator() const { return is_generator_; }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000504
505 private:
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000506 class StrictModeBits: public BitField<bool, 0, 1> {};
507 class IsGeneratorBits: public BitField<bool, 1, 1> {};
508
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000509 Major MajorKey() { return FastNewClosure; }
verwaest@chromium.org662436e2013-08-28 08:41:27 +0000510 int NotMissMinorKey() {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000511 return StrictModeBits::encode(language_mode_ != CLASSIC_MODE) |
512 IsGeneratorBits::encode(is_generator_);
513 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000514
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000515 LanguageMode language_mode_;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000516 bool is_generator_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000517};
518
519
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000520class FastNewContextStub : public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000521 public:
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000522 static const int kMaximumSlots = 64;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000523
524 explicit FastNewContextStub(int slots) : slots_(slots) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000525 ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000526 }
527
528 void Generate(MacroAssembler* masm);
529
530 private:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000531 int slots_;
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000532
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000533 Major MajorKey() { return FastNewContext; }
534 int MinorKey() { return slots_; }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000535};
536
537
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000538class FastNewBlockContextStub : public PlatformCodeStub {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000539 public:
540 static const int kMaximumSlots = 64;
541
542 explicit FastNewBlockContextStub(int slots) : slots_(slots) {
543 ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
544 }
545
546 void Generate(MacroAssembler* masm);
547
548 private:
549 int slots_;
550
551 Major MajorKey() { return FastNewBlockContext; }
552 int MinorKey() { return slots_; }
553};
554
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000555class StoreGlobalStub : public HydrogenCodeStub {
556 public:
557 StoreGlobalStub(StrictModeFlag strict_mode, bool is_constant) {
558 bit_field_ = StrictModeBits::encode(strict_mode) |
559 IsConstantBits::encode(is_constant);
560 }
561
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000562 virtual Handle<Code> GenerateCode(Isolate* isolate);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000563
564 virtual void InitializeInterfaceDescriptor(
565 Isolate* isolate,
566 CodeStubInterfaceDescriptor* descriptor);
567
568 virtual Code::Kind GetCodeKind() const { return Code::STORE_IC; }
569 virtual InlineCacheState GetICState() { return MONOMORPHIC; }
570 virtual Code::ExtraICState GetExtraICState() { return bit_field_; }
571
572 bool is_constant() {
573 return IsConstantBits::decode(bit_field_);
574 }
575 void set_is_constant(bool value) {
576 bit_field_ = IsConstantBits::update(bit_field_, value);
577 }
578
579 Representation representation() {
580 return Representation::FromKind(RepresentationBits::decode(bit_field_));
581 }
582 void set_representation(Representation r) {
583 bit_field_ = RepresentationBits::update(bit_field_, r.kind());
584 }
585
586 private:
587 virtual int NotMissMinorKey() { return GetExtraICState(); }
588 Major MajorKey() { return StoreGlobal; }
589
590 class StrictModeBits: public BitField<StrictModeFlag, 0, 1> {};
591 class IsConstantBits: public BitField<bool, 1, 1> {};
592 class RepresentationBits: public BitField<Representation::Kind, 2, 8> {};
593
594 int bit_field_;
595
596 DISALLOW_COPY_AND_ASSIGN(StoreGlobalStub);
597};
598
599
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000600class FastCloneShallowArrayStub : public HydrogenCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000601 public:
602 // Maximum length of copied elements array.
603 static const int kMaximumClonedLength = 8;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000604 enum Mode {
605 CLONE_ELEMENTS,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000606 CLONE_DOUBLE_ELEMENTS,
erikcorry0ad885c2011-11-21 13:51:57 +0000607 COPY_ON_WRITE_ELEMENTS,
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000608 CLONE_ANY_ELEMENTS,
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000609 LAST_CLONE_MODE = CLONE_ANY_ELEMENTS
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000610 };
611
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000612 static const int kFastCloneModeCount = LAST_CLONE_MODE + 1;
613
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000614 FastCloneShallowArrayStub(Mode mode,
615 AllocationSiteMode allocation_site_mode,
616 int length)
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000617 : mode_(mode),
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000618 allocation_site_mode_(allocation_site_mode),
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000619 length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000620 ASSERT_GE(length_, 0);
621 ASSERT_LE(length_, kMaximumClonedLength);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000622 }
623
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000624 Mode mode() const { return mode_; }
625 int length() const { return length_; }
626 AllocationSiteMode allocation_site_mode() const {
627 return allocation_site_mode_;
628 }
629
630 ElementsKind ComputeElementsKind() const {
631 switch (mode()) {
632 case CLONE_ELEMENTS:
633 case COPY_ON_WRITE_ELEMENTS:
634 return FAST_ELEMENTS;
635 case CLONE_DOUBLE_ELEMENTS:
636 return FAST_DOUBLE_ELEMENTS;
637 case CLONE_ANY_ELEMENTS:
638 /*fall-through*/;
639 }
640 UNREACHABLE();
641 return LAST_ELEMENTS_KIND;
642 }
643
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000644 virtual Handle<Code> GenerateCode(Isolate* isolate);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000645
646 virtual void InitializeInterfaceDescriptor(
647 Isolate* isolate,
648 CodeStubInterfaceDescriptor* descriptor);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000649
650 private:
651 Mode mode_;
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000652 AllocationSiteMode allocation_site_mode_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000653 int length_;
654
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000655 class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
656 class ModeBits: public BitField<Mode, 1, 4> {};
657 class LengthBits: public BitField<int, 5, 4> {};
658 // Ensure data fits within available bits.
659 STATIC_ASSERT(LAST_ALLOCATION_SITE_MODE == 1);
660 STATIC_ASSERT(kFastCloneModeCount < 16);
661 STATIC_ASSERT(kMaximumClonedLength < 16);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000662 Major MajorKey() { return FastCloneShallowArray; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000663 int NotMissMinorKey() {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000664 return AllocationSiteModeBits::encode(allocation_site_mode_)
665 | ModeBits::encode(mode_)
666 | LengthBits::encode(length_);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000667 }
668};
669
670
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000671class FastCloneShallowObjectStub : public HydrogenCodeStub {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000672 public:
673 // Maximum number of properties in copied object.
674 static const int kMaximumClonedProperties = 6;
675
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000676 explicit FastCloneShallowObjectStub(int length)
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000677 : length_(length) {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000678 ASSERT_GE(length_, 0);
679 ASSERT_LE(length_, kMaximumClonedProperties);
680 }
681
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000682 int length() const { return length_; }
683
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000684 virtual Handle<Code> GenerateCode(Isolate* isolate);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000685
686 virtual void InitializeInterfaceDescriptor(
687 Isolate* isolate,
688 CodeStubInterfaceDescriptor* descriptor);
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000689
690 private:
691 int length_;
692
693 Major MajorKey() { return FastCloneShallowObject; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000694 int NotMissMinorKey() { return length_; }
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000695
696 DISALLOW_COPY_AND_ASSIGN(FastCloneShallowObjectStub);
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000697};
698
699
danno@chromium.orgbee51992013-07-10 14:57:15 +0000700class CreateAllocationSiteStub : public HydrogenCodeStub {
701 public:
702 explicit CreateAllocationSiteStub() { }
703
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000704 virtual Handle<Code> GenerateCode(Isolate* isolate);
danno@chromium.orgbee51992013-07-10 14:57:15 +0000705
dslomov@chromium.orge97852d2013-09-12 09:02:59 +0000706 virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE { return true; }
danno@chromium.orgbee51992013-07-10 14:57:15 +0000707
708 static void GenerateAheadOfTime(Isolate* isolate);
709
710 virtual void InitializeInterfaceDescriptor(
711 Isolate* isolate,
712 CodeStubInterfaceDescriptor* descriptor);
713
714 private:
715 Major MajorKey() { return CreateAllocationSite; }
716 int NotMissMinorKey() { return 0; }
717
718 DISALLOW_COPY_AND_ASSIGN(CreateAllocationSiteStub);
719};
720
721
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000722class InstanceofStub: public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000723 public:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000724 enum Flags {
725 kNoFlags = 0,
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000726 kArgsInRegisters = 1 << 0,
727 kCallSiteInlineCheck = 1 << 1,
728 kReturnTrueFalseObject = 1 << 2
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000729 };
730
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000731 explicit InstanceofStub(Flags flags) : flags_(flags) { }
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000732
733 static Register left();
734 static Register right();
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000735
736 void Generate(MacroAssembler* masm);
737
738 private:
739 Major MajorKey() { return Instanceof; }
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000740 int MinorKey() { return static_cast<int>(flags_); }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000741
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000742 bool HasArgsInRegisters() const {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000743 return (flags_ & kArgsInRegisters) != 0;
744 }
745
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000746 bool HasCallSiteInlineCheck() const {
747 return (flags_ & kCallSiteInlineCheck) != 0;
748 }
749
750 bool ReturnTrueFalseObject() const {
751 return (flags_ & kReturnTrueFalseObject) != 0;
752 }
753
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000754 virtual void PrintName(StringStream* stream);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000755
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000756 Flags flags_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000757};
758
759
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000760enum AllocationSiteOverrideMode {
761 DONT_OVERRIDE,
762 DISABLE_ALLOCATION_SITES,
763 LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
764};
765
766
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000767class ArrayConstructorStub: public PlatformCodeStub {
768 public:
769 enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
770 ArrayConstructorStub(Isolate* isolate, int argument_count);
771 explicit ArrayConstructorStub(Isolate* isolate);
772
773 void Generate(MacroAssembler* masm);
774
775 private:
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000776 void GenerateDispatchToArrayStub(MacroAssembler* masm,
777 AllocationSiteOverrideMode mode);
778
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000779 virtual CodeStub::Major MajorKey() { return ArrayConstructor; }
780 virtual int MinorKey() { return argument_count_; }
781
782 ArgumentCountKey argument_count_;
783};
784
785
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000786class InternalArrayConstructorStub: public PlatformCodeStub {
787 public:
788 explicit InternalArrayConstructorStub(Isolate* isolate);
789
790 void Generate(MacroAssembler* masm);
791
792 private:
793 virtual CodeStub::Major MajorKey() { return InternalArrayConstructor; }
794 virtual int MinorKey() { return 0; }
795
796 void GenerateCase(MacroAssembler* masm, ElementsKind kind);
797};
798
799
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000800class MathPowStub: public PlatformCodeStub {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000801 public:
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000802 enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK };
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000803
804 explicit MathPowStub(ExponentType exponent_type)
805 : exponent_type_(exponent_type) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000806 virtual void Generate(MacroAssembler* masm);
807
808 private:
809 virtual CodeStub::Major MajorKey() { return MathPow; }
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000810 virtual int MinorKey() { return exponent_type_; }
811
812 ExponentType exponent_type_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000813};
814
815
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000816class ICStub: public PlatformCodeStub {
817 public:
818 explicit ICStub(Code::Kind kind) : kind_(kind) { }
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000819 virtual Code::Kind GetCodeKind() const { return kind_; }
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000820 virtual InlineCacheState GetICState() { return MONOMORPHIC; }
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000821
822 bool Describes(Code* code) {
823 return GetMajorKey(code) == MajorKey() && code->stub_info() == MinorKey();
824 }
825
826 protected:
827 class KindBits: public BitField<Code::Kind, 0, 4> {};
828 virtual void FinishCode(Handle<Code> code) {
829 code->set_stub_info(MinorKey());
830 }
831 Code::Kind kind() { return kind_; }
832
833 virtual int MinorKey() {
834 return KindBits::encode(kind_);
835 }
836
837 private:
838 Code::Kind kind_;
839};
840
841
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000842class FunctionPrototypeStub: public ICStub {
843 public:
844 explicit FunctionPrototypeStub(Code::Kind kind) : ICStub(kind) { }
845 virtual void Generate(MacroAssembler* masm);
846
847 private:
848 virtual CodeStub::Major MajorKey() { return FunctionPrototype; }
849};
850
851
852class StringLengthStub: public ICStub {
853 public:
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000854 explicit StringLengthStub(Code::Kind kind) : ICStub(kind) { }
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000855 virtual void Generate(MacroAssembler* masm);
856
857 private:
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000858 STATIC_ASSERT(KindBits::kSize == 4);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000859 virtual CodeStub::Major MajorKey() { return StringLength; }
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000860};
861
862
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000863class StoreICStub: public ICStub {
864 public:
865 StoreICStub(Code::Kind kind, StrictModeFlag strict_mode)
866 : ICStub(kind), strict_mode_(strict_mode) { }
867
868 protected:
869 virtual Code::ExtraICState GetExtraICState() {
870 return strict_mode_;
871 }
872
873 private:
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000874 STATIC_ASSERT(KindBits::kSize == 4);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000875 class StrictModeBits: public BitField<bool, 4, 1> {};
876 virtual int MinorKey() {
877 return KindBits::encode(kind()) | StrictModeBits::encode(strict_mode_);
878 }
879
880 StrictModeFlag strict_mode_;
881};
882
883
884class StoreArrayLengthStub: public StoreICStub {
885 public:
886 explicit StoreArrayLengthStub(Code::Kind kind, StrictModeFlag strict_mode)
887 : StoreICStub(kind, strict_mode) { }
888 virtual void Generate(MacroAssembler* masm);
889
890 private:
891 virtual CodeStub::Major MajorKey() { return StoreArrayLength; }
892};
893
894
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000895class HICStub: public HydrogenCodeStub {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000896 public:
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000897 virtual Code::Kind GetCodeKind() const { return kind(); }
898 virtual InlineCacheState GetICState() { return MONOMORPHIC; }
899
900 protected:
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000901 HICStub() { }
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000902 class KindBits: public BitField<Code::Kind, 0, 4> {};
903 virtual Code::Kind kind() const = 0;
904};
905
906
907class HandlerStub: public HICStub {
908 public:
jkummerow@chromium.org32aa03c2013-10-01 08:21:50 +0000909 virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
ulan@chromium.org750145a2013-03-07 15:14:13 +0000910 virtual int GetStubFlags() { return kind(); }
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000911
912 protected:
913 HandlerStub() : HICStub() { }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000914};
915
916
917class LoadFieldStub: public HandlerStub {
918 public:
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000919 LoadFieldStub(bool inobject, int index, Representation representation)
920 : HandlerStub() {
921 Initialize(Code::LOAD_IC, inobject, index, representation);
922 }
923
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000924 virtual Handle<Code> GenerateCode(Isolate* isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000925
926 virtual void InitializeInterfaceDescriptor(
927 Isolate* isolate,
928 CodeStubInterfaceDescriptor* descriptor);
929
930 Representation representation() {
931 if (unboxed_double()) return Representation::Double();
932 return Representation::Tagged();
933 }
934
935 virtual Code::Kind kind() const {
936 return KindBits::decode(bit_field_);
937 }
938
939 bool is_inobject() {
940 return InobjectBits::decode(bit_field_);
941 }
942
943 int offset() {
944 int index = IndexBits::decode(bit_field_);
945 int offset = index * kPointerSize;
946 if (is_inobject()) return offset;
947 return FixedArray::kHeaderSize + offset;
948 }
949
950 bool unboxed_double() {
951 return UnboxedDoubleBits::decode(bit_field_);
952 }
953
954 virtual Code::StubType GetStubType() { return Code::FIELD; }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000955
956 protected:
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000957 LoadFieldStub() : HandlerStub() { }
958
959 void Initialize(Code::Kind kind,
960 bool inobject,
961 int index,
962 Representation representation) {
963 bool unboxed_double = FLAG_track_double_fields && representation.IsDouble();
964 bit_field_ = KindBits::encode(kind)
965 | InobjectBits::encode(inobject)
966 | IndexBits::encode(index)
967 | UnboxedDoubleBits::encode(unboxed_double);
968 }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000969
970 private:
971 STATIC_ASSERT(KindBits::kSize == 4);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000972 class InobjectBits: public BitField<bool, 4, 1> {};
973 class IndexBits: public BitField<int, 5, 11> {};
974 class UnboxedDoubleBits: public BitField<bool, 16, 1> {};
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000975 virtual CodeStub::Major MajorKey() { return LoadField; }
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000976 virtual int NotMissMinorKey() { return bit_field_; }
977
978 int bit_field_;
979};
980
981
982class KeyedLoadFieldStub: public LoadFieldStub {
983 public:
984 KeyedLoadFieldStub(bool inobject, int index, Representation representation)
985 : LoadFieldStub() {
986 Initialize(Code::KEYED_LOAD_IC, inobject, index, representation);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000987 }
988
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000989 virtual void InitializeInterfaceDescriptor(
990 Isolate* isolate,
991 CodeStubInterfaceDescriptor* descriptor);
992
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000993 virtual Handle<Code> GenerateCode(Isolate* isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000994
995 private:
996 virtual CodeStub::Major MajorKey() { return KeyedLoadField; }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000997};
998
999
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +00001000class BinaryOpStub: public HydrogenCodeStub {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001001 public:
1002 BinaryOpStub(Token::Value op, OverwriteMode mode)
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +00001003 : HydrogenCodeStub(UNINITIALIZED), op_(op), mode_(mode) {
1004 ASSERT(op <= LAST_TOKEN && op >= FIRST_TOKEN);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001005 Initialize();
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001006 }
1007
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +00001008 explicit BinaryOpStub(Code::ExtraICState state)
1009 : op_(decode_token(OpBits::decode(state))),
1010 mode_(OverwriteModeField::decode(state)),
1011 fixed_right_arg_(
1012 Maybe<int>(HasFixedRightArgBits::decode(state),
1013 decode_arg_value(FixedRightArgValueBits::decode(state)))),
1014 left_state_(LeftStateField::decode(state)),
1015 right_state_(fixed_right_arg_.has_value
1016 ? ((fixed_right_arg_.value <= Smi::kMaxValue) ? SMI : INT32)
1017 : RightStateField::decode(state)),
1018 result_state_(ResultStateField::decode(state)) {
1019 // We don't deserialize the SSE2 Field, since this is only used to be able
1020 // to include SSE2 as well as non-SSE2 versions in the snapshot. For code
1021 // generation we always want it to reflect the current state.
1022 ASSERT(!fixed_right_arg_.has_value ||
1023 can_encode_arg_value(fixed_right_arg_.value));
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001024 }
1025
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +00001026 static const int FIRST_TOKEN = Token::BIT_OR;
1027 static const int LAST_TOKEN = Token::MOD;
1028
1029 static void GenerateAheadOfTime(Isolate* isolate);
1030 virtual void InitializeInterfaceDescriptor(
1031 Isolate* isolate, CodeStubInterfaceDescriptor* descriptor);
1032 static void InitializeForIsolate(Isolate* isolate) {
1033 BinaryOpStub binopStub(UNINITIALIZED);
1034 binopStub.InitializeInterfaceDescriptor(
1035 isolate, isolate->code_stub_interface_descriptor(CodeStub::BinaryOp));
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001036 }
1037
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001038 virtual Code::Kind GetCodeKind() const { return Code::BINARY_OP_IC; }
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001039 virtual InlineCacheState GetICState() {
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +00001040 if (Max(left_state_, right_state_) == NONE) {
1041 return ::v8::internal::UNINITIALIZED;
1042 }
1043 if (Max(left_state_, right_state_) == GENERIC) return MEGAMORPHIC;
1044 return MONOMORPHIC;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001045 }
1046
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +00001047 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
1048 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1049 }
1050
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +00001051 virtual Code::ExtraICState GetExtraICState() {
1052 bool sse_field = Max(result_state_, Max(left_state_, right_state_)) > SMI &&
1053 CpuFeatures::IsSafeForSnapshot(SSE2);
1054
1055 return OpBits::encode(encode_token(op_))
1056 | LeftStateField::encode(left_state_)
1057 | RightStateField::encode(fixed_right_arg_.has_value
1058 ? NONE : right_state_)
1059 | ResultStateField::encode(result_state_)
1060 | HasFixedRightArgBits::encode(fixed_right_arg_.has_value)
1061 | FixedRightArgValueBits::encode(fixed_right_arg_.has_value
1062 ? encode_arg_value(
1063 fixed_right_arg_.value)
1064 : 0)
1065 | SSE2Field::encode(sse_field)
1066 | OverwriteModeField::encode(mode_);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001067 }
1068
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +00001069 bool CanReuseDoubleBox() {
1070 return result_state_ <= NUMBER && result_state_ > SMI &&
1071 ((left_state_ > SMI && left_state_ <= NUMBER &&
1072 mode_ == OVERWRITE_LEFT) ||
1073 (right_state_ > SMI && right_state_ <= NUMBER &&
1074 mode_ == OVERWRITE_RIGHT));
1075 }
1076
1077 bool HasSideEffects(Isolate* isolate) const {
1078 Handle<Type> left = GetLeftType(isolate);
1079 Handle<Type> right = GetRightType(isolate);
1080 return left->Maybe(Type::Receiver()) || right->Maybe(Type::Receiver());
1081 }
1082
1083 virtual Handle<Code> GenerateCode(Isolate* isolate);
1084
1085 Maybe<Handle<Object> > Result(Handle<Object> left,
1086 Handle<Object> right,
1087 Isolate* isolate);
1088
1089 Token::Value operation() const { return op_; }
1090 OverwriteMode mode() const { return mode_; }
1091 Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }
1092
1093 Handle<Type> GetLeftType(Isolate* isolate) const;
1094 Handle<Type> GetRightType(Isolate* isolate) const;
1095 Handle<Type> GetResultType(Isolate* isolate) const;
1096
1097 void UpdateStatus(Handle<Object> left,
1098 Handle<Object> right,
1099 Maybe<Handle<Object> > result);
1100
1101 void PrintState(StringStream* stream);
1102
1103 private:
1104 explicit BinaryOpStub(InitializationState state) : HydrogenCodeStub(state),
1105 op_(Token::ADD),
1106 mode_(NO_OVERWRITE) {
1107 Initialize();
1108 }
1109 void Initialize();
1110
1111 enum State { NONE, SMI, INT32, NUMBER, STRING, GENERIC };
1112
1113 // We truncate the last bit of the token.
1114 STATIC_ASSERT(LAST_TOKEN - FIRST_TOKEN < (1 << 5));
1115 class LeftStateField: public BitField<State, 0, 3> {};
1116 // When fixed right arg is set, we don't need to store the right state.
1117 // Thus the two fields can overlap.
1118 class HasFixedRightArgBits: public BitField<bool, 4, 1> {};
1119 class FixedRightArgValueBits: public BitField<int, 5, 4> {};
1120 class RightStateField: public BitField<State, 5, 3> {};
1121 class ResultStateField: public BitField<State, 9, 3> {};
1122 class SSE2Field: public BitField<bool, 12, 1> {};
1123 class OverwriteModeField: public BitField<OverwriteMode, 13, 2> {};
1124 class OpBits: public BitField<int, 15, 5> {};
1125
1126 virtual CodeStub::Major MajorKey() { return BinaryOp; }
1127 virtual int NotMissMinorKey() { return GetExtraICState(); }
1128
1129 static Handle<Type> StateToType(State state,
1130 Isolate* isolate);
1131
1132 static void Generate(Token::Value op,
1133 State left,
1134 int right,
1135 State result,
1136 OverwriteMode mode,
1137 Isolate* isolate);
1138
1139 static void Generate(Token::Value op,
1140 State left,
1141 State right,
1142 State result,
1143 OverwriteMode mode,
1144 Isolate* isolate);
1145
1146 void UpdateStatus(Handle<Object> object,
1147 State* state);
1148
1149 bool can_encode_arg_value(int32_t value) const;
1150 int encode_arg_value(int32_t value) const;
1151 int32_t decode_arg_value(int value) const;
1152 int encode_token(Token::Value op) const;
1153 Token::Value decode_token(int op) const;
1154
1155 bool has_int_result() const {
1156 return op_ == Token::BIT_XOR || op_ == Token::BIT_AND ||
1157 op_ == Token::BIT_OR || op_ == Token::SAR || op_ == Token::SHL;
1158 }
1159
1160 const char* StateToName(State state);
1161
1162 void PrintBaseName(StringStream* stream);
1163
1164 Token::Value op_;
1165 OverwriteMode mode_;
1166
1167 Maybe<int> fixed_right_arg_;
1168 State left_state_;
1169 State right_state_;
1170 State result_state_;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001171};
1172
1173
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001174class ICCompareStub: public PlatformCodeStub {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001175 public:
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001176 ICCompareStub(Token::Value op,
1177 CompareIC::State left,
1178 CompareIC::State right,
1179 CompareIC::State handler)
1180 : op_(op),
1181 left_(left),
1182 right_(right),
1183 state_(handler) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001184 ASSERT(Token::IsCompareOp(op));
1185 }
1186
1187 virtual void Generate(MacroAssembler* masm);
1188
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001189 void set_known_map(Handle<Map> map) { known_map_ = map; }
1190
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001191 static void DecodeMinorKey(int minor_key,
1192 CompareIC::State* left_state,
1193 CompareIC::State* right_state,
1194 CompareIC::State* handler_state,
1195 Token::Value* op);
1196
1197 static CompareIC::State CompareState(int minor_key) {
1198 return static_cast<CompareIC::State>(HandlerStateField::decode(minor_key));
1199 }
1200
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001201 virtual InlineCacheState GetICState();
1202
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001203 private:
1204 class OpField: public BitField<int, 0, 3> { };
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001205 class LeftStateField: public BitField<int, 3, 4> { };
1206 class RightStateField: public BitField<int, 7, 4> { };
1207 class HandlerStateField: public BitField<int, 11, 4> { };
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001208
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +00001209 virtual void FinishCode(Handle<Code> code) {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001210 code->set_stub_info(MinorKey());
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +00001211 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001212
1213 virtual CodeStub::Major MajorKey() { return CompareIC; }
1214 virtual int MinorKey();
1215
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001216 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_IC; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001217
1218 void GenerateSmis(MacroAssembler* masm);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001219 void GenerateNumbers(MacroAssembler* masm);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001220 void GenerateInternalizedStrings(MacroAssembler* masm);
lrn@chromium.org1c092762011-05-09 09:42:16 +00001221 void GenerateStrings(MacroAssembler* masm);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001222 void GenerateUniqueNames(MacroAssembler* masm);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001223 void GenerateObjects(MacroAssembler* masm);
1224 void GenerateMiss(MacroAssembler* masm);
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001225 void GenerateKnownObjects(MacroAssembler* masm);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001226 void GenerateGeneric(MacroAssembler* masm);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001227
1228 bool strict() const { return op_ == Token::EQ_STRICT; }
1229 Condition GetCondition() const { return CompareIC::ComputeCondition(op_); }
1230
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001231 virtual void AddToSpecialCache(Handle<Code> new_object);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00001232 virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001233 virtual bool UseSpecialCache() { return state_ == CompareIC::KNOWN_OBJECT; }
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001234
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001235 Token::Value op_;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001236 CompareIC::State left_;
1237 CompareIC::State right_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001238 CompareIC::State state_;
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001239 Handle<Map> known_map_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001240};
1241
1242
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001243class CompareNilICStub : public HydrogenCodeStub {
1244 public:
danno@chromium.org169691d2013-07-15 08:01:13 +00001245 Handle<Type> GetType(Isolate* isolate, Handle<Map> map = Handle<Map>());
1246 Handle<Type> GetInputType(Isolate* isolate, Handle<Map> map);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001247
danno@chromium.org169691d2013-07-15 08:01:13 +00001248 explicit CompareNilICStub(NilValue nil) : nil_value_(nil) { }
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001249
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001250 CompareNilICStub(Code::ExtraICState ic_state,
1251 InitializationState init_state = INITIALIZED)
danno@chromium.org169691d2013-07-15 08:01:13 +00001252 : HydrogenCodeStub(init_state),
1253 nil_value_(NilValueField::decode(ic_state)),
1254 state_(State(TypesField::decode(ic_state))) {
1255 }
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001256
1257 static Handle<Code> GetUninitialized(Isolate* isolate,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001258 NilValue nil) {
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001259 return CompareNilICStub(nil, UNINITIALIZED).GetCode(isolate);
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001260 }
1261
1262 virtual void InitializeInterfaceDescriptor(
1263 Isolate* isolate,
1264 CodeStubInterfaceDescriptor* descriptor);
1265
1266 static void InitializeForIsolate(Isolate* isolate) {
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001267 CompareNilICStub compare_stub(kNullValue, UNINITIALIZED);
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001268 compare_stub.InitializeInterfaceDescriptor(
1269 isolate,
1270 isolate->code_stub_interface_descriptor(CodeStub::CompareNilIC));
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001271 }
1272
1273 virtual InlineCacheState GetICState() {
danno@chromium.org169691d2013-07-15 08:01:13 +00001274 if (state_.Contains(GENERIC)) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001275 return MEGAMORPHIC;
danno@chromium.org41728482013-06-12 22:31:22 +00001276 } else if (state_.Contains(MONOMORPHIC_MAP)) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001277 return MONOMORPHIC;
1278 } else {
1279 return PREMONOMORPHIC;
1280 }
1281 }
1282
1283 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_NIL_IC; }
1284
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00001285 virtual Handle<Code> GenerateCode(Isolate* isolate);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001286
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001287 virtual Code::ExtraICState GetExtraICState() {
danno@chromium.org169691d2013-07-15 08:01:13 +00001288 return NilValueField::encode(nil_value_) |
1289 TypesField::encode(state_.ToIntegral());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001290 }
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001291
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001292 void UpdateStatus(Handle<Object> object);
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001293
danno@chromium.org41728482013-06-12 22:31:22 +00001294 bool IsMonomorphic() const { return state_.Contains(MONOMORPHIC_MAP); }
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001295 NilValue GetNilValue() const { return nil_value_; }
danno@chromium.org41728482013-06-12 22:31:22 +00001296 void ClearState() { state_.RemoveAll(); }
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001297
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001298 virtual void PrintState(StringStream* stream);
1299 virtual void PrintBaseName(StringStream* stream);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001300
1301 private:
1302 friend class CompareNilIC;
1303
danno@chromium.org169691d2013-07-15 08:01:13 +00001304 enum CompareNilType {
1305 UNDEFINED,
1306 NULL_TYPE,
1307 MONOMORPHIC_MAP,
1308 GENERIC,
1309 NUMBER_OF_TYPES
1310 };
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001311
danno@chromium.org169691d2013-07-15 08:01:13 +00001312 // At most 6 different types can be distinguished, because the Code object
1313 // only has room for a single byte to hold a set and there are two more
1314 // boolean flags we need to store. :-P
1315 STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
1316
1317 class State : public EnumSet<CompareNilType, byte> {
1318 public:
1319 State() : EnumSet<CompareNilType, byte>(0) { }
1320 explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
1321
1322 void Print(StringStream* stream) const;
1323 };
1324
1325 CompareNilICStub(NilValue nil, InitializationState init_state)
1326 : HydrogenCodeStub(init_state), nil_value_(nil) { }
1327
1328 class NilValueField : public BitField<NilValue, 0, 1> {};
1329 class TypesField : public BitField<byte, 1, NUMBER_OF_TYPES> {};
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001330
1331 virtual CodeStub::Major MajorKey() { return CompareNilIC; }
1332 virtual int NotMissMinorKey() { return GetExtraICState(); }
1333
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001334 NilValue nil_value_;
danno@chromium.org41728482013-06-12 22:31:22 +00001335 State state_;
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001336
1337 DISALLOW_COPY_AND_ASSIGN(CompareNilICStub);
1338};
1339
1340
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001341class CEntryStub : public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001342 public:
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001343 explicit CEntryStub(int result_size,
1344 SaveFPRegsMode save_doubles = kDontSaveFPRegs)
1345 : result_size_(result_size), save_doubles_(save_doubles) { }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001346
1347 void Generate(MacroAssembler* masm);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001348
1349 // The version of this stub that doesn't save doubles is generated ahead of
1350 // time, so it's OK to call it from other stubs that can't cope with GC during
1351 // their code generation. On machines that always have gp registers (x64) we
1352 // can generate both variants ahead of time.
dslomov@chromium.orge97852d2013-09-12 09:02:59 +00001353 virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE;
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001354 static void GenerateAheadOfTime(Isolate* isolate);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001355
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +00001356 protected:
1357 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
1358 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1359 };
1360
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001361 private:
1362 void GenerateCore(MacroAssembler* masm,
1363 Label* throw_normal_exception,
1364 Label* throw_termination_exception,
1365 Label* throw_out_of_memory_exception,
1366 bool do_gc,
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001367 bool always_allocate_scope);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001368
1369 // Number of pointers/values returned.
dslomov@chromium.orge97852d2013-09-12 09:02:59 +00001370 Isolate* isolate_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001371 const int result_size_;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001372 SaveFPRegsMode save_doubles_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001373
1374 Major MajorKey() { return CEntry; }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001375 int MinorKey();
1376
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001377 bool NeedsImmovableCode();
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001378};
1379
1380
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001381class JSEntryStub : public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001382 public:
1383 JSEntryStub() { }
1384
1385 void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
1386
1387 protected:
1388 void GenerateBody(MacroAssembler* masm, bool is_construct);
1389
1390 private:
1391 Major MajorKey() { return JSEntry; }
1392 int MinorKey() { return 0; }
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +00001393
1394 virtual void FinishCode(Handle<Code> code);
1395
1396 int handler_offset_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001397};
1398
1399
1400class JSConstructEntryStub : public JSEntryStub {
1401 public:
1402 JSConstructEntryStub() { }
1403
1404 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
1405
1406 private:
1407 int MinorKey() { return 1; }
1408
whesse@chromium.org030d38e2011-07-13 13:23:34 +00001409 virtual void PrintName(StringStream* stream) {
1410 stream->Add("JSConstructEntryStub");
1411 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001412};
1413
1414
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001415class ArgumentsAccessStub: public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001416 public:
1417 enum Type {
1418 READ_ELEMENT,
whesse@chromium.org7b260152011-06-20 15:33:18 +00001419 NEW_NON_STRICT_FAST,
1420 NEW_NON_STRICT_SLOW,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001421 NEW_STRICT
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001422 };
1423
1424 explicit ArgumentsAccessStub(Type type) : type_(type) { }
1425
1426 private:
1427 Type type_;
1428
1429 Major MajorKey() { return ArgumentsAccess; }
1430 int MinorKey() { return type_; }
1431
1432 void Generate(MacroAssembler* masm);
1433 void GenerateReadElement(MacroAssembler* masm);
whesse@chromium.org7b260152011-06-20 15:33:18 +00001434 void GenerateNewStrict(MacroAssembler* masm);
1435 void GenerateNewNonStrictFast(MacroAssembler* masm);
1436 void GenerateNewNonStrictSlow(MacroAssembler* masm);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001437
whesse@chromium.org030d38e2011-07-13 13:23:34 +00001438 virtual void PrintName(StringStream* stream);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001439};
1440
1441
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001442class RegExpExecStub: public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001443 public:
1444 RegExpExecStub() { }
1445
1446 private:
1447 Major MajorKey() { return RegExpExec; }
1448 int MinorKey() { return 0; }
1449
1450 void Generate(MacroAssembler* masm);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001451};
1452
1453
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001454class RegExpConstructResultStub: public PlatformCodeStub {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001455 public:
1456 RegExpConstructResultStub() { }
1457
1458 private:
1459 Major MajorKey() { return RegExpConstructResult; }
1460 int MinorKey() { return 0; }
1461
1462 void Generate(MacroAssembler* masm);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001463};
1464
1465
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001466class CallFunctionStub: public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001467 public:
lrn@chromium.org34e60782011-09-15 07:25:40 +00001468 CallFunctionStub(int argc, CallFunctionFlags flags)
1469 : argc_(argc), flags_(flags) { }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001470
1471 void Generate(MacroAssembler* masm);
1472
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001473 virtual void FinishCode(Handle<Code> code) {
1474 code->set_has_function_cache(RecordCallTarget());
1475 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001476
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001477 static int ExtractArgcFromMinorKey(int minor_key) {
1478 return ArgcBits::decode(minor_key);
1479 }
1480
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001481 private:
1482 int argc_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001483 CallFunctionFlags flags_;
1484
whesse@chromium.org030d38e2011-07-13 13:23:34 +00001485 virtual void PrintName(StringStream* stream);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001486
1487 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001488 class FlagBits: public BitField<CallFunctionFlags, 0, 2> {};
1489 class ArgcBits: public BitField<unsigned, 2, 32 - 2> {};
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001490
1491 Major MajorKey() { return CallFunction; }
1492 int MinorKey() {
1493 // Encode the parameters in a unique 32 bit value.
lrn@chromium.org34e60782011-09-15 07:25:40 +00001494 return FlagBits::encode(flags_) | ArgcBits::encode(argc_);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001495 }
1496
danno@chromium.org40cb8782011-05-25 07:58:50 +00001497 bool ReceiverMightBeImplicit() {
1498 return (flags_ & RECEIVER_MIGHT_BE_IMPLICIT) != 0;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001499 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001500
1501 bool RecordCallTarget() {
1502 return (flags_ & RECORD_CALL_TARGET) != 0;
1503 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001504};
1505
1506
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001507class CallConstructStub: public PlatformCodeStub {
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001508 public:
1509 explicit CallConstructStub(CallFunctionFlags flags) : flags_(flags) {}
1510
1511 void Generate(MacroAssembler* masm);
1512
1513 virtual void FinishCode(Handle<Code> code) {
1514 code->set_has_function_cache(RecordCallTarget());
1515 }
1516
1517 private:
1518 CallFunctionFlags flags_;
1519
1520 virtual void PrintName(StringStream* stream);
1521
1522 Major MajorKey() { return CallConstruct; }
1523 int MinorKey() { return flags_; }
1524
1525 bool RecordCallTarget() {
1526 return (flags_ & RECORD_CALL_TARGET) != 0;
1527 }
1528};
1529
1530
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001531enum StringIndexFlags {
1532 // Accepts smis or heap numbers.
1533 STRING_INDEX_IS_NUMBER,
1534
1535 // Accepts smis or heap numbers that are valid array indices
1536 // (ECMA-262 15.4). Invalid indices are reported as being out of
1537 // range.
1538 STRING_INDEX_IS_ARRAY_INDEX
1539};
1540
1541
1542// Generates code implementing String.prototype.charCodeAt.
1543//
1544// Only supports the case when the receiver is a string and the index
1545// is a number (smi or heap number) that is a valid index into the
1546// string. Additional index constraints are specified by the
1547// flags. Otherwise, bails out to the provided labels.
1548//
1549// Register usage: |object| may be changed to another string in a way
1550// that doesn't affect charCodeAt/charAt semantics, |index| is
1551// preserved, |scratch| and |result| are clobbered.
1552class StringCharCodeAtGenerator {
1553 public:
1554 StringCharCodeAtGenerator(Register object,
1555 Register index,
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001556 Register result,
1557 Label* receiver_not_string,
1558 Label* index_not_number,
1559 Label* index_out_of_range,
1560 StringIndexFlags index_flags)
1561 : object_(object),
1562 index_(index),
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001563 result_(result),
1564 receiver_not_string_(receiver_not_string),
1565 index_not_number_(index_not_number),
1566 index_out_of_range_(index_out_of_range),
1567 index_flags_(index_flags) {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001568 ASSERT(!result_.is(object_));
1569 ASSERT(!result_.is(index_));
1570 }
1571
1572 // Generates the fast case code. On the fallthrough path |result|
1573 // register contains the result.
1574 void GenerateFast(MacroAssembler* masm);
1575
1576 // Generates the slow case code. Must not be naturally
1577 // reachable. Expected to be put after a ret instruction (e.g., in
1578 // deferred code). Always jumps back to the fast case.
1579 void GenerateSlow(MacroAssembler* masm,
1580 const RuntimeCallHelper& call_helper);
1581
ulan@chromium.org2e04b582013-02-21 14:06:02 +00001582 // Skip handling slow case and directly jump to bailout.
1583 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1584 masm->bind(&index_not_smi_);
1585 masm->bind(&call_runtime_);
1586 masm->jmp(bailout);
1587 }
1588
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001589 private:
1590 Register object_;
1591 Register index_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001592 Register result_;
1593
1594 Label* receiver_not_string_;
1595 Label* index_not_number_;
1596 Label* index_out_of_range_;
1597
1598 StringIndexFlags index_flags_;
1599
1600 Label call_runtime_;
1601 Label index_not_smi_;
1602 Label got_smi_index_;
1603 Label exit_;
1604
1605 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
1606};
1607
1608
1609// Generates code for creating a one-char string from a char code.
1610class StringCharFromCodeGenerator {
1611 public:
1612 StringCharFromCodeGenerator(Register code,
1613 Register result)
1614 : code_(code),
1615 result_(result) {
1616 ASSERT(!code_.is(result_));
1617 }
1618
1619 // Generates the fast case code. On the fallthrough path |result|
1620 // register contains the result.
1621 void GenerateFast(MacroAssembler* masm);
1622
1623 // Generates the slow case code. Must not be naturally
1624 // reachable. Expected to be put after a ret instruction (e.g., in
1625 // deferred code). Always jumps back to the fast case.
1626 void GenerateSlow(MacroAssembler* masm,
1627 const RuntimeCallHelper& call_helper);
1628
ulan@chromium.org2e04b582013-02-21 14:06:02 +00001629 // Skip handling slow case and directly jump to bailout.
1630 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1631 masm->bind(&slow_case_);
1632 masm->jmp(bailout);
1633 }
1634
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001635 private:
1636 Register code_;
1637 Register result_;
1638
1639 Label slow_case_;
1640 Label exit_;
1641
1642 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
1643};
1644
1645
1646// Generates code implementing String.prototype.charAt.
1647//
1648// Only supports the case when the receiver is a string and the index
1649// is a number (smi or heap number) that is a valid index into the
1650// string. Additional index constraints are specified by the
1651// flags. Otherwise, bails out to the provided labels.
1652//
1653// Register usage: |object| may be changed to another string in a way
1654// that doesn't affect charCodeAt/charAt semantics, |index| is
1655// preserved, |scratch1|, |scratch2|, and |result| are clobbered.
1656class StringCharAtGenerator {
1657 public:
1658 StringCharAtGenerator(Register object,
1659 Register index,
danno@chromium.orgc612e022011-11-10 11:38:15 +00001660 Register scratch,
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001661 Register result,
1662 Label* receiver_not_string,
1663 Label* index_not_number,
1664 Label* index_out_of_range,
1665 StringIndexFlags index_flags)
1666 : char_code_at_generator_(object,
1667 index,
danno@chromium.orgc612e022011-11-10 11:38:15 +00001668 scratch,
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001669 receiver_not_string,
1670 index_not_number,
1671 index_out_of_range,
1672 index_flags),
danno@chromium.orgc612e022011-11-10 11:38:15 +00001673 char_from_code_generator_(scratch, result) {}
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001674
1675 // Generates the fast case code. On the fallthrough path |result|
1676 // register contains the result.
ulan@chromium.org2e04b582013-02-21 14:06:02 +00001677 void GenerateFast(MacroAssembler* masm) {
1678 char_code_at_generator_.GenerateFast(masm);
1679 char_from_code_generator_.GenerateFast(masm);
1680 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001681
1682 // Generates the slow case code. Must not be naturally
1683 // reachable. Expected to be put after a ret instruction (e.g., in
1684 // deferred code). Always jumps back to the fast case.
1685 void GenerateSlow(MacroAssembler* masm,
ulan@chromium.org2e04b582013-02-21 14:06:02 +00001686 const RuntimeCallHelper& call_helper) {
1687 char_code_at_generator_.GenerateSlow(masm, call_helper);
1688 char_from_code_generator_.GenerateSlow(masm, call_helper);
1689 }
1690
1691 // Skip handling slow case and directly jump to bailout.
1692 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1693 char_code_at_generator_.SkipSlow(masm, bailout);
1694 char_from_code_generator_.SkipSlow(masm, bailout);
1695 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001696
1697 private:
1698 StringCharCodeAtGenerator char_code_at_generator_;
1699 StringCharFromCodeGenerator char_from_code_generator_;
1700
1701 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
1702};
1703
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001704
1705class AllowStubCallsScope {
1706 public:
1707 AllowStubCallsScope(MacroAssembler* masm, bool allow)
1708 : masm_(masm), previous_allow_(masm->allow_stub_calls()) {
1709 masm_->set_allow_stub_calls(allow);
1710 }
1711 ~AllowStubCallsScope() {
1712 masm_->set_allow_stub_calls(previous_allow_);
1713 }
1714
1715 private:
1716 MacroAssembler* masm_;
1717 bool previous_allow_;
1718
1719 DISALLOW_COPY_AND_ASSIGN(AllowStubCallsScope);
1720};
1721
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001722
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001723class KeyedLoadDictionaryElementStub : public PlatformCodeStub {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001724 public:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001725 KeyedLoadDictionaryElementStub() {}
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001726
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001727 void Generate(MacroAssembler* masm);
1728
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00001729 private:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001730 Major MajorKey() { return KeyedLoadElement; }
1731 int MinorKey() { return DICTIONARY_ELEMENTS; }
1732
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001733 DISALLOW_COPY_AND_ASSIGN(KeyedLoadDictionaryElementStub);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001734};
1735
1736
danno@chromium.org169691d2013-07-15 08:01:13 +00001737class DoubleToIStub : public PlatformCodeStub {
1738 public:
1739 DoubleToIStub(Register source,
1740 Register destination,
1741 int offset,
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00001742 bool is_truncating,
1743 bool skip_fastpath = false) : bit_field_(0) {
danno@chromium.org169691d2013-07-15 08:01:13 +00001744 bit_field_ = SourceRegisterBits::encode(source.code_) |
1745 DestinationRegisterBits::encode(destination.code_) |
1746 OffsetBits::encode(offset) |
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00001747 IsTruncatingBits::encode(is_truncating) |
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +00001748 SkipFastPathBits::encode(skip_fastpath) |
1749 SSEBits::encode(CpuFeatures::IsSafeForSnapshot(SSE2) ?
1750 CpuFeatures::IsSafeForSnapshot(SSE3) ? 2 : 1 : 0);
danno@chromium.org169691d2013-07-15 08:01:13 +00001751 }
1752
1753 Register source() {
1754 Register result = { SourceRegisterBits::decode(bit_field_) };
1755 return result;
1756 }
1757
1758 Register destination() {
1759 Register result = { DestinationRegisterBits::decode(bit_field_) };
1760 return result;
1761 }
1762
1763 bool is_truncating() {
1764 return IsTruncatingBits::decode(bit_field_);
1765 }
1766
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00001767 bool skip_fastpath() {
1768 return SkipFastPathBits::decode(bit_field_);
1769 }
1770
danno@chromium.org169691d2013-07-15 08:01:13 +00001771 int offset() {
1772 return OffsetBits::decode(bit_field_);
1773 }
1774
1775 void Generate(MacroAssembler* masm);
1776
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00001777 virtual bool SometimesSetsUpAFrame() { return false; }
1778
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +00001779 protected:
1780 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
1781 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1782 }
1783
danno@chromium.org169691d2013-07-15 08:01:13 +00001784 private:
1785 static const int kBitsPerRegisterNumber = 6;
1786 STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
1787 class SourceRegisterBits:
1788 public BitField<int, 0, kBitsPerRegisterNumber> {}; // NOLINT
1789 class DestinationRegisterBits:
1790 public BitField<int, kBitsPerRegisterNumber,
1791 kBitsPerRegisterNumber> {}; // NOLINT
1792 class IsTruncatingBits:
1793 public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {}; // NOLINT
1794 class OffsetBits:
1795 public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {}; // NOLINT
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00001796 class SkipFastPathBits:
1797 public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {}; // NOLINT
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +00001798 class SSEBits:
1799 public BitField<int, 2 * kBitsPerRegisterNumber + 5, 2> {}; // NOLINT
danno@chromium.org169691d2013-07-15 08:01:13 +00001800
1801 Major MajorKey() { return DoubleToI; }
1802 int MinorKey() { return bit_field_; }
1803
1804 int bit_field_;
1805
1806 DISALLOW_COPY_AND_ASSIGN(DoubleToIStub);
1807};
1808
1809
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001810class KeyedLoadFastElementStub : public HydrogenCodeStub {
1811 public:
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001812 KeyedLoadFastElementStub(bool is_js_array, ElementsKind elements_kind) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001813 bit_field_ = ElementsKindBits::encode(elements_kind) |
1814 IsJSArrayBits::encode(is_js_array);
1815 }
1816
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001817 bool is_js_array() const {
1818 return IsJSArrayBits::decode(bit_field_);
1819 }
1820
1821 ElementsKind elements_kind() const {
1822 return ElementsKindBits::decode(bit_field_);
1823 }
1824
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00001825 virtual Handle<Code> GenerateCode(Isolate* isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001826
1827 virtual void InitializeInterfaceDescriptor(
1828 Isolate* isolate,
1829 CodeStubInterfaceDescriptor* descriptor);
1830
1831 private:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001832 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001833 class IsJSArrayBits: public BitField<bool, 8, 1> {};
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001834 uint32_t bit_field_;
1835
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001836 Major MajorKey() { return KeyedLoadElement; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001837 int NotMissMinorKey() { return bit_field_; }
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001838
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001839 DISALLOW_COPY_AND_ASSIGN(KeyedLoadFastElementStub);
1840};
1841
1842
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001843class KeyedStoreFastElementStub : public HydrogenCodeStub {
1844 public:
1845 KeyedStoreFastElementStub(bool is_js_array,
1846 ElementsKind elements_kind,
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001847 KeyedAccessStoreMode mode) {
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001848 bit_field_ = ElementsKindBits::encode(elements_kind) |
1849 IsJSArrayBits::encode(is_js_array) |
1850 StoreModeBits::encode(mode);
1851 }
1852
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001853 bool is_js_array() const {
1854 return IsJSArrayBits::decode(bit_field_);
1855 }
1856
1857 ElementsKind elements_kind() const {
1858 return ElementsKindBits::decode(bit_field_);
1859 }
1860
1861 KeyedAccessStoreMode store_mode() const {
1862 return StoreModeBits::decode(bit_field_);
1863 }
1864
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00001865 virtual Handle<Code> GenerateCode(Isolate* isolate);
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001866
1867 virtual void InitializeInterfaceDescriptor(
1868 Isolate* isolate,
1869 CodeStubInterfaceDescriptor* descriptor);
1870
1871 private:
1872 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
1873 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
1874 class IsJSArrayBits: public BitField<bool, 12, 1> {};
1875 uint32_t bit_field_;
1876
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001877 Major MajorKey() { return KeyedStoreElement; }
1878 int NotMissMinorKey() { return bit_field_; }
1879
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001880 DISALLOW_COPY_AND_ASSIGN(KeyedStoreFastElementStub);
1881};
1882
1883
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001884class TransitionElementsKindStub : public HydrogenCodeStub {
1885 public:
1886 TransitionElementsKindStub(ElementsKind from_kind,
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001887 ElementsKind to_kind) {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001888 bit_field_ = FromKindBits::encode(from_kind) |
1889 ToKindBits::encode(to_kind);
1890 }
1891
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001892 ElementsKind from_kind() const {
1893 return FromKindBits::decode(bit_field_);
1894 }
1895
1896 ElementsKind to_kind() const {
1897 return ToKindBits::decode(bit_field_);
1898 }
1899
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00001900 virtual Handle<Code> GenerateCode(Isolate* isolate);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001901
1902 virtual void InitializeInterfaceDescriptor(
1903 Isolate* isolate,
1904 CodeStubInterfaceDescriptor* descriptor);
1905
1906 private:
1907 class FromKindBits: public BitField<ElementsKind, 8, 8> {};
1908 class ToKindBits: public BitField<ElementsKind, 0, 8> {};
1909 uint32_t bit_field_;
1910
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001911 Major MajorKey() { return TransitionElementsKind; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001912 int NotMissMinorKey() { return bit_field_; }
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001913
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001914 DISALLOW_COPY_AND_ASSIGN(TransitionElementsKindStub);
1915};
1916
1917
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001918enum ContextCheckMode {
1919 CONTEXT_CHECK_REQUIRED,
1920 CONTEXT_CHECK_NOT_REQUIRED,
1921 LAST_CONTEXT_CHECK_MODE = CONTEXT_CHECK_NOT_REQUIRED
1922};
1923
1924
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001925class ArrayConstructorStubBase : public HydrogenCodeStub {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001926 public:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001927 ArrayConstructorStubBase(ElementsKind kind, ContextCheckMode context_mode,
1928 AllocationSiteOverrideMode override_mode) {
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001929 // It only makes sense to override local allocation site behavior
1930 // if there is a difference between the global allocation site policy
1931 // for an ElementsKind and the desired usage of the stub.
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +00001932 ASSERT(!(FLAG_track_allocation_sites &&
1933 override_mode == DISABLE_ALLOCATION_SITES) ||
danno@chromium.orgbee51992013-07-10 14:57:15 +00001934 AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001935 bit_field_ = ElementsKindBits::encode(kind) |
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001936 AllocationSiteOverrideModeBits::encode(override_mode) |
1937 ContextCheckModeBits::encode(context_mode);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001938 }
1939
1940 ElementsKind elements_kind() const {
1941 return ElementsKindBits::decode(bit_field_);
1942 }
1943
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001944 AllocationSiteOverrideMode override_mode() const {
1945 return AllocationSiteOverrideModeBits::decode(bit_field_);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001946 }
1947
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001948 ContextCheckMode context_mode() const {
1949 return ContextCheckModeBits::decode(bit_field_);
1950 }
1951
dslomov@chromium.orge97852d2013-09-12 09:02:59 +00001952 virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001953 // We only pre-generate stubs that verify correct context
1954 return context_mode() == CONTEXT_CHECK_REQUIRED;
1955 }
1956
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001957 static void GenerateStubsAheadOfTime(Isolate* isolate);
1958 static void InstallDescriptors(Isolate* isolate);
1959
1960 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001961 static const int kConstructor = 0;
1962 static const int kPropertyCell = 1;
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001963
1964 private:
1965 int NotMissMinorKey() { return bit_field_; }
1966
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001967 // Ensure data fits within available bits.
1968 STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
1969 STATIC_ASSERT(LAST_CONTEXT_CHECK_MODE == 1);
1970
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001971 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001972 class AllocationSiteOverrideModeBits: public
1973 BitField<AllocationSiteOverrideMode, 8, 1> {}; // NOLINT
1974 class ContextCheckModeBits: public BitField<ContextCheckMode, 9, 1> {};
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001975 uint32_t bit_field_;
1976
1977 DISALLOW_COPY_AND_ASSIGN(ArrayConstructorStubBase);
1978};
1979
1980
1981class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
1982 public:
1983 ArrayNoArgumentConstructorStub(
1984 ElementsKind kind,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001985 ContextCheckMode context_mode = CONTEXT_CHECK_REQUIRED,
1986 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
1987 : ArrayConstructorStubBase(kind, context_mode, override_mode) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001988 }
1989
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00001990 virtual Handle<Code> GenerateCode(Isolate* isolate);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001991
1992 virtual void InitializeInterfaceDescriptor(
1993 Isolate* isolate,
1994 CodeStubInterfaceDescriptor* descriptor);
1995
1996 private:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001997 Major MajorKey() { return ArrayNoArgumentConstructor; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001998
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001999 DISALLOW_COPY_AND_ASSIGN(ArrayNoArgumentConstructorStub);
2000};
2001
2002
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002003class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002004 public:
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002005 ArraySingleArgumentConstructorStub(
2006 ElementsKind kind,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002007 ContextCheckMode context_mode = CONTEXT_CHECK_REQUIRED,
2008 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2009 : ArrayConstructorStubBase(kind, context_mode, override_mode) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002010 }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002011
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00002012 virtual Handle<Code> GenerateCode(Isolate* isolate);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002013
2014 virtual void InitializeInterfaceDescriptor(
2015 Isolate* isolate,
2016 CodeStubInterfaceDescriptor* descriptor);
2017
2018 private:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002019 Major MajorKey() { return ArraySingleArgumentConstructor; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002020
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002021 DISALLOW_COPY_AND_ASSIGN(ArraySingleArgumentConstructorStub);
2022};
2023
2024
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002025class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002026 public:
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002027 ArrayNArgumentsConstructorStub(
2028 ElementsKind kind,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002029 ContextCheckMode context_mode = CONTEXT_CHECK_REQUIRED,
2030 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2031 : ArrayConstructorStubBase(kind, context_mode, override_mode) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002032 }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002033
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00002034 virtual Handle<Code> GenerateCode(Isolate* isolate);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002035
2036 virtual void InitializeInterfaceDescriptor(
2037 Isolate* isolate,
2038 CodeStubInterfaceDescriptor* descriptor);
2039
2040 private:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002041 Major MajorKey() { return ArrayNArgumentsConstructor; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002042
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002043 DISALLOW_COPY_AND_ASSIGN(ArrayNArgumentsConstructorStub);
2044};
2045
2046
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002047class InternalArrayConstructorStubBase : public HydrogenCodeStub {
2048 public:
2049 explicit InternalArrayConstructorStubBase(ElementsKind kind) {
2050 kind_ = kind;
2051 }
2052
dslomov@chromium.orge97852d2013-09-12 09:02:59 +00002053 virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE { return true; }
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002054 static void GenerateStubsAheadOfTime(Isolate* isolate);
2055 static void InstallDescriptors(Isolate* isolate);
2056
2057 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2058 static const int kConstructor = 0;
2059
2060 ElementsKind elements_kind() const { return kind_; }
2061
2062 private:
2063 int NotMissMinorKey() { return kind_; }
2064
2065 ElementsKind kind_;
2066
2067 DISALLOW_COPY_AND_ASSIGN(InternalArrayConstructorStubBase);
2068};
2069
2070
2071class InternalArrayNoArgumentConstructorStub : public
2072 InternalArrayConstructorStubBase {
2073 public:
2074 explicit InternalArrayNoArgumentConstructorStub(ElementsKind kind)
2075 : InternalArrayConstructorStubBase(kind) { }
2076
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00002077 virtual Handle<Code> GenerateCode(Isolate* isolate);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002078
2079 virtual void InitializeInterfaceDescriptor(
2080 Isolate* isolate,
2081 CodeStubInterfaceDescriptor* descriptor);
2082
2083 private:
2084 Major MajorKey() { return InternalArrayNoArgumentConstructor; }
2085
2086 DISALLOW_COPY_AND_ASSIGN(InternalArrayNoArgumentConstructorStub);
2087};
2088
2089
2090class InternalArraySingleArgumentConstructorStub : public
2091 InternalArrayConstructorStubBase {
2092 public:
2093 explicit InternalArraySingleArgumentConstructorStub(ElementsKind kind)
2094 : InternalArrayConstructorStubBase(kind) { }
2095
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00002096 virtual Handle<Code> GenerateCode(Isolate* isolate);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002097
2098 virtual void InitializeInterfaceDescriptor(
2099 Isolate* isolate,
2100 CodeStubInterfaceDescriptor* descriptor);
2101
2102 private:
2103 Major MajorKey() { return InternalArraySingleArgumentConstructor; }
2104
2105 DISALLOW_COPY_AND_ASSIGN(InternalArraySingleArgumentConstructorStub);
2106};
2107
2108
2109class InternalArrayNArgumentsConstructorStub : public
2110 InternalArrayConstructorStubBase {
2111 public:
2112 explicit InternalArrayNArgumentsConstructorStub(ElementsKind kind)
2113 : InternalArrayConstructorStubBase(kind) { }
2114
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00002115 virtual Handle<Code> GenerateCode(Isolate* isolate);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002116
2117 virtual void InitializeInterfaceDescriptor(
2118 Isolate* isolate,
2119 CodeStubInterfaceDescriptor* descriptor);
2120
2121 private:
2122 Major MajorKey() { return InternalArrayNArgumentsConstructor; }
2123
2124 DISALLOW_COPY_AND_ASSIGN(InternalArrayNArgumentsConstructorStub);
2125};
2126
2127
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002128class KeyedStoreElementStub : public PlatformCodeStub {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00002129 public:
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00002130 KeyedStoreElementStub(bool is_js_array,
ulan@chromium.org65a89c22012-02-14 11:46:07 +00002131 ElementsKind elements_kind,
ulan@chromium.org750145a2013-03-07 15:14:13 +00002132 KeyedAccessStoreMode store_mode)
ulan@chromium.org65a89c22012-02-14 11:46:07 +00002133 : is_js_array_(is_js_array),
2134 elements_kind_(elements_kind),
ulan@chromium.org750145a2013-03-07 15:14:13 +00002135 store_mode_(store_mode),
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002136 fp_registers_(CanUseFPRegisters()) { }
ager@chromium.orgea91cc52011-05-23 06:06:11 +00002137
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00002138 Major MajorKey() { return KeyedStoreElement; }
2139 int MinorKey() {
ulan@chromium.org65a89c22012-02-14 11:46:07 +00002140 return ElementsKindBits::encode(elements_kind_) |
2141 IsJSArrayBits::encode(is_js_array_) |
ulan@chromium.org750145a2013-03-07 15:14:13 +00002142 StoreModeBits::encode(store_mode_) |
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002143 FPRegisters::encode(fp_registers_);
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00002144 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +00002145
2146 void Generate(MacroAssembler* masm);
2147
ager@chromium.orgea91cc52011-05-23 06:06:11 +00002148 private:
ulan@chromium.org750145a2013-03-07 15:14:13 +00002149 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2150 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
2151 class IsJSArrayBits: public BitField<bool, 12, 1> {};
2152 class FPRegisters: public BitField<bool, 13, 1> {};
ulan@chromium.org65a89c22012-02-14 11:46:07 +00002153
ager@chromium.orgea91cc52011-05-23 06:06:11 +00002154 bool is_js_array_;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00002155 ElementsKind elements_kind_;
ulan@chromium.org750145a2013-03-07 15:14:13 +00002156 KeyedAccessStoreMode store_mode_;
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002157 bool fp_registers_;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00002158
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00002159 DISALLOW_COPY_AND_ASSIGN(KeyedStoreElementStub);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00002160};
2161
2162
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002163class ToBooleanStub: public HydrogenCodeStub {
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00002164 public:
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002165 enum Type {
2166 UNDEFINED,
2167 BOOLEAN,
2168 NULL_TYPE,
2169 SMI,
2170 SPEC_OBJECT,
2171 STRING,
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00002172 SYMBOL,
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002173 HEAP_NUMBER,
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002174 NUMBER_OF_TYPES
2175 };
2176
2177 // At most 8 different types can be distinguished, because the Code object
2178 // only has room for a single byte to hold a set of these types. :-P
2179 STATIC_ASSERT(NUMBER_OF_TYPES <= 8);
2180
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00002181 class Types : public EnumSet<Type, byte> {
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002182 public:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002183 Types() : EnumSet<Type, byte>(0) {}
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00002184 explicit Types(byte bits) : EnumSet<Type, byte>(bits) {}
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002185
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00002186 byte ToByte() const { return ToIntegral(); }
vegorov@chromium.org7943d462011-08-01 11:41:52 +00002187 void Print(StringStream* stream) const;
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002188 bool UpdateStatus(Handle<Object> object);
vegorov@chromium.org7943d462011-08-01 11:41:52 +00002189 bool NeedsMap() const;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00002190 bool CanBeUndetectable() const;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002191 bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002192
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002193 static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
2194 };
ricow@chromium.org2c99e282011-07-28 09:15:17 +00002195
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002196 explicit ToBooleanStub(Types types = Types())
2197 : types_(types) { }
2198 explicit ToBooleanStub(Code::ExtraICState state)
2199 : types_(static_cast<byte>(state)) { }
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00002200
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002201 bool UpdateStatus(Handle<Object> object);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002202 Types GetTypes() { return types_; }
2203
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00002204 virtual Handle<Code> GenerateCode(Isolate* isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002205 virtual void InitializeInterfaceDescriptor(
2206 Isolate* isolate,
2207 CodeStubInterfaceDescriptor* descriptor);
2208
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00002209 virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; }
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002210 virtual void PrintState(StringStream* stream);
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00002211
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002212 virtual bool SometimesSetsUpAFrame() { return false; }
2213
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002214 static void InitializeForIsolate(Isolate* isolate) {
2215 ToBooleanStub stub;
2216 stub.InitializeInterfaceDescriptor(
2217 isolate,
2218 isolate->code_stub_interface_descriptor(CodeStub::ToBoolean));
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002219 }
2220
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002221 static Handle<Code> GetUninitialized(Isolate* isolate) {
2222 return ToBooleanStub(UNINITIALIZED).GetCode(isolate);
2223 }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002224
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002225 virtual Code::ExtraICState GetExtraICState() {
2226 return types_.ToIntegral();
2227 }
2228
danno@chromium.org1fd77d52013-06-07 16:01:45 +00002229 virtual InlineCacheState GetICState() {
2230 if (types_.IsEmpty()) {
2231 return ::v8::internal::UNINITIALIZED;
2232 } else {
2233 return MONOMORPHIC;
2234 }
2235 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002236
2237 private:
2238 Major MajorKey() { return ToBoolean; }
2239 int NotMissMinorKey() { return GetExtraICState(); }
2240
2241 explicit ToBooleanStub(InitializationState init_state) :
2242 HydrogenCodeStub(init_state) {}
2243
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002244 Types types_;
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00002245};
2246
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002247
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00002248class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002249 public:
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00002250 ElementsTransitionAndStoreStub(ElementsKind from_kind,
2251 ElementsKind to_kind,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002252 bool is_jsarray,
ulan@chromium.org750145a2013-03-07 15:14:13 +00002253 KeyedAccessStoreMode store_mode)
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00002254 : from_kind_(from_kind),
2255 to_kind_(to_kind),
2256 is_jsarray_(is_jsarray),
2257 store_mode_(store_mode) {}
2258
2259 ElementsKind from_kind() const { return from_kind_; }
2260 ElementsKind to_kind() const { return to_kind_; }
2261 bool is_jsarray() const { return is_jsarray_; }
2262 KeyedAccessStoreMode store_mode() const { return store_mode_; }
2263
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00002264 virtual Handle<Code> GenerateCode(Isolate* isolate);
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00002265
2266 void InitializeInterfaceDescriptor(
2267 Isolate* isolate,
2268 CodeStubInterfaceDescriptor* descriptor);
2269
2270 private:
2271 class FromBits: public BitField<ElementsKind, 0, 8> {};
2272 class ToBits: public BitField<ElementsKind, 8, 8> {};
2273 class IsJSArrayBits: public BitField<bool, 16, 1> {};
2274 class StoreModeBits: public BitField<KeyedAccessStoreMode, 17, 4> {};
2275
2276 Major MajorKey() { return ElementsTransitionAndStore; }
2277 int NotMissMinorKey() {
2278 return FromBits::encode(from_kind_) |
2279 ToBits::encode(to_kind_) |
2280 IsJSArrayBits::encode(is_jsarray_) |
2281 StoreModeBits::encode(store_mode_);
2282 }
2283
2284 ElementsKind from_kind_;
2285 ElementsKind to_kind_;
2286 bool is_jsarray_;
2287 KeyedAccessStoreMode store_mode_;
2288
2289 DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub);
2290};
2291
2292
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002293class StoreArrayLiteralElementStub : public PlatformCodeStub {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002294 public:
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002295 StoreArrayLiteralElementStub()
2296 : fp_registers_(CanUseFPRegisters()) { }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002297
2298 private:
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002299 class FPRegisters: public BitField<bool, 0, 1> {};
2300
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002301 Major MajorKey() { return StoreArrayLiteralElement; }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002302 int MinorKey() { return FPRegisters::encode(fp_registers_); }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002303
2304 void Generate(MacroAssembler* masm);
2305
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002306 bool fp_registers_;
2307
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002308 DISALLOW_COPY_AND_ASSIGN(StoreArrayLiteralElementStub);
2309};
2310
verwaest@chromium.org753aee42012-07-17 16:15:42 +00002311
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00002312class StubFailureTrampolineStub : public PlatformCodeStub {
2313 public:
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00002314 explicit StubFailureTrampolineStub(StubFunctionMode function_mode)
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002315 : fp_registers_(CanUseFPRegisters()), function_mode_(function_mode) {}
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +00002316
dslomov@chromium.orge97852d2013-09-12 09:02:59 +00002317 virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE { return true; }
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +00002318
hpayer@chromium.org8432c912013-02-28 15:55:26 +00002319 static void GenerateAheadOfTime(Isolate* isolate);
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00002320
2321 private:
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002322 class FPRegisters: public BitField<bool, 0, 1> {};
2323 class FunctionModeField: public BitField<StubFunctionMode, 1, 1> {};
2324
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00002325 Major MajorKey() { return StubFailureTrampoline; }
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002326 int MinorKey() {
2327 return FPRegisters::encode(fp_registers_) |
2328 FunctionModeField::encode(function_mode_);
2329 }
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00002330
2331 void Generate(MacroAssembler* masm);
2332
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002333 bool fp_registers_;
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00002334 StubFunctionMode function_mode_;
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +00002335
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00002336 DISALLOW_COPY_AND_ASSIGN(StubFailureTrampolineStub);
2337};
2338
2339
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002340class ProfileEntryHookStub : public PlatformCodeStub {
verwaest@chromium.org753aee42012-07-17 16:15:42 +00002341 public:
2342 explicit ProfileEntryHookStub() {}
2343
2344 // The profile entry hook function is not allowed to cause a GC.
2345 virtual bool SometimesSetsUpAFrame() { return false; }
2346
2347 // Generates a call to the entry hook if it's enabled.
2348 static void MaybeCallEntryHook(MacroAssembler* masm);
2349
verwaest@chromium.org753aee42012-07-17 16:15:42 +00002350 private:
2351 static void EntryHookTrampoline(intptr_t function,
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +00002352 intptr_t stack_pointer,
2353 Isolate* isolate);
verwaest@chromium.org753aee42012-07-17 16:15:42 +00002354
2355 Major MajorKey() { return ProfileEntryHook; }
2356 int MinorKey() { return 0; }
2357
2358 void Generate(MacroAssembler* masm);
2359
verwaest@chromium.org753aee42012-07-17 16:15:42 +00002360 DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub);
2361};
2362
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002363} } // namespace v8::internal
2364
2365#endif // V8_CODE_STUBS_H_