blob: 6bda5da709e8de9e1c4b0edfea73ebc63a83fe59 [file] [log] [blame]
Ben Murdoch086aeea2011-05-13 15:57:08 +01001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +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
Ben Murdoch257744e2011-11-30 15:57:28 +000031#include "allocation.h"
Steve Block6ded16b2010-05-10 14:33:55 +010032#include "globals.h"
Ben Murdoch592a9fc2012-03-05 11:04:45 +000033#include "codegen.h"
Steve Block6ded16b2010-05-10 14:33:55 +010034
Steve Blocka7e24c12009-10-30 11:49:00 +000035namespace v8 {
36namespace internal {
37
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000038// List of code stubs used on all platforms.
Steve Blockd0582a62009-12-15 09:54:21 +000039#define CODE_STUB_LIST_ALL_PLATFORMS(V) \
40 V(CallFunction) \
Ben Murdoch257744e2011-11-30 15:57:28 +000041 V(UnaryOp) \
42 V(BinaryOp) \
Steve Blockd0582a62009-12-15 09:54:21 +000043 V(StringAdd) \
Leon Clarkee46be812010-01-19 14:06:41 +000044 V(SubString) \
45 V(StringCompare) \
Steve Blockd0582a62009-12-15 09:54:21 +000046 V(Compare) \
Ben Murdochb0fe1622011-05-05 13:52:32 +010047 V(CompareIC) \
48 V(MathPow) \
Ben Murdoch592a9fc2012-03-05 11:04:45 +000049 V(RecordWrite) \
50 V(StoreBufferOverflow) \
51 V(RegExpExec) \
Ben Murdochb0fe1622011-05-05 13:52:32 +010052 V(TranscendentalCache) \
Ben Murdoch086aeea2011-05-13 15:57:08 +010053 V(Instanceof) \
Steve Blockd0582a62009-12-15 09:54:21 +000054 V(ConvertToDouble) \
55 V(WriteInt32ToHeapNumber) \
56 V(StackCheck) \
Leon Clarkee46be812010-01-19 14:06:41 +000057 V(FastNewClosure) \
58 V(FastNewContext) \
Ben Murdoch592a9fc2012-03-05 11:04:45 +000059 V(FastNewBlockContext) \
Leon Clarkee46be812010-01-19 14:06:41 +000060 V(FastCloneShallowArray) \
Ben Murdoch592a9fc2012-03-05 11:04:45 +000061 V(FastCloneShallowObject) \
Steve Blockd0582a62009-12-15 09:54:21 +000062 V(ToBoolean) \
Steve Block1e0659c2011-05-24 12:43:12 +010063 V(ToNumber) \
Steve Blockd0582a62009-12-15 09:54:21 +000064 V(ArgumentsAccess) \
Ben Murdochb0fe1622011-05-05 13:52:32 +010065 V(RegExpConstructResult) \
Andrei Popescu402d9372010-02-26 13:31:12 +000066 V(NumberToString) \
Steve Blockd0582a62009-12-15 09:54:21 +000067 V(CEntry) \
Leon Clarke4515c472010-02-03 11:58:03 +000068 V(JSEntry) \
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000069 V(KeyedLoadElement) \
70 V(KeyedStoreElement) \
Ben Murdoch257744e2011-11-30 15:57:28 +000071 V(DebuggerStatement) \
Ben Murdoch592a9fc2012-03-05 11:04:45 +000072 V(StringDictionaryLookup) \
73 V(ElementsTransitionAndStore) \
74 V(StoreArrayLiteralElement)
Steve Blockd0582a62009-12-15 09:54:21 +000075
76// List of code stubs only used on ARM platforms.
77#ifdef V8_TARGET_ARCH_ARM
78#define CODE_STUB_LIST_ARM(V) \
79 V(GetProperty) \
80 V(SetProperty) \
81 V(InvokeBuiltin) \
Steve Block1e0659c2011-05-24 12:43:12 +010082 V(RegExpCEntry) \
83 V(DirectCEntry)
Steve Blockd0582a62009-12-15 09:54:21 +000084#else
85#define CODE_STUB_LIST_ARM(V)
86#endif
87
Steve Block44f0eee2011-05-26 01:26:41 +010088// List of code stubs only used on MIPS platforms.
89#ifdef V8_TARGET_ARCH_MIPS
90#define CODE_STUB_LIST_MIPS(V) \
Ben Murdoch257744e2011-11-30 15:57:28 +000091 V(RegExpCEntry) \
92 V(DirectCEntry)
Steve Block44f0eee2011-05-26 01:26:41 +010093#else
94#define CODE_STUB_LIST_MIPS(V)
95#endif
96
Steve Blockd0582a62009-12-15 09:54:21 +000097// Combined list of code stubs.
98#define CODE_STUB_LIST(V) \
99 CODE_STUB_LIST_ALL_PLATFORMS(V) \
Steve Block44f0eee2011-05-26 01:26:41 +0100100 CODE_STUB_LIST_ARM(V) \
101 CODE_STUB_LIST_MIPS(V)
Steve Blocka7e24c12009-10-30 11:49:00 +0000102
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100103// Mode to overwrite BinaryExpression values.
104enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
105enum UnaryOverwriteMode { UNARY_OVERWRITE, UNARY_NO_OVERWRITE };
106
107
Steve Blocka7e24c12009-10-30 11:49:00 +0000108// Stub is base classes of all stubs.
109class CodeStub BASE_EMBEDDED {
110 public:
111 enum Major {
Steve Blockd0582a62009-12-15 09:54:21 +0000112#define DEF_ENUM(name) name,
113 CODE_STUB_LIST(DEF_ENUM)
114#undef DEF_ENUM
115 NoCache, // marker for stubs that do custom caching
Steve Blocka7e24c12009-10-30 11:49:00 +0000116 NUMBER_OF_IDS
117 };
118
119 // Retrieve the code for the stub. Generate the code if needed.
120 Handle<Code> GetCode();
121
122 static Major MajorKeyFromKey(uint32_t key) {
123 return static_cast<Major>(MajorKeyBits::decode(key));
Iain Merrick9ac36c92010-09-13 15:29:50 +0100124 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000125 static int MinorKeyFromKey(uint32_t key) {
126 return MinorKeyBits::decode(key);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100127 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100128
129 // Gets the major key from a code object that is a code stub or binary op IC.
130 static Major GetMajorKey(Code* code_stub) {
131 return static_cast<Major>(code_stub->major_key());
132 }
133
Andrei Popescu31002712010-02-23 13:46:05 +0000134 static const char* MajorName(Major major_key, bool allow_unknown_keys);
Steve Blocka7e24c12009-10-30 11:49:00 +0000135
136 virtual ~CodeStub() {}
137
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000138 bool CompilingCallsToThisStubIsGCSafe() {
139 bool is_pregenerated = IsPregenerated();
140 Code* code = NULL;
141 CHECK(!is_pregenerated || FindCodeInCache(&code));
142 return is_pregenerated;
143 }
144
145 // See comment above, where Instanceof is defined.
146 virtual bool IsPregenerated() { return false; }
147
148 static void GenerateStubsAheadOfTime();
149 static void GenerateFPStubs();
150
151 // Some stubs put untagged junk on the stack that cannot be scanned by the
152 // GC. This means that we must be statically sure that no GC can occur while
153 // they are running. If that is the case they should override this to return
154 // true, which will cause an assertion if we try to call something that can
155 // GC or if we try to put a stack frame on top of the junk, which would not
156 // result in a traversable stack.
157 virtual bool SometimesSetsUpAFrame() { return true; }
158
159 // Lookup the code in the (possibly custom) cache.
160 bool FindCodeInCache(Code** code_out);
161
Steve Blocka7e24c12009-10-30 11:49:00 +0000162 protected:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100163 static const int kMajorBits = 6;
Steve Blocka7e24c12009-10-30 11:49:00 +0000164 static const int kMinorBits = kBitsPerInt - kSmiTagSize - kMajorBits;
165
166 private:
Leon Clarkee46be812010-01-19 14:06:41 +0000167 // Nonvirtual wrapper around the stub-specific Generate function. Call
168 // this function to set up the macro assembler and generate the code.
169 void GenerateCode(MacroAssembler* masm);
170
Steve Blocka7e24c12009-10-30 11:49:00 +0000171 // Generates the assembler code for the stub.
172 virtual void Generate(MacroAssembler* masm) = 0;
173
Leon Clarkee46be812010-01-19 14:06:41 +0000174 // Perform bookkeeping required after code generation when stub code is
175 // initially generated.
176 void RecordCodeGeneration(Code* code, MacroAssembler* masm);
177
Ben Murdochb0fe1622011-05-05 13:52:32 +0100178 // Finish the code object after it has been generated.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000179 virtual void FinishCode(Handle<Code> code) { }
180
181 // Activate newly generated stub. Is called after
182 // registering stub in the stub cache.
183 virtual void Activate(Code* code) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100184
Steve Blocka7e24c12009-10-30 11:49:00 +0000185 // Returns information for computing the number key.
186 virtual Major MajorKey() = 0;
187 virtual int MinorKey() = 0;
188
Ben Murdoch257744e2011-11-30 15:57:28 +0000189 // BinaryOpStub needs to override this.
Steve Block6ded16b2010-05-10 14:33:55 +0100190 virtual int GetCodeKind();
191
Ben Murdoch257744e2011-11-30 15:57:28 +0000192 // BinaryOpStub needs to override this.
Steve Block6ded16b2010-05-10 14:33:55 +0100193 virtual InlineCacheState GetICState() {
194 return UNINITIALIZED;
195 }
196
Steve Blocka7e24c12009-10-30 11:49:00 +0000197 // Returns a name for logging/debugging purposes.
Ben Murdoch589d6972011-11-30 16:04:58 +0000198 SmartArrayPointer<const char> GetName();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000199 virtual void PrintName(StringStream* stream);
Steve Blocka7e24c12009-10-30 11:49:00 +0000200
Steve Block44f0eee2011-05-26 01:26:41 +0100201 // Returns whether the code generated for this stub needs to be allocated as
202 // a fixed (non-moveable) code object.
203 virtual bool NeedsImmovableCode() { return false; }
204
Steve Blocka7e24c12009-10-30 11:49:00 +0000205 // Computes the key based on major and minor.
206 uint32_t GetKey() {
207 ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
208 return MinorKeyBits::encode(MinorKey()) |
209 MajorKeyBits::encode(MajorKey());
210 }
211
Steve Blocka7e24c12009-10-30 11:49:00 +0000212 class MajorKeyBits: public BitField<uint32_t, 0, kMajorBits> {};
213 class MinorKeyBits: public BitField<uint32_t, kMajorBits, kMinorBits> {};
214
215 friend class BreakPointIterator;
216};
217
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100218
219// Helper interface to prepare to/restore after making runtime calls.
220class RuntimeCallHelper {
221 public:
222 virtual ~RuntimeCallHelper() {}
223
224 virtual void BeforeCall(MacroAssembler* masm) const = 0;
225
226 virtual void AfterCall(MacroAssembler* masm) const = 0;
227
228 protected:
229 RuntimeCallHelper() {}
230
231 private:
232 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
233};
234
235} } // namespace v8::internal
236
237#if V8_TARGET_ARCH_IA32
238#include "ia32/code-stubs-ia32.h"
239#elif V8_TARGET_ARCH_X64
240#include "x64/code-stubs-x64.h"
241#elif V8_TARGET_ARCH_ARM
242#include "arm/code-stubs-arm.h"
243#elif V8_TARGET_ARCH_MIPS
244#include "mips/code-stubs-mips.h"
245#else
246#error Unsupported target architecture.
247#endif
248
249namespace v8 {
250namespace internal {
251
252
Ben Murdochb0fe1622011-05-05 13:52:32 +0100253// RuntimeCallHelper implementation used in stubs: enters/leaves a
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100254// newly created internal frame before/after the runtime call.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100255class StubRuntimeCallHelper : public RuntimeCallHelper {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100256 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100257 StubRuntimeCallHelper() {}
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100258
259 virtual void BeforeCall(MacroAssembler* masm) const;
260
261 virtual void AfterCall(MacroAssembler* masm) const;
262};
263
264
265// Trivial RuntimeCallHelper implementation.
266class NopRuntimeCallHelper : public RuntimeCallHelper {
267 public:
268 NopRuntimeCallHelper() {}
269
270 virtual void BeforeCall(MacroAssembler* masm) const {}
271
272 virtual void AfterCall(MacroAssembler* masm) const {}
273};
274
275
276class StackCheckStub : public CodeStub {
277 public:
278 StackCheckStub() { }
279
280 void Generate(MacroAssembler* masm);
281
282 private:
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100283 Major MajorKey() { return StackCheck; }
284 int MinorKey() { return 0; }
285};
286
287
Steve Block1e0659c2011-05-24 12:43:12 +0100288class ToNumberStub: public CodeStub {
289 public:
290 ToNumberStub() { }
291
292 void Generate(MacroAssembler* masm);
293
294 private:
295 Major MajorKey() { return ToNumber; }
296 int MinorKey() { return 0; }
Steve Block1e0659c2011-05-24 12:43:12 +0100297};
298
299
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100300class FastNewClosureStub : public CodeStub {
301 public:
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000302 explicit FastNewClosureStub(LanguageMode language_mode)
303 : language_mode_(language_mode) { }
Steve Block44f0eee2011-05-26 01:26:41 +0100304
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100305 void Generate(MacroAssembler* masm);
306
307 private:
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100308 Major MajorKey() { return FastNewClosure; }
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000309 int MinorKey() { return language_mode_ == CLASSIC_MODE
310 ? kNonStrictMode : kStrictMode; }
Steve Block44f0eee2011-05-26 01:26:41 +0100311
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000312 LanguageMode language_mode_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100313};
314
315
316class FastNewContextStub : public CodeStub {
317 public:
318 static const int kMaximumSlots = 64;
319
320 explicit FastNewContextStub(int slots) : slots_(slots) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000321 ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100322 }
323
324 void Generate(MacroAssembler* masm);
325
326 private:
327 int slots_;
328
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100329 Major MajorKey() { return FastNewContext; }
330 int MinorKey() { return slots_; }
331};
332
333
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000334class FastNewBlockContextStub : public CodeStub {
335 public:
336 static const int kMaximumSlots = 64;
337
338 explicit FastNewBlockContextStub(int slots) : slots_(slots) {
339 ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
340 }
341
342 void Generate(MacroAssembler* masm);
343
344 private:
345 int slots_;
346
347 Major MajorKey() { return FastNewBlockContext; }
348 int MinorKey() { return slots_; }
349};
350
351
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100352class FastCloneShallowArrayStub : public CodeStub {
353 public:
354 // Maximum length of copied elements array.
355 static const int kMaximumClonedLength = 8;
356
357 enum Mode {
358 CLONE_ELEMENTS,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000359 CLONE_DOUBLE_ELEMENTS,
360 COPY_ON_WRITE_ELEMENTS,
361 CLONE_ANY_ELEMENTS
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100362 };
363
364 FastCloneShallowArrayStub(Mode mode, int length)
365 : mode_(mode),
366 length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000367 ASSERT_GE(length_, 0);
368 ASSERT_LE(length_, kMaximumClonedLength);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100369 }
370
371 void Generate(MacroAssembler* masm);
372
373 private:
374 Mode mode_;
375 int length_;
376
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100377 Major MajorKey() { return FastCloneShallowArray; }
378 int MinorKey() {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000379 ASSERT(mode_ == 0 || mode_ == 1 || mode_ == 2 || mode_ == 3);
380 return length_ * 4 + mode_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100381 }
382};
383
384
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000385class FastCloneShallowObjectStub : public CodeStub {
386 public:
387 // Maximum number of properties in copied object.
388 static const int kMaximumClonedProperties = 6;
389
390 explicit FastCloneShallowObjectStub(int length) : length_(length) {
391 ASSERT_GE(length_, 0);
392 ASSERT_LE(length_, kMaximumClonedProperties);
393 }
394
395 void Generate(MacroAssembler* masm);
396
397 private:
398 int length_;
399
400 Major MajorKey() { return FastCloneShallowObject; }
401 int MinorKey() { return length_; }
402};
403
404
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100405class InstanceofStub: public CodeStub {
406 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100407 enum Flags {
408 kNoFlags = 0,
Ben Murdoch086aeea2011-05-13 15:57:08 +0100409 kArgsInRegisters = 1 << 0,
410 kCallSiteInlineCheck = 1 << 1,
411 kReturnTrueFalseObject = 1 << 2
Ben Murdochb0fe1622011-05-05 13:52:32 +0100412 };
413
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000414 explicit InstanceofStub(Flags flags) : flags_(flags) { }
Ben Murdoch086aeea2011-05-13 15:57:08 +0100415
416 static Register left();
417 static Register right();
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100418
419 void Generate(MacroAssembler* masm);
420
421 private:
422 Major MajorKey() { return Instanceof; }
Ben Murdoch086aeea2011-05-13 15:57:08 +0100423 int MinorKey() { return static_cast<int>(flags_); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100424
Ben Murdoch086aeea2011-05-13 15:57:08 +0100425 bool HasArgsInRegisters() const {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100426 return (flags_ & kArgsInRegisters) != 0;
427 }
428
Ben Murdoch086aeea2011-05-13 15:57:08 +0100429 bool HasCallSiteInlineCheck() const {
430 return (flags_ & kCallSiteInlineCheck) != 0;
431 }
432
433 bool ReturnTrueFalseObject() const {
434 return (flags_ & kReturnTrueFalseObject) != 0;
435 }
436
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000437 virtual void PrintName(StringStream* stream);
Ben Murdoch086aeea2011-05-13 15:57:08 +0100438
Ben Murdochb0fe1622011-05-05 13:52:32 +0100439 Flags flags_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100440};
441
442
Ben Murdochb0fe1622011-05-05 13:52:32 +0100443class MathPowStub: public CodeStub {
444 public:
445 MathPowStub() {}
446 virtual void Generate(MacroAssembler* masm);
447
448 private:
449 virtual CodeStub::Major MajorKey() { return MathPow; }
450 virtual int MinorKey() { return 0; }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100451};
452
453
Ben Murdochb0fe1622011-05-05 13:52:32 +0100454class ICCompareStub: public CodeStub {
455 public:
456 ICCompareStub(Token::Value op, CompareIC::State state)
457 : op_(op), state_(state) {
458 ASSERT(Token::IsCompareOp(op));
459 }
460
461 virtual void Generate(MacroAssembler* masm);
462
463 private:
464 class OpField: public BitField<int, 0, 3> { };
465 class StateField: public BitField<int, 3, 5> { };
466
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000467 virtual void FinishCode(Handle<Code> code) {
468 code->set_compare_state(state_);
469 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100470
471 virtual CodeStub::Major MajorKey() { return CompareIC; }
472 virtual int MinorKey();
473
474 virtual int GetCodeKind() { return Code::COMPARE_IC; }
475
476 void GenerateSmis(MacroAssembler* masm);
477 void GenerateHeapNumbers(MacroAssembler* masm);
Ben Murdoch257744e2011-11-30 15:57:28 +0000478 void GenerateSymbols(MacroAssembler* masm);
479 void GenerateStrings(MacroAssembler* masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100480 void GenerateObjects(MacroAssembler* masm);
481 void GenerateMiss(MacroAssembler* masm);
482
483 bool strict() const { return op_ == Token::EQ_STRICT; }
484 Condition GetCondition() const { return CompareIC::ComputeCondition(op_); }
485
486 Token::Value op_;
487 CompareIC::State state_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100488};
489
490
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100491// Flags that control the compare stub code generation.
492enum CompareFlags {
493 NO_COMPARE_FLAGS = 0,
494 NO_SMI_COMPARE_IN_STUB = 1 << 0,
495 NO_NUMBER_COMPARE_IN_STUB = 1 << 1,
496 CANT_BOTH_BE_NAN = 1 << 2
497};
498
499
Ben Murdochb0fe1622011-05-05 13:52:32 +0100500enum NaNInformation {
501 kBothCouldBeNaN,
502 kCantBothBeNaN
503};
504
505
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100506class CompareStub: public CodeStub {
507 public:
508 CompareStub(Condition cc,
509 bool strict,
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100510 CompareFlags flags,
511 Register lhs,
512 Register rhs) :
Ben Murdochb0fe1622011-05-05 13:52:32 +0100513 cc_(cc),
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100514 strict_(strict),
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100515 never_nan_nan_((flags & CANT_BOTH_BE_NAN) != 0),
516 include_number_compare_((flags & NO_NUMBER_COMPARE_IN_STUB) == 0),
517 include_smi_compare_((flags & NO_SMI_COMPARE_IN_STUB) == 0),
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100518 lhs_(lhs),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000519 rhs_(rhs) { }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100520
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100521 CompareStub(Condition cc,
522 bool strict,
523 CompareFlags flags) :
524 cc_(cc),
525 strict_(strict),
526 never_nan_nan_((flags & CANT_BOTH_BE_NAN) != 0),
527 include_number_compare_((flags & NO_NUMBER_COMPARE_IN_STUB) == 0),
528 include_smi_compare_((flags & NO_SMI_COMPARE_IN_STUB) == 0),
529 lhs_(no_reg),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000530 rhs_(no_reg) { }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100531
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100532 void Generate(MacroAssembler* masm);
533
534 private:
535 Condition cc_;
536 bool strict_;
537 // Only used for 'equal' comparisons. Tells the stub that we already know
538 // that at least one side of the comparison is not NaN. This allows the
539 // stub to use object identity in the positive case. We ignore it when
540 // generating the minor key for other comparisons to avoid creating more
541 // stubs.
542 bool never_nan_nan_;
543 // Do generate the number comparison code in the stub. Stubs without number
544 // comparison code is used when the number comparison has been inlined, and
545 // the stub will be called if one of the operands is not a number.
546 bool include_number_compare_;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100547
548 // Generate the comparison code for two smi operands in the stub.
549 bool include_smi_compare_;
550
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100551 // Register holding the left hand side of the comparison if the stub gives
552 // a choice, no_reg otherwise.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100553
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100554 Register lhs_;
555 // Register holding the right hand side of the comparison if the stub gives
556 // a choice, no_reg otherwise.
557 Register rhs_;
558
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100559 // Encoding of the minor key in 16 bits.
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100560 class StrictField: public BitField<bool, 0, 1> {};
561 class NeverNanNanField: public BitField<bool, 1, 1> {};
562 class IncludeNumberCompareField: public BitField<bool, 2, 1> {};
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100563 class IncludeSmiCompareField: public BitField<bool, 3, 1> {};
564 class RegisterField: public BitField<bool, 4, 1> {};
565 class ConditionField: public BitField<int, 5, 11> {};
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100566
567 Major MajorKey() { return Compare; }
568
569 int MinorKey();
570
Ben Murdochb0fe1622011-05-05 13:52:32 +0100571 virtual int GetCodeKind() { return Code::COMPARE_IC; }
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000572 virtual void FinishCode(Handle<Code> code) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100573 code->set_compare_state(CompareIC::GENERIC);
574 }
575
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100576 // Branch to the label if the given object isn't a symbol.
577 void BranchIfNonSymbol(MacroAssembler* masm,
578 Label* label,
579 Register object,
580 Register scratch);
581
582 // Unfortunately you have to run without snapshots to see most of these
583 // names in the profile since most compare stubs end up in the snapshot.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000584 virtual void PrintName(StringStream* stream);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100585};
586
587
588class CEntryStub : public CodeStub {
589 public:
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000590 explicit CEntryStub(int result_size,
591 SaveFPRegsMode save_doubles = kDontSaveFPRegs)
592 : result_size_(result_size), save_doubles_(save_doubles) { }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100593
594 void Generate(MacroAssembler* masm);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000595
596 // The version of this stub that doesn't save doubles is generated ahead of
597 // time, so it's OK to call it from other stubs that can't cope with GC during
598 // their code generation. On machines that always have gp registers (x64) we
599 // can generate both variants ahead of time.
600 virtual bool IsPregenerated();
601 static void GenerateAheadOfTime();
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100602
603 private:
604 void GenerateCore(MacroAssembler* masm,
605 Label* throw_normal_exception,
606 Label* throw_termination_exception,
607 Label* throw_out_of_memory_exception,
608 bool do_gc,
Steve Block1e0659c2011-05-24 12:43:12 +0100609 bool always_allocate_scope);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100610 void GenerateThrowTOS(MacroAssembler* masm);
611 void GenerateThrowUncatchable(MacroAssembler* masm,
612 UncatchableExceptionType type);
613
614 // Number of pointers/values returned.
615 const int result_size_;
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000616 SaveFPRegsMode save_doubles_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100617
618 Major MajorKey() { return CEntry; }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100619 int MinorKey();
620
Steve Block44f0eee2011-05-26 01:26:41 +0100621 bool NeedsImmovableCode();
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100622};
623
624
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100625class JSEntryStub : public CodeStub {
626 public:
627 JSEntryStub() { }
628
629 void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
630
631 protected:
632 void GenerateBody(MacroAssembler* masm, bool is_construct);
633
634 private:
635 Major MajorKey() { return JSEntry; }
636 int MinorKey() { return 0; }
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000637
638 virtual void FinishCode(Handle<Code> code);
639
640 int handler_offset_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100641};
642
643
644class JSConstructEntryStub : public JSEntryStub {
645 public:
646 JSConstructEntryStub() { }
647
648 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
649
650 private:
651 int MinorKey() { return 1; }
652
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000653 virtual void PrintName(StringStream* stream) {
654 stream->Add("JSConstructEntryStub");
655 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100656};
657
658
659class ArgumentsAccessStub: public CodeStub {
660 public:
661 enum Type {
662 READ_ELEMENT,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000663 NEW_NON_STRICT_FAST,
664 NEW_NON_STRICT_SLOW,
Steve Block44f0eee2011-05-26 01:26:41 +0100665 NEW_STRICT
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100666 };
667
668 explicit ArgumentsAccessStub(Type type) : type_(type) { }
669
670 private:
671 Type type_;
672
673 Major MajorKey() { return ArgumentsAccess; }
674 int MinorKey() { return type_; }
675
676 void Generate(MacroAssembler* masm);
677 void GenerateReadElement(MacroAssembler* masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000678 void GenerateNewStrict(MacroAssembler* masm);
679 void GenerateNewNonStrictFast(MacroAssembler* masm);
680 void GenerateNewNonStrictSlow(MacroAssembler* masm);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100681
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000682 virtual void PrintName(StringStream* stream);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100683};
684
685
686class RegExpExecStub: public CodeStub {
687 public:
688 RegExpExecStub() { }
689
690 private:
691 Major MajorKey() { return RegExpExec; }
692 int MinorKey() { return 0; }
693
694 void Generate(MacroAssembler* masm);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100695};
696
697
Ben Murdochb0fe1622011-05-05 13:52:32 +0100698class RegExpConstructResultStub: public CodeStub {
699 public:
700 RegExpConstructResultStub() { }
701
702 private:
703 Major MajorKey() { return RegExpConstructResult; }
704 int MinorKey() { return 0; }
705
706 void Generate(MacroAssembler* masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100707};
708
709
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100710class CallFunctionStub: public CodeStub {
711 public:
Ben Murdoch589d6972011-11-30 16:04:58 +0000712 CallFunctionStub(int argc, CallFunctionFlags flags)
713 : argc_(argc), flags_(flags) { }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100714
715 void Generate(MacroAssembler* masm);
716
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000717 virtual void FinishCode(Handle<Code> code);
718
719 static void Clear(Heap* heap, Address address);
720
721 static Object* GetCachedValue(Address address);
722
Ben Murdoch086aeea2011-05-13 15:57:08 +0100723 static int ExtractArgcFromMinorKey(int minor_key) {
724 return ArgcBits::decode(minor_key);
725 }
726
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000727 // The object that indicates an uninitialized cache.
728 static Handle<Object> UninitializedSentinel(Isolate* isolate) {
729 return isolate->factory()->the_hole_value();
730 }
731
732 // A raw version of the uninitialized sentinel that's safe to read during
733 // garbage collection (e.g., for patching the cache).
734 static Object* RawUninitializedSentinel(Heap* heap) {
735 return heap->raw_unchecked_the_hole_value();
736 }
737
738 // The object that indicates a megamorphic state.
739 static Handle<Object> MegamorphicSentinel(Isolate* isolate) {
740 return isolate->factory()->undefined_value();
741 }
742
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100743 private:
744 int argc_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100745 CallFunctionFlags flags_;
746
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000747 virtual void PrintName(StringStream* stream);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100748
749 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000750 class FlagBits: public BitField<CallFunctionFlags, 0, 2> {};
751 class ArgcBits: public BitField<unsigned, 2, 32 - 2> {};
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100752
753 Major MajorKey() { return CallFunction; }
754 int MinorKey() {
755 // Encode the parameters in a unique 32 bit value.
Ben Murdoch589d6972011-11-30 16:04:58 +0000756 return FlagBits::encode(flags_) | ArgcBits::encode(argc_);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100757 }
758
Ben Murdoch257744e2011-11-30 15:57:28 +0000759 bool ReceiverMightBeImplicit() {
760 return (flags_ & RECEIVER_MIGHT_BE_IMPLICIT) != 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100761 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000762
763 bool RecordCallTarget() {
764 return (flags_ & RECORD_CALL_TARGET) != 0;
765 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100766};
767
768
769enum StringIndexFlags {
770 // Accepts smis or heap numbers.
771 STRING_INDEX_IS_NUMBER,
772
773 // Accepts smis or heap numbers that are valid array indices
774 // (ECMA-262 15.4). Invalid indices are reported as being out of
775 // range.
776 STRING_INDEX_IS_ARRAY_INDEX
777};
778
779
780// Generates code implementing String.prototype.charCodeAt.
781//
782// Only supports the case when the receiver is a string and the index
783// is a number (smi or heap number) that is a valid index into the
784// string. Additional index constraints are specified by the
785// flags. Otherwise, bails out to the provided labels.
786//
787// Register usage: |object| may be changed to another string in a way
788// that doesn't affect charCodeAt/charAt semantics, |index| is
789// preserved, |scratch| and |result| are clobbered.
790class StringCharCodeAtGenerator {
791 public:
792 StringCharCodeAtGenerator(Register object,
793 Register index,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100794 Register result,
795 Label* receiver_not_string,
796 Label* index_not_number,
797 Label* index_out_of_range,
798 StringIndexFlags index_flags)
799 : object_(object),
800 index_(index),
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100801 result_(result),
802 receiver_not_string_(receiver_not_string),
803 index_not_number_(index_not_number),
804 index_out_of_range_(index_out_of_range),
805 index_flags_(index_flags) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100806 ASSERT(!result_.is(object_));
807 ASSERT(!result_.is(index_));
808 }
809
810 // Generates the fast case code. On the fallthrough path |result|
811 // register contains the result.
812 void GenerateFast(MacroAssembler* masm);
813
814 // Generates the slow case code. Must not be naturally
815 // reachable. Expected to be put after a ret instruction (e.g., in
816 // deferred code). Always jumps back to the fast case.
817 void GenerateSlow(MacroAssembler* masm,
818 const RuntimeCallHelper& call_helper);
819
820 private:
821 Register object_;
822 Register index_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100823 Register result_;
824
825 Label* receiver_not_string_;
826 Label* index_not_number_;
827 Label* index_out_of_range_;
828
829 StringIndexFlags index_flags_;
830
831 Label call_runtime_;
832 Label index_not_smi_;
833 Label got_smi_index_;
834 Label exit_;
835
836 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
837};
838
839
840// Generates code for creating a one-char string from a char code.
841class StringCharFromCodeGenerator {
842 public:
843 StringCharFromCodeGenerator(Register code,
844 Register result)
845 : code_(code),
846 result_(result) {
847 ASSERT(!code_.is(result_));
848 }
849
850 // Generates the fast case code. On the fallthrough path |result|
851 // register contains the result.
852 void GenerateFast(MacroAssembler* masm);
853
854 // Generates the slow case code. Must not be naturally
855 // reachable. Expected to be put after a ret instruction (e.g., in
856 // deferred code). Always jumps back to the fast case.
857 void GenerateSlow(MacroAssembler* masm,
858 const RuntimeCallHelper& call_helper);
859
860 private:
861 Register code_;
862 Register result_;
863
864 Label slow_case_;
865 Label exit_;
866
867 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
868};
869
870
871// Generates code implementing String.prototype.charAt.
872//
873// Only supports the case when the receiver is a string and the index
874// is a number (smi or heap number) that is a valid index into the
875// string. Additional index constraints are specified by the
876// flags. Otherwise, bails out to the provided labels.
877//
878// Register usage: |object| may be changed to another string in a way
879// that doesn't affect charCodeAt/charAt semantics, |index| is
880// preserved, |scratch1|, |scratch2|, and |result| are clobbered.
881class StringCharAtGenerator {
882 public:
883 StringCharAtGenerator(Register object,
884 Register index,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000885 Register scratch,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100886 Register result,
887 Label* receiver_not_string,
888 Label* index_not_number,
889 Label* index_out_of_range,
890 StringIndexFlags index_flags)
891 : char_code_at_generator_(object,
892 index,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000893 scratch,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100894 receiver_not_string,
895 index_not_number,
896 index_out_of_range,
897 index_flags),
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000898 char_from_code_generator_(scratch, result) {}
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100899
900 // Generates the fast case code. On the fallthrough path |result|
901 // register contains the result.
902 void GenerateFast(MacroAssembler* masm);
903
904 // Generates the slow case code. Must not be naturally
905 // reachable. Expected to be put after a ret instruction (e.g., in
906 // deferred code). Always jumps back to the fast case.
907 void GenerateSlow(MacroAssembler* masm,
908 const RuntimeCallHelper& call_helper);
909
910 private:
911 StringCharCodeAtGenerator char_code_at_generator_;
912 StringCharFromCodeGenerator char_from_code_generator_;
913
914 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
915};
916
Ben Murdoch086aeea2011-05-13 15:57:08 +0100917
918class AllowStubCallsScope {
919 public:
920 AllowStubCallsScope(MacroAssembler* masm, bool allow)
921 : masm_(masm), previous_allow_(masm->allow_stub_calls()) {
922 masm_->set_allow_stub_calls(allow);
923 }
924 ~AllowStubCallsScope() {
925 masm_->set_allow_stub_calls(previous_allow_);
926 }
927
928 private:
929 MacroAssembler* masm_;
930 bool previous_allow_;
931
932 DISALLOW_COPY_AND_ASSIGN(AllowStubCallsScope);
933};
934
Ben Murdoch257744e2011-11-30 15:57:28 +0000935
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000936class KeyedLoadElementStub : public CodeStub {
Ben Murdoch257744e2011-11-30 15:57:28 +0000937 public:
Ben Murdoch589d6972011-11-30 16:04:58 +0000938 explicit KeyedLoadElementStub(ElementsKind elements_kind)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000939 : elements_kind_(elements_kind)
940 { }
Ben Murdoch257744e2011-11-30 15:57:28 +0000941
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000942 Major MajorKey() { return KeyedLoadElement; }
943 int MinorKey() { return elements_kind_; }
Ben Murdoch257744e2011-11-30 15:57:28 +0000944
945 void Generate(MacroAssembler* masm);
946
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000947 private:
Ben Murdoch589d6972011-11-30 16:04:58 +0000948 ElementsKind elements_kind_;
Ben Murdoch257744e2011-11-30 15:57:28 +0000949
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000950 DISALLOW_COPY_AND_ASSIGN(KeyedLoadElementStub);
Ben Murdoch257744e2011-11-30 15:57:28 +0000951};
952
953
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000954class KeyedStoreElementStub : public CodeStub {
Ben Murdoch257744e2011-11-30 15:57:28 +0000955 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000956 KeyedStoreElementStub(bool is_js_array,
Ben Murdoch589d6972011-11-30 16:04:58 +0000957 ElementsKind elements_kind)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000958 : is_js_array_(is_js_array),
959 elements_kind_(elements_kind) { }
Ben Murdoch257744e2011-11-30 15:57:28 +0000960
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000961 Major MajorKey() { return KeyedStoreElement; }
962 int MinorKey() {
Ben Murdoch589d6972011-11-30 16:04:58 +0000963 return (is_js_array_ ? 0 : kElementsKindCount) + elements_kind_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000964 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000965
966 void Generate(MacroAssembler* masm);
967
Ben Murdoch257744e2011-11-30 15:57:28 +0000968 private:
969 bool is_js_array_;
Ben Murdoch589d6972011-11-30 16:04:58 +0000970 ElementsKind elements_kind_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000971
972 DISALLOW_COPY_AND_ASSIGN(KeyedStoreElementStub);
Ben Murdoch257744e2011-11-30 15:57:28 +0000973};
974
975
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000976class ToBooleanStub: public CodeStub {
Ben Murdoch257744e2011-11-30 15:57:28 +0000977 public:
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000978 enum Type {
979 UNDEFINED,
980 BOOLEAN,
981 NULL_TYPE,
982 SMI,
983 SPEC_OBJECT,
984 STRING,
985 HEAP_NUMBER,
986 NUMBER_OF_TYPES
987 };
988
989 // At most 8 different types can be distinguished, because the Code object
990 // only has room for a single byte to hold a set of these types. :-P
991 STATIC_ASSERT(NUMBER_OF_TYPES <= 8);
992
993 class Types {
994 public:
995 Types() {}
996 explicit Types(byte bits) : set_(bits) {}
997
998 bool IsEmpty() const { return set_.IsEmpty(); }
999 bool Contains(Type type) const { return set_.Contains(type); }
1000 void Add(Type type) { set_.Add(type); }
1001 byte ToByte() const { return set_.ToIntegral(); }
1002 void Print(StringStream* stream) const;
1003 void TraceTransition(Types to) const;
1004 bool Record(Handle<Object> object);
1005 bool NeedsMap() const;
1006 bool CanBeUndetectable() const;
1007
1008 private:
1009 EnumSet<Type, byte> set_;
1010 };
1011
1012 static Types no_types() { return Types(); }
1013 static Types all_types() { return Types((1 << NUMBER_OF_TYPES) - 1); }
1014
1015 explicit ToBooleanStub(Register tos, Types types = Types())
1016 : tos_(tos), types_(types) { }
Ben Murdoch257744e2011-11-30 15:57:28 +00001017
1018 void Generate(MacroAssembler* masm);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001019 virtual int GetCodeKind() { return Code::TO_BOOLEAN_IC; }
1020 virtual void PrintName(StringStream* stream);
Ben Murdoch257744e2011-11-30 15:57:28 +00001021
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001022 virtual bool SometimesSetsUpAFrame() { return false; }
1023
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001024 private:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001025 Major MajorKey() { return ToBoolean; }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001026 int MinorKey() { return (tos_.code() << NUMBER_OF_TYPES) | types_.ToByte(); }
1027
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001028 virtual void FinishCode(Handle<Code> code) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001029 code->set_to_boolean_state(types_.ToByte());
1030 }
1031
1032 void CheckOddball(MacroAssembler* masm,
1033 Type type,
1034 Heap::RootListIndex value,
1035 bool result);
1036 void GenerateTypeTransition(MacroAssembler* masm);
1037
1038 Register tos_;
1039 Types types_;
Ben Murdoch257744e2011-11-30 15:57:28 +00001040};
1041
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001042
1043class ElementsTransitionAndStoreStub : public CodeStub {
1044 public:
1045 ElementsTransitionAndStoreStub(ElementsKind from,
1046 ElementsKind to,
1047 bool is_jsarray,
1048 StrictModeFlag strict_mode)
1049 : from_(from),
1050 to_(to),
1051 is_jsarray_(is_jsarray),
1052 strict_mode_(strict_mode) {}
1053
1054 private:
1055 class FromBits: public BitField<ElementsKind, 0, 8> {};
1056 class ToBits: public BitField<ElementsKind, 8, 8> {};
1057 class IsJSArrayBits: public BitField<bool, 16, 8> {};
1058 class StrictModeBits: public BitField<StrictModeFlag, 24, 8> {};
1059
1060 Major MajorKey() { return ElementsTransitionAndStore; }
1061 int MinorKey() {
1062 return FromBits::encode(from_) |
1063 ToBits::encode(to_) |
1064 IsJSArrayBits::encode(is_jsarray_) |
1065 StrictModeBits::encode(strict_mode_);
1066 }
1067
1068 void Generate(MacroAssembler* masm);
1069
1070 ElementsKind from_;
1071 ElementsKind to_;
1072 bool is_jsarray_;
1073 StrictModeFlag strict_mode_;
1074
1075 DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub);
1076};
1077
1078
1079class StoreArrayLiteralElementStub : public CodeStub {
1080 public:
1081 explicit StoreArrayLiteralElementStub() {}
1082
1083 private:
1084 Major MajorKey() { return StoreArrayLiteralElement; }
1085 int MinorKey() { return 0; }
1086
1087 void Generate(MacroAssembler* masm);
1088
1089 DISALLOW_COPY_AND_ASSIGN(StoreArrayLiteralElementStub);
1090};
1091
Steve Blocka7e24c12009-10-30 11:49:00 +00001092} } // namespace v8::internal
1093
1094#endif // V8_CODE_STUBS_H_