blob: 34da148e5d1a9d8ca6f3603d8eee025e15b5b865 [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
Ben Murdochc7cc0282012-03-05 14:35:55 +0000197 // Add the code to a specialized cache, specific to an individual
198 // stub type. Please note, this method must add the code object to a
199 // roots object, otherwise we will remove the code during GC.
200 virtual void AddToSpecialCache(Handle<Code> new_object) { }
201
202 // Find code in a specialized cache, work is delegated to the specific stub.
203 virtual bool FindCodeInSpecialCache(Code** code_out) { return false; }
204
205 // If a stub uses a special cache override this.
206 virtual bool UseSpecialCache() { return false; }
207
Steve Blocka7e24c12009-10-30 11:49:00 +0000208 // Returns a name for logging/debugging purposes.
Ben Murdoch589d6972011-11-30 16:04:58 +0000209 SmartArrayPointer<const char> GetName();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000210 virtual void PrintName(StringStream* stream);
Steve Blocka7e24c12009-10-30 11:49:00 +0000211
Steve Block44f0eee2011-05-26 01:26:41 +0100212 // Returns whether the code generated for this stub needs to be allocated as
213 // a fixed (non-moveable) code object.
214 virtual bool NeedsImmovableCode() { return false; }
215
Steve Blocka7e24c12009-10-30 11:49:00 +0000216 // Computes the key based on major and minor.
217 uint32_t GetKey() {
218 ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
219 return MinorKeyBits::encode(MinorKey()) |
220 MajorKeyBits::encode(MajorKey());
221 }
222
Steve Blocka7e24c12009-10-30 11:49:00 +0000223 class MajorKeyBits: public BitField<uint32_t, 0, kMajorBits> {};
224 class MinorKeyBits: public BitField<uint32_t, kMajorBits, kMinorBits> {};
225
226 friend class BreakPointIterator;
227};
228
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100229
230// Helper interface to prepare to/restore after making runtime calls.
231class RuntimeCallHelper {
232 public:
233 virtual ~RuntimeCallHelper() {}
234
235 virtual void BeforeCall(MacroAssembler* masm) const = 0;
236
237 virtual void AfterCall(MacroAssembler* masm) const = 0;
238
239 protected:
240 RuntimeCallHelper() {}
241
242 private:
243 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
244};
245
246} } // namespace v8::internal
247
248#if V8_TARGET_ARCH_IA32
249#include "ia32/code-stubs-ia32.h"
250#elif V8_TARGET_ARCH_X64
251#include "x64/code-stubs-x64.h"
252#elif V8_TARGET_ARCH_ARM
253#include "arm/code-stubs-arm.h"
254#elif V8_TARGET_ARCH_MIPS
255#include "mips/code-stubs-mips.h"
256#else
257#error Unsupported target architecture.
258#endif
259
260namespace v8 {
261namespace internal {
262
263
Ben Murdochb0fe1622011-05-05 13:52:32 +0100264// RuntimeCallHelper implementation used in stubs: enters/leaves a
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100265// newly created internal frame before/after the runtime call.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100266class StubRuntimeCallHelper : public RuntimeCallHelper {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100267 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100268 StubRuntimeCallHelper() {}
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100269
270 virtual void BeforeCall(MacroAssembler* masm) const;
271
272 virtual void AfterCall(MacroAssembler* masm) const;
273};
274
275
276// Trivial RuntimeCallHelper implementation.
277class NopRuntimeCallHelper : public RuntimeCallHelper {
278 public:
279 NopRuntimeCallHelper() {}
280
281 virtual void BeforeCall(MacroAssembler* masm) const {}
282
283 virtual void AfterCall(MacroAssembler* masm) const {}
284};
285
286
287class StackCheckStub : public CodeStub {
288 public:
289 StackCheckStub() { }
290
291 void Generate(MacroAssembler* masm);
292
293 private:
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100294 Major MajorKey() { return StackCheck; }
295 int MinorKey() { return 0; }
296};
297
298
Steve Block1e0659c2011-05-24 12:43:12 +0100299class ToNumberStub: public CodeStub {
300 public:
301 ToNumberStub() { }
302
303 void Generate(MacroAssembler* masm);
304
305 private:
306 Major MajorKey() { return ToNumber; }
307 int MinorKey() { return 0; }
Steve Block1e0659c2011-05-24 12:43:12 +0100308};
309
310
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100311class FastNewClosureStub : public CodeStub {
312 public:
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000313 explicit FastNewClosureStub(LanguageMode language_mode)
314 : language_mode_(language_mode) { }
Steve Block44f0eee2011-05-26 01:26:41 +0100315
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100316 void Generate(MacroAssembler* masm);
317
318 private:
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100319 Major MajorKey() { return FastNewClosure; }
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000320 int MinorKey() { return language_mode_ == CLASSIC_MODE
321 ? kNonStrictMode : kStrictMode; }
Steve Block44f0eee2011-05-26 01:26:41 +0100322
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000323 LanguageMode language_mode_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100324};
325
326
327class FastNewContextStub : public CodeStub {
328 public:
329 static const int kMaximumSlots = 64;
330
331 explicit FastNewContextStub(int slots) : slots_(slots) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000332 ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100333 }
334
335 void Generate(MacroAssembler* masm);
336
337 private:
338 int slots_;
339
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100340 Major MajorKey() { return FastNewContext; }
341 int MinorKey() { return slots_; }
342};
343
344
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000345class FastNewBlockContextStub : public CodeStub {
346 public:
347 static const int kMaximumSlots = 64;
348
349 explicit FastNewBlockContextStub(int slots) : slots_(slots) {
350 ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
351 }
352
353 void Generate(MacroAssembler* masm);
354
355 private:
356 int slots_;
357
358 Major MajorKey() { return FastNewBlockContext; }
359 int MinorKey() { return slots_; }
360};
361
362
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100363class FastCloneShallowArrayStub : public CodeStub {
364 public:
365 // Maximum length of copied elements array.
366 static const int kMaximumClonedLength = 8;
367
368 enum Mode {
369 CLONE_ELEMENTS,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000370 CLONE_DOUBLE_ELEMENTS,
371 COPY_ON_WRITE_ELEMENTS,
372 CLONE_ANY_ELEMENTS
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100373 };
374
375 FastCloneShallowArrayStub(Mode mode, int length)
376 : mode_(mode),
377 length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000378 ASSERT_GE(length_, 0);
379 ASSERT_LE(length_, kMaximumClonedLength);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100380 }
381
382 void Generate(MacroAssembler* masm);
383
384 private:
385 Mode mode_;
386 int length_;
387
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100388 Major MajorKey() { return FastCloneShallowArray; }
389 int MinorKey() {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000390 ASSERT(mode_ == 0 || mode_ == 1 || mode_ == 2 || mode_ == 3);
391 return length_ * 4 + mode_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100392 }
393};
394
395
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000396class FastCloneShallowObjectStub : public CodeStub {
397 public:
398 // Maximum number of properties in copied object.
399 static const int kMaximumClonedProperties = 6;
400
401 explicit FastCloneShallowObjectStub(int length) : length_(length) {
402 ASSERT_GE(length_, 0);
403 ASSERT_LE(length_, kMaximumClonedProperties);
404 }
405
406 void Generate(MacroAssembler* masm);
407
408 private:
409 int length_;
410
411 Major MajorKey() { return FastCloneShallowObject; }
412 int MinorKey() { return length_; }
413};
414
415
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100416class InstanceofStub: public CodeStub {
417 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100418 enum Flags {
419 kNoFlags = 0,
Ben Murdoch086aeea2011-05-13 15:57:08 +0100420 kArgsInRegisters = 1 << 0,
421 kCallSiteInlineCheck = 1 << 1,
422 kReturnTrueFalseObject = 1 << 2
Ben Murdochb0fe1622011-05-05 13:52:32 +0100423 };
424
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000425 explicit InstanceofStub(Flags flags) : flags_(flags) { }
Ben Murdoch086aeea2011-05-13 15:57:08 +0100426
427 static Register left();
428 static Register right();
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100429
430 void Generate(MacroAssembler* masm);
431
432 private:
433 Major MajorKey() { return Instanceof; }
Ben Murdoch086aeea2011-05-13 15:57:08 +0100434 int MinorKey() { return static_cast<int>(flags_); }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100435
Ben Murdoch086aeea2011-05-13 15:57:08 +0100436 bool HasArgsInRegisters() const {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100437 return (flags_ & kArgsInRegisters) != 0;
438 }
439
Ben Murdoch086aeea2011-05-13 15:57:08 +0100440 bool HasCallSiteInlineCheck() const {
441 return (flags_ & kCallSiteInlineCheck) != 0;
442 }
443
444 bool ReturnTrueFalseObject() const {
445 return (flags_ & kReturnTrueFalseObject) != 0;
446 }
447
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000448 virtual void PrintName(StringStream* stream);
Ben Murdoch086aeea2011-05-13 15:57:08 +0100449
Ben Murdochb0fe1622011-05-05 13:52:32 +0100450 Flags flags_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100451};
452
453
Ben Murdochb0fe1622011-05-05 13:52:32 +0100454class MathPowStub: public CodeStub {
455 public:
Ben Murdochc7cc0282012-03-05 14:35:55 +0000456 enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK};
457
458 explicit MathPowStub(ExponentType exponent_type)
459 : exponent_type_(exponent_type) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100460 virtual void Generate(MacroAssembler* masm);
461
462 private:
463 virtual CodeStub::Major MajorKey() { return MathPow; }
Ben Murdochc7cc0282012-03-05 14:35:55 +0000464 virtual int MinorKey() { return exponent_type_; }
465
466 ExponentType exponent_type_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100467};
468
469
Ben Murdochb0fe1622011-05-05 13:52:32 +0100470class ICCompareStub: public CodeStub {
471 public:
472 ICCompareStub(Token::Value op, CompareIC::State state)
473 : op_(op), state_(state) {
474 ASSERT(Token::IsCompareOp(op));
475 }
476
477 virtual void Generate(MacroAssembler* masm);
478
Ben Murdochc7cc0282012-03-05 14:35:55 +0000479 void set_known_map(Handle<Map> map) { known_map_ = map; }
480
Ben Murdochb0fe1622011-05-05 13:52:32 +0100481 private:
482 class OpField: public BitField<int, 0, 3> { };
483 class StateField: public BitField<int, 3, 5> { };
484
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000485 virtual void FinishCode(Handle<Code> code) {
486 code->set_compare_state(state_);
487 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100488
489 virtual CodeStub::Major MajorKey() { return CompareIC; }
490 virtual int MinorKey();
491
492 virtual int GetCodeKind() { return Code::COMPARE_IC; }
493
494 void GenerateSmis(MacroAssembler* masm);
495 void GenerateHeapNumbers(MacroAssembler* masm);
Ben Murdoch257744e2011-11-30 15:57:28 +0000496 void GenerateSymbols(MacroAssembler* masm);
497 void GenerateStrings(MacroAssembler* masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100498 void GenerateObjects(MacroAssembler* masm);
499 void GenerateMiss(MacroAssembler* masm);
Ben Murdochc7cc0282012-03-05 14:35:55 +0000500 void GenerateKnownObjects(MacroAssembler* masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100501
502 bool strict() const { return op_ == Token::EQ_STRICT; }
503 Condition GetCondition() const { return CompareIC::ComputeCondition(op_); }
504
Ben Murdochc7cc0282012-03-05 14:35:55 +0000505 virtual void AddToSpecialCache(Handle<Code> new_object);
506 virtual bool FindCodeInSpecialCache(Code** code_out);
507 virtual bool UseSpecialCache() { return state_ == CompareIC::KNOWN_OBJECTS; }
508
Ben Murdochb0fe1622011-05-05 13:52:32 +0100509 Token::Value op_;
510 CompareIC::State state_;
Ben Murdochc7cc0282012-03-05 14:35:55 +0000511 Handle<Map> known_map_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100512};
513
514
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100515// Flags that control the compare stub code generation.
516enum CompareFlags {
517 NO_COMPARE_FLAGS = 0,
518 NO_SMI_COMPARE_IN_STUB = 1 << 0,
519 NO_NUMBER_COMPARE_IN_STUB = 1 << 1,
520 CANT_BOTH_BE_NAN = 1 << 2
521};
522
523
Ben Murdochb0fe1622011-05-05 13:52:32 +0100524enum NaNInformation {
525 kBothCouldBeNaN,
526 kCantBothBeNaN
527};
528
529
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100530class CompareStub: public CodeStub {
531 public:
532 CompareStub(Condition cc,
533 bool strict,
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100534 CompareFlags flags,
535 Register lhs,
536 Register rhs) :
Ben Murdochb0fe1622011-05-05 13:52:32 +0100537 cc_(cc),
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100538 strict_(strict),
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100539 never_nan_nan_((flags & CANT_BOTH_BE_NAN) != 0),
540 include_number_compare_((flags & NO_NUMBER_COMPARE_IN_STUB) == 0),
541 include_smi_compare_((flags & NO_SMI_COMPARE_IN_STUB) == 0),
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100542 lhs_(lhs),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000543 rhs_(rhs) { }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100544
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100545 CompareStub(Condition cc,
546 bool strict,
547 CompareFlags flags) :
548 cc_(cc),
549 strict_(strict),
550 never_nan_nan_((flags & CANT_BOTH_BE_NAN) != 0),
551 include_number_compare_((flags & NO_NUMBER_COMPARE_IN_STUB) == 0),
552 include_smi_compare_((flags & NO_SMI_COMPARE_IN_STUB) == 0),
553 lhs_(no_reg),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000554 rhs_(no_reg) { }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100555
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100556 void Generate(MacroAssembler* masm);
557
558 private:
559 Condition cc_;
560 bool strict_;
561 // Only used for 'equal' comparisons. Tells the stub that we already know
562 // that at least one side of the comparison is not NaN. This allows the
563 // stub to use object identity in the positive case. We ignore it when
564 // generating the minor key for other comparisons to avoid creating more
565 // stubs.
566 bool never_nan_nan_;
567 // Do generate the number comparison code in the stub. Stubs without number
568 // comparison code is used when the number comparison has been inlined, and
569 // the stub will be called if one of the operands is not a number.
570 bool include_number_compare_;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100571
572 // Generate the comparison code for two smi operands in the stub.
573 bool include_smi_compare_;
574
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100575 // Register holding the left hand side of the comparison if the stub gives
576 // a choice, no_reg otherwise.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100577
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100578 Register lhs_;
579 // Register holding the right hand side of the comparison if the stub gives
580 // a choice, no_reg otherwise.
581 Register rhs_;
582
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100583 // Encoding of the minor key in 16 bits.
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100584 class StrictField: public BitField<bool, 0, 1> {};
585 class NeverNanNanField: public BitField<bool, 1, 1> {};
586 class IncludeNumberCompareField: public BitField<bool, 2, 1> {};
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100587 class IncludeSmiCompareField: public BitField<bool, 3, 1> {};
588 class RegisterField: public BitField<bool, 4, 1> {};
589 class ConditionField: public BitField<int, 5, 11> {};
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100590
591 Major MajorKey() { return Compare; }
592
593 int MinorKey();
594
Ben Murdochb0fe1622011-05-05 13:52:32 +0100595 virtual int GetCodeKind() { return Code::COMPARE_IC; }
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000596 virtual void FinishCode(Handle<Code> code) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100597 code->set_compare_state(CompareIC::GENERIC);
598 }
599
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100600 // Branch to the label if the given object isn't a symbol.
601 void BranchIfNonSymbol(MacroAssembler* masm,
602 Label* label,
603 Register object,
604 Register scratch);
605
606 // Unfortunately you have to run without snapshots to see most of these
607 // names in the profile since most compare stubs end up in the snapshot.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000608 virtual void PrintName(StringStream* stream);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100609};
610
611
612class CEntryStub : public CodeStub {
613 public:
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000614 explicit CEntryStub(int result_size,
615 SaveFPRegsMode save_doubles = kDontSaveFPRegs)
616 : result_size_(result_size), save_doubles_(save_doubles) { }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100617
618 void Generate(MacroAssembler* masm);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000619
620 // The version of this stub that doesn't save doubles is generated ahead of
621 // time, so it's OK to call it from other stubs that can't cope with GC during
622 // their code generation. On machines that always have gp registers (x64) we
623 // can generate both variants ahead of time.
624 virtual bool IsPregenerated();
625 static void GenerateAheadOfTime();
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100626
627 private:
628 void GenerateCore(MacroAssembler* masm,
629 Label* throw_normal_exception,
630 Label* throw_termination_exception,
631 Label* throw_out_of_memory_exception,
632 bool do_gc,
Steve Block1e0659c2011-05-24 12:43:12 +0100633 bool always_allocate_scope);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100634 void GenerateThrowTOS(MacroAssembler* masm);
635 void GenerateThrowUncatchable(MacroAssembler* masm,
636 UncatchableExceptionType type);
637
638 // Number of pointers/values returned.
639 const int result_size_;
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000640 SaveFPRegsMode save_doubles_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100641
642 Major MajorKey() { return CEntry; }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100643 int MinorKey();
644
Steve Block44f0eee2011-05-26 01:26:41 +0100645 bool NeedsImmovableCode();
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100646};
647
648
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100649class JSEntryStub : public CodeStub {
650 public:
651 JSEntryStub() { }
652
653 void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
654
655 protected:
656 void GenerateBody(MacroAssembler* masm, bool is_construct);
657
658 private:
659 Major MajorKey() { return JSEntry; }
660 int MinorKey() { return 0; }
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000661
662 virtual void FinishCode(Handle<Code> code);
663
664 int handler_offset_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100665};
666
667
668class JSConstructEntryStub : public JSEntryStub {
669 public:
670 JSConstructEntryStub() { }
671
672 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
673
674 private:
675 int MinorKey() { return 1; }
676
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000677 virtual void PrintName(StringStream* stream) {
678 stream->Add("JSConstructEntryStub");
679 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100680};
681
682
683class ArgumentsAccessStub: public CodeStub {
684 public:
685 enum Type {
686 READ_ELEMENT,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000687 NEW_NON_STRICT_FAST,
688 NEW_NON_STRICT_SLOW,
Steve Block44f0eee2011-05-26 01:26:41 +0100689 NEW_STRICT
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100690 };
691
692 explicit ArgumentsAccessStub(Type type) : type_(type) { }
693
694 private:
695 Type type_;
696
697 Major MajorKey() { return ArgumentsAccess; }
698 int MinorKey() { return type_; }
699
700 void Generate(MacroAssembler* masm);
701 void GenerateReadElement(MacroAssembler* masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000702 void GenerateNewStrict(MacroAssembler* masm);
703 void GenerateNewNonStrictFast(MacroAssembler* masm);
704 void GenerateNewNonStrictSlow(MacroAssembler* masm);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100705
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000706 virtual void PrintName(StringStream* stream);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100707};
708
709
710class RegExpExecStub: public CodeStub {
711 public:
712 RegExpExecStub() { }
713
714 private:
715 Major MajorKey() { return RegExpExec; }
716 int MinorKey() { return 0; }
717
718 void Generate(MacroAssembler* masm);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100719};
720
721
Ben Murdochb0fe1622011-05-05 13:52:32 +0100722class RegExpConstructResultStub: public CodeStub {
723 public:
724 RegExpConstructResultStub() { }
725
726 private:
727 Major MajorKey() { return RegExpConstructResult; }
728 int MinorKey() { return 0; }
729
730 void Generate(MacroAssembler* masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100731};
732
733
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100734class CallFunctionStub: public CodeStub {
735 public:
Ben Murdoch589d6972011-11-30 16:04:58 +0000736 CallFunctionStub(int argc, CallFunctionFlags flags)
737 : argc_(argc), flags_(flags) { }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100738
739 void Generate(MacroAssembler* masm);
740
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000741 virtual void FinishCode(Handle<Code> code);
742
743 static void Clear(Heap* heap, Address address);
744
745 static Object* GetCachedValue(Address address);
746
Ben Murdoch086aeea2011-05-13 15:57:08 +0100747 static int ExtractArgcFromMinorKey(int minor_key) {
748 return ArgcBits::decode(minor_key);
749 }
750
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000751 // The object that indicates an uninitialized cache.
752 static Handle<Object> UninitializedSentinel(Isolate* isolate) {
753 return isolate->factory()->the_hole_value();
754 }
755
756 // A raw version of the uninitialized sentinel that's safe to read during
757 // garbage collection (e.g., for patching the cache).
758 static Object* RawUninitializedSentinel(Heap* heap) {
759 return heap->raw_unchecked_the_hole_value();
760 }
761
762 // The object that indicates a megamorphic state.
763 static Handle<Object> MegamorphicSentinel(Isolate* isolate) {
764 return isolate->factory()->undefined_value();
765 }
766
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100767 private:
768 int argc_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100769 CallFunctionFlags flags_;
770
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000771 virtual void PrintName(StringStream* stream);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100772
773 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000774 class FlagBits: public BitField<CallFunctionFlags, 0, 2> {};
775 class ArgcBits: public BitField<unsigned, 2, 32 - 2> {};
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100776
777 Major MajorKey() { return CallFunction; }
778 int MinorKey() {
779 // Encode the parameters in a unique 32 bit value.
Ben Murdoch589d6972011-11-30 16:04:58 +0000780 return FlagBits::encode(flags_) | ArgcBits::encode(argc_);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100781 }
782
Ben Murdoch257744e2011-11-30 15:57:28 +0000783 bool ReceiverMightBeImplicit() {
784 return (flags_ & RECEIVER_MIGHT_BE_IMPLICIT) != 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100785 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000786
787 bool RecordCallTarget() {
788 return (flags_ & RECORD_CALL_TARGET) != 0;
789 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100790};
791
792
793enum StringIndexFlags {
794 // Accepts smis or heap numbers.
795 STRING_INDEX_IS_NUMBER,
796
797 // Accepts smis or heap numbers that are valid array indices
798 // (ECMA-262 15.4). Invalid indices are reported as being out of
799 // range.
800 STRING_INDEX_IS_ARRAY_INDEX
801};
802
803
804// Generates code implementing String.prototype.charCodeAt.
805//
806// Only supports the case when the receiver is a string and the index
807// is a number (smi or heap number) that is a valid index into the
808// string. Additional index constraints are specified by the
809// flags. Otherwise, bails out to the provided labels.
810//
811// Register usage: |object| may be changed to another string in a way
812// that doesn't affect charCodeAt/charAt semantics, |index| is
813// preserved, |scratch| and |result| are clobbered.
814class StringCharCodeAtGenerator {
815 public:
816 StringCharCodeAtGenerator(Register object,
817 Register index,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100818 Register result,
819 Label* receiver_not_string,
820 Label* index_not_number,
821 Label* index_out_of_range,
822 StringIndexFlags index_flags)
823 : object_(object),
824 index_(index),
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100825 result_(result),
826 receiver_not_string_(receiver_not_string),
827 index_not_number_(index_not_number),
828 index_out_of_range_(index_out_of_range),
829 index_flags_(index_flags) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100830 ASSERT(!result_.is(object_));
831 ASSERT(!result_.is(index_));
832 }
833
834 // Generates the fast case code. On the fallthrough path |result|
835 // register contains the result.
836 void GenerateFast(MacroAssembler* masm);
837
838 // Generates the slow case code. Must not be naturally
839 // reachable. Expected to be put after a ret instruction (e.g., in
840 // deferred code). Always jumps back to the fast case.
841 void GenerateSlow(MacroAssembler* masm,
842 const RuntimeCallHelper& call_helper);
843
844 private:
845 Register object_;
846 Register index_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100847 Register result_;
848
849 Label* receiver_not_string_;
850 Label* index_not_number_;
851 Label* index_out_of_range_;
852
853 StringIndexFlags index_flags_;
854
855 Label call_runtime_;
856 Label index_not_smi_;
857 Label got_smi_index_;
858 Label exit_;
859
860 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
861};
862
863
864// Generates code for creating a one-char string from a char code.
865class StringCharFromCodeGenerator {
866 public:
867 StringCharFromCodeGenerator(Register code,
868 Register result)
869 : code_(code),
870 result_(result) {
871 ASSERT(!code_.is(result_));
872 }
873
874 // Generates the fast case code. On the fallthrough path |result|
875 // register contains the result.
876 void GenerateFast(MacroAssembler* masm);
877
878 // Generates the slow case code. Must not be naturally
879 // reachable. Expected to be put after a ret instruction (e.g., in
880 // deferred code). Always jumps back to the fast case.
881 void GenerateSlow(MacroAssembler* masm,
882 const RuntimeCallHelper& call_helper);
883
884 private:
885 Register code_;
886 Register result_;
887
888 Label slow_case_;
889 Label exit_;
890
891 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
892};
893
894
895// Generates code implementing String.prototype.charAt.
896//
897// Only supports the case when the receiver is a string and the index
898// is a number (smi or heap number) that is a valid index into the
899// string. Additional index constraints are specified by the
900// flags. Otherwise, bails out to the provided labels.
901//
902// Register usage: |object| may be changed to another string in a way
903// that doesn't affect charCodeAt/charAt semantics, |index| is
904// preserved, |scratch1|, |scratch2|, and |result| are clobbered.
905class StringCharAtGenerator {
906 public:
907 StringCharAtGenerator(Register object,
908 Register index,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000909 Register scratch,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100910 Register result,
911 Label* receiver_not_string,
912 Label* index_not_number,
913 Label* index_out_of_range,
914 StringIndexFlags index_flags)
915 : char_code_at_generator_(object,
916 index,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000917 scratch,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100918 receiver_not_string,
919 index_not_number,
920 index_out_of_range,
921 index_flags),
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000922 char_from_code_generator_(scratch, result) {}
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100923
924 // Generates the fast case code. On the fallthrough path |result|
925 // register contains the result.
926 void GenerateFast(MacroAssembler* masm);
927
928 // Generates the slow case code. Must not be naturally
929 // reachable. Expected to be put after a ret instruction (e.g., in
930 // deferred code). Always jumps back to the fast case.
931 void GenerateSlow(MacroAssembler* masm,
932 const RuntimeCallHelper& call_helper);
933
934 private:
935 StringCharCodeAtGenerator char_code_at_generator_;
936 StringCharFromCodeGenerator char_from_code_generator_;
937
938 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
939};
940
Ben Murdoch086aeea2011-05-13 15:57:08 +0100941
942class AllowStubCallsScope {
943 public:
944 AllowStubCallsScope(MacroAssembler* masm, bool allow)
945 : masm_(masm), previous_allow_(masm->allow_stub_calls()) {
946 masm_->set_allow_stub_calls(allow);
947 }
948 ~AllowStubCallsScope() {
949 masm_->set_allow_stub_calls(previous_allow_);
950 }
951
952 private:
953 MacroAssembler* masm_;
954 bool previous_allow_;
955
956 DISALLOW_COPY_AND_ASSIGN(AllowStubCallsScope);
957};
958
Ben Murdoch257744e2011-11-30 15:57:28 +0000959
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000960class KeyedLoadElementStub : public CodeStub {
Ben Murdoch257744e2011-11-30 15:57:28 +0000961 public:
Ben Murdoch589d6972011-11-30 16:04:58 +0000962 explicit KeyedLoadElementStub(ElementsKind elements_kind)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000963 : elements_kind_(elements_kind)
964 { }
Ben Murdoch257744e2011-11-30 15:57:28 +0000965
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000966 Major MajorKey() { return KeyedLoadElement; }
967 int MinorKey() { return elements_kind_; }
Ben Murdoch257744e2011-11-30 15:57:28 +0000968
969 void Generate(MacroAssembler* masm);
970
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000971 private:
Ben Murdoch589d6972011-11-30 16:04:58 +0000972 ElementsKind elements_kind_;
Ben Murdoch257744e2011-11-30 15:57:28 +0000973
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000974 DISALLOW_COPY_AND_ASSIGN(KeyedLoadElementStub);
Ben Murdoch257744e2011-11-30 15:57:28 +0000975};
976
977
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000978class KeyedStoreElementStub : public CodeStub {
Ben Murdoch257744e2011-11-30 15:57:28 +0000979 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000980 KeyedStoreElementStub(bool is_js_array,
Ben Murdoch589d6972011-11-30 16:04:58 +0000981 ElementsKind elements_kind)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000982 : is_js_array_(is_js_array),
983 elements_kind_(elements_kind) { }
Ben Murdoch257744e2011-11-30 15:57:28 +0000984
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000985 Major MajorKey() { return KeyedStoreElement; }
986 int MinorKey() {
Ben Murdoch589d6972011-11-30 16:04:58 +0000987 return (is_js_array_ ? 0 : kElementsKindCount) + elements_kind_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000988 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000989
990 void Generate(MacroAssembler* masm);
991
Ben Murdoch257744e2011-11-30 15:57:28 +0000992 private:
993 bool is_js_array_;
Ben Murdoch589d6972011-11-30 16:04:58 +0000994 ElementsKind elements_kind_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000995
996 DISALLOW_COPY_AND_ASSIGN(KeyedStoreElementStub);
Ben Murdoch257744e2011-11-30 15:57:28 +0000997};
998
999
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001000class ToBooleanStub: public CodeStub {
Ben Murdoch257744e2011-11-30 15:57:28 +00001001 public:
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001002 enum Type {
1003 UNDEFINED,
1004 BOOLEAN,
1005 NULL_TYPE,
1006 SMI,
1007 SPEC_OBJECT,
1008 STRING,
1009 HEAP_NUMBER,
1010 NUMBER_OF_TYPES
1011 };
1012
1013 // At most 8 different types can be distinguished, because the Code object
1014 // only has room for a single byte to hold a set of these types. :-P
1015 STATIC_ASSERT(NUMBER_OF_TYPES <= 8);
1016
1017 class Types {
1018 public:
1019 Types() {}
1020 explicit Types(byte bits) : set_(bits) {}
1021
1022 bool IsEmpty() const { return set_.IsEmpty(); }
1023 bool Contains(Type type) const { return set_.Contains(type); }
1024 void Add(Type type) { set_.Add(type); }
1025 byte ToByte() const { return set_.ToIntegral(); }
1026 void Print(StringStream* stream) const;
1027 void TraceTransition(Types to) const;
1028 bool Record(Handle<Object> object);
1029 bool NeedsMap() const;
1030 bool CanBeUndetectable() const;
1031
1032 private:
1033 EnumSet<Type, byte> set_;
1034 };
1035
1036 static Types no_types() { return Types(); }
1037 static Types all_types() { return Types((1 << NUMBER_OF_TYPES) - 1); }
1038
1039 explicit ToBooleanStub(Register tos, Types types = Types())
1040 : tos_(tos), types_(types) { }
Ben Murdoch257744e2011-11-30 15:57:28 +00001041
1042 void Generate(MacroAssembler* masm);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001043 virtual int GetCodeKind() { return Code::TO_BOOLEAN_IC; }
1044 virtual void PrintName(StringStream* stream);
Ben Murdoch257744e2011-11-30 15:57:28 +00001045
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001046 virtual bool SometimesSetsUpAFrame() { return false; }
1047
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001048 private:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001049 Major MajorKey() { return ToBoolean; }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001050 int MinorKey() { return (tos_.code() << NUMBER_OF_TYPES) | types_.ToByte(); }
1051
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001052 virtual void FinishCode(Handle<Code> code) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001053 code->set_to_boolean_state(types_.ToByte());
1054 }
1055
1056 void CheckOddball(MacroAssembler* masm,
1057 Type type,
1058 Heap::RootListIndex value,
1059 bool result);
1060 void GenerateTypeTransition(MacroAssembler* masm);
1061
1062 Register tos_;
1063 Types types_;
Ben Murdoch257744e2011-11-30 15:57:28 +00001064};
1065
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001066
1067class ElementsTransitionAndStoreStub : public CodeStub {
1068 public:
1069 ElementsTransitionAndStoreStub(ElementsKind from,
1070 ElementsKind to,
1071 bool is_jsarray,
1072 StrictModeFlag strict_mode)
1073 : from_(from),
1074 to_(to),
1075 is_jsarray_(is_jsarray),
1076 strict_mode_(strict_mode) {}
1077
1078 private:
1079 class FromBits: public BitField<ElementsKind, 0, 8> {};
1080 class ToBits: public BitField<ElementsKind, 8, 8> {};
1081 class IsJSArrayBits: public BitField<bool, 16, 8> {};
1082 class StrictModeBits: public BitField<StrictModeFlag, 24, 8> {};
1083
1084 Major MajorKey() { return ElementsTransitionAndStore; }
1085 int MinorKey() {
1086 return FromBits::encode(from_) |
1087 ToBits::encode(to_) |
1088 IsJSArrayBits::encode(is_jsarray_) |
1089 StrictModeBits::encode(strict_mode_);
1090 }
1091
1092 void Generate(MacroAssembler* masm);
1093
1094 ElementsKind from_;
1095 ElementsKind to_;
1096 bool is_jsarray_;
1097 StrictModeFlag strict_mode_;
1098
1099 DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub);
1100};
1101
1102
1103class StoreArrayLiteralElementStub : public CodeStub {
1104 public:
1105 explicit StoreArrayLiteralElementStub() {}
1106
1107 private:
1108 Major MajorKey() { return StoreArrayLiteralElement; }
1109 int MinorKey() { return 0; }
1110
1111 void Generate(MacroAssembler* masm);
1112
1113 DISALLOW_COPY_AND_ASSIGN(StoreArrayLiteralElementStub);
1114};
1115
Steve Blocka7e24c12009-10-30 11:49:00 +00001116} } // namespace v8::internal
1117
1118#endif // V8_CODE_STUBS_H_