blob: 646aee23eb2b87c4ae6ba26c901dd84fdb773cf2 [file] [log] [blame]
ulan@chromium.org65a89c22012-02-14 11:46:07 +00001// Copyright 2012 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_CODE_STUBS_H_
29#define V8_CODE_STUBS_H_
30
lrn@chromium.org1c092762011-05-09 09:42:16 +000031#include "allocation.h"
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000032#include "assembler.h"
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000033#include "globals.h"
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000034#include "codegen.h"
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000035
kasperl@chromium.org71affb52009-05-26 05:44:31 +000036namespace v8 {
37namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000038
ricow@chromium.orgc54d3652011-05-30 09:20:16 +000039// List of code stubs used on all platforms.
ager@chromium.orgc4c92722009-11-18 14:12:51 +000040#define CODE_STUB_LIST_ALL_PLATFORMS(V) \
41 V(CallFunction) \
danno@chromium.orgfa458e42012-02-01 10:48:36 +000042 V(CallConstruct) \
danno@chromium.org40cb8782011-05-25 07:58:50 +000043 V(UnaryOp) \
44 V(BinaryOp) \
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000045 V(StringAdd) \
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000046 V(SubString) \
47 V(StringCompare) \
ager@chromium.orgc4c92722009-11-18 14:12:51 +000048 V(Compare) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000049 V(CompareIC) \
danno@chromium.orgca29dd82013-04-26 11:59:48 +000050 V(CompareNilIC) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000051 V(MathPow) \
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +000052 V(StringLength) \
53 V(FunctionPrototype) \
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000054 V(StoreArrayLength) \
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000055 V(RecordWrite) \
56 V(StoreBufferOverflow) \
57 V(RegExpExec) \
whesse@chromium.org871db8c2010-12-21 15:17:57 +000058 V(TranscendentalCache) \
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000059 V(Instanceof) \
ager@chromium.orgc4c92722009-11-18 14:12:51 +000060 V(ConvertToDouble) \
61 V(WriteInt32ToHeapNumber) \
62 V(StackCheck) \
yangguo@chromium.org56454712012-02-16 15:33:53 +000063 V(Interrupt) \
sgjesse@chromium.org846fb742009-12-18 08:56:33 +000064 V(FastNewClosure) \
65 V(FastNewContext) \
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +000066 V(FastNewBlockContext) \
sgjesse@chromium.org846fb742009-12-18 08:56:33 +000067 V(FastCloneShallowArray) \
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +000068 V(FastCloneShallowObject) \
ager@chromium.orgc4c92722009-11-18 14:12:51 +000069 V(ToBoolean) \
whesse@chromium.org7a392b32011-01-31 11:30:36 +000070 V(ToNumber) \
ager@chromium.orgc4c92722009-11-18 14:12:51 +000071 V(ArgumentsAccess) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +000072 V(RegExpConstructResult) \
ager@chromium.org5c838252010-02-19 08:53:10 +000073 V(NumberToString) \
ager@chromium.orgc4c92722009-11-18 14:12:51 +000074 V(CEntry) \
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000075 V(JSEntry) \
sgjesse@chromium.org6db88712011-07-11 11:41:22 +000076 V(KeyedLoadElement) \
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000077 V(ArrayNoArgumentConstructor) \
78 V(ArraySingleArgumentConstructor) \
79 V(ArrayNArgumentsConstructor) \
sgjesse@chromium.org6db88712011-07-11 11:41:22 +000080 V(KeyedStoreElement) \
lrn@chromium.org1c092762011-05-09 09:42:16 +000081 V(DebuggerStatement) \
ulan@chromium.org750145a2013-03-07 15:14:13 +000082 V(NameDictionaryLookup) \
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000083 V(ElementsTransitionAndStore) \
danno@chromium.org94b0d6f2013-02-04 13:33:20 +000084 V(TransitionElementsKind) \
verwaest@chromium.org753aee42012-07-17 16:15:42 +000085 V(StoreArrayLiteralElement) \
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +000086 V(StubFailureTrampoline) \
danno@chromium.orgca29dd82013-04-26 11:59:48 +000087 V(ArrayConstructor) \
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000088 V(ProfileEntryHook) \
89 /* IC Handler stubs */ \
ulan@chromium.org57ff8812013-05-10 08:16:55 +000090 V(LoadField) \
91 V(KeyedLoadField)
ager@chromium.org3811b432009-10-28 14:53:37 +000092
93// List of code stubs only used on ARM platforms.
94#ifdef V8_TARGET_ARCH_ARM
95#define CODE_STUB_LIST_ARM(V) \
96 V(GetProperty) \
97 V(SetProperty) \
98 V(InvokeBuiltin) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +000099 V(RegExpCEntry) \
100 V(DirectCEntry)
ager@chromium.org3811b432009-10-28 14:53:37 +0000101#else
102#define CODE_STUB_LIST_ARM(V)
103#endif
104
lrn@chromium.org7516f052011-03-30 08:52:27 +0000105// List of code stubs only used on MIPS platforms.
106#ifdef V8_TARGET_ARCH_MIPS
107#define CODE_STUB_LIST_MIPS(V) \
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000108 V(RegExpCEntry) \
109 V(DirectCEntry)
lrn@chromium.org7516f052011-03-30 08:52:27 +0000110#else
111#define CODE_STUB_LIST_MIPS(V)
112#endif
113
ager@chromium.org3811b432009-10-28 14:53:37 +0000114// Combined list of code stubs.
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000115#define CODE_STUB_LIST(V) \
116 CODE_STUB_LIST_ALL_PLATFORMS(V) \
lrn@chromium.org7516f052011-03-30 08:52:27 +0000117 CODE_STUB_LIST_ARM(V) \
118 CODE_STUB_LIST_MIPS(V)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000119
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000120// Mode to overwrite BinaryExpression values.
121enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
122enum UnaryOverwriteMode { UNARY_OVERWRITE, UNARY_NO_OVERWRITE };
123
124
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000125// Stub is base classes of all stubs.
126class CodeStub BASE_EMBEDDED {
127 public:
128 enum Major {
ager@chromium.org3811b432009-10-28 14:53:37 +0000129#define DEF_ENUM(name) name,
130 CODE_STUB_LIST(DEF_ENUM)
131#undef DEF_ENUM
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000132 NoCache, // marker for stubs that do custom caching
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000133 NUMBER_OF_IDS
134 };
135
136 // Retrieve the code for the stub. Generate the code if needed.
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000137 Handle<Code> GetCode(Isolate* isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000138
139 static Major MajorKeyFromKey(uint32_t key) {
140 return static_cast<Major>(MajorKeyBits::decode(key));
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000141 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000142 static int MinorKeyFromKey(uint32_t key) {
143 return MinorKeyBits::decode(key);
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000144 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000145
146 // Gets the major key from a code object that is a code stub or binary op IC.
147 static Major GetMajorKey(Code* code_stub) {
148 return static_cast<Major>(code_stub->major_key());
149 }
150
ager@chromium.org5c838252010-02-19 08:53:10 +0000151 static const char* MajorName(Major major_key, bool allow_unknown_keys);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000152
153 virtual ~CodeStub() {}
154
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000155 bool CompilingCallsToThisStubIsGCSafe(Isolate* isolate) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000156 bool is_pregenerated = IsPregenerated();
157 Code* code = NULL;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000158 CHECK(!is_pregenerated || FindCodeInCache(&code, isolate));
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000159 return is_pregenerated;
160 }
161
162 // See comment above, where Instanceof is defined.
163 virtual bool IsPregenerated() { return false; }
164
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000165 static void GenerateStubsAheadOfTime(Isolate* isolate);
166 static void GenerateFPStubs(Isolate* isolate);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000167
168 // Some stubs put untagged junk on the stack that cannot be scanned by the
169 // GC. This means that we must be statically sure that no GC can occur while
170 // they are running. If that is the case they should override this to return
171 // true, which will cause an assertion if we try to call something that can
172 // GC or if we try to put a stack frame on top of the junk, which would not
173 // result in a traversable stack.
174 virtual bool SometimesSetsUpAFrame() { return true; }
175
danno@chromium.orgc612e022011-11-10 11:38:15 +0000176 // Lookup the code in the (possibly custom) cache.
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000177 bool FindCodeInCache(Code** code_out, Isolate* isolate);
danno@chromium.orgc612e022011-11-10 11:38:15 +0000178
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000179 // Returns information for computing the number key.
180 virtual Major MajorKey() = 0;
181 virtual int MinorKey() = 0;
182
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000183 virtual InlineCacheState GetICState() {
184 return UNINITIALIZED;
185 }
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000186 virtual Code::ExtraICState GetExtraICState() {
187 return Code::kNoExtraICState;
188 }
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000189 virtual Code::StubType GetStubType() {
190 return Code::NORMAL;
191 }
192 virtual int GetStubFlags() {
193 return -1;
194 }
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000195
196 protected:
197 static bool CanUseFPRegisters();
198
199 // Generates the assembler code for the stub.
200 virtual Handle<Code> GenerateCode() = 0;
201
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000202
203 // Returns whether the code generated for this stub needs to be allocated as
204 // a fixed (non-moveable) code object.
205 virtual bool NeedsImmovableCode() { return false; }
206
207 private:
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000208 // Perform bookkeeping required after code generation when stub code is
209 // initially generated.
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000210 void RecordCodeGeneration(Code* code, Isolate* isolate);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000211
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000212 // Finish the code object after it has been generated.
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +0000213 virtual void FinishCode(Handle<Code> code) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000214
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000215 // Activate newly generated stub. Is called after
216 // registering stub in the stub cache.
217 virtual void Activate(Code* code) { }
218
danno@chromium.org40cb8782011-05-25 07:58:50 +0000219 // BinaryOpStub needs to override this.
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000220 virtual Code::Kind GetCodeKind() const;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000221
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000222 // Add the code to a specialized cache, specific to an individual
223 // stub type. Please note, this method must add the code object to a
224 // roots object, otherwise we will remove the code during GC.
225 virtual void AddToSpecialCache(Handle<Code> new_object) { }
226
227 // Find code in a specialized cache, work is delegated to the specific stub.
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000228 virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate) {
229 return false;
230 }
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000231
232 // If a stub uses a special cache override this.
233 virtual bool UseSpecialCache() { return false; }
234
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000235 // Returns a name for logging/debugging purposes.
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000236 SmartArrayPointer<const char> GetName();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000237 virtual void PrintName(StringStream* stream);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000238
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000239 // Computes the key based on major and minor.
240 uint32_t GetKey() {
241 ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
242 return MinorKeyBits::encode(MinorKey()) |
243 MajorKeyBits::encode(MajorKey());
244 }
245
danno@chromium.org81cac2b2012-07-10 11:28:27 +0000246 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
247 class MinorKeyBits: public BitField<uint32_t,
248 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000249
250 friend class BreakPointIterator;
251};
252
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000253
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000254class PlatformCodeStub : public CodeStub {
255 public:
256 // Retrieve the code for the stub. Generate the code if needed.
257 virtual Handle<Code> GenerateCode();
258
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000259 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000260
261 protected:
262 // Generates the assembler code for the stub.
263 virtual void Generate(MacroAssembler* masm) = 0;
264};
265
266
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000267enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
268
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000269
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000270struct CodeStubInterfaceDescriptor {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000271 CodeStubInterfaceDescriptor();
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000272 int register_param_count_;
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000273 const Register* stack_parameter_count_;
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000274 // if hint_stack_parameter_count_ > 0, the code stub can optimize the
275 // return sequence. Default value is -1, which means it is ignored.
276 int hint_stack_parameter_count_;
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000277 StubFunctionMode function_mode_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000278 Register* register_params_;
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000279 Address deoptimization_handler_;
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000280 ExternalReference miss_handler_;
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000281
282 int environment_length() const {
283 if (stack_parameter_count_ != NULL) {
284 return register_param_count_ + 1;
285 }
286 return register_param_count_;
287 }
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000288
289 bool initialized() const { return register_param_count_ >= 0; }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000290};
291
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000292// A helper to make up for the fact that type Register is not fully
293// defined outside of the platform directories
294#define DESCRIPTOR_GET_PARAMETER_REGISTER(descriptor, index) \
295 ((index) == (descriptor)->register_param_count_) \
296 ? *((descriptor)->stack_parameter_count_) \
297 : (descriptor)->register_params_[(index)]
298
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000299
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000300class HydrogenCodeStub : public CodeStub {
301 public:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000302 enum InitializationState {
303 CODE_STUB_IS_NOT_MISS,
304 CODE_STUB_IS_MISS
305 };
306
307 explicit HydrogenCodeStub(InitializationState state) {
308 is_miss_ = (state == CODE_STUB_IS_MISS);
309 }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000310
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000311 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000312
313 CodeStubInterfaceDescriptor* GetInterfaceDescriptor(Isolate* isolate) {
314 return isolate->code_stub_interface_descriptor(MajorKey());
315 }
316
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000317 bool IsMiss() { return is_miss_; }
318
319 template<class SubClass>
320 static Handle<Code> GetUninitialized(Isolate* isolate) {
321 SubClass::GenerateAheadOfTime(isolate);
322 return SubClass().GetCode(isolate);
323 }
324
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000325 virtual void InitializeInterfaceDescriptor(
326 Isolate* isolate,
327 CodeStubInterfaceDescriptor* descriptor) = 0;
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000328
329 // Retrieve the code for the stub. Generate the code if needed.
330 virtual Handle<Code> GenerateCode() = 0;
331
332 virtual int NotMissMinorKey() = 0;
333
334 Handle<Code> GenerateLightweightMissCode(Isolate* isolate);
335
336 private:
337 class MinorKeyBits: public BitField<int, 0, kStubMinorKeyBits - 1> {};
338 class IsMissBits: public BitField<bool, kStubMinorKeyBits - 1, 1> {};
339
340 void GenerateLightweightMiss(MacroAssembler* masm);
341 virtual int MinorKey() {
342 return IsMissBits::encode(is_miss_) |
343 MinorKeyBits::encode(NotMissMinorKey());
344 }
345
346 bool is_miss_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000347};
348
349
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000350// Helper interface to prepare to/restore after making runtime calls.
351class RuntimeCallHelper {
352 public:
353 virtual ~RuntimeCallHelper() {}
354
355 virtual void BeforeCall(MacroAssembler* masm) const = 0;
356
357 virtual void AfterCall(MacroAssembler* masm) const = 0;
358
359 protected:
360 RuntimeCallHelper() {}
361
362 private:
363 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
364};
365
366} } // namespace v8::internal
367
368#if V8_TARGET_ARCH_IA32
369#include "ia32/code-stubs-ia32.h"
370#elif V8_TARGET_ARCH_X64
371#include "x64/code-stubs-x64.h"
372#elif V8_TARGET_ARCH_ARM
373#include "arm/code-stubs-arm.h"
374#elif V8_TARGET_ARCH_MIPS
375#include "mips/code-stubs-mips.h"
376#else
377#error Unsupported target architecture.
378#endif
379
380namespace v8 {
381namespace internal {
382
383
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000384// RuntimeCallHelper implementation used in stubs: enters/leaves a
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000385// newly created internal frame before/after the runtime call.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000386class StubRuntimeCallHelper : public RuntimeCallHelper {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000387 public:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000388 StubRuntimeCallHelper() {}
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000389
390 virtual void BeforeCall(MacroAssembler* masm) const;
391
392 virtual void AfterCall(MacroAssembler* masm) const;
393};
394
395
396// Trivial RuntimeCallHelper implementation.
397class NopRuntimeCallHelper : public RuntimeCallHelper {
398 public:
399 NopRuntimeCallHelper() {}
400
401 virtual void BeforeCall(MacroAssembler* masm) const {}
402
403 virtual void AfterCall(MacroAssembler* masm) const {}
404};
405
406
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000407class StackCheckStub : public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000408 public:
409 StackCheckStub() { }
410
411 void Generate(MacroAssembler* masm);
412
413 private:
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000414 Major MajorKey() { return StackCheck; }
415 int MinorKey() { return 0; }
416};
417
418
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000419class InterruptStub : public PlatformCodeStub {
yangguo@chromium.org56454712012-02-16 15:33:53 +0000420 public:
421 InterruptStub() { }
422
423 void Generate(MacroAssembler* masm);
424
425 private:
426 Major MajorKey() { return Interrupt; }
427 int MinorKey() { return 0; }
428};
429
430
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000431class ToNumberStub: public PlatformCodeStub {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000432 public:
433 ToNumberStub() { }
434
435 void Generate(MacroAssembler* masm);
436
437 private:
438 Major MajorKey() { return ToNumber; }
439 int MinorKey() { return 0; }
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000440};
441
442
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000443class FastNewClosureStub : public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000444 public:
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000445 explicit FastNewClosureStub(LanguageMode language_mode, bool is_generator)
446 : language_mode_(language_mode),
447 is_generator_(is_generator) { }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000448
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000449 void Generate(MacroAssembler* masm);
450
451 private:
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000452 class StrictModeBits: public BitField<bool, 0, 1> {};
453 class IsGeneratorBits: public BitField<bool, 1, 1> {};
454
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000455 Major MajorKey() { return FastNewClosure; }
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000456 int MinorKey() {
457 return StrictModeBits::encode(language_mode_ != CLASSIC_MODE) |
458 IsGeneratorBits::encode(is_generator_);
459 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000460
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000461 LanguageMode language_mode_;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000462 bool is_generator_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000463};
464
465
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000466class FastNewContextStub : public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000467 public:
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000468 static const int kMaximumSlots = 64;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000469
470 explicit FastNewContextStub(int slots) : slots_(slots) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000471 ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000472 }
473
474 void Generate(MacroAssembler* masm);
475
476 private:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000477 int slots_;
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000478
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000479 Major MajorKey() { return FastNewContext; }
480 int MinorKey() { return slots_; }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000481};
482
483
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000484class FastNewBlockContextStub : public PlatformCodeStub {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000485 public:
486 static const int kMaximumSlots = 64;
487
488 explicit FastNewBlockContextStub(int slots) : slots_(slots) {
489 ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
490 }
491
492 void Generate(MacroAssembler* masm);
493
494 private:
495 int slots_;
496
497 Major MajorKey() { return FastNewBlockContext; }
498 int MinorKey() { return slots_; }
499};
500
501
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000502class FastCloneShallowArrayStub : public HydrogenCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000503 public:
504 // Maximum length of copied elements array.
505 static const int kMaximumClonedLength = 8;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000506 enum Mode {
507 CLONE_ELEMENTS,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000508 CLONE_DOUBLE_ELEMENTS,
erikcorry0ad885c2011-11-21 13:51:57 +0000509 COPY_ON_WRITE_ELEMENTS,
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000510 CLONE_ANY_ELEMENTS,
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000511 LAST_CLONE_MODE = CLONE_ANY_ELEMENTS
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000512 };
513
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000514 static const int kFastCloneModeCount = LAST_CLONE_MODE + 1;
515
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000516 FastCloneShallowArrayStub(Mode mode,
517 AllocationSiteMode allocation_site_mode,
518 int length)
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000519 : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS),
520 mode_(mode),
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000521 allocation_site_mode_(allocation_site_mode),
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000522 length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000523 ASSERT_GE(length_, 0);
524 ASSERT_LE(length_, kMaximumClonedLength);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000525 }
526
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000527 Mode mode() const { return mode_; }
528 int length() const { return length_; }
529 AllocationSiteMode allocation_site_mode() const {
530 return allocation_site_mode_;
531 }
532
533 ElementsKind ComputeElementsKind() const {
534 switch (mode()) {
535 case CLONE_ELEMENTS:
536 case COPY_ON_WRITE_ELEMENTS:
537 return FAST_ELEMENTS;
538 case CLONE_DOUBLE_ELEMENTS:
539 return FAST_DOUBLE_ELEMENTS;
540 case CLONE_ANY_ELEMENTS:
541 /*fall-through*/;
542 }
543 UNREACHABLE();
544 return LAST_ELEMENTS_KIND;
545 }
546
547 virtual Handle<Code> GenerateCode();
548
549 virtual void InitializeInterfaceDescriptor(
550 Isolate* isolate,
551 CodeStubInterfaceDescriptor* descriptor);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000552
553 private:
554 Mode mode_;
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000555 AllocationSiteMode allocation_site_mode_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000556 int length_;
557
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000558 class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
559 class ModeBits: public BitField<Mode, 1, 4> {};
560 class LengthBits: public BitField<int, 5, 4> {};
561 // Ensure data fits within available bits.
562 STATIC_ASSERT(LAST_ALLOCATION_SITE_MODE == 1);
563 STATIC_ASSERT(kFastCloneModeCount < 16);
564 STATIC_ASSERT(kMaximumClonedLength < 16);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000565 Major MajorKey() { return FastCloneShallowArray; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000566 int NotMissMinorKey() {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000567 return AllocationSiteModeBits::encode(allocation_site_mode_)
568 | ModeBits::encode(mode_)
569 | LengthBits::encode(length_);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000570 }
571};
572
573
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000574class FastCloneShallowObjectStub : public HydrogenCodeStub {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000575 public:
576 // Maximum number of properties in copied object.
577 static const int kMaximumClonedProperties = 6;
578
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000579 explicit FastCloneShallowObjectStub(int length)
580 : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS),
581 length_(length) {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000582 ASSERT_GE(length_, 0);
583 ASSERT_LE(length_, kMaximumClonedProperties);
584 }
585
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000586 int length() const { return length_; }
587
588 virtual Handle<Code> GenerateCode();
589
590 virtual void InitializeInterfaceDescriptor(
591 Isolate* isolate,
592 CodeStubInterfaceDescriptor* descriptor);
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000593
594 private:
595 int length_;
596
597 Major MajorKey() { return FastCloneShallowObject; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000598 int NotMissMinorKey() { return length_; }
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000599
600 DISALLOW_COPY_AND_ASSIGN(FastCloneShallowObjectStub);
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000601};
602
603
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000604class InstanceofStub: public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000605 public:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000606 enum Flags {
607 kNoFlags = 0,
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000608 kArgsInRegisters = 1 << 0,
609 kCallSiteInlineCheck = 1 << 1,
610 kReturnTrueFalseObject = 1 << 2
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000611 };
612
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000613 explicit InstanceofStub(Flags flags) : flags_(flags) { }
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000614
615 static Register left();
616 static Register right();
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000617
618 void Generate(MacroAssembler* masm);
619
620 private:
621 Major MajorKey() { return Instanceof; }
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000622 int MinorKey() { return static_cast<int>(flags_); }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000623
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000624 bool HasArgsInRegisters() const {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000625 return (flags_ & kArgsInRegisters) != 0;
626 }
627
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000628 bool HasCallSiteInlineCheck() const {
629 return (flags_ & kCallSiteInlineCheck) != 0;
630 }
631
632 bool ReturnTrueFalseObject() const {
633 return (flags_ & kReturnTrueFalseObject) != 0;
634 }
635
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000636 virtual void PrintName(StringStream* stream);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000637
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000638 Flags flags_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000639};
640
641
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000642class ArrayConstructorStub: public PlatformCodeStub {
643 public:
644 enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
645 ArrayConstructorStub(Isolate* isolate, int argument_count);
646 explicit ArrayConstructorStub(Isolate* isolate);
647
648 void Generate(MacroAssembler* masm);
649
650 private:
651 virtual CodeStub::Major MajorKey() { return ArrayConstructor; }
652 virtual int MinorKey() { return argument_count_; }
653
654 ArgumentCountKey argument_count_;
655};
656
657
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000658class MathPowStub: public PlatformCodeStub {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000659 public:
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000660 enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK};
661
662 explicit MathPowStub(ExponentType exponent_type)
663 : exponent_type_(exponent_type) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000664 virtual void Generate(MacroAssembler* masm);
665
666 private:
667 virtual CodeStub::Major MajorKey() { return MathPow; }
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000668 virtual int MinorKey() { return exponent_type_; }
669
670 ExponentType exponent_type_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000671};
672
673
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000674class ICStub: public PlatformCodeStub {
675 public:
676 explicit ICStub(Code::Kind kind) : kind_(kind) { }
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000677 virtual Code::Kind GetCodeKind() const { return kind_; }
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000678 virtual InlineCacheState GetICState() { return MONOMORPHIC; }
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000679
680 bool Describes(Code* code) {
681 return GetMajorKey(code) == MajorKey() && code->stub_info() == MinorKey();
682 }
683
684 protected:
685 class KindBits: public BitField<Code::Kind, 0, 4> {};
686 virtual void FinishCode(Handle<Code> code) {
687 code->set_stub_info(MinorKey());
688 }
689 Code::Kind kind() { return kind_; }
690
691 virtual int MinorKey() {
692 return KindBits::encode(kind_);
693 }
694
695 private:
696 Code::Kind kind_;
697};
698
699
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000700class FunctionPrototypeStub: public ICStub {
701 public:
702 explicit FunctionPrototypeStub(Code::Kind kind) : ICStub(kind) { }
703 virtual void Generate(MacroAssembler* masm);
704
705 private:
706 virtual CodeStub::Major MajorKey() { return FunctionPrototype; }
707};
708
709
710class StringLengthStub: public ICStub {
711 public:
712 StringLengthStub(Code::Kind kind, bool support_wrapper)
713 : ICStub(kind), support_wrapper_(support_wrapper) { }
714 virtual void Generate(MacroAssembler* masm);
715
716 private:
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000717 STATIC_ASSERT(KindBits::kSize == 4);
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000718 class WrapperModeBits: public BitField<bool, 4, 1> {};
719 virtual CodeStub::Major MajorKey() { return StringLength; }
720 virtual int MinorKey() {
721 return KindBits::encode(kind()) | WrapperModeBits::encode(support_wrapper_);
722 }
723
724 bool support_wrapper_;
725};
726
727
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000728class StoreICStub: public ICStub {
729 public:
730 StoreICStub(Code::Kind kind, StrictModeFlag strict_mode)
731 : ICStub(kind), strict_mode_(strict_mode) { }
732
733 protected:
734 virtual Code::ExtraICState GetExtraICState() {
735 return strict_mode_;
736 }
737
738 private:
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000739 STATIC_ASSERT(KindBits::kSize == 4);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000740 class StrictModeBits: public BitField<bool, 4, 1> {};
741 virtual int MinorKey() {
742 return KindBits::encode(kind()) | StrictModeBits::encode(strict_mode_);
743 }
744
745 StrictModeFlag strict_mode_;
746};
747
748
749class StoreArrayLengthStub: public StoreICStub {
750 public:
751 explicit StoreArrayLengthStub(Code::Kind kind, StrictModeFlag strict_mode)
752 : StoreICStub(kind, strict_mode) { }
753 virtual void Generate(MacroAssembler* masm);
754
755 private:
756 virtual CodeStub::Major MajorKey() { return StoreArrayLength; }
757};
758
759
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000760class HICStub: public HydrogenCodeStub {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000761 public:
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000762 virtual Code::Kind GetCodeKind() const { return kind(); }
763 virtual InlineCacheState GetICState() { return MONOMORPHIC; }
764
765 protected:
766 HICStub() : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) { }
767 class KindBits: public BitField<Code::Kind, 0, 4> {};
768 virtual Code::Kind kind() const = 0;
769};
770
771
772class HandlerStub: public HICStub {
773 public:
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000774 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
ulan@chromium.org750145a2013-03-07 15:14:13 +0000775 virtual int GetStubFlags() { return kind(); }
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000776
777 protected:
778 HandlerStub() : HICStub() { }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000779};
780
781
782class LoadFieldStub: public HandlerStub {
783 public:
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000784 LoadFieldStub(bool inobject, int index, Representation representation)
785 : HandlerStub() {
786 Initialize(Code::LOAD_IC, inobject, index, representation);
787 }
788
789 virtual Handle<Code> GenerateCode();
790
791 virtual void InitializeInterfaceDescriptor(
792 Isolate* isolate,
793 CodeStubInterfaceDescriptor* descriptor);
794
795 Representation representation() {
796 if (unboxed_double()) return Representation::Double();
797 return Representation::Tagged();
798 }
799
800 virtual Code::Kind kind() const {
801 return KindBits::decode(bit_field_);
802 }
803
804 bool is_inobject() {
805 return InobjectBits::decode(bit_field_);
806 }
807
808 int offset() {
809 int index = IndexBits::decode(bit_field_);
810 int offset = index * kPointerSize;
811 if (is_inobject()) return offset;
812 return FixedArray::kHeaderSize + offset;
813 }
814
815 bool unboxed_double() {
816 return UnboxedDoubleBits::decode(bit_field_);
817 }
818
819 virtual Code::StubType GetStubType() { return Code::FIELD; }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000820
821 protected:
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000822 LoadFieldStub() : HandlerStub() { }
823
824 void Initialize(Code::Kind kind,
825 bool inobject,
826 int index,
827 Representation representation) {
828 bool unboxed_double = FLAG_track_double_fields && representation.IsDouble();
829 bit_field_ = KindBits::encode(kind)
830 | InobjectBits::encode(inobject)
831 | IndexBits::encode(index)
832 | UnboxedDoubleBits::encode(unboxed_double);
833 }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000834
835 private:
836 STATIC_ASSERT(KindBits::kSize == 4);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000837 class InobjectBits: public BitField<bool, 4, 1> {};
838 class IndexBits: public BitField<int, 5, 11> {};
839 class UnboxedDoubleBits: public BitField<bool, 16, 1> {};
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000840 virtual CodeStub::Major MajorKey() { return LoadField; }
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000841 virtual int NotMissMinorKey() { return bit_field_; }
842
843 int bit_field_;
844};
845
846
847class KeyedLoadFieldStub: public LoadFieldStub {
848 public:
849 KeyedLoadFieldStub(bool inobject, int index, Representation representation)
850 : LoadFieldStub() {
851 Initialize(Code::KEYED_LOAD_IC, inobject, index, representation);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000852 }
853
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000854 virtual void InitializeInterfaceDescriptor(
855 Isolate* isolate,
856 CodeStubInterfaceDescriptor* descriptor);
857
858 virtual Handle<Code> GenerateCode();
859
860 private:
861 virtual CodeStub::Major MajorKey() { return KeyedLoadField; }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000862};
863
864
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000865class BinaryOpStub: public PlatformCodeStub {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000866 public:
867 BinaryOpStub(Token::Value op, OverwriteMode mode)
868 : op_(op),
869 mode_(mode),
870 platform_specific_bit_(false),
871 left_type_(BinaryOpIC::UNINITIALIZED),
872 right_type_(BinaryOpIC::UNINITIALIZED),
873 result_type_(BinaryOpIC::UNINITIALIZED) {
874 Initialize();
875 ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
876 }
877
878 BinaryOpStub(
879 int key,
880 BinaryOpIC::TypeInfo left_type,
881 BinaryOpIC::TypeInfo right_type,
882 BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED)
883 : op_(OpBits::decode(key)),
884 mode_(ModeBits::decode(key)),
885 platform_specific_bit_(PlatformSpecificBits::decode(key)),
886 left_type_(left_type),
887 right_type_(right_type),
888 result_type_(result_type) { }
889
890 static void decode_types_from_minor_key(int minor_key,
891 BinaryOpIC::TypeInfo* left_type,
892 BinaryOpIC::TypeInfo* right_type,
893 BinaryOpIC::TypeInfo* result_type) {
894 *left_type =
895 static_cast<BinaryOpIC::TypeInfo>(LeftTypeBits::decode(minor_key));
896 *right_type =
897 static_cast<BinaryOpIC::TypeInfo>(RightTypeBits::decode(minor_key));
898 *result_type =
899 static_cast<BinaryOpIC::TypeInfo>(ResultTypeBits::decode(minor_key));
900 }
901
902 static Token::Value decode_op_from_minor_key(int minor_key) {
903 return static_cast<Token::Value>(OpBits::decode(minor_key));
904 }
905
906 enum SmiCodeGenerateHeapNumberResults {
907 ALLOW_HEAPNUMBER_RESULTS,
908 NO_HEAPNUMBER_RESULTS
909 };
910
911 private:
912 Token::Value op_;
913 OverwriteMode mode_;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000914 bool platform_specific_bit_; // Indicates SSE3 on IA32.
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000915
916 // Operand type information determined at runtime.
917 BinaryOpIC::TypeInfo left_type_;
918 BinaryOpIC::TypeInfo right_type_;
919 BinaryOpIC::TypeInfo result_type_;
920
921 virtual void PrintName(StringStream* stream);
922
923 // Minor key encoding in 19 bits TTTRRRLLLSOOOOOOOMM.
924 class ModeBits: public BitField<OverwriteMode, 0, 2> {};
925 class OpBits: public BitField<Token::Value, 2, 7> {};
926 class PlatformSpecificBits: public BitField<bool, 9, 1> {};
927 class LeftTypeBits: public BitField<BinaryOpIC::TypeInfo, 10, 3> {};
928 class RightTypeBits: public BitField<BinaryOpIC::TypeInfo, 13, 3> {};
929 class ResultTypeBits: public BitField<BinaryOpIC::TypeInfo, 16, 3> {};
930
931 Major MajorKey() { return BinaryOp; }
932 int MinorKey() {
933 return OpBits::encode(op_)
934 | ModeBits::encode(mode_)
935 | PlatformSpecificBits::encode(platform_specific_bit_)
936 | LeftTypeBits::encode(left_type_)
937 | RightTypeBits::encode(right_type_)
938 | ResultTypeBits::encode(result_type_);
939 }
940
941
942 // Platform-independent implementation.
943 void Generate(MacroAssembler* masm);
944 void GenerateCallRuntime(MacroAssembler* masm);
945
946 // Platform-independent signature, platform-specific implementation.
947 void Initialize();
948 void GenerateAddStrings(MacroAssembler* masm);
949 void GenerateBothStringStub(MacroAssembler* masm);
950 void GenerateGeneric(MacroAssembler* masm);
951 void GenerateGenericStub(MacroAssembler* masm);
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000952 void GenerateNumberStub(MacroAssembler* masm);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000953 void GenerateInt32Stub(MacroAssembler* masm);
954 void GenerateLoadArguments(MacroAssembler* masm);
955 void GenerateOddballStub(MacroAssembler* masm);
956 void GenerateRegisterArgsPush(MacroAssembler* masm);
957 void GenerateReturn(MacroAssembler* masm);
958 void GenerateSmiStub(MacroAssembler* masm);
959 void GenerateStringStub(MacroAssembler* masm);
960 void GenerateTypeTransition(MacroAssembler* masm);
961 void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
962 void GenerateUninitializedStub(MacroAssembler* masm);
963
964 // Entirely platform-specific methods are defined as static helper
965 // functions in the <arch>/code-stubs-<arch>.cc files.
966
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000967 virtual Code::Kind GetCodeKind() const { return Code::BINARY_OP_IC; }
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000968
969 virtual InlineCacheState GetICState() {
970 return BinaryOpIC::ToState(Max(left_type_, right_type_));
971 }
972
973 virtual void FinishCode(Handle<Code> code) {
974 code->set_stub_info(MinorKey());
975 }
976
977 friend class CodeGenerator;
978};
979
980
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000981class ICCompareStub: public PlatformCodeStub {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000982 public:
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000983 ICCompareStub(Token::Value op,
984 CompareIC::State left,
985 CompareIC::State right,
986 CompareIC::State handler)
987 : op_(op),
988 left_(left),
989 right_(right),
990 state_(handler) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000991 ASSERT(Token::IsCompareOp(op));
992 }
993
994 virtual void Generate(MacroAssembler* masm);
995
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000996 void set_known_map(Handle<Map> map) { known_map_ = map; }
997
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000998 static void DecodeMinorKey(int minor_key,
999 CompareIC::State* left_state,
1000 CompareIC::State* right_state,
1001 CompareIC::State* handler_state,
1002 Token::Value* op);
1003
1004 static CompareIC::State CompareState(int minor_key) {
1005 return static_cast<CompareIC::State>(HandlerStateField::decode(minor_key));
1006 }
1007
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001008 private:
1009 class OpField: public BitField<int, 0, 3> { };
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001010 class LeftStateField: public BitField<int, 3, 4> { };
1011 class RightStateField: public BitField<int, 7, 4> { };
1012 class HandlerStateField: public BitField<int, 11, 4> { };
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001013
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +00001014 virtual void FinishCode(Handle<Code> code) {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001015 code->set_stub_info(MinorKey());
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +00001016 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001017
1018 virtual CodeStub::Major MajorKey() { return CompareIC; }
1019 virtual int MinorKey();
1020
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001021 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_IC; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001022
1023 void GenerateSmis(MacroAssembler* masm);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001024 void GenerateNumbers(MacroAssembler* masm);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001025 void GenerateInternalizedStrings(MacroAssembler* masm);
lrn@chromium.org1c092762011-05-09 09:42:16 +00001026 void GenerateStrings(MacroAssembler* masm);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001027 void GenerateUniqueNames(MacroAssembler* masm);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001028 void GenerateObjects(MacroAssembler* masm);
1029 void GenerateMiss(MacroAssembler* masm);
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001030 void GenerateKnownObjects(MacroAssembler* masm);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001031 void GenerateGeneric(MacroAssembler* masm);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001032
1033 bool strict() const { return op_ == Token::EQ_STRICT; }
1034 Condition GetCondition() const { return CompareIC::ComputeCondition(op_); }
1035
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001036 virtual void AddToSpecialCache(Handle<Code> new_object);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00001037 virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001038 virtual bool UseSpecialCache() { return state_ == CompareIC::KNOWN_OBJECT; }
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001039
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001040 Token::Value op_;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001041 CompareIC::State left_;
1042 CompareIC::State right_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001043 CompareIC::State state_;
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001044 Handle<Map> known_map_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001045};
1046
1047
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001048class CompareNilICStub : public HydrogenCodeStub {
1049 public:
1050 enum Types {
1051 kCompareAgainstNull = 1 << 0,
1052 kCompareAgainstUndefined = 1 << 1,
1053 kCompareAgainstMonomorphicMap = 1 << 2,
1054 kCompareAgainstUndetectable = 1 << 3,
1055 kFullCompare = kCompareAgainstNull | kCompareAgainstUndefined |
1056 kCompareAgainstUndetectable
1057 };
1058
1059 CompareNilICStub(EqualityKind kind, NilValue nil, Types types)
1060 : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS), bit_field_(0) {
1061 bit_field_ = EqualityKindField::encode(kind) |
1062 NilValueField::encode(nil) |
1063 TypesField::encode(types);
1064 }
1065
1066 virtual InlineCacheState GetICState() {
1067 Types types = GetTypes();
1068 if (types == kFullCompare) {
1069 return MEGAMORPHIC;
1070 } else if ((types & kCompareAgainstMonomorphicMap) != 0) {
1071 return MONOMORPHIC;
1072 } else {
1073 return PREMONOMORPHIC;
1074 }
1075 }
1076
1077 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_NIL_IC; }
1078
1079 Handle<Code> GenerateCode();
1080
1081 static Handle<Code> GetUninitialized(Isolate* isolate,
1082 EqualityKind kind,
1083 NilValue nil) {
1084 return CompareNilICStub(kind, nil).GetCode(isolate);
1085 }
1086
1087 virtual void InitializeInterfaceDescriptor(
1088 Isolate* isolate,
1089 CodeStubInterfaceDescriptor* descriptor);
1090
1091 static void InitializeForIsolate(Isolate* isolate) {
1092 CompareNilICStub compare_stub(kStrictEquality, kNullValue);
1093 compare_stub.InitializeInterfaceDescriptor(
1094 isolate,
1095 isolate->code_stub_interface_descriptor(CodeStub::CompareNilIC));
1096 }
1097
1098 virtual Code::ExtraICState GetExtraICState() {
1099 return bit_field_;
1100 }
1101
1102 EqualityKind GetKind() { return EqualityKindField::decode(bit_field_); }
1103 NilValue GetNilValue() { return NilValueField::decode(bit_field_); }
1104 Types GetTypes() { return TypesField::decode(bit_field_); }
1105
1106 static Types TypesFromExtraICState(
1107 Code::ExtraICState state) {
1108 return TypesField::decode(state);
1109 }
1110 static EqualityKind EqualityKindFromExtraICState(
1111 Code::ExtraICState state) {
1112 return EqualityKindField::decode(state);
1113 }
1114 static NilValue NilValueFromExtraICState(Code::ExtraICState state) {
1115 return NilValueField::decode(state);
1116 }
1117
1118 static Types GetPatchedICFlags(Code::ExtraICState extra_ic_state,
1119 Handle<Object> object,
1120 bool* already_monomorphic);
1121
1122 private:
1123 friend class CompareNilIC;
1124
1125 class EqualityKindField : public BitField<EqualityKind, 0, 1> {};
1126 class NilValueField : public BitField<NilValue, 1, 1> {};
1127 class TypesField : public BitField<Types, 3, 4> {};
1128
1129 CompareNilICStub(EqualityKind kind, NilValue nil)
1130 : HydrogenCodeStub(CODE_STUB_IS_MISS), bit_field_(0) {
1131 bit_field_ = EqualityKindField::encode(kind) |
1132 NilValueField::encode(nil);
1133 }
1134
1135 virtual CodeStub::Major MajorKey() { return CompareNilIC; }
1136 virtual int NotMissMinorKey() { return bit_field_; }
1137
1138 int bit_field_;
1139
1140 DISALLOW_COPY_AND_ASSIGN(CompareNilICStub);
1141};
1142
1143
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001144class CEntryStub : public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001145 public:
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001146 explicit CEntryStub(int result_size,
1147 SaveFPRegsMode save_doubles = kDontSaveFPRegs)
1148 : result_size_(result_size), save_doubles_(save_doubles) { }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001149
1150 void Generate(MacroAssembler* masm);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001151
1152 // The version of this stub that doesn't save doubles is generated ahead of
1153 // time, so it's OK to call it from other stubs that can't cope with GC during
1154 // their code generation. On machines that always have gp registers (x64) we
1155 // can generate both variants ahead of time.
1156 virtual bool IsPregenerated();
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001157 static void GenerateAheadOfTime(Isolate* isolate);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001158
1159 private:
1160 void GenerateCore(MacroAssembler* masm,
1161 Label* throw_normal_exception,
1162 Label* throw_termination_exception,
1163 Label* throw_out_of_memory_exception,
1164 bool do_gc,
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001165 bool always_allocate_scope);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001166
1167 // Number of pointers/values returned.
1168 const int result_size_;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001169 SaveFPRegsMode save_doubles_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001170
1171 Major MajorKey() { return CEntry; }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001172 int MinorKey();
1173
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001174 bool NeedsImmovableCode();
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001175};
1176
1177
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001178class JSEntryStub : public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001179 public:
1180 JSEntryStub() { }
1181
1182 void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
1183
1184 protected:
1185 void GenerateBody(MacroAssembler* masm, bool is_construct);
1186
1187 private:
1188 Major MajorKey() { return JSEntry; }
1189 int MinorKey() { return 0; }
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +00001190
1191 virtual void FinishCode(Handle<Code> code);
1192
1193 int handler_offset_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001194};
1195
1196
1197class JSConstructEntryStub : public JSEntryStub {
1198 public:
1199 JSConstructEntryStub() { }
1200
1201 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
1202
1203 private:
1204 int MinorKey() { return 1; }
1205
whesse@chromium.org030d38e2011-07-13 13:23:34 +00001206 virtual void PrintName(StringStream* stream) {
1207 stream->Add("JSConstructEntryStub");
1208 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001209};
1210
1211
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001212class ArgumentsAccessStub: public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001213 public:
1214 enum Type {
1215 READ_ELEMENT,
whesse@chromium.org7b260152011-06-20 15:33:18 +00001216 NEW_NON_STRICT_FAST,
1217 NEW_NON_STRICT_SLOW,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001218 NEW_STRICT
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001219 };
1220
1221 explicit ArgumentsAccessStub(Type type) : type_(type) { }
1222
1223 private:
1224 Type type_;
1225
1226 Major MajorKey() { return ArgumentsAccess; }
1227 int MinorKey() { return type_; }
1228
1229 void Generate(MacroAssembler* masm);
1230 void GenerateReadElement(MacroAssembler* masm);
whesse@chromium.org7b260152011-06-20 15:33:18 +00001231 void GenerateNewStrict(MacroAssembler* masm);
1232 void GenerateNewNonStrictFast(MacroAssembler* masm);
1233 void GenerateNewNonStrictSlow(MacroAssembler* masm);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001234
whesse@chromium.org030d38e2011-07-13 13:23:34 +00001235 virtual void PrintName(StringStream* stream);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001236};
1237
1238
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001239class RegExpExecStub: public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001240 public:
1241 RegExpExecStub() { }
1242
1243 private:
1244 Major MajorKey() { return RegExpExec; }
1245 int MinorKey() { return 0; }
1246
1247 void Generate(MacroAssembler* masm);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001248};
1249
1250
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001251class RegExpConstructResultStub: public PlatformCodeStub {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001252 public:
1253 RegExpConstructResultStub() { }
1254
1255 private:
1256 Major MajorKey() { return RegExpConstructResult; }
1257 int MinorKey() { return 0; }
1258
1259 void Generate(MacroAssembler* masm);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001260};
1261
1262
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001263class CallFunctionStub: public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001264 public:
lrn@chromium.org34e60782011-09-15 07:25:40 +00001265 CallFunctionStub(int argc, CallFunctionFlags flags)
1266 : argc_(argc), flags_(flags) { }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001267
1268 void Generate(MacroAssembler* masm);
1269
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001270 virtual void FinishCode(Handle<Code> code) {
1271 code->set_has_function_cache(RecordCallTarget());
1272 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001273
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001274 static int ExtractArgcFromMinorKey(int minor_key) {
1275 return ArgcBits::decode(minor_key);
1276 }
1277
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001278 private:
1279 int argc_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001280 CallFunctionFlags flags_;
1281
whesse@chromium.org030d38e2011-07-13 13:23:34 +00001282 virtual void PrintName(StringStream* stream);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001283
1284 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001285 class FlagBits: public BitField<CallFunctionFlags, 0, 2> {};
1286 class ArgcBits: public BitField<unsigned, 2, 32 - 2> {};
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001287
1288 Major MajorKey() { return CallFunction; }
1289 int MinorKey() {
1290 // Encode the parameters in a unique 32 bit value.
lrn@chromium.org34e60782011-09-15 07:25:40 +00001291 return FlagBits::encode(flags_) | ArgcBits::encode(argc_);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001292 }
1293
danno@chromium.org40cb8782011-05-25 07:58:50 +00001294 bool ReceiverMightBeImplicit() {
1295 return (flags_ & RECEIVER_MIGHT_BE_IMPLICIT) != 0;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001296 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001297
1298 bool RecordCallTarget() {
1299 return (flags_ & RECORD_CALL_TARGET) != 0;
1300 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001301};
1302
1303
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001304class CallConstructStub: public PlatformCodeStub {
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001305 public:
1306 explicit CallConstructStub(CallFunctionFlags flags) : flags_(flags) {}
1307
1308 void Generate(MacroAssembler* masm);
1309
1310 virtual void FinishCode(Handle<Code> code) {
1311 code->set_has_function_cache(RecordCallTarget());
1312 }
1313
1314 private:
1315 CallFunctionFlags flags_;
1316
1317 virtual void PrintName(StringStream* stream);
1318
1319 Major MajorKey() { return CallConstruct; }
1320 int MinorKey() { return flags_; }
1321
1322 bool RecordCallTarget() {
1323 return (flags_ & RECORD_CALL_TARGET) != 0;
1324 }
1325};
1326
1327
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001328enum StringIndexFlags {
1329 // Accepts smis or heap numbers.
1330 STRING_INDEX_IS_NUMBER,
1331
1332 // Accepts smis or heap numbers that are valid array indices
1333 // (ECMA-262 15.4). Invalid indices are reported as being out of
1334 // range.
1335 STRING_INDEX_IS_ARRAY_INDEX
1336};
1337
1338
1339// Generates code implementing String.prototype.charCodeAt.
1340//
1341// Only supports the case when the receiver is a string and the index
1342// is a number (smi or heap number) that is a valid index into the
1343// string. Additional index constraints are specified by the
1344// flags. Otherwise, bails out to the provided labels.
1345//
1346// Register usage: |object| may be changed to another string in a way
1347// that doesn't affect charCodeAt/charAt semantics, |index| is
1348// preserved, |scratch| and |result| are clobbered.
1349class StringCharCodeAtGenerator {
1350 public:
1351 StringCharCodeAtGenerator(Register object,
1352 Register index,
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001353 Register result,
1354 Label* receiver_not_string,
1355 Label* index_not_number,
1356 Label* index_out_of_range,
1357 StringIndexFlags index_flags)
1358 : object_(object),
1359 index_(index),
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001360 result_(result),
1361 receiver_not_string_(receiver_not_string),
1362 index_not_number_(index_not_number),
1363 index_out_of_range_(index_out_of_range),
1364 index_flags_(index_flags) {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001365 ASSERT(!result_.is(object_));
1366 ASSERT(!result_.is(index_));
1367 }
1368
1369 // Generates the fast case code. On the fallthrough path |result|
1370 // register contains the result.
1371 void GenerateFast(MacroAssembler* masm);
1372
1373 // Generates the slow case code. Must not be naturally
1374 // reachable. Expected to be put after a ret instruction (e.g., in
1375 // deferred code). Always jumps back to the fast case.
1376 void GenerateSlow(MacroAssembler* masm,
1377 const RuntimeCallHelper& call_helper);
1378
ulan@chromium.org2e04b582013-02-21 14:06:02 +00001379 // Skip handling slow case and directly jump to bailout.
1380 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1381 masm->bind(&index_not_smi_);
1382 masm->bind(&call_runtime_);
1383 masm->jmp(bailout);
1384 }
1385
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001386 private:
1387 Register object_;
1388 Register index_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001389 Register result_;
1390
1391 Label* receiver_not_string_;
1392 Label* index_not_number_;
1393 Label* index_out_of_range_;
1394
1395 StringIndexFlags index_flags_;
1396
1397 Label call_runtime_;
1398 Label index_not_smi_;
1399 Label got_smi_index_;
1400 Label exit_;
1401
1402 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
1403};
1404
1405
1406// Generates code for creating a one-char string from a char code.
1407class StringCharFromCodeGenerator {
1408 public:
1409 StringCharFromCodeGenerator(Register code,
1410 Register result)
1411 : code_(code),
1412 result_(result) {
1413 ASSERT(!code_.is(result_));
1414 }
1415
1416 // Generates the fast case code. On the fallthrough path |result|
1417 // register contains the result.
1418 void GenerateFast(MacroAssembler* masm);
1419
1420 // Generates the slow case code. Must not be naturally
1421 // reachable. Expected to be put after a ret instruction (e.g., in
1422 // deferred code). Always jumps back to the fast case.
1423 void GenerateSlow(MacroAssembler* masm,
1424 const RuntimeCallHelper& call_helper);
1425
ulan@chromium.org2e04b582013-02-21 14:06:02 +00001426 // Skip handling slow case and directly jump to bailout.
1427 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1428 masm->bind(&slow_case_);
1429 masm->jmp(bailout);
1430 }
1431
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001432 private:
1433 Register code_;
1434 Register result_;
1435
1436 Label slow_case_;
1437 Label exit_;
1438
1439 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
1440};
1441
1442
1443// Generates code implementing String.prototype.charAt.
1444//
1445// Only supports the case when the receiver is a string and the index
1446// is a number (smi or heap number) that is a valid index into the
1447// string. Additional index constraints are specified by the
1448// flags. Otherwise, bails out to the provided labels.
1449//
1450// Register usage: |object| may be changed to another string in a way
1451// that doesn't affect charCodeAt/charAt semantics, |index| is
1452// preserved, |scratch1|, |scratch2|, and |result| are clobbered.
1453class StringCharAtGenerator {
1454 public:
1455 StringCharAtGenerator(Register object,
1456 Register index,
danno@chromium.orgc612e022011-11-10 11:38:15 +00001457 Register scratch,
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001458 Register result,
1459 Label* receiver_not_string,
1460 Label* index_not_number,
1461 Label* index_out_of_range,
1462 StringIndexFlags index_flags)
1463 : char_code_at_generator_(object,
1464 index,
danno@chromium.orgc612e022011-11-10 11:38:15 +00001465 scratch,
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001466 receiver_not_string,
1467 index_not_number,
1468 index_out_of_range,
1469 index_flags),
danno@chromium.orgc612e022011-11-10 11:38:15 +00001470 char_from_code_generator_(scratch, result) {}
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001471
1472 // Generates the fast case code. On the fallthrough path |result|
1473 // register contains the result.
ulan@chromium.org2e04b582013-02-21 14:06:02 +00001474 void GenerateFast(MacroAssembler* masm) {
1475 char_code_at_generator_.GenerateFast(masm);
1476 char_from_code_generator_.GenerateFast(masm);
1477 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001478
1479 // Generates the slow case code. Must not be naturally
1480 // reachable. Expected to be put after a ret instruction (e.g., in
1481 // deferred code). Always jumps back to the fast case.
1482 void GenerateSlow(MacroAssembler* masm,
ulan@chromium.org2e04b582013-02-21 14:06:02 +00001483 const RuntimeCallHelper& call_helper) {
1484 char_code_at_generator_.GenerateSlow(masm, call_helper);
1485 char_from_code_generator_.GenerateSlow(masm, call_helper);
1486 }
1487
1488 // Skip handling slow case and directly jump to bailout.
1489 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1490 char_code_at_generator_.SkipSlow(masm, bailout);
1491 char_from_code_generator_.SkipSlow(masm, bailout);
1492 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001493
1494 private:
1495 StringCharCodeAtGenerator char_code_at_generator_;
1496 StringCharFromCodeGenerator char_from_code_generator_;
1497
1498 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
1499};
1500
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001501
1502class AllowStubCallsScope {
1503 public:
1504 AllowStubCallsScope(MacroAssembler* masm, bool allow)
1505 : masm_(masm), previous_allow_(masm->allow_stub_calls()) {
1506 masm_->set_allow_stub_calls(allow);
1507 }
1508 ~AllowStubCallsScope() {
1509 masm_->set_allow_stub_calls(previous_allow_);
1510 }
1511
1512 private:
1513 MacroAssembler* masm_;
1514 bool previous_allow_;
1515
1516 DISALLOW_COPY_AND_ASSIGN(AllowStubCallsScope);
1517};
1518
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001519
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001520class KeyedLoadDictionaryElementStub : public PlatformCodeStub {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001521 public:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001522 KeyedLoadDictionaryElementStub() {}
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001523
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001524 void Generate(MacroAssembler* masm);
1525
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00001526 private:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001527 Major MajorKey() { return KeyedLoadElement; }
1528 int MinorKey() { return DICTIONARY_ELEMENTS; }
1529
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001530 DISALLOW_COPY_AND_ASSIGN(KeyedLoadDictionaryElementStub);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001531};
1532
1533
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001534class KeyedLoadFastElementStub : public HydrogenCodeStub {
1535 public:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001536 KeyedLoadFastElementStub(bool is_js_array, ElementsKind elements_kind)
1537 : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001538 bit_field_ = ElementsKindBits::encode(elements_kind) |
1539 IsJSArrayBits::encode(is_js_array);
1540 }
1541
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001542 bool is_js_array() const {
1543 return IsJSArrayBits::decode(bit_field_);
1544 }
1545
1546 ElementsKind elements_kind() const {
1547 return ElementsKindBits::decode(bit_field_);
1548 }
1549
1550 virtual Handle<Code> GenerateCode();
1551
1552 virtual void InitializeInterfaceDescriptor(
1553 Isolate* isolate,
1554 CodeStubInterfaceDescriptor* descriptor);
1555
1556 private:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001557 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001558 class IsJSArrayBits: public BitField<bool, 8, 1> {};
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001559 uint32_t bit_field_;
1560
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001561 Major MajorKey() { return KeyedLoadElement; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001562 int NotMissMinorKey() { return bit_field_; }
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001563
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001564 DISALLOW_COPY_AND_ASSIGN(KeyedLoadFastElementStub);
1565};
1566
1567
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001568class KeyedStoreFastElementStub : public HydrogenCodeStub {
1569 public:
1570 KeyedStoreFastElementStub(bool is_js_array,
1571 ElementsKind elements_kind,
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001572 KeyedAccessStoreMode mode)
1573 : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) {
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001574 bit_field_ = ElementsKindBits::encode(elements_kind) |
1575 IsJSArrayBits::encode(is_js_array) |
1576 StoreModeBits::encode(mode);
1577 }
1578
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001579 bool is_js_array() const {
1580 return IsJSArrayBits::decode(bit_field_);
1581 }
1582
1583 ElementsKind elements_kind() const {
1584 return ElementsKindBits::decode(bit_field_);
1585 }
1586
1587 KeyedAccessStoreMode store_mode() const {
1588 return StoreModeBits::decode(bit_field_);
1589 }
1590
1591 virtual Handle<Code> GenerateCode();
1592
1593 virtual void InitializeInterfaceDescriptor(
1594 Isolate* isolate,
1595 CodeStubInterfaceDescriptor* descriptor);
1596
1597 private:
1598 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
1599 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
1600 class IsJSArrayBits: public BitField<bool, 12, 1> {};
1601 uint32_t bit_field_;
1602
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001603 Major MajorKey() { return KeyedStoreElement; }
1604 int NotMissMinorKey() { return bit_field_; }
1605
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001606 DISALLOW_COPY_AND_ASSIGN(KeyedStoreFastElementStub);
1607};
1608
1609
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001610class TransitionElementsKindStub : public HydrogenCodeStub {
1611 public:
1612 TransitionElementsKindStub(ElementsKind from_kind,
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001613 ElementsKind to_kind)
1614 : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001615 bit_field_ = FromKindBits::encode(from_kind) |
1616 ToKindBits::encode(to_kind);
1617 }
1618
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001619 ElementsKind from_kind() const {
1620 return FromKindBits::decode(bit_field_);
1621 }
1622
1623 ElementsKind to_kind() const {
1624 return ToKindBits::decode(bit_field_);
1625 }
1626
1627 virtual Handle<Code> GenerateCode();
1628
1629 virtual void InitializeInterfaceDescriptor(
1630 Isolate* isolate,
1631 CodeStubInterfaceDescriptor* descriptor);
1632
1633 private:
1634 class FromKindBits: public BitField<ElementsKind, 8, 8> {};
1635 class ToKindBits: public BitField<ElementsKind, 0, 8> {};
1636 uint32_t bit_field_;
1637
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001638 Major MajorKey() { return TransitionElementsKind; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001639 int NotMissMinorKey() { return bit_field_; }
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001640
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001641 DISALLOW_COPY_AND_ASSIGN(TransitionElementsKindStub);
1642};
1643
1644
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001645class ArrayConstructorStubBase : public HydrogenCodeStub {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001646 public:
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001647 ArrayConstructorStubBase(ElementsKind kind, AllocationSiteMode mode)
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001648 : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001649 bit_field_ = ElementsKindBits::encode(kind) |
1650 AllocationSiteModeBits::encode(mode == TRACK_ALLOCATION_SITE);
1651 }
1652
1653 ElementsKind elements_kind() const {
1654 return ElementsKindBits::decode(bit_field_);
1655 }
1656
1657 AllocationSiteMode mode() const {
1658 return AllocationSiteModeBits::decode(bit_field_)
1659 ? TRACK_ALLOCATION_SITE
1660 : DONT_TRACK_ALLOCATION_SITE;
1661 }
1662
1663 virtual bool IsPregenerated() { return true; }
1664 static void GenerateStubsAheadOfTime(Isolate* isolate);
1665 static void InstallDescriptors(Isolate* isolate);
1666
1667 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001668 static const int kConstructor = 0;
1669 static const int kPropertyCell = 1;
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001670
1671 private:
1672 int NotMissMinorKey() { return bit_field_; }
1673
1674 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
1675 class AllocationSiteModeBits: public BitField<bool, 8, 1> {};
1676 uint32_t bit_field_;
1677
1678 DISALLOW_COPY_AND_ASSIGN(ArrayConstructorStubBase);
1679};
1680
1681
1682class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
1683 public:
1684 ArrayNoArgumentConstructorStub(
1685 ElementsKind kind,
1686 AllocationSiteMode mode = TRACK_ALLOCATION_SITE)
1687 : ArrayConstructorStubBase(kind, mode) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001688 }
1689
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001690 virtual Handle<Code> GenerateCode();
1691
1692 virtual void InitializeInterfaceDescriptor(
1693 Isolate* isolate,
1694 CodeStubInterfaceDescriptor* descriptor);
1695
1696 private:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001697 Major MajorKey() { return ArrayNoArgumentConstructor; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001698
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001699 DISALLOW_COPY_AND_ASSIGN(ArrayNoArgumentConstructorStub);
1700};
1701
1702
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001703class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001704 public:
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001705 ArraySingleArgumentConstructorStub(
1706 ElementsKind kind,
1707 AllocationSiteMode mode = TRACK_ALLOCATION_SITE)
1708 : ArrayConstructorStubBase(kind, mode) {
1709 }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001710
1711 virtual Handle<Code> GenerateCode();
1712
1713 virtual void InitializeInterfaceDescriptor(
1714 Isolate* isolate,
1715 CodeStubInterfaceDescriptor* descriptor);
1716
1717 private:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001718 Major MajorKey() { return ArraySingleArgumentConstructor; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001719
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001720 DISALLOW_COPY_AND_ASSIGN(ArraySingleArgumentConstructorStub);
1721};
1722
1723
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001724class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001725 public:
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001726 ArrayNArgumentsConstructorStub(
1727 ElementsKind kind,
1728 AllocationSiteMode mode = TRACK_ALLOCATION_SITE) :
1729 ArrayConstructorStubBase(kind, mode) {
1730 }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001731
1732 virtual Handle<Code> GenerateCode();
1733
1734 virtual void InitializeInterfaceDescriptor(
1735 Isolate* isolate,
1736 CodeStubInterfaceDescriptor* descriptor);
1737
1738 private:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001739 Major MajorKey() { return ArrayNArgumentsConstructor; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001740
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001741 DISALLOW_COPY_AND_ASSIGN(ArrayNArgumentsConstructorStub);
1742};
1743
1744
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001745class KeyedStoreElementStub : public PlatformCodeStub {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001746 public:
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00001747 KeyedStoreElementStub(bool is_js_array,
ulan@chromium.org65a89c22012-02-14 11:46:07 +00001748 ElementsKind elements_kind,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001749 KeyedAccessStoreMode store_mode)
ulan@chromium.org65a89c22012-02-14 11:46:07 +00001750 : is_js_array_(is_js_array),
1751 elements_kind_(elements_kind),
ulan@chromium.org750145a2013-03-07 15:14:13 +00001752 store_mode_(store_mode),
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00001753 fp_registers_(CanUseFPRegisters()) { }
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001754
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00001755 Major MajorKey() { return KeyedStoreElement; }
1756 int MinorKey() {
ulan@chromium.org65a89c22012-02-14 11:46:07 +00001757 return ElementsKindBits::encode(elements_kind_) |
1758 IsJSArrayBits::encode(is_js_array_) |
ulan@chromium.org750145a2013-03-07 15:14:13 +00001759 StoreModeBits::encode(store_mode_) |
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00001760 FPRegisters::encode(fp_registers_);
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00001761 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001762
1763 void Generate(MacroAssembler* masm);
1764
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001765 private:
ulan@chromium.org750145a2013-03-07 15:14:13 +00001766 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
1767 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
1768 class IsJSArrayBits: public BitField<bool, 12, 1> {};
1769 class FPRegisters: public BitField<bool, 13, 1> {};
ulan@chromium.org65a89c22012-02-14 11:46:07 +00001770
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001771 bool is_js_array_;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001772 ElementsKind elements_kind_;
ulan@chromium.org750145a2013-03-07 15:14:13 +00001773 KeyedAccessStoreMode store_mode_;
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00001774 bool fp_registers_;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001775
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00001776 DISALLOW_COPY_AND_ASSIGN(KeyedStoreElementStub);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001777};
1778
1779
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001780class ToBooleanStub: public PlatformCodeStub {
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001781 public:
ricow@chromium.org9fa09672011-07-25 11:05:35 +00001782 enum Type {
1783 UNDEFINED,
1784 BOOLEAN,
1785 NULL_TYPE,
1786 SMI,
1787 SPEC_OBJECT,
1788 STRING,
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00001789 SYMBOL,
ricow@chromium.org9fa09672011-07-25 11:05:35 +00001790 HEAP_NUMBER,
ricow@chromium.org9fa09672011-07-25 11:05:35 +00001791 NUMBER_OF_TYPES
1792 };
1793
1794 // At most 8 different types can be distinguished, because the Code object
1795 // only has room for a single byte to hold a set of these types. :-P
1796 STATIC_ASSERT(NUMBER_OF_TYPES <= 8);
1797
1798 class Types {
1799 public:
1800 Types() {}
1801 explicit Types(byte bits) : set_(bits) {}
1802
1803 bool IsEmpty() const { return set_.IsEmpty(); }
1804 bool Contains(Type type) const { return set_.Contains(type); }
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001805 bool ContainsAnyOf(Types types) const {
1806 return set_.ContainsAnyOf(types.set_);
1807 }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00001808 void Add(Type type) { set_.Add(type); }
1809 byte ToByte() const { return set_.ToIntegral(); }
vegorov@chromium.org7943d462011-08-01 11:41:52 +00001810 void Print(StringStream* stream) const;
1811 void TraceTransition(Types to) const;
ricow@chromium.org9fa09672011-07-25 11:05:35 +00001812 bool Record(Handle<Object> object);
vegorov@chromium.org7943d462011-08-01 11:41:52 +00001813 bool NeedsMap() const;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001814 bool CanBeUndetectable() const;
ricow@chromium.org9fa09672011-07-25 11:05:35 +00001815
1816 private:
1817 EnumSet<Type, byte> set_;
1818 };
1819
ricow@chromium.org2c99e282011-07-28 09:15:17 +00001820 static Types no_types() { return Types(); }
1821 static Types all_types() { return Types((1 << NUMBER_OF_TYPES) - 1); }
1822
ricow@chromium.org9fa09672011-07-25 11:05:35 +00001823 explicit ToBooleanStub(Register tos, Types types = Types())
1824 : tos_(tos), types_(types) { }
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001825
1826 void Generate(MacroAssembler* masm);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001827 virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00001828 virtual void PrintName(StringStream* stream);
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001829
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001830 virtual bool SometimesSetsUpAFrame() { return false; }
1831
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001832 private:
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001833 Major MajorKey() { return ToBoolean; }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00001834 int MinorKey() { return (tos_.code() << NUMBER_OF_TYPES) | types_.ToByte(); }
1835
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +00001836 virtual void FinishCode(Handle<Code> code) {
ricow@chromium.org9fa09672011-07-25 11:05:35 +00001837 code->set_to_boolean_state(types_.ToByte());
1838 }
1839
1840 void CheckOddball(MacroAssembler* masm,
1841 Type type,
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +00001842 Heap::RootListIndex value,
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001843 bool result);
ricow@chromium.org9fa09672011-07-25 11:05:35 +00001844 void GenerateTypeTransition(MacroAssembler* masm);
1845
1846 Register tos_;
1847 Types types_;
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001848};
1849
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001850
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001851class ElementsTransitionAndStoreStub : public PlatformCodeStub {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001852 public:
1853 ElementsTransitionAndStoreStub(ElementsKind from,
1854 ElementsKind to,
1855 bool is_jsarray,
ulan@chromium.org65a89c22012-02-14 11:46:07 +00001856 StrictModeFlag strict_mode,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001857 KeyedAccessStoreMode store_mode)
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001858 : from_(from),
1859 to_(to),
1860 is_jsarray_(is_jsarray),
ulan@chromium.org65a89c22012-02-14 11:46:07 +00001861 strict_mode_(strict_mode),
ulan@chromium.org750145a2013-03-07 15:14:13 +00001862 store_mode_(store_mode) {}
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001863
1864 private:
ulan@chromium.org750145a2013-03-07 15:14:13 +00001865 class FromBits: public BitField<ElementsKind, 0, 8> {};
1866 class ToBits: public BitField<ElementsKind, 8, 8> {};
1867 class IsJSArrayBits: public BitField<bool, 16, 1> {};
1868 class StrictModeBits: public BitField<StrictModeFlag, 17, 1> {};
1869 class StoreModeBits: public BitField<KeyedAccessStoreMode, 18, 4> {};
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001870
1871 Major MajorKey() { return ElementsTransitionAndStore; }
1872 int MinorKey() {
1873 return FromBits::encode(from_) |
1874 ToBits::encode(to_) |
1875 IsJSArrayBits::encode(is_jsarray_) |
ulan@chromium.org65a89c22012-02-14 11:46:07 +00001876 StrictModeBits::encode(strict_mode_) |
ulan@chromium.org750145a2013-03-07 15:14:13 +00001877 StoreModeBits::encode(store_mode_);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001878 }
1879
1880 void Generate(MacroAssembler* masm);
1881
1882 ElementsKind from_;
1883 ElementsKind to_;
1884 bool is_jsarray_;
1885 StrictModeFlag strict_mode_;
ulan@chromium.org750145a2013-03-07 15:14:13 +00001886 KeyedAccessStoreMode store_mode_;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001887
1888 DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub);
1889};
1890
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001891
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001892class StoreArrayLiteralElementStub : public PlatformCodeStub {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001893 public:
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00001894 StoreArrayLiteralElementStub()
1895 : fp_registers_(CanUseFPRegisters()) { }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001896
1897 private:
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00001898 class FPRegisters: public BitField<bool, 0, 1> {};
1899
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001900 Major MajorKey() { return StoreArrayLiteralElement; }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00001901 int MinorKey() { return FPRegisters::encode(fp_registers_); }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001902
1903 void Generate(MacroAssembler* masm);
1904
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00001905 bool fp_registers_;
1906
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001907 DISALLOW_COPY_AND_ASSIGN(StoreArrayLiteralElementStub);
1908};
1909
verwaest@chromium.org753aee42012-07-17 16:15:42 +00001910
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00001911class StubFailureTrampolineStub : public PlatformCodeStub {
1912 public:
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00001913 explicit StubFailureTrampolineStub(StubFunctionMode function_mode)
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001914 : fp_registers_(CanUseFPRegisters()), function_mode_(function_mode) {}
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +00001915
1916 virtual bool IsPregenerated() { return true; }
1917
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001918 static void GenerateAheadOfTime(Isolate* isolate);
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00001919
1920 private:
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001921 class FPRegisters: public BitField<bool, 0, 1> {};
1922 class FunctionModeField: public BitField<StubFunctionMode, 1, 1> {};
1923
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00001924 Major MajorKey() { return StubFailureTrampoline; }
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001925 int MinorKey() {
1926 return FPRegisters::encode(fp_registers_) |
1927 FunctionModeField::encode(function_mode_);
1928 }
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00001929
1930 void Generate(MacroAssembler* masm);
1931
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001932 bool fp_registers_;
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00001933 StubFunctionMode function_mode_;
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +00001934
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00001935 DISALLOW_COPY_AND_ASSIGN(StubFailureTrampolineStub);
1936};
1937
1938
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001939class ProfileEntryHookStub : public PlatformCodeStub {
verwaest@chromium.org753aee42012-07-17 16:15:42 +00001940 public:
1941 explicit ProfileEntryHookStub() {}
1942
1943 // The profile entry hook function is not allowed to cause a GC.
1944 virtual bool SometimesSetsUpAFrame() { return false; }
1945
1946 // Generates a call to the entry hook if it's enabled.
1947 static void MaybeCallEntryHook(MacroAssembler* masm);
1948
1949 // Sets or unsets the entry hook function. Returns true on success,
1950 // false on an attempt to replace a non-NULL entry hook with another
1951 // non-NULL hook.
1952 static bool SetFunctionEntryHook(FunctionEntryHook entry_hook);
1953
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00001954 static bool HasEntryHook() { return entry_hook_ != NULL; }
1955
verwaest@chromium.org753aee42012-07-17 16:15:42 +00001956 private:
1957 static void EntryHookTrampoline(intptr_t function,
1958 intptr_t stack_pointer);
1959
1960 Major MajorKey() { return ProfileEntryHook; }
1961 int MinorKey() { return 0; }
1962
1963 void Generate(MacroAssembler* masm);
1964
1965 // The current function entry hook.
1966 static FunctionEntryHook entry_hook_;
1967
1968 DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub);
1969};
1970
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001971} } // namespace v8::internal
1972
1973#endif // V8_CODE_STUBS_H_