blob: bb9ff78f47f0d42af112f1c9468ebb92ddca9873 [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"
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000033#include "codegen.h"
bmeurer@chromium.org0fdb2a62013-10-21 07:19:36 +000034#include "globals.h"
35#include "macro-assembler.h"
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000036
kasperl@chromium.org71affb52009-05-26 05:44:31 +000037namespace v8 {
38namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000039
ricow@chromium.orgc54d3652011-05-30 09:20:16 +000040// List of code stubs used on all platforms.
ager@chromium.orgc4c92722009-11-18 14:12:51 +000041#define CODE_STUB_LIST_ALL_PLATFORMS(V) \
42 V(CallFunction) \
danno@chromium.orgfa458e42012-02-01 10:48:36 +000043 V(CallConstruct) \
machenbach@chromium.orgce9c5142013-12-03 08:00:39 +000044 V(BinaryOpIC) \
ulan@chromium.org0f13e742014-01-03 15:51:11 +000045 V(BinaryOpICWithAllocationSite) \
46 V(BinaryOpWithAllocationSite) \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000047 V(StringAdd) \
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000048 V(NewStringAdd) \
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000049 V(SubString) \
50 V(StringCompare) \
ager@chromium.orgc4c92722009-11-18 14:12:51 +000051 V(Compare) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000052 V(CompareIC) \
danno@chromium.orgca29dd82013-04-26 11:59:48 +000053 V(CompareNilIC) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000054 V(MathPow) \
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +000055 V(StringLength) \
56 V(FunctionPrototype) \
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000057 V(StoreArrayLength) \
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000058 V(RecordWrite) \
59 V(StoreBufferOverflow) \
60 V(RegExpExec) \
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000061 V(Instanceof) \
ager@chromium.orgc4c92722009-11-18 14:12:51 +000062 V(ConvertToDouble) \
63 V(WriteInt32ToHeapNumber) \
64 V(StackCheck) \
yangguo@chromium.org56454712012-02-16 15:33:53 +000065 V(Interrupt) \
sgjesse@chromium.org846fb742009-12-18 08:56:33 +000066 V(FastNewClosure) \
67 V(FastNewContext) \
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +000068 V(FastNewBlockContext) \
sgjesse@chromium.org846fb742009-12-18 08:56:33 +000069 V(FastCloneShallowArray) \
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +000070 V(FastCloneShallowObject) \
danno@chromium.orgbee51992013-07-10 14:57:15 +000071 V(CreateAllocationSite) \
ager@chromium.orgc4c92722009-11-18 14:12:51 +000072 V(ToBoolean) \
whesse@chromium.org7a392b32011-01-31 11:30:36 +000073 V(ToNumber) \
ager@chromium.orgc4c92722009-11-18 14:12:51 +000074 V(ArgumentsAccess) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000075 V(RegExpConstructResult) \
ager@chromium.org5c838252010-02-19 08:53:10 +000076 V(NumberToString) \
danno@chromium.org169691d2013-07-15 08:01:13 +000077 V(DoubleToI) \
ager@chromium.orgc4c92722009-11-18 14:12:51 +000078 V(CEntry) \
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000079 V(JSEntry) \
sgjesse@chromium.org6db88712011-07-11 11:41:22 +000080 V(KeyedLoadElement) \
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000081 V(ArrayNoArgumentConstructor) \
82 V(ArraySingleArgumentConstructor) \
83 V(ArrayNArgumentsConstructor) \
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000084 V(InternalArrayNoArgumentConstructor) \
85 V(InternalArraySingleArgumentConstructor) \
86 V(InternalArrayNArgumentsConstructor) \
sgjesse@chromium.org6db88712011-07-11 11:41:22 +000087 V(KeyedStoreElement) \
lrn@chromium.org1c092762011-05-09 09:42:16 +000088 V(DebuggerStatement) \
ulan@chromium.org750145a2013-03-07 15:14:13 +000089 V(NameDictionaryLookup) \
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000090 V(ElementsTransitionAndStore) \
danno@chromium.org94b0d6f2013-02-04 13:33:20 +000091 V(TransitionElementsKind) \
verwaest@chromium.org753aee42012-07-17 16:15:42 +000092 V(StoreArrayLiteralElement) \
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +000093 V(StubFailureTrampoline) \
machenbach@chromium.orgea468882013-11-18 08:53:19 +000094 V(StubFailureTailCallTrampoline) \
danno@chromium.orgca29dd82013-04-26 11:59:48 +000095 V(ArrayConstructor) \
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000096 V(InternalArrayConstructor) \
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000097 V(ProfileEntryHook) \
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000098 V(StoreGlobal) \
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000099 /* IC Handler stubs */ \
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000100 V(LoadField) \
machenbach@chromium.orgea468882013-11-18 08:53:19 +0000101 V(KeyedLoadField) \
102 V(KeyedArrayCall)
ager@chromium.org3811b432009-10-28 14:53:37 +0000103
104// List of code stubs only used on ARM platforms.
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000105#if V8_TARGET_ARCH_ARM
ager@chromium.org3811b432009-10-28 14:53:37 +0000106#define CODE_STUB_LIST_ARM(V) \
107 V(GetProperty) \
108 V(SetProperty) \
109 V(InvokeBuiltin) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000110 V(DirectCEntry)
ager@chromium.org3811b432009-10-28 14:53:37 +0000111#else
112#define CODE_STUB_LIST_ARM(V)
113#endif
114
lrn@chromium.org7516f052011-03-30 08:52:27 +0000115// List of code stubs only used on MIPS platforms.
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000116#if V8_TARGET_ARCH_MIPS
lrn@chromium.org7516f052011-03-30 08:52:27 +0000117#define CODE_STUB_LIST_MIPS(V) \
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000118 V(RegExpCEntry) \
yangguo@chromium.org49546742013-12-23 16:17:49 +0000119 V(DirectCEntry) \
120 V(StoreRegistersState) \
121 V(RestoreRegistersState)
lrn@chromium.org7516f052011-03-30 08:52:27 +0000122#else
123#define CODE_STUB_LIST_MIPS(V)
124#endif
125
ager@chromium.org3811b432009-10-28 14:53:37 +0000126// Combined list of code stubs.
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000127#define CODE_STUB_LIST(V) \
128 CODE_STUB_LIST_ALL_PLATFORMS(V) \
lrn@chromium.org7516f052011-03-30 08:52:27 +0000129 CODE_STUB_LIST_ARM(V) \
130 CODE_STUB_LIST_MIPS(V)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000131
132// Stub is base classes of all stubs.
133class CodeStub BASE_EMBEDDED {
134 public:
135 enum Major {
jkummerow@chromium.org113035e2013-12-13 15:13:40 +0000136 UninitializedMajorKey = 0,
ager@chromium.org3811b432009-10-28 14:53:37 +0000137#define DEF_ENUM(name) name,
138 CODE_STUB_LIST(DEF_ENUM)
139#undef DEF_ENUM
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000140 NoCache, // marker for stubs that do custom caching
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000141 NUMBER_OF_IDS
142 };
143
144 // Retrieve the code for the stub. Generate the code if needed.
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000145 Handle<Code> GetCode(Isolate* isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000146
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000147 // Retrieve the code for the stub, make and return a copy of the code.
148 Handle<Code> GetCodeCopyFromTemplate(Isolate* isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000149 static Major MajorKeyFromKey(uint32_t key) {
150 return static_cast<Major>(MajorKeyBits::decode(key));
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000151 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000152 static int MinorKeyFromKey(uint32_t key) {
153 return MinorKeyBits::decode(key);
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000154 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000155
156 // Gets the major key from a code object that is a code stub or binary op IC.
157 static Major GetMajorKey(Code* code_stub) {
158 return static_cast<Major>(code_stub->major_key());
159 }
160
ager@chromium.org5c838252010-02-19 08:53:10 +0000161 static const char* MajorName(Major major_key, bool allow_unknown_keys);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000162
163 virtual ~CodeStub() {}
164
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000165 static void GenerateStubsAheadOfTime(Isolate* isolate);
machenbach@chromium.orgea468882013-11-18 08:53:19 +0000166 static void GenerateStubsRequiringBuiltinsAheadOfTime(Isolate* isolate);
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000167 static void GenerateFPStubs(Isolate* isolate);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000168
169 // Some stubs put untagged junk on the stack that cannot be scanned by the
170 // GC. This means that we must be statically sure that no GC can occur while
171 // they are running. If that is the case they should override this to return
172 // true, which will cause an assertion if we try to call something that can
173 // GC or if we try to put a stack frame on top of the junk, which would not
174 // result in a traversable stack.
175 virtual bool SometimesSetsUpAFrame() { return true; }
176
danno@chromium.orgc612e022011-11-10 11:38:15 +0000177 // Lookup the code in the (possibly custom) cache.
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000178 bool FindCodeInCache(Code** code_out, Isolate* isolate);
danno@chromium.orgc612e022011-11-10 11:38:15 +0000179
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000180 // Returns information for computing the number key.
181 virtual Major MajorKey() = 0;
182 virtual int MinorKey() = 0;
183
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000184 virtual InlineCacheState GetICState() {
185 return UNINITIALIZED;
186 }
yangguo@chromium.orgcc536052013-11-29 11:43:20 +0000187 virtual ExtraICState GetExtraICState() {
188 return kNoExtraICState;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000189 }
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000190 virtual Code::StubType GetStubType() {
191 return Code::NORMAL;
192 }
193 virtual int GetStubFlags() {
194 return -1;
195 }
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000196
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000197 virtual void PrintName(StringStream* stream);
198
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +0000199 // Returns a name for logging/debugging purposes.
200 SmartArrayPointer<const char> GetName();
201
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000202 protected:
203 static bool CanUseFPRegisters();
204
205 // Generates the assembler code for the stub.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000206 virtual Handle<Code> GenerateCode(Isolate* isolate) = 0;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000207
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +0000208 virtual void VerifyPlatformFeatures(Isolate* isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000209
210 // Returns whether the code generated for this stub needs to be allocated as
211 // a fixed (non-moveable) code object.
212 virtual bool NeedsImmovableCode() { return false; }
213
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000214 virtual void PrintBaseName(StringStream* stream);
215 virtual void PrintState(StringStream* stream) { }
216
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000217 private:
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000218 // Perform bookkeeping required after code generation when stub code is
219 // initially generated.
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000220 void RecordCodeGeneration(Code* code, Isolate* isolate);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000221
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000222 // Finish the code object after it has been generated.
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +0000223 virtual void FinishCode(Handle<Code> code) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000224
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000225 // Activate newly generated stub. Is called after
226 // registering stub in the stub cache.
227 virtual void Activate(Code* code) { }
228
danno@chromium.org40cb8782011-05-25 07:58:50 +0000229 // BinaryOpStub needs to override this.
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000230 virtual Code::Kind GetCodeKind() const;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000231
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000232 // Add the code to a specialized cache, specific to an individual
233 // stub type. Please note, this method must add the code object to a
234 // roots object, otherwise we will remove the code during GC.
235 virtual void AddToSpecialCache(Handle<Code> new_object) { }
236
237 // Find code in a specialized cache, work is delegated to the specific stub.
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000238 virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate) {
239 return false;
240 }
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000241
242 // If a stub uses a special cache override this.
243 virtual bool UseSpecialCache() { return false; }
244
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000245 // Computes the key based on major and minor.
246 uint32_t GetKey() {
247 ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
248 return MinorKeyBits::encode(MinorKey()) |
249 MajorKeyBits::encode(MajorKey());
250 }
251
jkummerow@chromium.org113035e2013-12-13 15:13:40 +0000252 STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
danno@chromium.org81cac2b2012-07-10 11:28:27 +0000253 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
254 class MinorKeyBits: public BitField<uint32_t,
255 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000256
257 friend class BreakPointIterator;
258};
259
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000260
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000261class PlatformCodeStub : public CodeStub {
262 public:
263 // Retrieve the code for the stub. Generate the code if needed.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000264 virtual Handle<Code> GenerateCode(Isolate* isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000265
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000266 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000267
268 protected:
269 // Generates the assembler code for the stub.
270 virtual void Generate(MacroAssembler* masm) = 0;
271};
272
273
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000274enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
machenbach@chromium.org0cc09502013-11-13 12:20:55 +0000275enum HandlerArgumentsMode { DONT_PASS_ARGUMENTS, PASS_ARGUMENTS };
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000276
machenbach@chromium.orgea468882013-11-18 08:53:19 +0000277enum ContinuationType { NORMAL_CONTINUATION, TAIL_CALL_CONTINUATION };
278
279
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_;
machenbach@chromium.org0cc09502013-11-13 12:20:55 +0000283
bmeurer@chromium.org0fdb2a62013-10-21 07:19:36 +0000284 Register stack_parameter_count_;
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000285 // if hint_stack_parameter_count_ > 0, the code stub can optimize the
286 // return sequence. Default value is -1, which means it is ignored.
287 int hint_stack_parameter_count_;
machenbach@chromium.orgea468882013-11-18 08:53:19 +0000288 ContinuationType continuation_type_;
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000289 StubFunctionMode function_mode_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000290 Register* register_params_;
machenbach@chromium.org0cc09502013-11-13 12:20:55 +0000291
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000292 Address deoptimization_handler_;
machenbach@chromium.org0cc09502013-11-13 12:20:55 +0000293 HandlerArgumentsMode handler_arguments_mode_;
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000294
machenbach@chromium.orgea468882013-11-18 08:53:19 +0000295 bool initialized() const { return register_param_count_ >= 0; }
296
297 bool HasTailCallContinuation() const {
298 return continuation_type_ == TAIL_CALL_CONTINUATION;
299 }
300
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000301 int environment_length() const {
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000302 return register_param_count_;
303 }
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000304
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000305 void SetMissHandler(ExternalReference handler) {
306 miss_handler_ = handler;
307 has_miss_handler_ = true;
machenbach@chromium.org0cc09502013-11-13 12:20:55 +0000308 // Our miss handler infrastructure doesn't currently support
309 // variable stack parameter counts.
310 ASSERT(!stack_parameter_count_.is_valid());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000311 }
312
313 ExternalReference miss_handler() {
314 ASSERT(has_miss_handler_);
315 return miss_handler_;
316 }
317
318 bool has_miss_handler() {
319 return has_miss_handler_;
320 }
321
machenbach@chromium.org0cc09502013-11-13 12:20:55 +0000322 Register GetParameterRegister(int index) {
323 return register_params_[index];
324 }
325
326 bool IsParameterCountRegister(int index) {
327 return GetParameterRegister(index).is(stack_parameter_count_);
328 }
329
330 int GetHandlerParameterCount() {
331 int params = environment_length();
332 if (handler_arguments_mode_ == PASS_ARGUMENTS) {
333 params += 1;
334 }
335 return params;
336 }
337
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000338 private:
339 ExternalReference miss_handler_;
340 bool has_miss_handler_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000341};
342
343
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000344class HydrogenCodeStub : public CodeStub {
345 public:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000346 enum InitializationState {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000347 UNINITIALIZED,
348 INITIALIZED
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000349 };
350
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000351 explicit HydrogenCodeStub(InitializationState state = INITIALIZED) {
352 is_uninitialized_ = (state == UNINITIALIZED);
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000353 }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000354
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000355 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000356
357 CodeStubInterfaceDescriptor* GetInterfaceDescriptor(Isolate* isolate) {
358 return isolate->code_stub_interface_descriptor(MajorKey());
359 }
360
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000361 bool IsUninitialized() { return is_uninitialized_; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000362
363 template<class SubClass>
364 static Handle<Code> GetUninitialized(Isolate* isolate) {
365 SubClass::GenerateAheadOfTime(isolate);
366 return SubClass().GetCode(isolate);
367 }
368
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000369 virtual void InitializeInterfaceDescriptor(
370 Isolate* isolate,
371 CodeStubInterfaceDescriptor* descriptor) = 0;
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000372
373 // Retrieve the code for the stub. Generate the code if needed.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000374 virtual Handle<Code> GenerateCode(Isolate* isolate) = 0;
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000375
376 virtual int NotMissMinorKey() = 0;
377
378 Handle<Code> GenerateLightweightMissCode(Isolate* isolate);
379
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000380 template<class StateType>
381 void TraceTransition(StateType from, StateType to);
382
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000383 private:
384 class MinorKeyBits: public BitField<int, 0, kStubMinorKeyBits - 1> {};
385 class IsMissBits: public BitField<bool, kStubMinorKeyBits - 1, 1> {};
386
387 void GenerateLightweightMiss(MacroAssembler* masm);
388 virtual int MinorKey() {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000389 return IsMissBits::encode(is_uninitialized_) |
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000390 MinorKeyBits::encode(NotMissMinorKey());
391 }
392
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000393 bool is_uninitialized_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000394};
395
396
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000397// Helper interface to prepare to/restore after making runtime calls.
398class RuntimeCallHelper {
399 public:
400 virtual ~RuntimeCallHelper() {}
401
402 virtual void BeforeCall(MacroAssembler* masm) const = 0;
403
404 virtual void AfterCall(MacroAssembler* masm) const = 0;
405
406 protected:
407 RuntimeCallHelper() {}
408
409 private:
410 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
411};
412
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +0000413
414// TODO(bmeurer): Move to the StringAddStub declaration once we're
415// done with the translation to a hydrogen code stub.
416enum StringAddFlags {
417 // Omit both parameter checks.
418 STRING_ADD_CHECK_NONE = 0,
419 // Check left parameter.
420 STRING_ADD_CHECK_LEFT = 1 << 0,
421 // Check right parameter.
422 STRING_ADD_CHECK_RIGHT = 1 << 1,
423 // Check both parameters.
bmeurer@chromium.orge94b5ff2013-10-25 09:22:31 +0000424 STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +0000425};
426
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000427} } // namespace v8::internal
428
429#if V8_TARGET_ARCH_IA32
430#include "ia32/code-stubs-ia32.h"
431#elif V8_TARGET_ARCH_X64
432#include "x64/code-stubs-x64.h"
433#elif V8_TARGET_ARCH_ARM
434#include "arm/code-stubs-arm.h"
435#elif V8_TARGET_ARCH_MIPS
436#include "mips/code-stubs-mips.h"
437#else
438#error Unsupported target architecture.
439#endif
440
441namespace v8 {
442namespace internal {
443
444
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000445// RuntimeCallHelper implementation used in stubs: enters/leaves a
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000446// newly created internal frame before/after the runtime call.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000447class StubRuntimeCallHelper : public RuntimeCallHelper {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000448 public:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000449 StubRuntimeCallHelper() {}
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000450
451 virtual void BeforeCall(MacroAssembler* masm) const;
452
453 virtual void AfterCall(MacroAssembler* masm) const;
454};
455
456
457// Trivial RuntimeCallHelper implementation.
458class NopRuntimeCallHelper : public RuntimeCallHelper {
459 public:
460 NopRuntimeCallHelper() {}
461
462 virtual void BeforeCall(MacroAssembler* masm) const {}
463
464 virtual void AfterCall(MacroAssembler* masm) const {}
465};
466
467
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000468class ToNumberStub: public HydrogenCodeStub {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000469 public:
470 ToNumberStub() { }
471
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000472 virtual Handle<Code> GenerateCode(Isolate* isolate);
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000473
474 virtual void InitializeInterfaceDescriptor(
475 Isolate* isolate,
476 CodeStubInterfaceDescriptor* descriptor);
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000477
478 private:
479 Major MajorKey() { return ToNumber; }
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000480 int NotMissMinorKey() { return 0; }
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000481};
482
483
machenbach@chromium.org3d079fe2013-09-25 08:19:55 +0000484class NumberToStringStub V8_FINAL : public HydrogenCodeStub {
485 public:
486 NumberToStringStub() {}
487
488 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
489
490 virtual void InitializeInterfaceDescriptor(
491 Isolate* isolate,
492 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
493
bmeurer@chromium.orge7a07452013-10-21 13:27:29 +0000494 static void InstallDescriptors(Isolate* isolate);
495
machenbach@chromium.org3d079fe2013-09-25 08:19:55 +0000496 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
497 static const int kNumber = 0;
498
499 private:
500 virtual Major MajorKey() V8_OVERRIDE { return NumberToString; }
501 virtual int NotMissMinorKey() V8_OVERRIDE { return 0; }
502};
503
504
verwaest@chromium.org662436e2013-08-28 08:41:27 +0000505class FastNewClosureStub : public HydrogenCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000506 public:
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000507 explicit FastNewClosureStub(LanguageMode language_mode, bool is_generator)
508 : language_mode_(language_mode),
509 is_generator_(is_generator) { }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000510
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000511 virtual Handle<Code> GenerateCode(Isolate* isolate);
verwaest@chromium.org662436e2013-08-28 08:41:27 +0000512
513 virtual void InitializeInterfaceDescriptor(
514 Isolate* isolate,
515 CodeStubInterfaceDescriptor* descriptor);
516
517 static void InstallDescriptors(Isolate* isolate);
518
519 LanguageMode language_mode() const { return language_mode_; }
520 bool is_generator() const { return is_generator_; }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000521
522 private:
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000523 class StrictModeBits: public BitField<bool, 0, 1> {};
524 class IsGeneratorBits: public BitField<bool, 1, 1> {};
525
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000526 Major MajorKey() { return FastNewClosure; }
verwaest@chromium.org662436e2013-08-28 08:41:27 +0000527 int NotMissMinorKey() {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000528 return StrictModeBits::encode(language_mode_ != CLASSIC_MODE) |
529 IsGeneratorBits::encode(is_generator_);
530 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000531
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000532 LanguageMode language_mode_;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000533 bool is_generator_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000534};
535
536
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000537class FastNewContextStub : public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000538 public:
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000539 static const int kMaximumSlots = 64;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000540
541 explicit FastNewContextStub(int slots) : slots_(slots) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000542 ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000543 }
544
545 void Generate(MacroAssembler* masm);
546
547 private:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000548 int slots_;
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000549
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000550 Major MajorKey() { return FastNewContext; }
551 int MinorKey() { return slots_; }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000552};
553
554
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000555class FastNewBlockContextStub : public PlatformCodeStub {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000556 public:
557 static const int kMaximumSlots = 64;
558
559 explicit FastNewBlockContextStub(int slots) : slots_(slots) {
560 ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
561 }
562
563 void Generate(MacroAssembler* masm);
564
565 private:
566 int slots_;
567
568 Major MajorKey() { return FastNewBlockContext; }
569 int MinorKey() { return slots_; }
570};
571
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000572class FastCloneShallowArrayStub : public HydrogenCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000573 public:
574 // Maximum length of copied elements array.
575 static const int kMaximumClonedLength = 8;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000576 enum Mode {
577 CLONE_ELEMENTS,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000578 CLONE_DOUBLE_ELEMENTS,
erikcorry0ad885c2011-11-21 13:51:57 +0000579 COPY_ON_WRITE_ELEMENTS,
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000580 CLONE_ANY_ELEMENTS,
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000581 LAST_CLONE_MODE = CLONE_ANY_ELEMENTS
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000582 };
583
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000584 static const int kFastCloneModeCount = LAST_CLONE_MODE + 1;
585
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000586 FastCloneShallowArrayStub(Mode mode,
587 AllocationSiteMode allocation_site_mode,
588 int length)
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000589 : mode_(mode),
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000590 allocation_site_mode_(allocation_site_mode),
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000591 length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000592 ASSERT_GE(length_, 0);
593 ASSERT_LE(length_, kMaximumClonedLength);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000594 }
595
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000596 Mode mode() const { return mode_; }
597 int length() const { return length_; }
598 AllocationSiteMode allocation_site_mode() const {
599 return allocation_site_mode_;
600 }
601
602 ElementsKind ComputeElementsKind() const {
603 switch (mode()) {
604 case CLONE_ELEMENTS:
605 case COPY_ON_WRITE_ELEMENTS:
606 return FAST_ELEMENTS;
607 case CLONE_DOUBLE_ELEMENTS:
608 return FAST_DOUBLE_ELEMENTS;
609 case CLONE_ANY_ELEMENTS:
610 /*fall-through*/;
611 }
612 UNREACHABLE();
613 return LAST_ELEMENTS_KIND;
614 }
615
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000616 virtual Handle<Code> GenerateCode(Isolate* isolate);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000617
618 virtual void InitializeInterfaceDescriptor(
619 Isolate* isolate,
620 CodeStubInterfaceDescriptor* descriptor);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000621
622 private:
623 Mode mode_;
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000624 AllocationSiteMode allocation_site_mode_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000625 int length_;
626
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000627 class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
628 class ModeBits: public BitField<Mode, 1, 4> {};
629 class LengthBits: public BitField<int, 5, 4> {};
630 // Ensure data fits within available bits.
631 STATIC_ASSERT(LAST_ALLOCATION_SITE_MODE == 1);
632 STATIC_ASSERT(kFastCloneModeCount < 16);
633 STATIC_ASSERT(kMaximumClonedLength < 16);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000634 Major MajorKey() { return FastCloneShallowArray; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000635 int NotMissMinorKey() {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000636 return AllocationSiteModeBits::encode(allocation_site_mode_)
637 | ModeBits::encode(mode_)
638 | LengthBits::encode(length_);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000639 }
640};
641
642
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000643class FastCloneShallowObjectStub : public HydrogenCodeStub {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000644 public:
645 // Maximum number of properties in copied object.
646 static const int kMaximumClonedProperties = 6;
647
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000648 explicit FastCloneShallowObjectStub(int length)
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000649 : length_(length) {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000650 ASSERT_GE(length_, 0);
651 ASSERT_LE(length_, kMaximumClonedProperties);
652 }
653
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000654 int length() const { return length_; }
655
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000656 virtual Handle<Code> GenerateCode(Isolate* isolate);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000657
658 virtual void InitializeInterfaceDescriptor(
659 Isolate* isolate,
660 CodeStubInterfaceDescriptor* descriptor);
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000661
662 private:
663 int length_;
664
665 Major MajorKey() { return FastCloneShallowObject; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000666 int NotMissMinorKey() { return length_; }
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000667
668 DISALLOW_COPY_AND_ASSIGN(FastCloneShallowObjectStub);
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000669};
670
671
danno@chromium.orgbee51992013-07-10 14:57:15 +0000672class CreateAllocationSiteStub : public HydrogenCodeStub {
673 public:
674 explicit CreateAllocationSiteStub() { }
675
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000676 virtual Handle<Code> GenerateCode(Isolate* isolate);
danno@chromium.orgbee51992013-07-10 14:57:15 +0000677
danno@chromium.orgbee51992013-07-10 14:57:15 +0000678 static void GenerateAheadOfTime(Isolate* isolate);
679
680 virtual void InitializeInterfaceDescriptor(
681 Isolate* isolate,
682 CodeStubInterfaceDescriptor* descriptor);
683
684 private:
685 Major MajorKey() { return CreateAllocationSite; }
686 int NotMissMinorKey() { return 0; }
687
688 DISALLOW_COPY_AND_ASSIGN(CreateAllocationSiteStub);
689};
690
691
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000692class InstanceofStub: public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000693 public:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000694 enum Flags {
695 kNoFlags = 0,
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000696 kArgsInRegisters = 1 << 0,
697 kCallSiteInlineCheck = 1 << 1,
698 kReturnTrueFalseObject = 1 << 2
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000699 };
700
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000701 explicit InstanceofStub(Flags flags) : flags_(flags) { }
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000702
703 static Register left();
704 static Register right();
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000705
706 void Generate(MacroAssembler* masm);
707
708 private:
709 Major MajorKey() { return Instanceof; }
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000710 int MinorKey() { return static_cast<int>(flags_); }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000711
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000712 bool HasArgsInRegisters() const {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000713 return (flags_ & kArgsInRegisters) != 0;
714 }
715
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000716 bool HasCallSiteInlineCheck() const {
717 return (flags_ & kCallSiteInlineCheck) != 0;
718 }
719
720 bool ReturnTrueFalseObject() const {
721 return (flags_ & kReturnTrueFalseObject) != 0;
722 }
723
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000724 virtual void PrintName(StringStream* stream);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000725
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000726 Flags flags_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000727};
728
729
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000730enum AllocationSiteOverrideMode {
731 DONT_OVERRIDE,
732 DISABLE_ALLOCATION_SITES,
733 LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
734};
735
736
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000737class ArrayConstructorStub: public PlatformCodeStub {
738 public:
739 enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
740 ArrayConstructorStub(Isolate* isolate, int argument_count);
741 explicit ArrayConstructorStub(Isolate* isolate);
742
743 void Generate(MacroAssembler* masm);
744
745 private:
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000746 void GenerateDispatchToArrayStub(MacroAssembler* masm,
747 AllocationSiteOverrideMode mode);
hpayer@chromium.org71ea97f2013-12-19 16:03:26 +0000748 virtual void PrintName(StringStream* stream);
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000749
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000750 virtual CodeStub::Major MajorKey() { return ArrayConstructor; }
751 virtual int MinorKey() { return argument_count_; }
752
753 ArgumentCountKey argument_count_;
754};
755
756
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000757class InternalArrayConstructorStub: public PlatformCodeStub {
758 public:
759 explicit InternalArrayConstructorStub(Isolate* isolate);
760
761 void Generate(MacroAssembler* masm);
762
763 private:
764 virtual CodeStub::Major MajorKey() { return InternalArrayConstructor; }
765 virtual int MinorKey() { return 0; }
766
767 void GenerateCase(MacroAssembler* masm, ElementsKind kind);
768};
769
770
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000771class MathPowStub: public PlatformCodeStub {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000772 public:
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000773 enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK };
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000774
775 explicit MathPowStub(ExponentType exponent_type)
776 : exponent_type_(exponent_type) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000777 virtual void Generate(MacroAssembler* masm);
778
779 private:
780 virtual CodeStub::Major MajorKey() { return MathPow; }
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000781 virtual int MinorKey() { return exponent_type_; }
782
783 ExponentType exponent_type_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000784};
785
786
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000787class ICStub: public PlatformCodeStub {
788 public:
789 explicit ICStub(Code::Kind kind) : kind_(kind) { }
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000790 virtual Code::Kind GetCodeKind() const { return kind_; }
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000791 virtual InlineCacheState GetICState() { return MONOMORPHIC; }
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000792
793 bool Describes(Code* code) {
794 return GetMajorKey(code) == MajorKey() && code->stub_info() == MinorKey();
795 }
796
797 protected:
798 class KindBits: public BitField<Code::Kind, 0, 4> {};
799 virtual void FinishCode(Handle<Code> code) {
800 code->set_stub_info(MinorKey());
801 }
802 Code::Kind kind() { return kind_; }
803
804 virtual int MinorKey() {
805 return KindBits::encode(kind_);
806 }
807
808 private:
809 Code::Kind kind_;
810};
811
812
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000813class FunctionPrototypeStub: public ICStub {
814 public:
815 explicit FunctionPrototypeStub(Code::Kind kind) : ICStub(kind) { }
816 virtual void Generate(MacroAssembler* masm);
817
818 private:
819 virtual CodeStub::Major MajorKey() { return FunctionPrototype; }
820};
821
822
823class StringLengthStub: public ICStub {
824 public:
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000825 explicit StringLengthStub(Code::Kind kind) : ICStub(kind) { }
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000826 virtual void Generate(MacroAssembler* masm);
827
828 private:
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000829 STATIC_ASSERT(KindBits::kSize == 4);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000830 virtual CodeStub::Major MajorKey() { return StringLength; }
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000831};
832
833
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000834class StoreICStub: public ICStub {
835 public:
836 StoreICStub(Code::Kind kind, StrictModeFlag strict_mode)
837 : ICStub(kind), strict_mode_(strict_mode) { }
838
839 protected:
yangguo@chromium.orgcc536052013-11-29 11:43:20 +0000840 virtual ExtraICState GetExtraICState() {
841 return StoreIC::ComputeExtraICState(strict_mode_);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000842 }
843
844 private:
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000845 STATIC_ASSERT(KindBits::kSize == 4);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000846 class StrictModeBits: public BitField<bool, 4, 1> {};
847 virtual int MinorKey() {
848 return KindBits::encode(kind()) | StrictModeBits::encode(strict_mode_);
849 }
850
851 StrictModeFlag strict_mode_;
852};
853
854
855class StoreArrayLengthStub: public StoreICStub {
856 public:
857 explicit StoreArrayLengthStub(Code::Kind kind, StrictModeFlag strict_mode)
858 : StoreICStub(kind, strict_mode) { }
859 virtual void Generate(MacroAssembler* masm);
860
861 private:
862 virtual CodeStub::Major MajorKey() { return StoreArrayLength; }
863};
864
865
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000866class HICStub: public HydrogenCodeStub {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000867 public:
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000868 virtual Code::Kind GetCodeKind() const { return kind(); }
869 virtual InlineCacheState GetICState() { return MONOMORPHIC; }
870
871 protected:
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000872 class KindBits: public BitField<Code::Kind, 0, 4> {};
873 virtual Code::Kind kind() const = 0;
874};
875
876
877class HandlerStub: public HICStub {
878 public:
jkummerow@chromium.org32aa03c2013-10-01 08:21:50 +0000879 virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
ulan@chromium.org750145a2013-03-07 15:14:13 +0000880 virtual int GetStubFlags() { return kind(); }
machenbach@chromium.orgea468882013-11-18 08:53:19 +0000881
882 protected:
883 HandlerStub() : HICStub() { }
884 virtual int NotMissMinorKey() { return bit_field_; }
885 int bit_field_;
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000886};
887
888
889class LoadFieldStub: public HandlerStub {
890 public:
machenbach@chromium.orge8412be2013-11-08 10:23:52 +0000891 LoadFieldStub(bool inobject, int index, Representation representation) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000892 Initialize(Code::LOAD_IC, inobject, index, representation);
893 }
894
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000895 virtual Handle<Code> GenerateCode(Isolate* isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000896
897 virtual void InitializeInterfaceDescriptor(
898 Isolate* isolate,
899 CodeStubInterfaceDescriptor* descriptor);
900
901 Representation representation() {
902 if (unboxed_double()) return Representation::Double();
903 return Representation::Tagged();
904 }
905
906 virtual Code::Kind kind() const {
907 return KindBits::decode(bit_field_);
908 }
909
910 bool is_inobject() {
911 return InobjectBits::decode(bit_field_);
912 }
913
914 int offset() {
915 int index = IndexBits::decode(bit_field_);
916 int offset = index * kPointerSize;
917 if (is_inobject()) return offset;
918 return FixedArray::kHeaderSize + offset;
919 }
920
921 bool unboxed_double() {
922 return UnboxedDoubleBits::decode(bit_field_);
923 }
924
machenbach@chromium.org9af454f2013-11-20 09:25:57 +0000925 virtual Code::StubType GetStubType() { return Code::FAST; }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000926
927 protected:
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000928 LoadFieldStub() : HandlerStub() { }
929
930 void Initialize(Code::Kind kind,
931 bool inobject,
932 int index,
933 Representation representation) {
934 bool unboxed_double = FLAG_track_double_fields && representation.IsDouble();
935 bit_field_ = KindBits::encode(kind)
936 | InobjectBits::encode(inobject)
937 | IndexBits::encode(index)
938 | UnboxedDoubleBits::encode(unboxed_double);
939 }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000940
941 private:
942 STATIC_ASSERT(KindBits::kSize == 4);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000943 class InobjectBits: public BitField<bool, 4, 1> {};
944 class IndexBits: public BitField<int, 5, 11> {};
945 class UnboxedDoubleBits: public BitField<bool, 16, 1> {};
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000946 virtual CodeStub::Major MajorKey() { return LoadField; }
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000947};
948
949
machenbach@chromium.orge8412be2013-11-08 10:23:52 +0000950class StoreGlobalStub : public HandlerStub {
951 public:
machenbach@chromium.orgc86e8c22013-11-27 15:11:04 +0000952 explicit StoreGlobalStub(bool is_constant) {
953 bit_field_ = IsConstantBits::encode(is_constant);
machenbach@chromium.orge8412be2013-11-08 10:23:52 +0000954 }
955
956 Handle<Code> GetCodeCopyFromTemplate(Isolate* isolate,
957 Map* receiver_map,
958 PropertyCell* cell) {
959 Handle<Code> code = CodeStub::GetCodeCopyFromTemplate(isolate);
960 // Replace the placeholder cell and global object map with the actual global
961 // cell and receiver map.
962 Map* cell_map = isolate->heap()->global_property_cell_map();
963 code->ReplaceNthObject(1, cell_map, cell);
964 code->ReplaceNthObject(1, isolate->heap()->meta_map(), receiver_map);
965 return code;
966 }
967
968 virtual Code::Kind kind() const { return Code::STORE_IC; }
969
970 virtual Handle<Code> GenerateCode(Isolate* isolate);
971
972 virtual void InitializeInterfaceDescriptor(
973 Isolate* isolate,
974 CodeStubInterfaceDescriptor* descriptor);
975
yangguo@chromium.orgcc536052013-11-29 11:43:20 +0000976 virtual ExtraICState GetExtraICState() { return bit_field_; }
machenbach@chromium.orge8412be2013-11-08 10:23:52 +0000977
978 bool is_constant() {
979 return IsConstantBits::decode(bit_field_);
980 }
981 void set_is_constant(bool value) {
982 bit_field_ = IsConstantBits::update(bit_field_, value);
983 }
984
985 Representation representation() {
986 return Representation::FromKind(RepresentationBits::decode(bit_field_));
987 }
988 void set_representation(Representation r) {
989 bit_field_ = RepresentationBits::update(bit_field_, r.kind());
990 }
991
992 private:
993 virtual int NotMissMinorKey() { return GetExtraICState(); }
994 Major MajorKey() { return StoreGlobal; }
995
machenbach@chromium.orgc86e8c22013-11-27 15:11:04 +0000996 class IsConstantBits: public BitField<bool, 0, 1> {};
997 class RepresentationBits: public BitField<Representation::Kind, 1, 8> {};
machenbach@chromium.orge8412be2013-11-08 10:23:52 +0000998
999 int bit_field_;
1000
1001 DISALLOW_COPY_AND_ASSIGN(StoreGlobalStub);
1002};
1003
1004
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001005class KeyedLoadFieldStub: public LoadFieldStub {
1006 public:
1007 KeyedLoadFieldStub(bool inobject, int index, Representation representation)
1008 : LoadFieldStub() {
1009 Initialize(Code::KEYED_LOAD_IC, inobject, index, representation);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001010 }
1011
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001012 virtual void InitializeInterfaceDescriptor(
1013 Isolate* isolate,
1014 CodeStubInterfaceDescriptor* descriptor);
1015
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00001016 virtual Handle<Code> GenerateCode(Isolate* isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001017
1018 private:
1019 virtual CodeStub::Major MajorKey() { return KeyedLoadField; }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001020};
1021
1022
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001023class KeyedArrayCallStub: public HICStub {
1024 public:
1025 KeyedArrayCallStub(bool holey, int argc) : HICStub(), argc_(argc) {
1026 bit_field_ = ContextualBits::encode(false) | HoleyBits::encode(holey);
1027 }
1028
1029 virtual Code::Kind kind() const { return Code::KEYED_CALL_IC; }
yangguo@chromium.orgcc536052013-11-29 11:43:20 +00001030 virtual ExtraICState GetExtraICState() { return bit_field_; }
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001031
1032 ElementsKind elements_kind() {
1033 return HoleyBits::decode(bit_field_) ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS;
1034 }
1035
1036 int argc() { return argc_; }
1037 virtual int GetStubFlags() { return argc(); }
1038
1039 static bool IsHoley(Handle<Code> code) {
yangguo@chromium.orgcc536052013-11-29 11:43:20 +00001040 ExtraICState state = code->extra_ic_state();
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001041 return HoleyBits::decode(state);
1042 }
1043
1044 virtual void InitializeInterfaceDescriptor(
1045 Isolate* isolate,
1046 CodeStubInterfaceDescriptor* descriptor);
1047
1048 virtual Handle<Code> GenerateCode(Isolate* isolate);
1049
1050 private:
1051 virtual int NotMissMinorKey() {
1052 return GetExtraICState() | ArgcBits::encode(argc_);
1053 }
1054
1055 class ContextualBits: public BitField<bool, 0, 1> {};
1056 STATIC_ASSERT(CallICBase::Contextual::kShift == ContextualBits::kShift);
1057 STATIC_ASSERT(CallICBase::Contextual::kSize == ContextualBits::kSize);
1058 class HoleyBits: public BitField<bool, 1, 1> {};
1059 STATIC_ASSERT(Code::kArgumentsBits <= kStubMinorKeyBits - 2);
1060 class ArgcBits: public BitField<int, 2, Code::kArgumentsBits> {};
1061 virtual CodeStub::Major MajorKey() { return KeyedArrayCall; }
1062 int bit_field_;
1063 int argc_;
1064};
1065
1066
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001067class BinaryOpICStub : public HydrogenCodeStub {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001068 public:
machenbach@chromium.orgce9c5142013-12-03 08:00:39 +00001069 BinaryOpICStub(Token::Value op, OverwriteMode mode)
1070 : HydrogenCodeStub(UNINITIALIZED), state_(op, mode) {}
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001071
machenbach@chromium.orgce9c5142013-12-03 08:00:39 +00001072 explicit BinaryOpICStub(const BinaryOpIC::State& state) : state_(state) {}
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +00001073
1074 static void GenerateAheadOfTime(Isolate* isolate);
machenbach@chromium.orgce9c5142013-12-03 08:00:39 +00001075
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +00001076 virtual void InitializeInterfaceDescriptor(
machenbach@chromium.orgce9c5142013-12-03 08:00:39 +00001077 Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1078
1079 static void InstallDescriptors(Isolate* isolate);
1080
1081 virtual Code::Kind GetCodeKind() const V8_OVERRIDE {
1082 return Code::BINARY_OP_IC;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001083 }
1084
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001085 virtual InlineCacheState GetICState() V8_FINAL V8_OVERRIDE {
1086 return state_.GetICState();
1087 }
1088
1089 virtual ExtraICState GetExtraICState() V8_FINAL V8_OVERRIDE {
1090 return state_.GetExtraICState();
1091 }
1092
1093 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_FINAL V8_OVERRIDE {
1094 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1095 }
1096
1097 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
1098
1099 const BinaryOpIC::State& state() const { return state_; }
1100
1101 virtual void PrintState(StringStream* stream) V8_FINAL V8_OVERRIDE;
1102
1103 virtual Major MajorKey() V8_OVERRIDE { return BinaryOpIC; }
1104 virtual int NotMissMinorKey() V8_FINAL V8_OVERRIDE {
1105 return GetExtraICState();
1106 }
1107
1108 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1109 static const int kLeft = 0;
1110 static const int kRight = 1;
1111
1112 private:
1113 static void GenerateAheadOfTime(Isolate* isolate,
1114 const BinaryOpIC::State& state);
1115
1116 BinaryOpIC::State state_;
1117
1118 DISALLOW_COPY_AND_ASSIGN(BinaryOpICStub);
1119};
1120
1121
1122// TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
1123// call support for stubs in Hydrogen.
1124class BinaryOpICWithAllocationSiteStub V8_FINAL : public PlatformCodeStub {
1125 public:
1126 explicit BinaryOpICWithAllocationSiteStub(const BinaryOpIC::State& state)
1127 : state_(state) {}
1128
1129 static void GenerateAheadOfTime(Isolate* isolate);
1130
1131 Handle<Code> GetCodeCopyFromTemplate(Isolate* isolate,
1132 Handle<AllocationSite> allocation_site) {
1133 Handle<Code> code = CodeStub::GetCodeCopyFromTemplate(isolate);
1134 // Replace the placeholder oddball with the actual allocation site.
1135 code->ReplaceNthObject(1, isolate->heap()->oddball_map(), *allocation_site);
1136 return code;
1137 }
1138
1139 virtual Code::Kind GetCodeKind() const V8_OVERRIDE {
1140 return Code::BINARY_OP_IC;
1141 }
1142
machenbach@chromium.orgce9c5142013-12-03 08:00:39 +00001143 virtual InlineCacheState GetICState() V8_OVERRIDE {
1144 return state_.GetICState();
1145 }
1146
1147 virtual ExtraICState GetExtraICState() V8_OVERRIDE {
1148 return state_.GetExtraICState();
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001149 }
1150
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +00001151 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
1152 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1153 }
1154
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001155 virtual void Generate(MacroAssembler* masm) V8_OVERRIDE;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001156
machenbach@chromium.orgce9c5142013-12-03 08:00:39 +00001157 virtual void PrintState(StringStream* stream) V8_OVERRIDE;
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +00001158
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001159 virtual Major MajorKey() V8_OVERRIDE { return BinaryOpICWithAllocationSite; }
1160 virtual int MinorKey() V8_OVERRIDE { return GetExtraICState(); }
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +00001161
1162 private:
machenbach@chromium.orgce9c5142013-12-03 08:00:39 +00001163 static void GenerateAheadOfTime(Isolate* isolate,
1164 const BinaryOpIC::State& state);
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +00001165
machenbach@chromium.orgce9c5142013-12-03 08:00:39 +00001166 BinaryOpIC::State state_;
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +00001167
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001168 DISALLOW_COPY_AND_ASSIGN(BinaryOpICWithAllocationSiteStub);
1169};
1170
1171
1172class BinaryOpWithAllocationSiteStub V8_FINAL : public BinaryOpICStub {
1173 public:
1174 explicit BinaryOpWithAllocationSiteStub(const BinaryOpIC::State& state)
1175 : BinaryOpICStub(state) {}
1176
1177 virtual void InitializeInterfaceDescriptor(
1178 Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1179
1180 static void InstallDescriptors(Isolate* isolate);
1181
1182 virtual Code::Kind GetCodeKind() const V8_FINAL V8_OVERRIDE {
1183 return Code::STUB;
1184 }
1185
1186 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
1187
1188 virtual Major MajorKey() V8_OVERRIDE {
1189 return BinaryOpWithAllocationSite;
1190 }
1191
1192 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1193 static const int kAllocationSite = 0;
1194 static const int kLeft = 1;
1195 static const int kRight = 2;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001196};
1197
1198
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00001199// TODO(bmeurer): Rename to StringAddStub once we dropped the old StringAddStub.
1200class NewStringAddStub V8_FINAL : public HydrogenCodeStub {
1201 public:
1202 NewStringAddStub(StringAddFlags flags, PretenureFlag pretenure_flag)
1203 : bit_field_(StringAddFlagsBits::encode(flags) |
1204 PretenureFlagBits::encode(pretenure_flag)) {}
1205
1206 StringAddFlags flags() const {
1207 return StringAddFlagsBits::decode(bit_field_);
1208 }
1209
1210 PretenureFlag pretenure_flag() const {
1211 return PretenureFlagBits::decode(bit_field_);
1212 }
1213
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001214 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
1215 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1216 }
1217
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00001218 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
1219
1220 virtual void InitializeInterfaceDescriptor(
1221 Isolate* isolate,
1222 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1223
1224 static void InstallDescriptors(Isolate* isolate);
1225
1226 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1227 static const int kLeft = 0;
1228 static const int kRight = 1;
1229
1230 private:
1231 class StringAddFlagsBits: public BitField<StringAddFlags, 0, 2> {};
1232 class PretenureFlagBits: public BitField<PretenureFlag, 2, 1> {};
1233 uint32_t bit_field_;
1234
1235 virtual Major MajorKey() V8_OVERRIDE { return NewStringAdd; }
1236 virtual int NotMissMinorKey() V8_OVERRIDE { return bit_field_; }
1237
1238 virtual void PrintBaseName(StringStream* stream) V8_OVERRIDE;
1239
1240 DISALLOW_COPY_AND_ASSIGN(NewStringAddStub);
1241};
1242
1243
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001244class ICCompareStub: public PlatformCodeStub {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001245 public:
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001246 ICCompareStub(Token::Value op,
1247 CompareIC::State left,
1248 CompareIC::State right,
1249 CompareIC::State handler)
1250 : op_(op),
1251 left_(left),
1252 right_(right),
1253 state_(handler) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001254 ASSERT(Token::IsCompareOp(op));
1255 }
1256
1257 virtual void Generate(MacroAssembler* masm);
1258
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001259 void set_known_map(Handle<Map> map) { known_map_ = map; }
1260
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001261 static void DecodeMinorKey(int minor_key,
1262 CompareIC::State* left_state,
1263 CompareIC::State* right_state,
1264 CompareIC::State* handler_state,
1265 Token::Value* op);
1266
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001267 virtual InlineCacheState GetICState();
1268
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001269 private:
1270 class OpField: public BitField<int, 0, 3> { };
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001271 class LeftStateField: public BitField<int, 3, 4> { };
1272 class RightStateField: public BitField<int, 7, 4> { };
1273 class HandlerStateField: public BitField<int, 11, 4> { };
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001274
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +00001275 virtual void FinishCode(Handle<Code> code) {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001276 code->set_stub_info(MinorKey());
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +00001277 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001278
1279 virtual CodeStub::Major MajorKey() { return CompareIC; }
1280 virtual int MinorKey();
1281
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001282 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_IC; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001283
1284 void GenerateSmis(MacroAssembler* masm);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001285 void GenerateNumbers(MacroAssembler* masm);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001286 void GenerateInternalizedStrings(MacroAssembler* masm);
lrn@chromium.org1c092762011-05-09 09:42:16 +00001287 void GenerateStrings(MacroAssembler* masm);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001288 void GenerateUniqueNames(MacroAssembler* masm);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001289 void GenerateObjects(MacroAssembler* masm);
1290 void GenerateMiss(MacroAssembler* masm);
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001291 void GenerateKnownObjects(MacroAssembler* masm);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001292 void GenerateGeneric(MacroAssembler* masm);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001293
1294 bool strict() const { return op_ == Token::EQ_STRICT; }
1295 Condition GetCondition() const { return CompareIC::ComputeCondition(op_); }
1296
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001297 virtual void AddToSpecialCache(Handle<Code> new_object);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00001298 virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001299 virtual bool UseSpecialCache() { return state_ == CompareIC::KNOWN_OBJECT; }
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001300
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001301 Token::Value op_;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001302 CompareIC::State left_;
1303 CompareIC::State right_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001304 CompareIC::State state_;
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001305 Handle<Map> known_map_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001306};
1307
1308
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001309class CompareNilICStub : public HydrogenCodeStub {
1310 public:
danno@chromium.org169691d2013-07-15 08:01:13 +00001311 Handle<Type> GetType(Isolate* isolate, Handle<Map> map = Handle<Map>());
1312 Handle<Type> GetInputType(Isolate* isolate, Handle<Map> map);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001313
danno@chromium.org169691d2013-07-15 08:01:13 +00001314 explicit CompareNilICStub(NilValue nil) : nil_value_(nil) { }
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001315
yangguo@chromium.orgcc536052013-11-29 11:43:20 +00001316 CompareNilICStub(ExtraICState ic_state,
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001317 InitializationState init_state = INITIALIZED)
danno@chromium.org169691d2013-07-15 08:01:13 +00001318 : HydrogenCodeStub(init_state),
1319 nil_value_(NilValueField::decode(ic_state)),
1320 state_(State(TypesField::decode(ic_state))) {
1321 }
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001322
1323 static Handle<Code> GetUninitialized(Isolate* isolate,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001324 NilValue nil) {
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001325 return CompareNilICStub(nil, UNINITIALIZED).GetCode(isolate);
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001326 }
1327
1328 virtual void InitializeInterfaceDescriptor(
1329 Isolate* isolate,
1330 CodeStubInterfaceDescriptor* descriptor);
1331
1332 static void InitializeForIsolate(Isolate* isolate) {
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001333 CompareNilICStub compare_stub(kNullValue, UNINITIALIZED);
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001334 compare_stub.InitializeInterfaceDescriptor(
1335 isolate,
1336 isolate->code_stub_interface_descriptor(CodeStub::CompareNilIC));
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001337 }
1338
1339 virtual InlineCacheState GetICState() {
danno@chromium.org169691d2013-07-15 08:01:13 +00001340 if (state_.Contains(GENERIC)) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001341 return MEGAMORPHIC;
danno@chromium.org41728482013-06-12 22:31:22 +00001342 } else if (state_.Contains(MONOMORPHIC_MAP)) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001343 return MONOMORPHIC;
1344 } else {
1345 return PREMONOMORPHIC;
1346 }
1347 }
1348
1349 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_NIL_IC; }
1350
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00001351 virtual Handle<Code> GenerateCode(Isolate* isolate);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001352
yangguo@chromium.orgcc536052013-11-29 11:43:20 +00001353 virtual ExtraICState GetExtraICState() {
danno@chromium.org169691d2013-07-15 08:01:13 +00001354 return NilValueField::encode(nil_value_) |
1355 TypesField::encode(state_.ToIntegral());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001356 }
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001357
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001358 void UpdateStatus(Handle<Object> object);
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001359
danno@chromium.org41728482013-06-12 22:31:22 +00001360 bool IsMonomorphic() const { return state_.Contains(MONOMORPHIC_MAP); }
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001361 NilValue GetNilValue() const { return nil_value_; }
danno@chromium.org41728482013-06-12 22:31:22 +00001362 void ClearState() { state_.RemoveAll(); }
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001363
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001364 virtual void PrintState(StringStream* stream);
1365 virtual void PrintBaseName(StringStream* stream);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001366
1367 private:
1368 friend class CompareNilIC;
1369
danno@chromium.org169691d2013-07-15 08:01:13 +00001370 enum CompareNilType {
1371 UNDEFINED,
1372 NULL_TYPE,
1373 MONOMORPHIC_MAP,
1374 GENERIC,
1375 NUMBER_OF_TYPES
1376 };
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001377
danno@chromium.org169691d2013-07-15 08:01:13 +00001378 // At most 6 different types can be distinguished, because the Code object
1379 // only has room for a single byte to hold a set and there are two more
1380 // boolean flags we need to store. :-P
1381 STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
1382
1383 class State : public EnumSet<CompareNilType, byte> {
1384 public:
1385 State() : EnumSet<CompareNilType, byte>(0) { }
1386 explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
1387
1388 void Print(StringStream* stream) const;
1389 };
1390
1391 CompareNilICStub(NilValue nil, InitializationState init_state)
1392 : HydrogenCodeStub(init_state), nil_value_(nil) { }
1393
1394 class NilValueField : public BitField<NilValue, 0, 1> {};
1395 class TypesField : public BitField<byte, 1, NUMBER_OF_TYPES> {};
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001396
1397 virtual CodeStub::Major MajorKey() { return CompareNilIC; }
1398 virtual int NotMissMinorKey() { return GetExtraICState(); }
1399
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001400 NilValue nil_value_;
danno@chromium.org41728482013-06-12 22:31:22 +00001401 State state_;
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001402
1403 DISALLOW_COPY_AND_ASSIGN(CompareNilICStub);
1404};
1405
1406
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001407class CEntryStub : public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001408 public:
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001409 explicit CEntryStub(int result_size,
1410 SaveFPRegsMode save_doubles = kDontSaveFPRegs)
1411 : result_size_(result_size), save_doubles_(save_doubles) { }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001412
1413 void Generate(MacroAssembler* masm);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001414
1415 // The version of this stub that doesn't save doubles is generated ahead of
1416 // time, so it's OK to call it from other stubs that can't cope with GC during
1417 // their code generation. On machines that always have gp registers (x64) we
1418 // can generate both variants ahead of time.
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001419 static void GenerateAheadOfTime(Isolate* isolate);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001420
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +00001421 protected:
1422 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
1423 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1424 };
1425
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001426 private:
1427 void GenerateCore(MacroAssembler* masm,
1428 Label* throw_normal_exception,
1429 Label* throw_termination_exception,
1430 Label* throw_out_of_memory_exception,
1431 bool do_gc,
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001432 bool always_allocate_scope);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001433
1434 // Number of pointers/values returned.
dslomov@chromium.orge97852d2013-09-12 09:02:59 +00001435 Isolate* isolate_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001436 const int result_size_;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001437 SaveFPRegsMode save_doubles_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001438
1439 Major MajorKey() { return CEntry; }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001440 int MinorKey();
1441
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001442 bool NeedsImmovableCode();
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001443};
1444
1445
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001446class JSEntryStub : public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001447 public:
1448 JSEntryStub() { }
1449
1450 void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
1451
1452 protected:
1453 void GenerateBody(MacroAssembler* masm, bool is_construct);
1454
1455 private:
1456 Major MajorKey() { return JSEntry; }
1457 int MinorKey() { return 0; }
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +00001458
1459 virtual void FinishCode(Handle<Code> code);
1460
1461 int handler_offset_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001462};
1463
1464
1465class JSConstructEntryStub : public JSEntryStub {
1466 public:
1467 JSConstructEntryStub() { }
1468
1469 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
1470
1471 private:
1472 int MinorKey() { return 1; }
1473
whesse@chromium.org030d38e2011-07-13 13:23:34 +00001474 virtual void PrintName(StringStream* stream) {
1475 stream->Add("JSConstructEntryStub");
1476 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001477};
1478
1479
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001480class ArgumentsAccessStub: public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001481 public:
1482 enum Type {
1483 READ_ELEMENT,
whesse@chromium.org7b260152011-06-20 15:33:18 +00001484 NEW_NON_STRICT_FAST,
1485 NEW_NON_STRICT_SLOW,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001486 NEW_STRICT
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001487 };
1488
1489 explicit ArgumentsAccessStub(Type type) : type_(type) { }
1490
1491 private:
1492 Type type_;
1493
1494 Major MajorKey() { return ArgumentsAccess; }
1495 int MinorKey() { return type_; }
1496
1497 void Generate(MacroAssembler* masm);
1498 void GenerateReadElement(MacroAssembler* masm);
whesse@chromium.org7b260152011-06-20 15:33:18 +00001499 void GenerateNewStrict(MacroAssembler* masm);
1500 void GenerateNewNonStrictFast(MacroAssembler* masm);
1501 void GenerateNewNonStrictSlow(MacroAssembler* masm);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001502
whesse@chromium.org030d38e2011-07-13 13:23:34 +00001503 virtual void PrintName(StringStream* stream);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001504};
1505
1506
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001507class RegExpExecStub: public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001508 public:
1509 RegExpExecStub() { }
1510
1511 private:
1512 Major MajorKey() { return RegExpExec; }
1513 int MinorKey() { return 0; }
1514
1515 void Generate(MacroAssembler* masm);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001516};
1517
1518
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001519class RegExpConstructResultStub: public PlatformCodeStub {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001520 public:
1521 RegExpConstructResultStub() { }
1522
1523 private:
1524 Major MajorKey() { return RegExpConstructResult; }
1525 int MinorKey() { return 0; }
1526
1527 void Generate(MacroAssembler* masm);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001528};
1529
1530
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001531class CallFunctionStub: public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001532 public:
lrn@chromium.org34e60782011-09-15 07:25:40 +00001533 CallFunctionStub(int argc, CallFunctionFlags flags)
1534 : argc_(argc), flags_(flags) { }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001535
1536 void Generate(MacroAssembler* masm);
1537
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001538 virtual void FinishCode(Handle<Code> code) {
1539 code->set_has_function_cache(RecordCallTarget());
1540 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001541
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001542 static int ExtractArgcFromMinorKey(int minor_key) {
1543 return ArgcBits::decode(minor_key);
1544 }
1545
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001546 private:
1547 int argc_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001548 CallFunctionFlags flags_;
1549
whesse@chromium.org030d38e2011-07-13 13:23:34 +00001550 virtual void PrintName(StringStream* stream);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001551
1552 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001553 class FlagBits: public BitField<CallFunctionFlags, 0, 2> {};
1554 class ArgcBits: public BitField<unsigned, 2, 32 - 2> {};
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001555
1556 Major MajorKey() { return CallFunction; }
1557 int MinorKey() {
1558 // Encode the parameters in a unique 32 bit value.
lrn@chromium.org34e60782011-09-15 07:25:40 +00001559 return FlagBits::encode(flags_) | ArgcBits::encode(argc_);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001560 }
1561
danno@chromium.org40cb8782011-05-25 07:58:50 +00001562 bool ReceiverMightBeImplicit() {
1563 return (flags_ & RECEIVER_MIGHT_BE_IMPLICIT) != 0;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001564 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001565
1566 bool RecordCallTarget() {
1567 return (flags_ & RECORD_CALL_TARGET) != 0;
1568 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001569};
1570
1571
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001572class CallConstructStub: public PlatformCodeStub {
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001573 public:
1574 explicit CallConstructStub(CallFunctionFlags flags) : flags_(flags) {}
1575
1576 void Generate(MacroAssembler* masm);
1577
1578 virtual void FinishCode(Handle<Code> code) {
1579 code->set_has_function_cache(RecordCallTarget());
1580 }
1581
1582 private:
1583 CallFunctionFlags flags_;
1584
1585 virtual void PrintName(StringStream* stream);
1586
1587 Major MajorKey() { return CallConstruct; }
1588 int MinorKey() { return flags_; }
1589
1590 bool RecordCallTarget() {
1591 return (flags_ & RECORD_CALL_TARGET) != 0;
1592 }
1593};
1594
1595
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001596enum StringIndexFlags {
1597 // Accepts smis or heap numbers.
1598 STRING_INDEX_IS_NUMBER,
1599
1600 // Accepts smis or heap numbers that are valid array indices
1601 // (ECMA-262 15.4). Invalid indices are reported as being out of
1602 // range.
1603 STRING_INDEX_IS_ARRAY_INDEX
1604};
1605
1606
1607// Generates code implementing String.prototype.charCodeAt.
1608//
1609// Only supports the case when the receiver is a string and the index
1610// is a number (smi or heap number) that is a valid index into the
1611// string. Additional index constraints are specified by the
1612// flags. Otherwise, bails out to the provided labels.
1613//
1614// Register usage: |object| may be changed to another string in a way
1615// that doesn't affect charCodeAt/charAt semantics, |index| is
1616// preserved, |scratch| and |result| are clobbered.
1617class StringCharCodeAtGenerator {
1618 public:
1619 StringCharCodeAtGenerator(Register object,
1620 Register index,
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001621 Register result,
1622 Label* receiver_not_string,
1623 Label* index_not_number,
1624 Label* index_out_of_range,
1625 StringIndexFlags index_flags)
1626 : object_(object),
1627 index_(index),
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001628 result_(result),
1629 receiver_not_string_(receiver_not_string),
1630 index_not_number_(index_not_number),
1631 index_out_of_range_(index_out_of_range),
1632 index_flags_(index_flags) {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001633 ASSERT(!result_.is(object_));
1634 ASSERT(!result_.is(index_));
1635 }
1636
1637 // Generates the fast case code. On the fallthrough path |result|
1638 // register contains the result.
1639 void GenerateFast(MacroAssembler* masm);
1640
1641 // Generates the slow case code. Must not be naturally
1642 // reachable. Expected to be put after a ret instruction (e.g., in
1643 // deferred code). Always jumps back to the fast case.
1644 void GenerateSlow(MacroAssembler* masm,
1645 const RuntimeCallHelper& call_helper);
1646
ulan@chromium.org2e04b582013-02-21 14:06:02 +00001647 // Skip handling slow case and directly jump to bailout.
1648 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1649 masm->bind(&index_not_smi_);
1650 masm->bind(&call_runtime_);
1651 masm->jmp(bailout);
1652 }
1653
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001654 private:
1655 Register object_;
1656 Register index_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001657 Register result_;
1658
1659 Label* receiver_not_string_;
1660 Label* index_not_number_;
1661 Label* index_out_of_range_;
1662
1663 StringIndexFlags index_flags_;
1664
1665 Label call_runtime_;
1666 Label index_not_smi_;
1667 Label got_smi_index_;
1668 Label exit_;
1669
1670 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
1671};
1672
1673
1674// Generates code for creating a one-char string from a char code.
1675class StringCharFromCodeGenerator {
1676 public:
1677 StringCharFromCodeGenerator(Register code,
1678 Register result)
1679 : code_(code),
1680 result_(result) {
1681 ASSERT(!code_.is(result_));
1682 }
1683
1684 // Generates the fast case code. On the fallthrough path |result|
1685 // register contains the result.
1686 void GenerateFast(MacroAssembler* masm);
1687
1688 // Generates the slow case code. Must not be naturally
1689 // reachable. Expected to be put after a ret instruction (e.g., in
1690 // deferred code). Always jumps back to the fast case.
1691 void GenerateSlow(MacroAssembler* masm,
1692 const RuntimeCallHelper& call_helper);
1693
ulan@chromium.org2e04b582013-02-21 14:06:02 +00001694 // Skip handling slow case and directly jump to bailout.
1695 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1696 masm->bind(&slow_case_);
1697 masm->jmp(bailout);
1698 }
1699
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001700 private:
1701 Register code_;
1702 Register result_;
1703
1704 Label slow_case_;
1705 Label exit_;
1706
1707 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
1708};
1709
1710
1711// Generates code implementing String.prototype.charAt.
1712//
1713// Only supports the case when the receiver is a string and the index
1714// is a number (smi or heap number) that is a valid index into the
1715// string. Additional index constraints are specified by the
1716// flags. Otherwise, bails out to the provided labels.
1717//
1718// Register usage: |object| may be changed to another string in a way
1719// that doesn't affect charCodeAt/charAt semantics, |index| is
1720// preserved, |scratch1|, |scratch2|, and |result| are clobbered.
1721class StringCharAtGenerator {
1722 public:
1723 StringCharAtGenerator(Register object,
1724 Register index,
danno@chromium.orgc612e022011-11-10 11:38:15 +00001725 Register scratch,
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001726 Register result,
1727 Label* receiver_not_string,
1728 Label* index_not_number,
1729 Label* index_out_of_range,
1730 StringIndexFlags index_flags)
1731 : char_code_at_generator_(object,
1732 index,
danno@chromium.orgc612e022011-11-10 11:38:15 +00001733 scratch,
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001734 receiver_not_string,
1735 index_not_number,
1736 index_out_of_range,
1737 index_flags),
danno@chromium.orgc612e022011-11-10 11:38:15 +00001738 char_from_code_generator_(scratch, result) {}
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001739
1740 // Generates the fast case code. On the fallthrough path |result|
1741 // register contains the result.
ulan@chromium.org2e04b582013-02-21 14:06:02 +00001742 void GenerateFast(MacroAssembler* masm) {
1743 char_code_at_generator_.GenerateFast(masm);
1744 char_from_code_generator_.GenerateFast(masm);
1745 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001746
1747 // Generates the slow case code. Must not be naturally
1748 // reachable. Expected to be put after a ret instruction (e.g., in
1749 // deferred code). Always jumps back to the fast case.
1750 void GenerateSlow(MacroAssembler* masm,
ulan@chromium.org2e04b582013-02-21 14:06:02 +00001751 const RuntimeCallHelper& call_helper) {
1752 char_code_at_generator_.GenerateSlow(masm, call_helper);
1753 char_from_code_generator_.GenerateSlow(masm, call_helper);
1754 }
1755
1756 // Skip handling slow case and directly jump to bailout.
1757 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1758 char_code_at_generator_.SkipSlow(masm, bailout);
1759 char_from_code_generator_.SkipSlow(masm, bailout);
1760 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001761
1762 private:
1763 StringCharCodeAtGenerator char_code_at_generator_;
1764 StringCharFromCodeGenerator char_from_code_generator_;
1765
1766 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
1767};
1768
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001769
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001770class KeyedLoadDictionaryElementStub : public HydrogenCodeStub {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001771 public:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001772 KeyedLoadDictionaryElementStub() {}
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001773
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001774 virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
1775
1776 virtual void InitializeInterfaceDescriptor(
1777 Isolate* isolate,
1778 CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
1779
1780 private:
1781 Major MajorKey() { return KeyedLoadElement; }
1782 int NotMissMinorKey() { return DICTIONARY_ELEMENTS; }
1783
1784 DISALLOW_COPY_AND_ASSIGN(KeyedLoadDictionaryElementStub);
1785};
1786
1787
1788class KeyedLoadDictionaryElementPlatformStub : public PlatformCodeStub {
1789 public:
1790 KeyedLoadDictionaryElementPlatformStub() {}
1791
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001792 void Generate(MacroAssembler* masm);
1793
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00001794 private:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001795 Major MajorKey() { return KeyedLoadElement; }
1796 int MinorKey() { return DICTIONARY_ELEMENTS; }
1797
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001798 DISALLOW_COPY_AND_ASSIGN(KeyedLoadDictionaryElementPlatformStub);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001799};
1800
1801
danno@chromium.org169691d2013-07-15 08:01:13 +00001802class DoubleToIStub : public PlatformCodeStub {
1803 public:
1804 DoubleToIStub(Register source,
1805 Register destination,
1806 int offset,
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00001807 bool is_truncating,
1808 bool skip_fastpath = false) : bit_field_(0) {
danno@chromium.org169691d2013-07-15 08:01:13 +00001809 bit_field_ = SourceRegisterBits::encode(source.code_) |
1810 DestinationRegisterBits::encode(destination.code_) |
1811 OffsetBits::encode(offset) |
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00001812 IsTruncatingBits::encode(is_truncating) |
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +00001813 SkipFastPathBits::encode(skip_fastpath) |
1814 SSEBits::encode(CpuFeatures::IsSafeForSnapshot(SSE2) ?
1815 CpuFeatures::IsSafeForSnapshot(SSE3) ? 2 : 1 : 0);
danno@chromium.org169691d2013-07-15 08:01:13 +00001816 }
1817
1818 Register source() {
1819 Register result = { SourceRegisterBits::decode(bit_field_) };
1820 return result;
1821 }
1822
1823 Register destination() {
1824 Register result = { DestinationRegisterBits::decode(bit_field_) };
1825 return result;
1826 }
1827
1828 bool is_truncating() {
1829 return IsTruncatingBits::decode(bit_field_);
1830 }
1831
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00001832 bool skip_fastpath() {
1833 return SkipFastPathBits::decode(bit_field_);
1834 }
1835
danno@chromium.org169691d2013-07-15 08:01:13 +00001836 int offset() {
1837 return OffsetBits::decode(bit_field_);
1838 }
1839
1840 void Generate(MacroAssembler* masm);
1841
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00001842 virtual bool SometimesSetsUpAFrame() { return false; }
1843
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +00001844 protected:
1845 virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
1846 ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
1847 }
1848
danno@chromium.org169691d2013-07-15 08:01:13 +00001849 private:
1850 static const int kBitsPerRegisterNumber = 6;
1851 STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
1852 class SourceRegisterBits:
1853 public BitField<int, 0, kBitsPerRegisterNumber> {}; // NOLINT
1854 class DestinationRegisterBits:
1855 public BitField<int, kBitsPerRegisterNumber,
1856 kBitsPerRegisterNumber> {}; // NOLINT
1857 class IsTruncatingBits:
1858 public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {}; // NOLINT
1859 class OffsetBits:
1860 public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {}; // NOLINT
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00001861 class SkipFastPathBits:
1862 public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {}; // NOLINT
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +00001863 class SSEBits:
1864 public BitField<int, 2 * kBitsPerRegisterNumber + 5, 2> {}; // NOLINT
danno@chromium.org169691d2013-07-15 08:01:13 +00001865
1866 Major MajorKey() { return DoubleToI; }
1867 int MinorKey() { return bit_field_; }
1868
1869 int bit_field_;
1870
1871 DISALLOW_COPY_AND_ASSIGN(DoubleToIStub);
1872};
1873
1874
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001875class KeyedLoadFastElementStub : public HydrogenCodeStub {
1876 public:
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001877 KeyedLoadFastElementStub(bool is_js_array, ElementsKind elements_kind) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001878 bit_field_ = ElementsKindBits::encode(elements_kind) |
1879 IsJSArrayBits::encode(is_js_array);
1880 }
1881
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001882 bool is_js_array() const {
1883 return IsJSArrayBits::decode(bit_field_);
1884 }
1885
1886 ElementsKind elements_kind() const {
1887 return ElementsKindBits::decode(bit_field_);
1888 }
1889
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00001890 virtual Handle<Code> GenerateCode(Isolate* isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001891
1892 virtual void InitializeInterfaceDescriptor(
1893 Isolate* isolate,
1894 CodeStubInterfaceDescriptor* descriptor);
1895
1896 private:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001897 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001898 class IsJSArrayBits: public BitField<bool, 8, 1> {};
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001899 uint32_t bit_field_;
1900
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001901 Major MajorKey() { return KeyedLoadElement; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001902 int NotMissMinorKey() { return bit_field_; }
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001903
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001904 DISALLOW_COPY_AND_ASSIGN(KeyedLoadFastElementStub);
1905};
1906
1907
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001908class KeyedStoreFastElementStub : public HydrogenCodeStub {
1909 public:
1910 KeyedStoreFastElementStub(bool is_js_array,
1911 ElementsKind elements_kind,
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001912 KeyedAccessStoreMode mode) {
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001913 bit_field_ = ElementsKindBits::encode(elements_kind) |
1914 IsJSArrayBits::encode(is_js_array) |
1915 StoreModeBits::encode(mode);
1916 }
1917
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001918 bool is_js_array() const {
1919 return IsJSArrayBits::decode(bit_field_);
1920 }
1921
1922 ElementsKind elements_kind() const {
1923 return ElementsKindBits::decode(bit_field_);
1924 }
1925
1926 KeyedAccessStoreMode store_mode() const {
1927 return StoreModeBits::decode(bit_field_);
1928 }
1929
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00001930 virtual Handle<Code> GenerateCode(Isolate* isolate);
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001931
1932 virtual void InitializeInterfaceDescriptor(
1933 Isolate* isolate,
1934 CodeStubInterfaceDescriptor* descriptor);
1935
1936 private:
1937 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
1938 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
1939 class IsJSArrayBits: public BitField<bool, 12, 1> {};
1940 uint32_t bit_field_;
1941
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001942 Major MajorKey() { return KeyedStoreElement; }
1943 int NotMissMinorKey() { return bit_field_; }
1944
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001945 DISALLOW_COPY_AND_ASSIGN(KeyedStoreFastElementStub);
1946};
1947
1948
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001949class TransitionElementsKindStub : public HydrogenCodeStub {
1950 public:
1951 TransitionElementsKindStub(ElementsKind from_kind,
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001952 ElementsKind to_kind) {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001953 bit_field_ = FromKindBits::encode(from_kind) |
1954 ToKindBits::encode(to_kind);
1955 }
1956
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001957 ElementsKind from_kind() const {
1958 return FromKindBits::decode(bit_field_);
1959 }
1960
1961 ElementsKind to_kind() const {
1962 return ToKindBits::decode(bit_field_);
1963 }
1964
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00001965 virtual Handle<Code> GenerateCode(Isolate* isolate);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001966
1967 virtual void InitializeInterfaceDescriptor(
1968 Isolate* isolate,
1969 CodeStubInterfaceDescriptor* descriptor);
1970
1971 private:
1972 class FromKindBits: public BitField<ElementsKind, 8, 8> {};
1973 class ToKindBits: public BitField<ElementsKind, 0, 8> {};
1974 uint32_t bit_field_;
1975
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001976 Major MajorKey() { return TransitionElementsKind; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001977 int NotMissMinorKey() { return bit_field_; }
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001978
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001979 DISALLOW_COPY_AND_ASSIGN(TransitionElementsKindStub);
1980};
1981
1982
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001983enum ContextCheckMode {
1984 CONTEXT_CHECK_REQUIRED,
1985 CONTEXT_CHECK_NOT_REQUIRED,
1986 LAST_CONTEXT_CHECK_MODE = CONTEXT_CHECK_NOT_REQUIRED
1987};
1988
1989
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001990class ArrayConstructorStubBase : public HydrogenCodeStub {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001991 public:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001992 ArrayConstructorStubBase(ElementsKind kind, ContextCheckMode context_mode,
1993 AllocationSiteOverrideMode override_mode) {
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001994 // It only makes sense to override local allocation site behavior
1995 // if there is a difference between the global allocation site policy
1996 // for an ElementsKind and the desired usage of the stub.
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +00001997 ASSERT(!(FLAG_track_allocation_sites &&
1998 override_mode == DISABLE_ALLOCATION_SITES) ||
danno@chromium.orgbee51992013-07-10 14:57:15 +00001999 AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002000 bit_field_ = ElementsKindBits::encode(kind) |
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002001 AllocationSiteOverrideModeBits::encode(override_mode) |
2002 ContextCheckModeBits::encode(context_mode);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002003 }
2004
2005 ElementsKind elements_kind() const {
2006 return ElementsKindBits::decode(bit_field_);
2007 }
2008
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002009 AllocationSiteOverrideMode override_mode() const {
2010 return AllocationSiteOverrideModeBits::decode(bit_field_);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002011 }
2012
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002013 ContextCheckMode context_mode() const {
2014 return ContextCheckModeBits::decode(bit_field_);
2015 }
2016
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002017 static void GenerateStubsAheadOfTime(Isolate* isolate);
2018 static void InstallDescriptors(Isolate* isolate);
2019
2020 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
ulan@chromium.org57ff8812013-05-10 08:16:55 +00002021 static const int kConstructor = 0;
2022 static const int kPropertyCell = 1;
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002023
hpayer@chromium.org71ea97f2013-12-19 16:03:26 +00002024 protected:
2025 void BasePrintName(const char* name, StringStream* stream);
2026
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002027 private:
2028 int NotMissMinorKey() { return bit_field_; }
2029
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002030 // Ensure data fits within available bits.
2031 STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
2032 STATIC_ASSERT(LAST_CONTEXT_CHECK_MODE == 1);
2033
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002034 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002035 class AllocationSiteOverrideModeBits: public
2036 BitField<AllocationSiteOverrideMode, 8, 1> {}; // NOLINT
2037 class ContextCheckModeBits: public BitField<ContextCheckMode, 9, 1> {};
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002038 uint32_t bit_field_;
2039
2040 DISALLOW_COPY_AND_ASSIGN(ArrayConstructorStubBase);
2041};
2042
2043
2044class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
2045 public:
2046 ArrayNoArgumentConstructorStub(
2047 ElementsKind kind,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002048 ContextCheckMode context_mode = CONTEXT_CHECK_REQUIRED,
2049 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2050 : ArrayConstructorStubBase(kind, context_mode, override_mode) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002051 }
2052
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00002053 virtual Handle<Code> GenerateCode(Isolate* isolate);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002054
2055 virtual void InitializeInterfaceDescriptor(
2056 Isolate* isolate,
2057 CodeStubInterfaceDescriptor* descriptor);
2058
2059 private:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002060 Major MajorKey() { return ArrayNoArgumentConstructor; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002061
hpayer@chromium.org71ea97f2013-12-19 16:03:26 +00002062 virtual void PrintName(StringStream* stream) {
2063 BasePrintName("ArrayNoArgumentConstructorStub", stream);
2064 }
2065
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002066 DISALLOW_COPY_AND_ASSIGN(ArrayNoArgumentConstructorStub);
2067};
2068
2069
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002070class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002071 public:
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002072 ArraySingleArgumentConstructorStub(
2073 ElementsKind kind,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002074 ContextCheckMode context_mode = CONTEXT_CHECK_REQUIRED,
2075 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2076 : ArrayConstructorStubBase(kind, context_mode, override_mode) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002077 }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002078
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00002079 virtual Handle<Code> GenerateCode(Isolate* isolate);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002080
2081 virtual void InitializeInterfaceDescriptor(
2082 Isolate* isolate,
2083 CodeStubInterfaceDescriptor* descriptor);
2084
2085 private:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002086 Major MajorKey() { return ArraySingleArgumentConstructor; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002087
hpayer@chromium.org71ea97f2013-12-19 16:03:26 +00002088 virtual void PrintName(StringStream* stream) {
2089 BasePrintName("ArraySingleArgumentConstructorStub", stream);
2090 }
2091
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002092 DISALLOW_COPY_AND_ASSIGN(ArraySingleArgumentConstructorStub);
2093};
2094
2095
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002096class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002097 public:
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002098 ArrayNArgumentsConstructorStub(
2099 ElementsKind kind,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002100 ContextCheckMode context_mode = CONTEXT_CHECK_REQUIRED,
2101 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2102 : ArrayConstructorStubBase(kind, context_mode, override_mode) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002103 }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002104
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00002105 virtual Handle<Code> GenerateCode(Isolate* isolate);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002106
2107 virtual void InitializeInterfaceDescriptor(
2108 Isolate* isolate,
2109 CodeStubInterfaceDescriptor* descriptor);
2110
2111 private:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002112 Major MajorKey() { return ArrayNArgumentsConstructor; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002113
hpayer@chromium.org71ea97f2013-12-19 16:03:26 +00002114 virtual void PrintName(StringStream* stream) {
2115 BasePrintName("ArrayNArgumentsConstructorStub", stream);
2116 }
2117
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00002118 DISALLOW_COPY_AND_ASSIGN(ArrayNArgumentsConstructorStub);
2119};
2120
2121
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002122class InternalArrayConstructorStubBase : public HydrogenCodeStub {
2123 public:
2124 explicit InternalArrayConstructorStubBase(ElementsKind kind) {
2125 kind_ = kind;
2126 }
2127
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002128 static void GenerateStubsAheadOfTime(Isolate* isolate);
2129 static void InstallDescriptors(Isolate* isolate);
2130
2131 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2132 static const int kConstructor = 0;
2133
2134 ElementsKind elements_kind() const { return kind_; }
2135
2136 private:
2137 int NotMissMinorKey() { return kind_; }
2138
2139 ElementsKind kind_;
2140
2141 DISALLOW_COPY_AND_ASSIGN(InternalArrayConstructorStubBase);
2142};
2143
2144
2145class InternalArrayNoArgumentConstructorStub : public
2146 InternalArrayConstructorStubBase {
2147 public:
2148 explicit InternalArrayNoArgumentConstructorStub(ElementsKind kind)
2149 : InternalArrayConstructorStubBase(kind) { }
2150
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00002151 virtual Handle<Code> GenerateCode(Isolate* isolate);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002152
2153 virtual void InitializeInterfaceDescriptor(
2154 Isolate* isolate,
2155 CodeStubInterfaceDescriptor* descriptor);
2156
2157 private:
2158 Major MajorKey() { return InternalArrayNoArgumentConstructor; }
2159
2160 DISALLOW_COPY_AND_ASSIGN(InternalArrayNoArgumentConstructorStub);
2161};
2162
2163
2164class InternalArraySingleArgumentConstructorStub : public
2165 InternalArrayConstructorStubBase {
2166 public:
2167 explicit InternalArraySingleArgumentConstructorStub(ElementsKind kind)
2168 : InternalArrayConstructorStubBase(kind) { }
2169
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00002170 virtual Handle<Code> GenerateCode(Isolate* isolate);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002171
2172 virtual void InitializeInterfaceDescriptor(
2173 Isolate* isolate,
2174 CodeStubInterfaceDescriptor* descriptor);
2175
2176 private:
2177 Major MajorKey() { return InternalArraySingleArgumentConstructor; }
2178
2179 DISALLOW_COPY_AND_ASSIGN(InternalArraySingleArgumentConstructorStub);
2180};
2181
2182
2183class InternalArrayNArgumentsConstructorStub : public
2184 InternalArrayConstructorStubBase {
2185 public:
2186 explicit InternalArrayNArgumentsConstructorStub(ElementsKind kind)
2187 : InternalArrayConstructorStubBase(kind) { }
2188
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00002189 virtual Handle<Code> GenerateCode(Isolate* isolate);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00002190
2191 virtual void InitializeInterfaceDescriptor(
2192 Isolate* isolate,
2193 CodeStubInterfaceDescriptor* descriptor);
2194
2195 private:
2196 Major MajorKey() { return InternalArrayNArgumentsConstructor; }
2197
2198 DISALLOW_COPY_AND_ASSIGN(InternalArrayNArgumentsConstructorStub);
2199};
2200
2201
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002202class KeyedStoreElementStub : public PlatformCodeStub {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00002203 public:
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00002204 KeyedStoreElementStub(bool is_js_array,
ulan@chromium.org65a89c22012-02-14 11:46:07 +00002205 ElementsKind elements_kind,
ulan@chromium.org750145a2013-03-07 15:14:13 +00002206 KeyedAccessStoreMode store_mode)
ulan@chromium.org65a89c22012-02-14 11:46:07 +00002207 : is_js_array_(is_js_array),
2208 elements_kind_(elements_kind),
ulan@chromium.org750145a2013-03-07 15:14:13 +00002209 store_mode_(store_mode),
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002210 fp_registers_(CanUseFPRegisters()) { }
ager@chromium.orgea91cc52011-05-23 06:06:11 +00002211
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00002212 Major MajorKey() { return KeyedStoreElement; }
2213 int MinorKey() {
ulan@chromium.org65a89c22012-02-14 11:46:07 +00002214 return ElementsKindBits::encode(elements_kind_) |
2215 IsJSArrayBits::encode(is_js_array_) |
ulan@chromium.org750145a2013-03-07 15:14:13 +00002216 StoreModeBits::encode(store_mode_) |
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002217 FPRegisters::encode(fp_registers_);
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00002218 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +00002219
2220 void Generate(MacroAssembler* masm);
2221
ager@chromium.orgea91cc52011-05-23 06:06:11 +00002222 private:
ulan@chromium.org750145a2013-03-07 15:14:13 +00002223 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2224 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
2225 class IsJSArrayBits: public BitField<bool, 12, 1> {};
2226 class FPRegisters: public BitField<bool, 13, 1> {};
ulan@chromium.org65a89c22012-02-14 11:46:07 +00002227
ager@chromium.orgea91cc52011-05-23 06:06:11 +00002228 bool is_js_array_;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00002229 ElementsKind elements_kind_;
ulan@chromium.org750145a2013-03-07 15:14:13 +00002230 KeyedAccessStoreMode store_mode_;
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002231 bool fp_registers_;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00002232
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00002233 DISALLOW_COPY_AND_ASSIGN(KeyedStoreElementStub);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00002234};
2235
2236
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002237class ToBooleanStub: public HydrogenCodeStub {
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00002238 public:
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002239 enum Type {
2240 UNDEFINED,
2241 BOOLEAN,
2242 NULL_TYPE,
2243 SMI,
2244 SPEC_OBJECT,
2245 STRING,
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00002246 SYMBOL,
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002247 HEAP_NUMBER,
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002248 NUMBER_OF_TYPES
2249 };
2250
2251 // At most 8 different types can be distinguished, because the Code object
2252 // only has room for a single byte to hold a set of these types. :-P
2253 STATIC_ASSERT(NUMBER_OF_TYPES <= 8);
2254
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00002255 class Types : public EnumSet<Type, byte> {
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002256 public:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002257 Types() : EnumSet<Type, byte>(0) {}
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00002258 explicit Types(byte bits) : EnumSet<Type, byte>(bits) {}
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002259
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00002260 byte ToByte() const { return ToIntegral(); }
vegorov@chromium.org7943d462011-08-01 11:41:52 +00002261 void Print(StringStream* stream) const;
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002262 bool UpdateStatus(Handle<Object> object);
vegorov@chromium.org7943d462011-08-01 11:41:52 +00002263 bool NeedsMap() const;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00002264 bool CanBeUndetectable() const;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002265 bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002266
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002267 static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
2268 };
ricow@chromium.org2c99e282011-07-28 09:15:17 +00002269
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002270 explicit ToBooleanStub(Types types = Types())
2271 : types_(types) { }
yangguo@chromium.orgcc536052013-11-29 11:43:20 +00002272 explicit ToBooleanStub(ExtraICState state)
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002273 : types_(static_cast<byte>(state)) { }
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00002274
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002275 bool UpdateStatus(Handle<Object> object);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002276 Types GetTypes() { return types_; }
2277
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00002278 virtual Handle<Code> GenerateCode(Isolate* isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002279 virtual void InitializeInterfaceDescriptor(
2280 Isolate* isolate,
2281 CodeStubInterfaceDescriptor* descriptor);
2282
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00002283 virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; }
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002284 virtual void PrintState(StringStream* stream);
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00002285
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002286 virtual bool SometimesSetsUpAFrame() { return false; }
2287
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002288 static void InitializeForIsolate(Isolate* isolate) {
2289 ToBooleanStub stub;
2290 stub.InitializeInterfaceDescriptor(
2291 isolate,
2292 isolate->code_stub_interface_descriptor(CodeStub::ToBoolean));
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002293 }
2294
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002295 static Handle<Code> GetUninitialized(Isolate* isolate) {
2296 return ToBooleanStub(UNINITIALIZED).GetCode(isolate);
2297 }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002298
yangguo@chromium.orgcc536052013-11-29 11:43:20 +00002299 virtual ExtraICState GetExtraICState() {
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002300 return types_.ToIntegral();
2301 }
2302
danno@chromium.org1fd77d52013-06-07 16:01:45 +00002303 virtual InlineCacheState GetICState() {
2304 if (types_.IsEmpty()) {
2305 return ::v8::internal::UNINITIALIZED;
2306 } else {
2307 return MONOMORPHIC;
2308 }
2309 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002310
2311 private:
2312 Major MajorKey() { return ToBoolean; }
2313 int NotMissMinorKey() { return GetExtraICState(); }
2314
2315 explicit ToBooleanStub(InitializationState init_state) :
2316 HydrogenCodeStub(init_state) {}
2317
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002318 Types types_;
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00002319};
2320
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002321
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00002322class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002323 public:
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00002324 ElementsTransitionAndStoreStub(ElementsKind from_kind,
2325 ElementsKind to_kind,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002326 bool is_jsarray,
ulan@chromium.org750145a2013-03-07 15:14:13 +00002327 KeyedAccessStoreMode store_mode)
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00002328 : from_kind_(from_kind),
2329 to_kind_(to_kind),
2330 is_jsarray_(is_jsarray),
2331 store_mode_(store_mode) {}
2332
2333 ElementsKind from_kind() const { return from_kind_; }
2334 ElementsKind to_kind() const { return to_kind_; }
2335 bool is_jsarray() const { return is_jsarray_; }
2336 KeyedAccessStoreMode store_mode() const { return store_mode_; }
2337
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00002338 virtual Handle<Code> GenerateCode(Isolate* isolate);
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00002339
2340 void InitializeInterfaceDescriptor(
2341 Isolate* isolate,
2342 CodeStubInterfaceDescriptor* descriptor);
2343
2344 private:
2345 class FromBits: public BitField<ElementsKind, 0, 8> {};
2346 class ToBits: public BitField<ElementsKind, 8, 8> {};
2347 class IsJSArrayBits: public BitField<bool, 16, 1> {};
2348 class StoreModeBits: public BitField<KeyedAccessStoreMode, 17, 4> {};
2349
2350 Major MajorKey() { return ElementsTransitionAndStore; }
2351 int NotMissMinorKey() {
2352 return FromBits::encode(from_kind_) |
2353 ToBits::encode(to_kind_) |
2354 IsJSArrayBits::encode(is_jsarray_) |
2355 StoreModeBits::encode(store_mode_);
2356 }
2357
2358 ElementsKind from_kind_;
2359 ElementsKind to_kind_;
2360 bool is_jsarray_;
2361 KeyedAccessStoreMode store_mode_;
2362
2363 DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub);
2364};
2365
2366
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002367class StoreArrayLiteralElementStub : public PlatformCodeStub {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002368 public:
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002369 StoreArrayLiteralElementStub()
2370 : fp_registers_(CanUseFPRegisters()) { }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002371
2372 private:
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002373 class FPRegisters: public BitField<bool, 0, 1> {};
2374
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002375 Major MajorKey() { return StoreArrayLiteralElement; }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002376 int MinorKey() { return FPRegisters::encode(fp_registers_); }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002377
2378 void Generate(MacroAssembler* masm);
2379
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002380 bool fp_registers_;
2381
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002382 DISALLOW_COPY_AND_ASSIGN(StoreArrayLiteralElementStub);
2383};
2384
verwaest@chromium.org753aee42012-07-17 16:15:42 +00002385
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00002386class StubFailureTrampolineStub : public PlatformCodeStub {
2387 public:
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00002388 explicit StubFailureTrampolineStub(StubFunctionMode function_mode)
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002389 : fp_registers_(CanUseFPRegisters()), function_mode_(function_mode) {}
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +00002390
hpayer@chromium.org8432c912013-02-28 15:55:26 +00002391 static void GenerateAheadOfTime(Isolate* isolate);
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00002392
2393 private:
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002394 class FPRegisters: public BitField<bool, 0, 1> {};
2395 class FunctionModeField: public BitField<StubFunctionMode, 1, 1> {};
2396
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00002397 Major MajorKey() { return StubFailureTrampoline; }
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002398 int MinorKey() {
2399 return FPRegisters::encode(fp_registers_) |
2400 FunctionModeField::encode(function_mode_);
2401 }
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00002402
2403 void Generate(MacroAssembler* masm);
2404
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002405 bool fp_registers_;
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00002406 StubFunctionMode function_mode_;
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +00002407
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00002408 DISALLOW_COPY_AND_ASSIGN(StubFailureTrampolineStub);
2409};
2410
2411
machenbach@chromium.orgea468882013-11-18 08:53:19 +00002412class StubFailureTailCallTrampolineStub : public PlatformCodeStub {
2413 public:
2414 StubFailureTailCallTrampolineStub() : fp_registers_(CanUseFPRegisters()) {}
2415
machenbach@chromium.orgea468882013-11-18 08:53:19 +00002416 static void GenerateAheadOfTime(Isolate* isolate);
2417
2418 private:
2419 class FPRegisters: public BitField<bool, 0, 1> {};
2420 Major MajorKey() { return StubFailureTailCallTrampoline; }
2421 int MinorKey() { return FPRegisters::encode(fp_registers_); }
2422
2423 void Generate(MacroAssembler* masm);
2424
2425 bool fp_registers_;
2426
2427 DISALLOW_COPY_AND_ASSIGN(StubFailureTailCallTrampolineStub);
2428};
2429
2430
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002431class ProfileEntryHookStub : public PlatformCodeStub {
verwaest@chromium.org753aee42012-07-17 16:15:42 +00002432 public:
2433 explicit ProfileEntryHookStub() {}
2434
2435 // The profile entry hook function is not allowed to cause a GC.
2436 virtual bool SometimesSetsUpAFrame() { return false; }
2437
2438 // Generates a call to the entry hook if it's enabled.
2439 static void MaybeCallEntryHook(MacroAssembler* masm);
2440
verwaest@chromium.org753aee42012-07-17 16:15:42 +00002441 private:
2442 static void EntryHookTrampoline(intptr_t function,
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +00002443 intptr_t stack_pointer,
2444 Isolate* isolate);
verwaest@chromium.org753aee42012-07-17 16:15:42 +00002445
2446 Major MajorKey() { return ProfileEntryHook; }
2447 int MinorKey() { return 0; }
2448
2449 void Generate(MacroAssembler* masm);
2450
verwaest@chromium.org753aee42012-07-17 16:15:42 +00002451 DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub);
2452};
2453
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002454} } // namespace v8::internal
2455
2456#endif // V8_CODE_STUBS_H_