blob: c7076b6f126174a7f33a6150204ef93d0a1d25a1 [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) \
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000080 V(InternalArrayNoArgumentConstructor) \
81 V(InternalArraySingleArgumentConstructor) \
82 V(InternalArrayNArgumentsConstructor) \
sgjesse@chromium.org6db88712011-07-11 11:41:22 +000083 V(KeyedStoreElement) \
lrn@chromium.org1c092762011-05-09 09:42:16 +000084 V(DebuggerStatement) \
ulan@chromium.org750145a2013-03-07 15:14:13 +000085 V(NameDictionaryLookup) \
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000086 V(ElementsTransitionAndStore) \
danno@chromium.org94b0d6f2013-02-04 13:33:20 +000087 V(TransitionElementsKind) \
verwaest@chromium.org753aee42012-07-17 16:15:42 +000088 V(StoreArrayLiteralElement) \
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +000089 V(StubFailureTrampoline) \
danno@chromium.orgca29dd82013-04-26 11:59:48 +000090 V(ArrayConstructor) \
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000091 V(InternalArrayConstructor) \
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000092 V(ProfileEntryHook) \
93 /* IC Handler stubs */ \
ulan@chromium.org57ff8812013-05-10 08:16:55 +000094 V(LoadField) \
95 V(KeyedLoadField)
ager@chromium.org3811b432009-10-28 14:53:37 +000096
97// List of code stubs only used on ARM platforms.
98#ifdef V8_TARGET_ARCH_ARM
99#define CODE_STUB_LIST_ARM(V) \
100 V(GetProperty) \
101 V(SetProperty) \
102 V(InvokeBuiltin) \
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000103 V(RegExpCEntry) \
104 V(DirectCEntry)
ager@chromium.org3811b432009-10-28 14:53:37 +0000105#else
106#define CODE_STUB_LIST_ARM(V)
107#endif
108
lrn@chromium.org7516f052011-03-30 08:52:27 +0000109// List of code stubs only used on MIPS platforms.
110#ifdef V8_TARGET_ARCH_MIPS
111#define CODE_STUB_LIST_MIPS(V) \
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000112 V(RegExpCEntry) \
113 V(DirectCEntry)
lrn@chromium.org7516f052011-03-30 08:52:27 +0000114#else
115#define CODE_STUB_LIST_MIPS(V)
116#endif
117
ager@chromium.org3811b432009-10-28 14:53:37 +0000118// Combined list of code stubs.
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000119#define CODE_STUB_LIST(V) \
120 CODE_STUB_LIST_ALL_PLATFORMS(V) \
lrn@chromium.org7516f052011-03-30 08:52:27 +0000121 CODE_STUB_LIST_ARM(V) \
122 CODE_STUB_LIST_MIPS(V)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000123
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000124// Mode to overwrite BinaryExpression values.
125enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
126enum UnaryOverwriteMode { UNARY_OVERWRITE, UNARY_NO_OVERWRITE };
127
128
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000129// Stub is base classes of all stubs.
130class CodeStub BASE_EMBEDDED {
131 public:
132 enum Major {
ager@chromium.org3811b432009-10-28 14:53:37 +0000133#define DEF_ENUM(name) name,
134 CODE_STUB_LIST(DEF_ENUM)
135#undef DEF_ENUM
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000136 NoCache, // marker for stubs that do custom caching
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000137 NUMBER_OF_IDS
138 };
139
140 // Retrieve the code for the stub. Generate the code if needed.
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000141 Handle<Code> GetCode(Isolate* isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000142
143 static Major MajorKeyFromKey(uint32_t key) {
144 return static_cast<Major>(MajorKeyBits::decode(key));
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000145 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000146 static int MinorKeyFromKey(uint32_t key) {
147 return MinorKeyBits::decode(key);
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000148 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000149
150 // Gets the major key from a code object that is a code stub or binary op IC.
151 static Major GetMajorKey(Code* code_stub) {
152 return static_cast<Major>(code_stub->major_key());
153 }
154
ager@chromium.org5c838252010-02-19 08:53:10 +0000155 static const char* MajorName(Major major_key, bool allow_unknown_keys);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000156
157 virtual ~CodeStub() {}
158
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000159 bool CompilingCallsToThisStubIsGCSafe(Isolate* isolate) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000160 bool is_pregenerated = IsPregenerated();
161 Code* code = NULL;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000162 CHECK(!is_pregenerated || FindCodeInCache(&code, isolate));
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000163 return is_pregenerated;
164 }
165
166 // See comment above, where Instanceof is defined.
167 virtual bool IsPregenerated() { return false; }
168
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000169 static void GenerateStubsAheadOfTime(Isolate* isolate);
170 static void GenerateFPStubs(Isolate* isolate);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000171
172 // Some stubs put untagged junk on the stack that cannot be scanned by the
173 // GC. This means that we must be statically sure that no GC can occur while
174 // they are running. If that is the case they should override this to return
175 // true, which will cause an assertion if we try to call something that can
176 // GC or if we try to put a stack frame on top of the junk, which would not
177 // result in a traversable stack.
178 virtual bool SometimesSetsUpAFrame() { return true; }
179
danno@chromium.orgc612e022011-11-10 11:38:15 +0000180 // Lookup the code in the (possibly custom) cache.
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000181 bool FindCodeInCache(Code** code_out, Isolate* isolate);
danno@chromium.orgc612e022011-11-10 11:38:15 +0000182
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000183 // Returns information for computing the number key.
184 virtual Major MajorKey() = 0;
185 virtual int MinorKey() = 0;
186
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000187 virtual InlineCacheState GetICState() {
188 return UNINITIALIZED;
189 }
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000190 virtual Code::ExtraICState GetExtraICState() {
191 return Code::kNoExtraICState;
192 }
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000193 virtual Code::StubType GetStubType() {
194 return Code::NORMAL;
195 }
196 virtual int GetStubFlags() {
197 return -1;
198 }
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000199
200 protected:
201 static bool CanUseFPRegisters();
202
203 // Generates the assembler code for the stub.
204 virtual Handle<Code> GenerateCode() = 0;
205
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000206
207 // Returns whether the code generated for this stub needs to be allocated as
208 // a fixed (non-moveable) code object.
209 virtual bool NeedsImmovableCode() { return false; }
210
211 private:
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000212 // Perform bookkeeping required after code generation when stub code is
213 // initially generated.
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000214 void RecordCodeGeneration(Code* code, Isolate* isolate);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000215
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000216 // Finish the code object after it has been generated.
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +0000217 virtual void FinishCode(Handle<Code> code) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000218
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000219 // Activate newly generated stub. Is called after
220 // registering stub in the stub cache.
221 virtual void Activate(Code* code) { }
222
danno@chromium.org40cb8782011-05-25 07:58:50 +0000223 // BinaryOpStub needs to override this.
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000224 virtual Code::Kind GetCodeKind() const;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000225
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000226 // Add the code to a specialized cache, specific to an individual
227 // stub type. Please note, this method must add the code object to a
228 // roots object, otherwise we will remove the code during GC.
229 virtual void AddToSpecialCache(Handle<Code> new_object) { }
230
231 // Find code in a specialized cache, work is delegated to the specific stub.
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000232 virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate) {
233 return false;
234 }
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000235
236 // If a stub uses a special cache override this.
237 virtual bool UseSpecialCache() { return false; }
238
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000239 // Returns a name for logging/debugging purposes.
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000240 SmartArrayPointer<const char> GetName();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000241 virtual void PrintName(StringStream* stream);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000242
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000243 // Computes the key based on major and minor.
244 uint32_t GetKey() {
245 ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
246 return MinorKeyBits::encode(MinorKey()) |
247 MajorKeyBits::encode(MajorKey());
248 }
249
danno@chromium.org81cac2b2012-07-10 11:28:27 +0000250 class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
251 class MinorKeyBits: public BitField<uint32_t,
252 kStubMajorKeyBits, kStubMinorKeyBits> {}; // NOLINT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000253
254 friend class BreakPointIterator;
255};
256
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000257
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000258class PlatformCodeStub : public CodeStub {
259 public:
260 // Retrieve the code for the stub. Generate the code if needed.
261 virtual Handle<Code> GenerateCode();
262
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000263 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000264
265 protected:
266 // Generates the assembler code for the stub.
267 virtual void Generate(MacroAssembler* masm) = 0;
268};
269
270
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000271enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
272
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000273
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000274struct CodeStubInterfaceDescriptor {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000275 CodeStubInterfaceDescriptor();
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000276 int register_param_count_;
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000277 const Register* stack_parameter_count_;
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000278 // if hint_stack_parameter_count_ > 0, the code stub can optimize the
279 // return sequence. Default value is -1, which means it is ignored.
280 int hint_stack_parameter_count_;
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000281 StubFunctionMode function_mode_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000282 Register* register_params_;
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000283 Address deoptimization_handler_;
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000284
285 int environment_length() const {
286 if (stack_parameter_count_ != NULL) {
287 return register_param_count_ + 1;
288 }
289 return register_param_count_;
290 }
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000291
292 bool initialized() const { return register_param_count_ >= 0; }
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000293
294 void SetMissHandler(ExternalReference handler) {
295 miss_handler_ = handler;
296 has_miss_handler_ = true;
297 }
298
299 ExternalReference miss_handler() {
300 ASSERT(has_miss_handler_);
301 return miss_handler_;
302 }
303
304 bool has_miss_handler() {
305 return has_miss_handler_;
306 }
307
308 private:
309 ExternalReference miss_handler_;
310 bool has_miss_handler_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000311};
312
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000313// A helper to make up for the fact that type Register is not fully
314// defined outside of the platform directories
315#define DESCRIPTOR_GET_PARAMETER_REGISTER(descriptor, index) \
316 ((index) == (descriptor)->register_param_count_) \
317 ? *((descriptor)->stack_parameter_count_) \
318 : (descriptor)->register_params_[(index)]
319
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000320
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000321class HydrogenCodeStub : public CodeStub {
322 public:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000323 enum InitializationState {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000324 UNINITIALIZED,
325 INITIALIZED
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000326 };
327
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000328 explicit HydrogenCodeStub(InitializationState state = INITIALIZED) {
329 is_uninitialized_ = (state == UNINITIALIZED);
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000330 }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000331
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000332 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000333
334 CodeStubInterfaceDescriptor* GetInterfaceDescriptor(Isolate* isolate) {
335 return isolate->code_stub_interface_descriptor(MajorKey());
336 }
337
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000338 bool IsUninitialized() { return is_uninitialized_; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000339
340 template<class SubClass>
341 static Handle<Code> GetUninitialized(Isolate* isolate) {
342 SubClass::GenerateAheadOfTime(isolate);
343 return SubClass().GetCode(isolate);
344 }
345
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000346 virtual void InitializeInterfaceDescriptor(
347 Isolate* isolate,
348 CodeStubInterfaceDescriptor* descriptor) = 0;
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000349
350 // Retrieve the code for the stub. Generate the code if needed.
351 virtual Handle<Code> GenerateCode() = 0;
352
353 virtual int NotMissMinorKey() = 0;
354
355 Handle<Code> GenerateLightweightMissCode(Isolate* isolate);
356
357 private:
358 class MinorKeyBits: public BitField<int, 0, kStubMinorKeyBits - 1> {};
359 class IsMissBits: public BitField<bool, kStubMinorKeyBits - 1, 1> {};
360
361 void GenerateLightweightMiss(MacroAssembler* masm);
362 virtual int MinorKey() {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000363 return IsMissBits::encode(is_uninitialized_) |
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000364 MinorKeyBits::encode(NotMissMinorKey());
365 }
366
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000367 bool is_uninitialized_;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000368};
369
370
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000371// Helper interface to prepare to/restore after making runtime calls.
372class RuntimeCallHelper {
373 public:
374 virtual ~RuntimeCallHelper() {}
375
376 virtual void BeforeCall(MacroAssembler* masm) const = 0;
377
378 virtual void AfterCall(MacroAssembler* masm) const = 0;
379
380 protected:
381 RuntimeCallHelper() {}
382
383 private:
384 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
385};
386
387} } // namespace v8::internal
388
389#if V8_TARGET_ARCH_IA32
390#include "ia32/code-stubs-ia32.h"
391#elif V8_TARGET_ARCH_X64
392#include "x64/code-stubs-x64.h"
393#elif V8_TARGET_ARCH_ARM
394#include "arm/code-stubs-arm.h"
395#elif V8_TARGET_ARCH_MIPS
396#include "mips/code-stubs-mips.h"
397#else
398#error Unsupported target architecture.
399#endif
400
401namespace v8 {
402namespace internal {
403
404
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000405// RuntimeCallHelper implementation used in stubs: enters/leaves a
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000406// newly created internal frame before/after the runtime call.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000407class StubRuntimeCallHelper : public RuntimeCallHelper {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000408 public:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000409 StubRuntimeCallHelper() {}
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000410
411 virtual void BeforeCall(MacroAssembler* masm) const;
412
413 virtual void AfterCall(MacroAssembler* masm) const;
414};
415
416
417// Trivial RuntimeCallHelper implementation.
418class NopRuntimeCallHelper : public RuntimeCallHelper {
419 public:
420 NopRuntimeCallHelper() {}
421
422 virtual void BeforeCall(MacroAssembler* masm) const {}
423
424 virtual void AfterCall(MacroAssembler* masm) const {}
425};
426
427
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000428class StackCheckStub : public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000429 public:
430 StackCheckStub() { }
431
432 void Generate(MacroAssembler* masm);
433
434 private:
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000435 Major MajorKey() { return StackCheck; }
436 int MinorKey() { return 0; }
437};
438
439
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000440class InterruptStub : public PlatformCodeStub {
yangguo@chromium.org56454712012-02-16 15:33:53 +0000441 public:
442 InterruptStub() { }
443
444 void Generate(MacroAssembler* masm);
445
446 private:
447 Major MajorKey() { return Interrupt; }
448 int MinorKey() { return 0; }
449};
450
451
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000452class ToNumberStub: public PlatformCodeStub {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000453 public:
454 ToNumberStub() { }
455
456 void Generate(MacroAssembler* masm);
457
458 private:
459 Major MajorKey() { return ToNumber; }
460 int MinorKey() { return 0; }
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000461};
462
463
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000464class FastNewClosureStub : public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000465 public:
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000466 explicit FastNewClosureStub(LanguageMode language_mode, bool is_generator)
467 : language_mode_(language_mode),
468 is_generator_(is_generator) { }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000469
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000470 void Generate(MacroAssembler* masm);
471
472 private:
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000473 class StrictModeBits: public BitField<bool, 0, 1> {};
474 class IsGeneratorBits: public BitField<bool, 1, 1> {};
475
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000476 Major MajorKey() { return FastNewClosure; }
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000477 int MinorKey() {
478 return StrictModeBits::encode(language_mode_ != CLASSIC_MODE) |
479 IsGeneratorBits::encode(is_generator_);
480 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000481
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000482 LanguageMode language_mode_;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000483 bool is_generator_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000484};
485
486
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000487class FastNewContextStub : public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000488 public:
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000489 static const int kMaximumSlots = 64;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000490
491 explicit FastNewContextStub(int slots) : slots_(slots) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000492 ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000493 }
494
495 void Generate(MacroAssembler* masm);
496
497 private:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000498 int slots_;
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000499
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000500 Major MajorKey() { return FastNewContext; }
501 int MinorKey() { return slots_; }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000502};
503
504
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000505class FastNewBlockContextStub : public PlatformCodeStub {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000506 public:
507 static const int kMaximumSlots = 64;
508
509 explicit FastNewBlockContextStub(int slots) : slots_(slots) {
510 ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
511 }
512
513 void Generate(MacroAssembler* masm);
514
515 private:
516 int slots_;
517
518 Major MajorKey() { return FastNewBlockContext; }
519 int MinorKey() { return slots_; }
520};
521
522
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000523class FastCloneShallowArrayStub : public HydrogenCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000524 public:
525 // Maximum length of copied elements array.
526 static const int kMaximumClonedLength = 8;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000527 enum Mode {
528 CLONE_ELEMENTS,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000529 CLONE_DOUBLE_ELEMENTS,
erikcorry0ad885c2011-11-21 13:51:57 +0000530 COPY_ON_WRITE_ELEMENTS,
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000531 CLONE_ANY_ELEMENTS,
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000532 LAST_CLONE_MODE = CLONE_ANY_ELEMENTS
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000533 };
534
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000535 static const int kFastCloneModeCount = LAST_CLONE_MODE + 1;
536
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000537 FastCloneShallowArrayStub(Mode mode,
538 AllocationSiteMode allocation_site_mode,
539 int length)
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000540 : mode_(mode),
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000541 allocation_site_mode_(allocation_site_mode),
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000542 length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000543 ASSERT_GE(length_, 0);
544 ASSERT_LE(length_, kMaximumClonedLength);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000545 }
546
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000547 Mode mode() const { return mode_; }
548 int length() const { return length_; }
549 AllocationSiteMode allocation_site_mode() const {
550 return allocation_site_mode_;
551 }
552
553 ElementsKind ComputeElementsKind() const {
554 switch (mode()) {
555 case CLONE_ELEMENTS:
556 case COPY_ON_WRITE_ELEMENTS:
557 return FAST_ELEMENTS;
558 case CLONE_DOUBLE_ELEMENTS:
559 return FAST_DOUBLE_ELEMENTS;
560 case CLONE_ANY_ELEMENTS:
561 /*fall-through*/;
562 }
563 UNREACHABLE();
564 return LAST_ELEMENTS_KIND;
565 }
566
567 virtual Handle<Code> GenerateCode();
568
569 virtual void InitializeInterfaceDescriptor(
570 Isolate* isolate,
571 CodeStubInterfaceDescriptor* descriptor);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000572
573 private:
574 Mode mode_;
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000575 AllocationSiteMode allocation_site_mode_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000576 int length_;
577
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000578 class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
579 class ModeBits: public BitField<Mode, 1, 4> {};
580 class LengthBits: public BitField<int, 5, 4> {};
581 // Ensure data fits within available bits.
582 STATIC_ASSERT(LAST_ALLOCATION_SITE_MODE == 1);
583 STATIC_ASSERT(kFastCloneModeCount < 16);
584 STATIC_ASSERT(kMaximumClonedLength < 16);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000585 Major MajorKey() { return FastCloneShallowArray; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000586 int NotMissMinorKey() {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000587 return AllocationSiteModeBits::encode(allocation_site_mode_)
588 | ModeBits::encode(mode_)
589 | LengthBits::encode(length_);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000590 }
591};
592
593
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000594class FastCloneShallowObjectStub : public HydrogenCodeStub {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000595 public:
596 // Maximum number of properties in copied object.
597 static const int kMaximumClonedProperties = 6;
598
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000599 explicit FastCloneShallowObjectStub(int length)
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000600 : length_(length) {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000601 ASSERT_GE(length_, 0);
602 ASSERT_LE(length_, kMaximumClonedProperties);
603 }
604
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000605 int length() const { return length_; }
606
607 virtual Handle<Code> GenerateCode();
608
609 virtual void InitializeInterfaceDescriptor(
610 Isolate* isolate,
611 CodeStubInterfaceDescriptor* descriptor);
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000612
613 private:
614 int length_;
615
616 Major MajorKey() { return FastCloneShallowObject; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +0000617 int NotMissMinorKey() { return length_; }
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000618
619 DISALLOW_COPY_AND_ASSIGN(FastCloneShallowObjectStub);
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000620};
621
622
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000623class InstanceofStub: public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000624 public:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000625 enum Flags {
626 kNoFlags = 0,
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000627 kArgsInRegisters = 1 << 0,
628 kCallSiteInlineCheck = 1 << 1,
629 kReturnTrueFalseObject = 1 << 2
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000630 };
631
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000632 explicit InstanceofStub(Flags flags) : flags_(flags) { }
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000633
634 static Register left();
635 static Register right();
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000636
637 void Generate(MacroAssembler* masm);
638
639 private:
640 Major MajorKey() { return Instanceof; }
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000641 int MinorKey() { return static_cast<int>(flags_); }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000642
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000643 bool HasArgsInRegisters() const {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000644 return (flags_ & kArgsInRegisters) != 0;
645 }
646
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000647 bool HasCallSiteInlineCheck() const {
648 return (flags_ & kCallSiteInlineCheck) != 0;
649 }
650
651 bool ReturnTrueFalseObject() const {
652 return (flags_ & kReturnTrueFalseObject) != 0;
653 }
654
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000655 virtual void PrintName(StringStream* stream);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000656
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000657 Flags flags_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000658};
659
660
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000661class ArrayConstructorStub: public PlatformCodeStub {
662 public:
663 enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
664 ArrayConstructorStub(Isolate* isolate, int argument_count);
665 explicit ArrayConstructorStub(Isolate* isolate);
666
667 void Generate(MacroAssembler* masm);
668
669 private:
670 virtual CodeStub::Major MajorKey() { return ArrayConstructor; }
671 virtual int MinorKey() { return argument_count_; }
672
673 ArgumentCountKey argument_count_;
674};
675
676
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000677class InternalArrayConstructorStub: public PlatformCodeStub {
678 public:
679 explicit InternalArrayConstructorStub(Isolate* isolate);
680
681 void Generate(MacroAssembler* masm);
682
683 private:
684 virtual CodeStub::Major MajorKey() { return InternalArrayConstructor; }
685 virtual int MinorKey() { return 0; }
686
687 void GenerateCase(MacroAssembler* masm, ElementsKind kind);
688};
689
690
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000691class MathPowStub: public PlatformCodeStub {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000692 public:
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000693 enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK };
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000694
695 explicit MathPowStub(ExponentType exponent_type)
696 : exponent_type_(exponent_type) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000697 virtual void Generate(MacroAssembler* masm);
698
699 private:
700 virtual CodeStub::Major MajorKey() { return MathPow; }
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000701 virtual int MinorKey() { return exponent_type_; }
702
703 ExponentType exponent_type_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000704};
705
706
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000707class ICStub: public PlatformCodeStub {
708 public:
709 explicit ICStub(Code::Kind kind) : kind_(kind) { }
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000710 virtual Code::Kind GetCodeKind() const { return kind_; }
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000711 virtual InlineCacheState GetICState() { return MONOMORPHIC; }
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000712
713 bool Describes(Code* code) {
714 return GetMajorKey(code) == MajorKey() && code->stub_info() == MinorKey();
715 }
716
717 protected:
718 class KindBits: public BitField<Code::Kind, 0, 4> {};
719 virtual void FinishCode(Handle<Code> code) {
720 code->set_stub_info(MinorKey());
721 }
722 Code::Kind kind() { return kind_; }
723
724 virtual int MinorKey() {
725 return KindBits::encode(kind_);
726 }
727
728 private:
729 Code::Kind kind_;
730};
731
732
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000733class FunctionPrototypeStub: public ICStub {
734 public:
735 explicit FunctionPrototypeStub(Code::Kind kind) : ICStub(kind) { }
736 virtual void Generate(MacroAssembler* masm);
737
738 private:
739 virtual CodeStub::Major MajorKey() { return FunctionPrototype; }
740};
741
742
743class StringLengthStub: public ICStub {
744 public:
745 StringLengthStub(Code::Kind kind, bool support_wrapper)
746 : ICStub(kind), support_wrapper_(support_wrapper) { }
747 virtual void Generate(MacroAssembler* masm);
748
749 private:
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000750 STATIC_ASSERT(KindBits::kSize == 4);
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000751 class WrapperModeBits: public BitField<bool, 4, 1> {};
752 virtual CodeStub::Major MajorKey() { return StringLength; }
753 virtual int MinorKey() {
754 return KindBits::encode(kind()) | WrapperModeBits::encode(support_wrapper_);
755 }
756
757 bool support_wrapper_;
758};
759
760
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000761class StoreICStub: public ICStub {
762 public:
763 StoreICStub(Code::Kind kind, StrictModeFlag strict_mode)
764 : ICStub(kind), strict_mode_(strict_mode) { }
765
766 protected:
767 virtual Code::ExtraICState GetExtraICState() {
768 return strict_mode_;
769 }
770
771 private:
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000772 STATIC_ASSERT(KindBits::kSize == 4);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000773 class StrictModeBits: public BitField<bool, 4, 1> {};
774 virtual int MinorKey() {
775 return KindBits::encode(kind()) | StrictModeBits::encode(strict_mode_);
776 }
777
778 StrictModeFlag strict_mode_;
779};
780
781
782class StoreArrayLengthStub: public StoreICStub {
783 public:
784 explicit StoreArrayLengthStub(Code::Kind kind, StrictModeFlag strict_mode)
785 : StoreICStub(kind, strict_mode) { }
786 virtual void Generate(MacroAssembler* masm);
787
788 private:
789 virtual CodeStub::Major MajorKey() { return StoreArrayLength; }
790};
791
792
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000793class HICStub: public HydrogenCodeStub {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000794 public:
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000795 virtual Code::Kind GetCodeKind() const { return kind(); }
796 virtual InlineCacheState GetICState() { return MONOMORPHIC; }
797
798 protected:
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000799 HICStub() { }
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000800 class KindBits: public BitField<Code::Kind, 0, 4> {};
801 virtual Code::Kind kind() const = 0;
802};
803
804
805class HandlerStub: public HICStub {
806 public:
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000807 virtual Code::Kind GetCodeKind() const { return Code::STUB; }
ulan@chromium.org750145a2013-03-07 15:14:13 +0000808 virtual int GetStubFlags() { return kind(); }
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000809
810 protected:
811 HandlerStub() : HICStub() { }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000812};
813
814
815class LoadFieldStub: public HandlerStub {
816 public:
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000817 LoadFieldStub(bool inobject, int index, Representation representation)
818 : HandlerStub() {
819 Initialize(Code::LOAD_IC, inobject, index, representation);
820 }
821
822 virtual Handle<Code> GenerateCode();
823
824 virtual void InitializeInterfaceDescriptor(
825 Isolate* isolate,
826 CodeStubInterfaceDescriptor* descriptor);
827
828 Representation representation() {
829 if (unboxed_double()) return Representation::Double();
830 return Representation::Tagged();
831 }
832
833 virtual Code::Kind kind() const {
834 return KindBits::decode(bit_field_);
835 }
836
837 bool is_inobject() {
838 return InobjectBits::decode(bit_field_);
839 }
840
841 int offset() {
842 int index = IndexBits::decode(bit_field_);
843 int offset = index * kPointerSize;
844 if (is_inobject()) return offset;
845 return FixedArray::kHeaderSize + offset;
846 }
847
848 bool unboxed_double() {
849 return UnboxedDoubleBits::decode(bit_field_);
850 }
851
852 virtual Code::StubType GetStubType() { return Code::FIELD; }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000853
854 protected:
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000855 LoadFieldStub() : HandlerStub() { }
856
857 void Initialize(Code::Kind kind,
858 bool inobject,
859 int index,
860 Representation representation) {
861 bool unboxed_double = FLAG_track_double_fields && representation.IsDouble();
862 bit_field_ = KindBits::encode(kind)
863 | InobjectBits::encode(inobject)
864 | IndexBits::encode(index)
865 | UnboxedDoubleBits::encode(unboxed_double);
866 }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000867
868 private:
869 STATIC_ASSERT(KindBits::kSize == 4);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000870 class InobjectBits: public BitField<bool, 4, 1> {};
871 class IndexBits: public BitField<int, 5, 11> {};
872 class UnboxedDoubleBits: public BitField<bool, 16, 1> {};
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000873 virtual CodeStub::Major MajorKey() { return LoadField; }
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000874 virtual int NotMissMinorKey() { return bit_field_; }
875
876 int bit_field_;
877};
878
879
880class KeyedLoadFieldStub: public LoadFieldStub {
881 public:
882 KeyedLoadFieldStub(bool inobject, int index, Representation representation)
883 : LoadFieldStub() {
884 Initialize(Code::KEYED_LOAD_IC, inobject, index, representation);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000885 }
886
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000887 virtual void InitializeInterfaceDescriptor(
888 Isolate* isolate,
889 CodeStubInterfaceDescriptor* descriptor);
890
891 virtual Handle<Code> GenerateCode();
892
893 private:
894 virtual CodeStub::Major MajorKey() { return KeyedLoadField; }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000895};
896
897
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000898class BinaryOpStub: public PlatformCodeStub {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000899 public:
900 BinaryOpStub(Token::Value op, OverwriteMode mode)
901 : op_(op),
902 mode_(mode),
903 platform_specific_bit_(false),
904 left_type_(BinaryOpIC::UNINITIALIZED),
905 right_type_(BinaryOpIC::UNINITIALIZED),
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000906 result_type_(BinaryOpIC::UNINITIALIZED),
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000907 encoded_right_arg_(false, encode_arg_value(1)) {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000908 Initialize();
909 ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
910 }
911
912 BinaryOpStub(
913 int key,
914 BinaryOpIC::TypeInfo left_type,
915 BinaryOpIC::TypeInfo right_type,
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000916 BinaryOpIC::TypeInfo result_type,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000917 Maybe<int32_t> fixed_right_arg)
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000918 : op_(OpBits::decode(key)),
919 mode_(ModeBits::decode(key)),
920 platform_specific_bit_(PlatformSpecificBits::decode(key)),
921 left_type_(left_type),
922 right_type_(right_type),
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000923 result_type_(result_type),
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000924 encoded_right_arg_(fixed_right_arg.has_value,
925 encode_arg_value(fixed_right_arg.value)) { }
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000926
927 static void decode_types_from_minor_key(int minor_key,
928 BinaryOpIC::TypeInfo* left_type,
929 BinaryOpIC::TypeInfo* right_type,
930 BinaryOpIC::TypeInfo* result_type) {
931 *left_type =
932 static_cast<BinaryOpIC::TypeInfo>(LeftTypeBits::decode(minor_key));
933 *right_type =
934 static_cast<BinaryOpIC::TypeInfo>(RightTypeBits::decode(minor_key));
935 *result_type =
936 static_cast<BinaryOpIC::TypeInfo>(ResultTypeBits::decode(minor_key));
937 }
938
939 static Token::Value decode_op_from_minor_key(int minor_key) {
940 return static_cast<Token::Value>(OpBits::decode(minor_key));
941 }
942
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000943 static Maybe<int> decode_fixed_right_arg_from_minor_key(int minor_key) {
944 return Maybe<int>(
945 HasFixedRightArgBits::decode(minor_key),
946 decode_arg_value(FixedRightArgValueBits::decode(minor_key)));
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000947 }
948
949 int fixed_right_arg_value() const {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000950 return decode_arg_value(encoded_right_arg_.value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000951 }
952
953 static bool can_encode_arg_value(int32_t value) {
954 return value > 0 &&
955 IsPowerOf2(value) &&
956 FixedRightArgValueBits::is_valid(WhichPowerOf2(value));
957 }
958
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000959 enum SmiCodeGenerateHeapNumberResults {
960 ALLOW_HEAPNUMBER_RESULTS,
961 NO_HEAPNUMBER_RESULTS
962 };
963
964 private:
965 Token::Value op_;
966 OverwriteMode mode_;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000967 bool platform_specific_bit_; // Indicates SSE3 on IA32.
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000968
969 // Operand type information determined at runtime.
970 BinaryOpIC::TypeInfo left_type_;
971 BinaryOpIC::TypeInfo right_type_;
972 BinaryOpIC::TypeInfo result_type_;
973
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000974 Maybe<int> encoded_right_arg_;
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000975
976 static int encode_arg_value(int32_t value) {
977 ASSERT(can_encode_arg_value(value));
978 return WhichPowerOf2(value);
979 }
980
981 static int32_t decode_arg_value(int value) {
982 return 1 << value;
983 }
984
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000985 virtual void PrintName(StringStream* stream);
986
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000987 // Minor key encoding in all 25 bits FFFFFHTTTRRRLLLPOOOOOOOMM.
988 // Note: We actually do not need 7 bits for the operation, just 4 bits to
989 // encode ADD, SUB, MUL, DIV, MOD, BIT_OR, BIT_AND, BIT_XOR, SAR, SHL, SHR.
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000990 class ModeBits: public BitField<OverwriteMode, 0, 2> {};
991 class OpBits: public BitField<Token::Value, 2, 7> {};
992 class PlatformSpecificBits: public BitField<bool, 9, 1> {};
993 class LeftTypeBits: public BitField<BinaryOpIC::TypeInfo, 10, 3> {};
994 class RightTypeBits: public BitField<BinaryOpIC::TypeInfo, 13, 3> {};
995 class ResultTypeBits: public BitField<BinaryOpIC::TypeInfo, 16, 3> {};
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000996 class HasFixedRightArgBits: public BitField<bool, 19, 1> {};
997 class FixedRightArgValueBits: public BitField<int, 20, 5> {};
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000998
999 Major MajorKey() { return BinaryOp; }
1000 int MinorKey() {
1001 return OpBits::encode(op_)
1002 | ModeBits::encode(mode_)
1003 | PlatformSpecificBits::encode(platform_specific_bit_)
1004 | LeftTypeBits::encode(left_type_)
1005 | RightTypeBits::encode(right_type_)
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001006 | ResultTypeBits::encode(result_type_)
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001007 | HasFixedRightArgBits::encode(encoded_right_arg_.has_value)
1008 | FixedRightArgValueBits::encode(encoded_right_arg_.value);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001009 }
1010
1011
1012 // Platform-independent implementation.
1013 void Generate(MacroAssembler* masm);
1014 void GenerateCallRuntime(MacroAssembler* masm);
1015
1016 // Platform-independent signature, platform-specific implementation.
1017 void Initialize();
1018 void GenerateAddStrings(MacroAssembler* masm);
1019 void GenerateBothStringStub(MacroAssembler* masm);
1020 void GenerateGeneric(MacroAssembler* masm);
1021 void GenerateGenericStub(MacroAssembler* masm);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001022 void GenerateNumberStub(MacroAssembler* masm);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001023 void GenerateInt32Stub(MacroAssembler* masm);
1024 void GenerateLoadArguments(MacroAssembler* masm);
1025 void GenerateOddballStub(MacroAssembler* masm);
1026 void GenerateRegisterArgsPush(MacroAssembler* masm);
1027 void GenerateReturn(MacroAssembler* masm);
1028 void GenerateSmiStub(MacroAssembler* masm);
1029 void GenerateStringStub(MacroAssembler* masm);
1030 void GenerateTypeTransition(MacroAssembler* masm);
1031 void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
1032 void GenerateUninitializedStub(MacroAssembler* masm);
1033
1034 // Entirely platform-specific methods are defined as static helper
1035 // functions in the <arch>/code-stubs-<arch>.cc files.
1036
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001037 virtual Code::Kind GetCodeKind() const { return Code::BINARY_OP_IC; }
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001038
1039 virtual InlineCacheState GetICState() {
1040 return BinaryOpIC::ToState(Max(left_type_, right_type_));
1041 }
1042
1043 virtual void FinishCode(Handle<Code> code) {
1044 code->set_stub_info(MinorKey());
1045 }
1046
1047 friend class CodeGenerator;
1048};
1049
1050
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001051class ICCompareStub: public PlatformCodeStub {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001052 public:
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001053 ICCompareStub(Token::Value op,
1054 CompareIC::State left,
1055 CompareIC::State right,
1056 CompareIC::State handler)
1057 : op_(op),
1058 left_(left),
1059 right_(right),
1060 state_(handler) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001061 ASSERT(Token::IsCompareOp(op));
1062 }
1063
1064 virtual void Generate(MacroAssembler* masm);
1065
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001066 void set_known_map(Handle<Map> map) { known_map_ = map; }
1067
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001068 static void DecodeMinorKey(int minor_key,
1069 CompareIC::State* left_state,
1070 CompareIC::State* right_state,
1071 CompareIC::State* handler_state,
1072 Token::Value* op);
1073
1074 static CompareIC::State CompareState(int minor_key) {
1075 return static_cast<CompareIC::State>(HandlerStateField::decode(minor_key));
1076 }
1077
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001078 virtual InlineCacheState GetICState();
1079
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001080 private:
1081 class OpField: public BitField<int, 0, 3> { };
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001082 class LeftStateField: public BitField<int, 3, 4> { };
1083 class RightStateField: public BitField<int, 7, 4> { };
1084 class HandlerStateField: public BitField<int, 11, 4> { };
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001085
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +00001086 virtual void FinishCode(Handle<Code> code) {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001087 code->set_stub_info(MinorKey());
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +00001088 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001089
1090 virtual CodeStub::Major MajorKey() { return CompareIC; }
1091 virtual int MinorKey();
1092
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001093 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_IC; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001094
1095 void GenerateSmis(MacroAssembler* masm);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001096 void GenerateNumbers(MacroAssembler* masm);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001097 void GenerateInternalizedStrings(MacroAssembler* masm);
lrn@chromium.org1c092762011-05-09 09:42:16 +00001098 void GenerateStrings(MacroAssembler* masm);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001099 void GenerateUniqueNames(MacroAssembler* masm);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001100 void GenerateObjects(MacroAssembler* masm);
1101 void GenerateMiss(MacroAssembler* masm);
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001102 void GenerateKnownObjects(MacroAssembler* masm);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001103 void GenerateGeneric(MacroAssembler* masm);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001104
1105 bool strict() const { return op_ == Token::EQ_STRICT; }
1106 Condition GetCondition() const { return CompareIC::ComputeCondition(op_); }
1107
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001108 virtual void AddToSpecialCache(Handle<Code> new_object);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00001109 virtual bool FindCodeInSpecialCache(Code** code_out, Isolate* isolate);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001110 virtual bool UseSpecialCache() { return state_ == CompareIC::KNOWN_OBJECT; }
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001111
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001112 Token::Value op_;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001113 CompareIC::State left_;
1114 CompareIC::State right_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001115 CompareIC::State state_;
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001116 Handle<Map> known_map_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001117};
1118
1119
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001120class CompareNilICStub : public HydrogenCodeStub {
1121 public:
danno@chromium.org41728482013-06-12 22:31:22 +00001122 enum CompareNilType {
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001123 UNDEFINED,
1124 NULL_TYPE,
1125 MONOMORPHIC_MAP,
1126 UNDETECTABLE,
danno@chromium.org41728482013-06-12 22:31:22 +00001127 GENERIC,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001128 NUMBER_OF_TYPES
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001129 };
1130
danno@chromium.org41728482013-06-12 22:31:22 +00001131 class State : public EnumSet<CompareNilType, byte> {
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001132 public:
danno@chromium.org41728482013-06-12 22:31:22 +00001133 State() : EnumSet<CompareNilType, byte>(0) { }
1134 explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001135
danno@chromium.org41728482013-06-12 22:31:22 +00001136 static State Generic() {
1137 State set;
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001138 set.Add(UNDEFINED);
1139 set.Add(NULL_TYPE);
1140 set.Add(UNDETECTABLE);
danno@chromium.org41728482013-06-12 22:31:22 +00001141 set.Add(GENERIC);
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001142 return set;
1143 }
1144
1145 void Print(StringStream* stream) const;
danno@chromium.org41728482013-06-12 22:31:22 +00001146 void TraceTransition(State to) const;
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001147 };
1148
danno@chromium.org41728482013-06-12 22:31:22 +00001149 static Handle<Type> StateToType(
1150 Isolate* isolate, State state, Handle<Map> map = Handle<Map>());
1151
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001152 // At most 6 different types can be distinguished, because the Code object
1153 // only has room for a single byte to hold a set and there are two more
1154 // boolean flags we need to store. :-P
1155 STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
1156
danno@chromium.org41728482013-06-12 22:31:22 +00001157 CompareNilICStub(NilValue nil, State state = State())
1158 : nil_value_(nil), state_(state) {
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001159 }
1160
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001161 CompareNilICStub(Code::ExtraICState ic_state,
1162 InitializationState init_state = INITIALIZED)
1163 : HydrogenCodeStub(init_state) {
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001164 nil_value_ = NilValueField::decode(ic_state);
danno@chromium.org41728482013-06-12 22:31:22 +00001165 state_ = State(ExtractTypesFromExtraICState(ic_state));
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001166 }
1167
1168 static Handle<Code> GetUninitialized(Isolate* isolate,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001169 NilValue nil) {
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001170 return CompareNilICStub(nil, UNINITIALIZED).GetCode(isolate);
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001171 }
1172
1173 virtual void InitializeInterfaceDescriptor(
1174 Isolate* isolate,
1175 CodeStubInterfaceDescriptor* descriptor);
1176
1177 static void InitializeForIsolate(Isolate* isolate) {
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001178 CompareNilICStub compare_stub(kNullValue, UNINITIALIZED);
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001179 compare_stub.InitializeInterfaceDescriptor(
1180 isolate,
1181 isolate->code_stub_interface_descriptor(CodeStub::CompareNilIC));
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001182 }
1183
1184 virtual InlineCacheState GetICState() {
danno@chromium.org41728482013-06-12 22:31:22 +00001185 if (state_ == State::Generic()) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001186 return MEGAMORPHIC;
danno@chromium.org41728482013-06-12 22:31:22 +00001187 } else if (state_.Contains(MONOMORPHIC_MAP)) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001188 return MONOMORPHIC;
1189 } else {
1190 return PREMONOMORPHIC;
1191 }
1192 }
1193
1194 virtual Code::Kind GetCodeKind() const { return Code::COMPARE_NIL_IC; }
1195
1196 Handle<Code> GenerateCode();
1197
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001198 // extra ic state = nil_value | type_n-1 | ... | type_0
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001199 virtual Code::ExtraICState GetExtraICState() {
danno@chromium.org41728482013-06-12 22:31:22 +00001200 return NilValueField::encode(nil_value_) | state_.ToIntegral();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001201 }
danno@chromium.org41728482013-06-12 22:31:22 +00001202 static byte ExtractTypesFromExtraICState(Code::ExtraICState state) {
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001203 return state & ((1 << NUMBER_OF_TYPES) - 1);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001204 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001205 static NilValue ExtractNilValueFromExtraICState(Code::ExtraICState state) {
1206 return NilValueField::decode(state);
1207 }
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001208
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001209 void Record(Handle<Object> object);
1210
danno@chromium.org41728482013-06-12 22:31:22 +00001211 bool IsMonomorphic() const { return state_.Contains(MONOMORPHIC_MAP); }
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001212 NilValue GetNilValue() const { return nil_value_; }
danno@chromium.org41728482013-06-12 22:31:22 +00001213 State GetState() const { return state_; }
1214 void ClearState() { state_.RemoveAll(); }
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001215
1216 virtual void PrintName(StringStream* stream);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001217
1218 private:
1219 friend class CompareNilIC;
1220
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001221 CompareNilICStub(NilValue nil, InitializationState init_state)
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001222 : HydrogenCodeStub(init_state) {
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001223 nil_value_ = nil;
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001224 }
1225
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001226 class NilValueField : public BitField<NilValue, NUMBER_OF_TYPES, 1> {};
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001227
1228 virtual CodeStub::Major MajorKey() { return CompareNilIC; }
1229 virtual int NotMissMinorKey() { return GetExtraICState(); }
1230
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001231 NilValue nil_value_;
danno@chromium.org41728482013-06-12 22:31:22 +00001232 State state_;
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001233
1234 DISALLOW_COPY_AND_ASSIGN(CompareNilICStub);
1235};
1236
1237
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001238class CEntryStub : public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001239 public:
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001240 explicit CEntryStub(int result_size,
1241 SaveFPRegsMode save_doubles = kDontSaveFPRegs)
1242 : result_size_(result_size), save_doubles_(save_doubles) { }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001243
1244 void Generate(MacroAssembler* masm);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001245
1246 // The version of this stub that doesn't save doubles is generated ahead of
1247 // time, so it's OK to call it from other stubs that can't cope with GC during
1248 // their code generation. On machines that always have gp registers (x64) we
1249 // can generate both variants ahead of time.
1250 virtual bool IsPregenerated();
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001251 static void GenerateAheadOfTime(Isolate* isolate);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001252
1253 private:
1254 void GenerateCore(MacroAssembler* masm,
1255 Label* throw_normal_exception,
1256 Label* throw_termination_exception,
1257 Label* throw_out_of_memory_exception,
1258 bool do_gc,
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001259 bool always_allocate_scope);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001260
1261 // Number of pointers/values returned.
1262 const int result_size_;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001263 SaveFPRegsMode save_doubles_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001264
1265 Major MajorKey() { return CEntry; }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001266 int MinorKey();
1267
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001268 bool NeedsImmovableCode();
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001269};
1270
1271
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001272class JSEntryStub : public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001273 public:
1274 JSEntryStub() { }
1275
1276 void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
1277
1278 protected:
1279 void GenerateBody(MacroAssembler* masm, bool is_construct);
1280
1281 private:
1282 Major MajorKey() { return JSEntry; }
1283 int MinorKey() { return 0; }
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +00001284
1285 virtual void FinishCode(Handle<Code> code);
1286
1287 int handler_offset_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001288};
1289
1290
1291class JSConstructEntryStub : public JSEntryStub {
1292 public:
1293 JSConstructEntryStub() { }
1294
1295 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
1296
1297 private:
1298 int MinorKey() { return 1; }
1299
whesse@chromium.org030d38e2011-07-13 13:23:34 +00001300 virtual void PrintName(StringStream* stream) {
1301 stream->Add("JSConstructEntryStub");
1302 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001303};
1304
1305
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001306class ArgumentsAccessStub: public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001307 public:
1308 enum Type {
1309 READ_ELEMENT,
whesse@chromium.org7b260152011-06-20 15:33:18 +00001310 NEW_NON_STRICT_FAST,
1311 NEW_NON_STRICT_SLOW,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001312 NEW_STRICT
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001313 };
1314
1315 explicit ArgumentsAccessStub(Type type) : type_(type) { }
1316
1317 private:
1318 Type type_;
1319
1320 Major MajorKey() { return ArgumentsAccess; }
1321 int MinorKey() { return type_; }
1322
1323 void Generate(MacroAssembler* masm);
1324 void GenerateReadElement(MacroAssembler* masm);
whesse@chromium.org7b260152011-06-20 15:33:18 +00001325 void GenerateNewStrict(MacroAssembler* masm);
1326 void GenerateNewNonStrictFast(MacroAssembler* masm);
1327 void GenerateNewNonStrictSlow(MacroAssembler* masm);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001328
whesse@chromium.org030d38e2011-07-13 13:23:34 +00001329 virtual void PrintName(StringStream* stream);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001330};
1331
1332
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001333class RegExpExecStub: public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001334 public:
1335 RegExpExecStub() { }
1336
1337 private:
1338 Major MajorKey() { return RegExpExec; }
1339 int MinorKey() { return 0; }
1340
1341 void Generate(MacroAssembler* masm);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001342};
1343
1344
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001345class RegExpConstructResultStub: public PlatformCodeStub {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001346 public:
1347 RegExpConstructResultStub() { }
1348
1349 private:
1350 Major MajorKey() { return RegExpConstructResult; }
1351 int MinorKey() { return 0; }
1352
1353 void Generate(MacroAssembler* masm);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001354};
1355
1356
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001357class CallFunctionStub: public PlatformCodeStub {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001358 public:
lrn@chromium.org34e60782011-09-15 07:25:40 +00001359 CallFunctionStub(int argc, CallFunctionFlags flags)
1360 : argc_(argc), flags_(flags) { }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001361
1362 void Generate(MacroAssembler* masm);
1363
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001364 virtual void FinishCode(Handle<Code> code) {
1365 code->set_has_function_cache(RecordCallTarget());
1366 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001367
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001368 static int ExtractArgcFromMinorKey(int minor_key) {
1369 return ArgcBits::decode(minor_key);
1370 }
1371
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001372 private:
1373 int argc_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001374 CallFunctionFlags flags_;
1375
whesse@chromium.org030d38e2011-07-13 13:23:34 +00001376 virtual void PrintName(StringStream* stream);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001377
1378 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001379 class FlagBits: public BitField<CallFunctionFlags, 0, 2> {};
1380 class ArgcBits: public BitField<unsigned, 2, 32 - 2> {};
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001381
1382 Major MajorKey() { return CallFunction; }
1383 int MinorKey() {
1384 // Encode the parameters in a unique 32 bit value.
lrn@chromium.org34e60782011-09-15 07:25:40 +00001385 return FlagBits::encode(flags_) | ArgcBits::encode(argc_);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001386 }
1387
danno@chromium.org40cb8782011-05-25 07:58:50 +00001388 bool ReceiverMightBeImplicit() {
1389 return (flags_ & RECEIVER_MIGHT_BE_IMPLICIT) != 0;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001390 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001391
1392 bool RecordCallTarget() {
1393 return (flags_ & RECORD_CALL_TARGET) != 0;
1394 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001395};
1396
1397
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001398class CallConstructStub: public PlatformCodeStub {
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001399 public:
1400 explicit CallConstructStub(CallFunctionFlags flags) : flags_(flags) {}
1401
1402 void Generate(MacroAssembler* masm);
1403
1404 virtual void FinishCode(Handle<Code> code) {
1405 code->set_has_function_cache(RecordCallTarget());
1406 }
1407
1408 private:
1409 CallFunctionFlags flags_;
1410
1411 virtual void PrintName(StringStream* stream);
1412
1413 Major MajorKey() { return CallConstruct; }
1414 int MinorKey() { return flags_; }
1415
1416 bool RecordCallTarget() {
1417 return (flags_ & RECORD_CALL_TARGET) != 0;
1418 }
1419};
1420
1421
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001422enum StringIndexFlags {
1423 // Accepts smis or heap numbers.
1424 STRING_INDEX_IS_NUMBER,
1425
1426 // Accepts smis or heap numbers that are valid array indices
1427 // (ECMA-262 15.4). Invalid indices are reported as being out of
1428 // range.
1429 STRING_INDEX_IS_ARRAY_INDEX
1430};
1431
1432
1433// Generates code implementing String.prototype.charCodeAt.
1434//
1435// Only supports the case when the receiver is a string and the index
1436// is a number (smi or heap number) that is a valid index into the
1437// string. Additional index constraints are specified by the
1438// flags. Otherwise, bails out to the provided labels.
1439//
1440// Register usage: |object| may be changed to another string in a way
1441// that doesn't affect charCodeAt/charAt semantics, |index| is
1442// preserved, |scratch| and |result| are clobbered.
1443class StringCharCodeAtGenerator {
1444 public:
1445 StringCharCodeAtGenerator(Register object,
1446 Register index,
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001447 Register result,
1448 Label* receiver_not_string,
1449 Label* index_not_number,
1450 Label* index_out_of_range,
1451 StringIndexFlags index_flags)
1452 : object_(object),
1453 index_(index),
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001454 result_(result),
1455 receiver_not_string_(receiver_not_string),
1456 index_not_number_(index_not_number),
1457 index_out_of_range_(index_out_of_range),
1458 index_flags_(index_flags) {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001459 ASSERT(!result_.is(object_));
1460 ASSERT(!result_.is(index_));
1461 }
1462
1463 // Generates the fast case code. On the fallthrough path |result|
1464 // register contains the result.
1465 void GenerateFast(MacroAssembler* masm);
1466
1467 // Generates the slow case code. Must not be naturally
1468 // reachable. Expected to be put after a ret instruction (e.g., in
1469 // deferred code). Always jumps back to the fast case.
1470 void GenerateSlow(MacroAssembler* masm,
1471 const RuntimeCallHelper& call_helper);
1472
ulan@chromium.org2e04b582013-02-21 14:06:02 +00001473 // Skip handling slow case and directly jump to bailout.
1474 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1475 masm->bind(&index_not_smi_);
1476 masm->bind(&call_runtime_);
1477 masm->jmp(bailout);
1478 }
1479
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001480 private:
1481 Register object_;
1482 Register index_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001483 Register result_;
1484
1485 Label* receiver_not_string_;
1486 Label* index_not_number_;
1487 Label* index_out_of_range_;
1488
1489 StringIndexFlags index_flags_;
1490
1491 Label call_runtime_;
1492 Label index_not_smi_;
1493 Label got_smi_index_;
1494 Label exit_;
1495
1496 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
1497};
1498
1499
1500// Generates code for creating a one-char string from a char code.
1501class StringCharFromCodeGenerator {
1502 public:
1503 StringCharFromCodeGenerator(Register code,
1504 Register result)
1505 : code_(code),
1506 result_(result) {
1507 ASSERT(!code_.is(result_));
1508 }
1509
1510 // Generates the fast case code. On the fallthrough path |result|
1511 // register contains the result.
1512 void GenerateFast(MacroAssembler* masm);
1513
1514 // Generates the slow case code. Must not be naturally
1515 // reachable. Expected to be put after a ret instruction (e.g., in
1516 // deferred code). Always jumps back to the fast case.
1517 void GenerateSlow(MacroAssembler* masm,
1518 const RuntimeCallHelper& call_helper);
1519
ulan@chromium.org2e04b582013-02-21 14:06:02 +00001520 // Skip handling slow case and directly jump to bailout.
1521 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1522 masm->bind(&slow_case_);
1523 masm->jmp(bailout);
1524 }
1525
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001526 private:
1527 Register code_;
1528 Register result_;
1529
1530 Label slow_case_;
1531 Label exit_;
1532
1533 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
1534};
1535
1536
1537// Generates code implementing String.prototype.charAt.
1538//
1539// Only supports the case when the receiver is a string and the index
1540// is a number (smi or heap number) that is a valid index into the
1541// string. Additional index constraints are specified by the
1542// flags. Otherwise, bails out to the provided labels.
1543//
1544// Register usage: |object| may be changed to another string in a way
1545// that doesn't affect charCodeAt/charAt semantics, |index| is
1546// preserved, |scratch1|, |scratch2|, and |result| are clobbered.
1547class StringCharAtGenerator {
1548 public:
1549 StringCharAtGenerator(Register object,
1550 Register index,
danno@chromium.orgc612e022011-11-10 11:38:15 +00001551 Register scratch,
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001552 Register result,
1553 Label* receiver_not_string,
1554 Label* index_not_number,
1555 Label* index_out_of_range,
1556 StringIndexFlags index_flags)
1557 : char_code_at_generator_(object,
1558 index,
danno@chromium.orgc612e022011-11-10 11:38:15 +00001559 scratch,
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001560 receiver_not_string,
1561 index_not_number,
1562 index_out_of_range,
1563 index_flags),
danno@chromium.orgc612e022011-11-10 11:38:15 +00001564 char_from_code_generator_(scratch, result) {}
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001565
1566 // Generates the fast case code. On the fallthrough path |result|
1567 // register contains the result.
ulan@chromium.org2e04b582013-02-21 14:06:02 +00001568 void GenerateFast(MacroAssembler* masm) {
1569 char_code_at_generator_.GenerateFast(masm);
1570 char_from_code_generator_.GenerateFast(masm);
1571 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001572
1573 // Generates the slow case code. Must not be naturally
1574 // reachable. Expected to be put after a ret instruction (e.g., in
1575 // deferred code). Always jumps back to the fast case.
1576 void GenerateSlow(MacroAssembler* masm,
ulan@chromium.org2e04b582013-02-21 14:06:02 +00001577 const RuntimeCallHelper& call_helper) {
1578 char_code_at_generator_.GenerateSlow(masm, call_helper);
1579 char_from_code_generator_.GenerateSlow(masm, call_helper);
1580 }
1581
1582 // Skip handling slow case and directly jump to bailout.
1583 void SkipSlow(MacroAssembler* masm, Label* bailout) {
1584 char_code_at_generator_.SkipSlow(masm, bailout);
1585 char_from_code_generator_.SkipSlow(masm, bailout);
1586 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001587
1588 private:
1589 StringCharCodeAtGenerator char_code_at_generator_;
1590 StringCharFromCodeGenerator char_from_code_generator_;
1591
1592 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
1593};
1594
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001595
1596class AllowStubCallsScope {
1597 public:
1598 AllowStubCallsScope(MacroAssembler* masm, bool allow)
1599 : masm_(masm), previous_allow_(masm->allow_stub_calls()) {
1600 masm_->set_allow_stub_calls(allow);
1601 }
1602 ~AllowStubCallsScope() {
1603 masm_->set_allow_stub_calls(previous_allow_);
1604 }
1605
1606 private:
1607 MacroAssembler* masm_;
1608 bool previous_allow_;
1609
1610 DISALLOW_COPY_AND_ASSIGN(AllowStubCallsScope);
1611};
1612
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001613
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001614class KeyedLoadDictionaryElementStub : public PlatformCodeStub {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001615 public:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001616 KeyedLoadDictionaryElementStub() {}
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001617
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001618 void Generate(MacroAssembler* masm);
1619
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00001620 private:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001621 Major MajorKey() { return KeyedLoadElement; }
1622 int MinorKey() { return DICTIONARY_ELEMENTS; }
1623
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001624 DISALLOW_COPY_AND_ASSIGN(KeyedLoadDictionaryElementStub);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001625};
1626
1627
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001628class KeyedLoadFastElementStub : public HydrogenCodeStub {
1629 public:
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001630 KeyedLoadFastElementStub(bool is_js_array, ElementsKind elements_kind) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001631 bit_field_ = ElementsKindBits::encode(elements_kind) |
1632 IsJSArrayBits::encode(is_js_array);
1633 }
1634
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001635 bool is_js_array() const {
1636 return IsJSArrayBits::decode(bit_field_);
1637 }
1638
1639 ElementsKind elements_kind() const {
1640 return ElementsKindBits::decode(bit_field_);
1641 }
1642
1643 virtual Handle<Code> GenerateCode();
1644
1645 virtual void InitializeInterfaceDescriptor(
1646 Isolate* isolate,
1647 CodeStubInterfaceDescriptor* descriptor);
1648
1649 private:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001650 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001651 class IsJSArrayBits: public BitField<bool, 8, 1> {};
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001652 uint32_t bit_field_;
1653
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001654 Major MajorKey() { return KeyedLoadElement; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001655 int NotMissMinorKey() { return bit_field_; }
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001656
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001657 DISALLOW_COPY_AND_ASSIGN(KeyedLoadFastElementStub);
1658};
1659
1660
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001661class KeyedStoreFastElementStub : public HydrogenCodeStub {
1662 public:
1663 KeyedStoreFastElementStub(bool is_js_array,
1664 ElementsKind elements_kind,
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001665 KeyedAccessStoreMode mode) {
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001666 bit_field_ = ElementsKindBits::encode(elements_kind) |
1667 IsJSArrayBits::encode(is_js_array) |
1668 StoreModeBits::encode(mode);
1669 }
1670
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001671 bool is_js_array() const {
1672 return IsJSArrayBits::decode(bit_field_);
1673 }
1674
1675 ElementsKind elements_kind() const {
1676 return ElementsKindBits::decode(bit_field_);
1677 }
1678
1679 KeyedAccessStoreMode store_mode() const {
1680 return StoreModeBits::decode(bit_field_);
1681 }
1682
1683 virtual Handle<Code> GenerateCode();
1684
1685 virtual void InitializeInterfaceDescriptor(
1686 Isolate* isolate,
1687 CodeStubInterfaceDescriptor* descriptor);
1688
1689 private:
1690 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
1691 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
1692 class IsJSArrayBits: public BitField<bool, 12, 1> {};
1693 uint32_t bit_field_;
1694
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001695 Major MajorKey() { return KeyedStoreElement; }
1696 int NotMissMinorKey() { return bit_field_; }
1697
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001698 DISALLOW_COPY_AND_ASSIGN(KeyedStoreFastElementStub);
1699};
1700
1701
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001702class TransitionElementsKindStub : public HydrogenCodeStub {
1703 public:
1704 TransitionElementsKindStub(ElementsKind from_kind,
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001705 ElementsKind to_kind) {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001706 bit_field_ = FromKindBits::encode(from_kind) |
1707 ToKindBits::encode(to_kind);
1708 }
1709
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001710 ElementsKind from_kind() const {
1711 return FromKindBits::decode(bit_field_);
1712 }
1713
1714 ElementsKind to_kind() const {
1715 return ToKindBits::decode(bit_field_);
1716 }
1717
1718 virtual Handle<Code> GenerateCode();
1719
1720 virtual void InitializeInterfaceDescriptor(
1721 Isolate* isolate,
1722 CodeStubInterfaceDescriptor* descriptor);
1723
1724 private:
1725 class FromKindBits: public BitField<ElementsKind, 8, 8> {};
1726 class ToKindBits: public BitField<ElementsKind, 0, 8> {};
1727 uint32_t bit_field_;
1728
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001729 Major MajorKey() { return TransitionElementsKind; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001730 int NotMissMinorKey() { return bit_field_; }
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001731
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001732 DISALLOW_COPY_AND_ASSIGN(TransitionElementsKindStub);
1733};
1734
1735
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001736enum ContextCheckMode {
1737 CONTEXT_CHECK_REQUIRED,
1738 CONTEXT_CHECK_NOT_REQUIRED,
1739 LAST_CONTEXT_CHECK_MODE = CONTEXT_CHECK_NOT_REQUIRED
1740};
1741
1742
1743enum AllocationSiteOverrideMode {
1744 DONT_OVERRIDE,
1745 DISABLE_ALLOCATION_SITES,
1746 LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
1747};
1748
1749
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001750class ArrayConstructorStubBase : public HydrogenCodeStub {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001751 public:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001752 ArrayConstructorStubBase(ElementsKind kind, ContextCheckMode context_mode,
1753 AllocationSiteOverrideMode override_mode) {
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001754 // It only makes sense to override local allocation site behavior
1755 // if there is a difference between the global allocation site policy
1756 // for an ElementsKind and the desired usage of the stub.
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001757 ASSERT(override_mode != DISABLE_ALLOCATION_SITES ||
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001758 AllocationSiteInfo::GetMode(kind) == TRACK_ALLOCATION_SITE);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001759 bit_field_ = ElementsKindBits::encode(kind) |
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001760 AllocationSiteOverrideModeBits::encode(override_mode) |
1761 ContextCheckModeBits::encode(context_mode);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001762 }
1763
1764 ElementsKind elements_kind() const {
1765 return ElementsKindBits::decode(bit_field_);
1766 }
1767
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001768 AllocationSiteOverrideMode override_mode() const {
1769 return AllocationSiteOverrideModeBits::decode(bit_field_);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001770 }
1771
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001772 ContextCheckMode context_mode() const {
1773 return ContextCheckModeBits::decode(bit_field_);
1774 }
1775
1776 virtual bool IsPregenerated() {
1777 // We only pre-generate stubs that verify correct context
1778 return context_mode() == CONTEXT_CHECK_REQUIRED;
1779 }
1780
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001781 static void GenerateStubsAheadOfTime(Isolate* isolate);
1782 static void InstallDescriptors(Isolate* isolate);
1783
1784 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001785 static const int kConstructor = 0;
1786 static const int kPropertyCell = 1;
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001787
1788 private:
1789 int NotMissMinorKey() { return bit_field_; }
1790
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001791 // Ensure data fits within available bits.
1792 STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
1793 STATIC_ASSERT(LAST_CONTEXT_CHECK_MODE == 1);
1794
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001795 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001796 class AllocationSiteOverrideModeBits: public
1797 BitField<AllocationSiteOverrideMode, 8, 1> {}; // NOLINT
1798 class ContextCheckModeBits: public BitField<ContextCheckMode, 9, 1> {};
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001799 uint32_t bit_field_;
1800
1801 DISALLOW_COPY_AND_ASSIGN(ArrayConstructorStubBase);
1802};
1803
1804
1805class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
1806 public:
1807 ArrayNoArgumentConstructorStub(
1808 ElementsKind kind,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001809 ContextCheckMode context_mode = CONTEXT_CHECK_REQUIRED,
1810 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
1811 : ArrayConstructorStubBase(kind, context_mode, override_mode) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001812 }
1813
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001814 virtual Handle<Code> GenerateCode();
1815
1816 virtual void InitializeInterfaceDescriptor(
1817 Isolate* isolate,
1818 CodeStubInterfaceDescriptor* descriptor);
1819
1820 private:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001821 Major MajorKey() { return ArrayNoArgumentConstructor; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001822
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001823 DISALLOW_COPY_AND_ASSIGN(ArrayNoArgumentConstructorStub);
1824};
1825
1826
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001827class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001828 public:
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001829 ArraySingleArgumentConstructorStub(
1830 ElementsKind kind,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001831 ContextCheckMode context_mode = CONTEXT_CHECK_REQUIRED,
1832 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
1833 : ArrayConstructorStubBase(kind, context_mode, override_mode) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001834 }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001835
1836 virtual Handle<Code> GenerateCode();
1837
1838 virtual void InitializeInterfaceDescriptor(
1839 Isolate* isolate,
1840 CodeStubInterfaceDescriptor* descriptor);
1841
1842 private:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001843 Major MajorKey() { return ArraySingleArgumentConstructor; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001844
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001845 DISALLOW_COPY_AND_ASSIGN(ArraySingleArgumentConstructorStub);
1846};
1847
1848
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001849class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001850 public:
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001851 ArrayNArgumentsConstructorStub(
1852 ElementsKind kind,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001853 ContextCheckMode context_mode = CONTEXT_CHECK_REQUIRED,
1854 AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
1855 : ArrayConstructorStubBase(kind, context_mode, override_mode) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001856 }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001857
1858 virtual Handle<Code> GenerateCode();
1859
1860 virtual void InitializeInterfaceDescriptor(
1861 Isolate* isolate,
1862 CodeStubInterfaceDescriptor* descriptor);
1863
1864 private:
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001865 Major MajorKey() { return ArrayNArgumentsConstructor; }
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001866
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001867 DISALLOW_COPY_AND_ASSIGN(ArrayNArgumentsConstructorStub);
1868};
1869
1870
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001871class InternalArrayConstructorStubBase : public HydrogenCodeStub {
1872 public:
1873 explicit InternalArrayConstructorStubBase(ElementsKind kind) {
1874 kind_ = kind;
1875 }
1876
1877 virtual bool IsPregenerated() { return true; }
1878 static void GenerateStubsAheadOfTime(Isolate* isolate);
1879 static void InstallDescriptors(Isolate* isolate);
1880
1881 // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1882 static const int kConstructor = 0;
1883
1884 ElementsKind elements_kind() const { return kind_; }
1885
1886 private:
1887 int NotMissMinorKey() { return kind_; }
1888
1889 ElementsKind kind_;
1890
1891 DISALLOW_COPY_AND_ASSIGN(InternalArrayConstructorStubBase);
1892};
1893
1894
1895class InternalArrayNoArgumentConstructorStub : public
1896 InternalArrayConstructorStubBase {
1897 public:
1898 explicit InternalArrayNoArgumentConstructorStub(ElementsKind kind)
1899 : InternalArrayConstructorStubBase(kind) { }
1900
1901 virtual Handle<Code> GenerateCode();
1902
1903 virtual void InitializeInterfaceDescriptor(
1904 Isolate* isolate,
1905 CodeStubInterfaceDescriptor* descriptor);
1906
1907 private:
1908 Major MajorKey() { return InternalArrayNoArgumentConstructor; }
1909
1910 DISALLOW_COPY_AND_ASSIGN(InternalArrayNoArgumentConstructorStub);
1911};
1912
1913
1914class InternalArraySingleArgumentConstructorStub : public
1915 InternalArrayConstructorStubBase {
1916 public:
1917 explicit InternalArraySingleArgumentConstructorStub(ElementsKind kind)
1918 : InternalArrayConstructorStubBase(kind) { }
1919
1920 virtual Handle<Code> GenerateCode();
1921
1922 virtual void InitializeInterfaceDescriptor(
1923 Isolate* isolate,
1924 CodeStubInterfaceDescriptor* descriptor);
1925
1926 private:
1927 Major MajorKey() { return InternalArraySingleArgumentConstructor; }
1928
1929 DISALLOW_COPY_AND_ASSIGN(InternalArraySingleArgumentConstructorStub);
1930};
1931
1932
1933class InternalArrayNArgumentsConstructorStub : public
1934 InternalArrayConstructorStubBase {
1935 public:
1936 explicit InternalArrayNArgumentsConstructorStub(ElementsKind kind)
1937 : InternalArrayConstructorStubBase(kind) { }
1938
1939 virtual Handle<Code> GenerateCode();
1940
1941 virtual void InitializeInterfaceDescriptor(
1942 Isolate* isolate,
1943 CodeStubInterfaceDescriptor* descriptor);
1944
1945 private:
1946 Major MajorKey() { return InternalArrayNArgumentsConstructor; }
1947
1948 DISALLOW_COPY_AND_ASSIGN(InternalArrayNArgumentsConstructorStub);
1949};
1950
1951
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001952class KeyedStoreElementStub : public PlatformCodeStub {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001953 public:
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00001954 KeyedStoreElementStub(bool is_js_array,
ulan@chromium.org65a89c22012-02-14 11:46:07 +00001955 ElementsKind elements_kind,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001956 KeyedAccessStoreMode store_mode)
ulan@chromium.org65a89c22012-02-14 11:46:07 +00001957 : is_js_array_(is_js_array),
1958 elements_kind_(elements_kind),
ulan@chromium.org750145a2013-03-07 15:14:13 +00001959 store_mode_(store_mode),
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00001960 fp_registers_(CanUseFPRegisters()) { }
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001961
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00001962 Major MajorKey() { return KeyedStoreElement; }
1963 int MinorKey() {
ulan@chromium.org65a89c22012-02-14 11:46:07 +00001964 return ElementsKindBits::encode(elements_kind_) |
1965 IsJSArrayBits::encode(is_js_array_) |
ulan@chromium.org750145a2013-03-07 15:14:13 +00001966 StoreModeBits::encode(store_mode_) |
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00001967 FPRegisters::encode(fp_registers_);
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00001968 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001969
1970 void Generate(MacroAssembler* masm);
1971
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001972 private:
ulan@chromium.org750145a2013-03-07 15:14:13 +00001973 class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
1974 class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
1975 class IsJSArrayBits: public BitField<bool, 12, 1> {};
1976 class FPRegisters: public BitField<bool, 13, 1> {};
ulan@chromium.org65a89c22012-02-14 11:46:07 +00001977
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001978 bool is_js_array_;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001979 ElementsKind elements_kind_;
ulan@chromium.org750145a2013-03-07 15:14:13 +00001980 KeyedAccessStoreMode store_mode_;
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00001981 bool fp_registers_;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001982
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00001983 DISALLOW_COPY_AND_ASSIGN(KeyedStoreElementStub);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001984};
1985
1986
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001987class ToBooleanStub: public HydrogenCodeStub {
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001988 public:
ricow@chromium.org9fa09672011-07-25 11:05:35 +00001989 enum Type {
1990 UNDEFINED,
1991 BOOLEAN,
1992 NULL_TYPE,
1993 SMI,
1994 SPEC_OBJECT,
1995 STRING,
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00001996 SYMBOL,
ricow@chromium.org9fa09672011-07-25 11:05:35 +00001997 HEAP_NUMBER,
ricow@chromium.org9fa09672011-07-25 11:05:35 +00001998 NUMBER_OF_TYPES
1999 };
2000
2001 // At most 8 different types can be distinguished, because the Code object
2002 // only has room for a single byte to hold a set of these types. :-P
2003 STATIC_ASSERT(NUMBER_OF_TYPES <= 8);
2004
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00002005 class Types : public EnumSet<Type, byte> {
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002006 public:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002007 Types() : EnumSet<Type, byte>(0) {}
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00002008 explicit Types(byte bits) : EnumSet<Type, byte>(bits) {}
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002009
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00002010 byte ToByte() const { return ToIntegral(); }
vegorov@chromium.org7943d462011-08-01 11:41:52 +00002011 void Print(StringStream* stream) const;
2012 void TraceTransition(Types to) const;
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002013 bool Record(Handle<Object> object);
vegorov@chromium.org7943d462011-08-01 11:41:52 +00002014 bool NeedsMap() const;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00002015 bool CanBeUndetectable() const;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002016 bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002017
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002018 static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
2019 };
ricow@chromium.org2c99e282011-07-28 09:15:17 +00002020
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002021 explicit ToBooleanStub(Types types = Types())
2022 : types_(types) { }
2023 explicit ToBooleanStub(Code::ExtraICState state)
2024 : types_(static_cast<byte>(state)) { }
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00002025
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002026 bool Record(Handle<Object> object);
2027 Types GetTypes() { return types_; }
2028
2029 virtual Handle<Code> GenerateCode();
2030 virtual void InitializeInterfaceDescriptor(
2031 Isolate* isolate,
2032 CodeStubInterfaceDescriptor* descriptor);
2033
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00002034 virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002035 virtual void PrintName(StringStream* stream);
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00002036
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002037 virtual bool SometimesSetsUpAFrame() { return false; }
2038
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002039 static void InitializeForIsolate(Isolate* isolate) {
2040 ToBooleanStub stub;
2041 stub.InitializeInterfaceDescriptor(
2042 isolate,
2043 isolate->code_stub_interface_descriptor(CodeStub::ToBoolean));
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002044 }
2045
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002046 static Handle<Code> GetUninitialized(Isolate* isolate) {
2047 return ToBooleanStub(UNINITIALIZED).GetCode(isolate);
2048 }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002049
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002050 virtual Code::ExtraICState GetExtraICState() {
2051 return types_.ToIntegral();
2052 }
2053
danno@chromium.org1fd77d52013-06-07 16:01:45 +00002054 virtual InlineCacheState GetICState() {
2055 if (types_.IsEmpty()) {
2056 return ::v8::internal::UNINITIALIZED;
2057 } else {
2058 return MONOMORPHIC;
2059 }
2060 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002061
2062 private:
2063 Major MajorKey() { return ToBoolean; }
2064 int NotMissMinorKey() { return GetExtraICState(); }
2065
2066 explicit ToBooleanStub(InitializationState init_state) :
2067 HydrogenCodeStub(init_state) {}
2068
ricow@chromium.org9fa09672011-07-25 11:05:35 +00002069 Types types_;
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00002070};
2071
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002072
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002073class ElementsTransitionAndStoreStub : public PlatformCodeStub {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002074 public:
2075 ElementsTransitionAndStoreStub(ElementsKind from,
2076 ElementsKind to,
2077 bool is_jsarray,
ulan@chromium.org65a89c22012-02-14 11:46:07 +00002078 StrictModeFlag strict_mode,
ulan@chromium.org750145a2013-03-07 15:14:13 +00002079 KeyedAccessStoreMode store_mode)
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002080 : from_(from),
2081 to_(to),
2082 is_jsarray_(is_jsarray),
ulan@chromium.org65a89c22012-02-14 11:46:07 +00002083 strict_mode_(strict_mode),
ulan@chromium.org750145a2013-03-07 15:14:13 +00002084 store_mode_(store_mode) {}
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002085
2086 private:
ulan@chromium.org750145a2013-03-07 15:14:13 +00002087 class FromBits: public BitField<ElementsKind, 0, 8> {};
2088 class ToBits: public BitField<ElementsKind, 8, 8> {};
2089 class IsJSArrayBits: public BitField<bool, 16, 1> {};
2090 class StrictModeBits: public BitField<StrictModeFlag, 17, 1> {};
2091 class StoreModeBits: public BitField<KeyedAccessStoreMode, 18, 4> {};
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002092
2093 Major MajorKey() { return ElementsTransitionAndStore; }
2094 int MinorKey() {
2095 return FromBits::encode(from_) |
2096 ToBits::encode(to_) |
2097 IsJSArrayBits::encode(is_jsarray_) |
ulan@chromium.org65a89c22012-02-14 11:46:07 +00002098 StrictModeBits::encode(strict_mode_) |
ulan@chromium.org750145a2013-03-07 15:14:13 +00002099 StoreModeBits::encode(store_mode_);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002100 }
2101
2102 void Generate(MacroAssembler* masm);
2103
2104 ElementsKind from_;
2105 ElementsKind to_;
2106 bool is_jsarray_;
2107 StrictModeFlag strict_mode_;
ulan@chromium.org750145a2013-03-07 15:14:13 +00002108 KeyedAccessStoreMode store_mode_;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002109
2110 DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub);
2111};
2112
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002113
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002114class StoreArrayLiteralElementStub : public PlatformCodeStub {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002115 public:
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002116 StoreArrayLiteralElementStub()
2117 : fp_registers_(CanUseFPRegisters()) { }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002118
2119 private:
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002120 class FPRegisters: public BitField<bool, 0, 1> {};
2121
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002122 Major MajorKey() { return StoreArrayLiteralElement; }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002123 int MinorKey() { return FPRegisters::encode(fp_registers_); }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002124
2125 void Generate(MacroAssembler* masm);
2126
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002127 bool fp_registers_;
2128
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002129 DISALLOW_COPY_AND_ASSIGN(StoreArrayLiteralElementStub);
2130};
2131
verwaest@chromium.org753aee42012-07-17 16:15:42 +00002132
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00002133class StubFailureTrampolineStub : public PlatformCodeStub {
2134 public:
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00002135 explicit StubFailureTrampolineStub(StubFunctionMode function_mode)
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002136 : fp_registers_(CanUseFPRegisters()), function_mode_(function_mode) {}
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +00002137
2138 virtual bool IsPregenerated() { return true; }
2139
hpayer@chromium.org8432c912013-02-28 15:55:26 +00002140 static void GenerateAheadOfTime(Isolate* isolate);
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00002141
2142 private:
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002143 class FPRegisters: public BitField<bool, 0, 1> {};
2144 class FunctionModeField: public BitField<StubFunctionMode, 1, 1> {};
2145
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00002146 Major MajorKey() { return StubFailureTrampoline; }
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002147 int MinorKey() {
2148 return FPRegisters::encode(fp_registers_) |
2149 FunctionModeField::encode(function_mode_);
2150 }
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00002151
2152 void Generate(MacroAssembler* masm);
2153
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002154 bool fp_registers_;
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00002155 StubFunctionMode function_mode_;
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +00002156
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00002157 DISALLOW_COPY_AND_ASSIGN(StubFailureTrampolineStub);
2158};
2159
2160
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002161class ProfileEntryHookStub : public PlatformCodeStub {
verwaest@chromium.org753aee42012-07-17 16:15:42 +00002162 public:
2163 explicit ProfileEntryHookStub() {}
2164
2165 // The profile entry hook function is not allowed to cause a GC.
2166 virtual bool SometimesSetsUpAFrame() { return false; }
2167
2168 // Generates a call to the entry hook if it's enabled.
2169 static void MaybeCallEntryHook(MacroAssembler* masm);
2170
verwaest@chromium.org753aee42012-07-17 16:15:42 +00002171 private:
2172 static void EntryHookTrampoline(intptr_t function,
2173 intptr_t stack_pointer);
2174
2175 Major MajorKey() { return ProfileEntryHook; }
2176 int MinorKey() { return 0; }
2177
2178 void Generate(MacroAssembler* masm);
2179
verwaest@chromium.org753aee42012-07-17 16:15:42 +00002180 DISALLOW_COPY_AND_ASSIGN(ProfileEntryHookStub);
2181};
2182
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002183} } // namespace v8::internal
2184
2185#endif // V8_CODE_STUBS_H_