blob: b7804b77f28fb1f92c645aa3cf74557c4dc750b9 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
2// 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
Steve Block6ded16b2010-05-10 14:33:55 +010031#include "globals.h"
32
Steve Blocka7e24c12009-10-30 11:49:00 +000033namespace v8 {
34namespace internal {
35
Steve Blockd0582a62009-12-15 09:54:21 +000036// List of code stubs used on all platforms. The order in this list is important
37// as only the stubs up to and including RecordWrite allows nested stub calls.
38#define CODE_STUB_LIST_ALL_PLATFORMS(V) \
39 V(CallFunction) \
40 V(GenericBinaryOp) \
Ben Murdochb0fe1622011-05-05 13:52:32 +010041 V(TypeRecordingBinaryOp) \
Steve Blockd0582a62009-12-15 09:54:21 +000042 V(StringAdd) \
Ben Murdochb0fe1622011-05-05 13:52:32 +010043 V(StringCharAt) \
Leon Clarkee46be812010-01-19 14:06:41 +000044 V(SubString) \
45 V(StringCompare) \
Steve Blockd0582a62009-12-15 09:54:21 +000046 V(SmiOp) \
47 V(Compare) \
Ben Murdochb0fe1622011-05-05 13:52:32 +010048 V(CompareIC) \
49 V(MathPow) \
50 V(TranscendentalCache) \
Steve Blockd0582a62009-12-15 09:54:21 +000051 V(RecordWrite) \
52 V(ConvertToDouble) \
53 V(WriteInt32ToHeapNumber) \
Steve Block8defd9f2010-07-08 12:39:36 +010054 V(IntegerMod) \
Steve Blockd0582a62009-12-15 09:54:21 +000055 V(StackCheck) \
Leon Clarkee46be812010-01-19 14:06:41 +000056 V(FastNewClosure) \
57 V(FastNewContext) \
58 V(FastCloneShallowArray) \
59 V(GenericUnaryOp) \
Steve Blockd0582a62009-12-15 09:54:21 +000060 V(RevertToNumber) \
61 V(ToBoolean) \
62 V(Instanceof) \
63 V(CounterOp) \
64 V(ArgumentsAccess) \
Leon Clarkee46be812010-01-19 14:06:41 +000065 V(RegExpExec) \
Ben Murdochb0fe1622011-05-05 13:52:32 +010066 V(RegExpConstructResult) \
Andrei Popescu402d9372010-02-26 13:31:12 +000067 V(NumberToString) \
Steve Blockd0582a62009-12-15 09:54:21 +000068 V(CEntry) \
Leon Clarke4515c472010-02-03 11:58:03 +000069 V(JSEntry) \
70 V(DebuggerStatement)
Steve Blockd0582a62009-12-15 09:54:21 +000071
72// List of code stubs only used on ARM platforms.
73#ifdef V8_TARGET_ARCH_ARM
74#define CODE_STUB_LIST_ARM(V) \
75 V(GetProperty) \
76 V(SetProperty) \
77 V(InvokeBuiltin) \
78 V(RegExpCEntry)
79#else
80#define CODE_STUB_LIST_ARM(V)
81#endif
82
83// Combined list of code stubs.
84#define CODE_STUB_LIST(V) \
85 CODE_STUB_LIST_ALL_PLATFORMS(V) \
86 CODE_STUB_LIST_ARM(V)
Steve Blocka7e24c12009-10-30 11:49:00 +000087
Kristian Monsen80d68ea2010-09-08 11:05:35 +010088// Types of uncatchable exceptions.
89enum UncatchableExceptionType { OUT_OF_MEMORY, TERMINATION };
90
91// Mode to overwrite BinaryExpression values.
92enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
93enum UnaryOverwriteMode { UNARY_OVERWRITE, UNARY_NO_OVERWRITE };
94
95
Steve Blocka7e24c12009-10-30 11:49:00 +000096// Stub is base classes of all stubs.
97class CodeStub BASE_EMBEDDED {
98 public:
99 enum Major {
Steve Blockd0582a62009-12-15 09:54:21 +0000100#define DEF_ENUM(name) name,
101 CODE_STUB_LIST(DEF_ENUM)
102#undef DEF_ENUM
103 NoCache, // marker for stubs that do custom caching
Steve Blocka7e24c12009-10-30 11:49:00 +0000104 NUMBER_OF_IDS
105 };
106
107 // Retrieve the code for the stub. Generate the code if needed.
108 Handle<Code> GetCode();
109
Leon Clarkee46be812010-01-19 14:06:41 +0000110 // Retrieve the code for the stub if already generated. Do not
111 // generate the code if not already generated and instead return a
112 // retry after GC Failure object.
John Reck59135872010-11-02 12:39:01 -0700113 MUST_USE_RESULT MaybeObject* TryGetCode();
Leon Clarkee46be812010-01-19 14:06:41 +0000114
Steve Blocka7e24c12009-10-30 11:49:00 +0000115 static Major MajorKeyFromKey(uint32_t key) {
116 return static_cast<Major>(MajorKeyBits::decode(key));
Iain Merrick9ac36c92010-09-13 15:29:50 +0100117 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000118 static int MinorKeyFromKey(uint32_t key) {
119 return MinorKeyBits::decode(key);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100120 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100121
122 // Gets the major key from a code object that is a code stub or binary op IC.
123 static Major GetMajorKey(Code* code_stub) {
124 return static_cast<Major>(code_stub->major_key());
125 }
126
Andrei Popescu31002712010-02-23 13:46:05 +0000127 static const char* MajorName(Major major_key, bool allow_unknown_keys);
Steve Blocka7e24c12009-10-30 11:49:00 +0000128
129 virtual ~CodeStub() {}
130
Steve Blocka7e24c12009-10-30 11:49:00 +0000131 protected:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100132 static const int kMajorBits = 6;
Steve Blocka7e24c12009-10-30 11:49:00 +0000133 static const int kMinorBits = kBitsPerInt - kSmiTagSize - kMajorBits;
134
135 private:
Leon Clarkee46be812010-01-19 14:06:41 +0000136 // Lookup the code in the (possibly custom) cache.
137 bool FindCodeInCache(Code** code_out);
138
139 // Nonvirtual wrapper around the stub-specific Generate function. Call
140 // this function to set up the macro assembler and generate the code.
141 void GenerateCode(MacroAssembler* masm);
142
Steve Blocka7e24c12009-10-30 11:49:00 +0000143 // Generates the assembler code for the stub.
144 virtual void Generate(MacroAssembler* masm) = 0;
145
Leon Clarkee46be812010-01-19 14:06:41 +0000146 // Perform bookkeeping required after code generation when stub code is
147 // initially generated.
148 void RecordCodeGeneration(Code* code, MacroAssembler* masm);
149
Ben Murdochb0fe1622011-05-05 13:52:32 +0100150 // Finish the code object after it has been generated.
151 virtual void FinishCode(Code* code) { }
152
Steve Blocka7e24c12009-10-30 11:49:00 +0000153 // Returns information for computing the number key.
154 virtual Major MajorKey() = 0;
155 virtual int MinorKey() = 0;
156
157 // The CallFunctionStub needs to override this so it can encode whether a
158 // lazily generated function should be fully optimized or not.
159 virtual InLoopFlag InLoop() { return NOT_IN_LOOP; }
160
Steve Block6ded16b2010-05-10 14:33:55 +0100161 // GenericBinaryOpStub needs to override this.
162 virtual int GetCodeKind();
163
164 // GenericBinaryOpStub needs to override this.
165 virtual InlineCacheState GetICState() {
166 return UNINITIALIZED;
167 }
168
Steve Blocka7e24c12009-10-30 11:49:00 +0000169 // Returns a name for logging/debugging purposes.
Andrei Popescu31002712010-02-23 13:46:05 +0000170 virtual const char* GetName() { return MajorName(MajorKey(), false); }
Steve Blocka7e24c12009-10-30 11:49:00 +0000171
172#ifdef DEBUG
173 virtual void Print() { PrintF("%s\n", GetName()); }
174#endif
175
176 // Computes the key based on major and minor.
177 uint32_t GetKey() {
178 ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
179 return MinorKeyBits::encode(MinorKey()) |
180 MajorKeyBits::encode(MajorKey());
181 }
182
183 bool AllowsStubCalls() { return MajorKey() <= RecordWrite; }
184
185 class MajorKeyBits: public BitField<uint32_t, 0, kMajorBits> {};
186 class MinorKeyBits: public BitField<uint32_t, kMajorBits, kMinorBits> {};
187
188 friend class BreakPointIterator;
189};
190
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100191
192// Helper interface to prepare to/restore after making runtime calls.
193class RuntimeCallHelper {
194 public:
195 virtual ~RuntimeCallHelper() {}
196
197 virtual void BeforeCall(MacroAssembler* masm) const = 0;
198
199 virtual void AfterCall(MacroAssembler* masm) const = 0;
200
201 protected:
202 RuntimeCallHelper() {}
203
204 private:
205 DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
206};
207
208} } // namespace v8::internal
209
210#if V8_TARGET_ARCH_IA32
211#include "ia32/code-stubs-ia32.h"
212#elif V8_TARGET_ARCH_X64
213#include "x64/code-stubs-x64.h"
214#elif V8_TARGET_ARCH_ARM
215#include "arm/code-stubs-arm.h"
216#elif V8_TARGET_ARCH_MIPS
217#include "mips/code-stubs-mips.h"
218#else
219#error Unsupported target architecture.
220#endif
221
222namespace v8 {
223namespace internal {
224
225
Ben Murdochb0fe1622011-05-05 13:52:32 +0100226// RuntimeCallHelper implementation used in stubs: enters/leaves a
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100227// newly created internal frame before/after the runtime call.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100228class StubRuntimeCallHelper : public RuntimeCallHelper {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100229 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100230 StubRuntimeCallHelper() {}
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100231
232 virtual void BeforeCall(MacroAssembler* masm) const;
233
234 virtual void AfterCall(MacroAssembler* masm) const;
235};
236
237
238// Trivial RuntimeCallHelper implementation.
239class NopRuntimeCallHelper : public RuntimeCallHelper {
240 public:
241 NopRuntimeCallHelper() {}
242
243 virtual void BeforeCall(MacroAssembler* masm) const {}
244
245 virtual void AfterCall(MacroAssembler* masm) const {}
246};
247
248
249class StackCheckStub : public CodeStub {
250 public:
251 StackCheckStub() { }
252
253 void Generate(MacroAssembler* masm);
254
255 private:
256
257 const char* GetName() { return "StackCheckStub"; }
258
259 Major MajorKey() { return StackCheck; }
260 int MinorKey() { return 0; }
261};
262
263
264class FastNewClosureStub : public CodeStub {
265 public:
266 void Generate(MacroAssembler* masm);
267
268 private:
269 const char* GetName() { return "FastNewClosureStub"; }
270 Major MajorKey() { return FastNewClosure; }
271 int MinorKey() { return 0; }
272};
273
274
275class FastNewContextStub : public CodeStub {
276 public:
277 static const int kMaximumSlots = 64;
278
279 explicit FastNewContextStub(int slots) : slots_(slots) {
280 ASSERT(slots_ > 0 && slots <= kMaximumSlots);
281 }
282
283 void Generate(MacroAssembler* masm);
284
285 private:
286 int slots_;
287
288 const char* GetName() { return "FastNewContextStub"; }
289 Major MajorKey() { return FastNewContext; }
290 int MinorKey() { return slots_; }
291};
292
293
294class FastCloneShallowArrayStub : public CodeStub {
295 public:
296 // Maximum length of copied elements array.
297 static const int kMaximumClonedLength = 8;
298
299 enum Mode {
300 CLONE_ELEMENTS,
301 COPY_ON_WRITE_ELEMENTS
302 };
303
304 FastCloneShallowArrayStub(Mode mode, int length)
305 : mode_(mode),
306 length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
307 ASSERT(length_ >= 0);
308 ASSERT(length_ <= kMaximumClonedLength);
309 }
310
311 void Generate(MacroAssembler* masm);
312
313 private:
314 Mode mode_;
315 int length_;
316
317 const char* GetName() { return "FastCloneShallowArrayStub"; }
318 Major MajorKey() { return FastCloneShallowArray; }
319 int MinorKey() {
320 ASSERT(mode_ == 0 || mode_ == 1);
321 return (length_ << 1) | mode_;
322 }
323};
324
325
326class InstanceofStub: public CodeStub {
327 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100328 enum Flags {
329 kNoFlags = 0,
330 kArgsInRegisters = 1 << 0
331 };
332
333 explicit InstanceofStub(Flags flags) : flags_(flags) { }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100334
335 void Generate(MacroAssembler* masm);
336
337 private:
338 Major MajorKey() { return Instanceof; }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100339 int MinorKey() { return args_in_registers() ? 1 : 0; }
340
341 bool args_in_registers() {
342 return (flags_ & kArgsInRegisters) != 0;
343 }
344
345 Flags flags_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100346};
347
348
349enum NegativeZeroHandling {
350 kStrictNegativeZero,
351 kIgnoreNegativeZero
352};
353
354
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100355enum UnaryOpFlags {
356 NO_UNARY_FLAGS = 0,
357 NO_UNARY_SMI_CODE_IN_STUB = 1 << 0
358};
359
360
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100361class GenericUnaryOpStub : public CodeStub {
362 public:
363 GenericUnaryOpStub(Token::Value op,
364 UnaryOverwriteMode overwrite,
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100365 UnaryOpFlags flags,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100366 NegativeZeroHandling negative_zero = kStrictNegativeZero)
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100367 : op_(op),
368 overwrite_(overwrite),
369 include_smi_code_((flags & NO_UNARY_SMI_CODE_IN_STUB) == 0),
370 negative_zero_(negative_zero) { }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100371
372 private:
373 Token::Value op_;
374 UnaryOverwriteMode overwrite_;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100375 bool include_smi_code_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100376 NegativeZeroHandling negative_zero_;
377
378 class OverwriteField: public BitField<UnaryOverwriteMode, 0, 1> {};
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100379 class IncludeSmiCodeField: public BitField<bool, 1, 1> {};
380 class NegativeZeroField: public BitField<NegativeZeroHandling, 2, 1> {};
381 class OpField: public BitField<Token::Value, 3, kMinorBits - 3> {};
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100382
383 Major MajorKey() { return GenericUnaryOp; }
384 int MinorKey() {
385 return OpField::encode(op_) |
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100386 OverwriteField::encode(overwrite_) |
387 IncludeSmiCodeField::encode(include_smi_code_) |
388 NegativeZeroField::encode(negative_zero_);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100389 }
390
391 void Generate(MacroAssembler* masm);
392
393 const char* GetName();
394};
395
396
Ben Murdochb0fe1622011-05-05 13:52:32 +0100397class MathPowStub: public CodeStub {
398 public:
399 MathPowStub() {}
400 virtual void Generate(MacroAssembler* masm);
401
402 private:
403 virtual CodeStub::Major MajorKey() { return MathPow; }
404 virtual int MinorKey() { return 0; }
405
406 const char* GetName() { return "MathPowStub"; }
407};
408
409
410class StringCharAtStub: public CodeStub {
411 public:
412 StringCharAtStub() {}
413
414 private:
415 Major MajorKey() { return StringCharAt; }
416 int MinorKey() { return 0; }
417
418 void Generate(MacroAssembler* masm);
419};
420
421
422class ICCompareStub: public CodeStub {
423 public:
424 ICCompareStub(Token::Value op, CompareIC::State state)
425 : op_(op), state_(state) {
426 ASSERT(Token::IsCompareOp(op));
427 }
428
429 virtual void Generate(MacroAssembler* masm);
430
431 private:
432 class OpField: public BitField<int, 0, 3> { };
433 class StateField: public BitField<int, 3, 5> { };
434
435 virtual void FinishCode(Code* code) { code->set_compare_state(state_); }
436
437 virtual CodeStub::Major MajorKey() { return CompareIC; }
438 virtual int MinorKey();
439
440 virtual int GetCodeKind() { return Code::COMPARE_IC; }
441
442 void GenerateSmis(MacroAssembler* masm);
443 void GenerateHeapNumbers(MacroAssembler* masm);
444 void GenerateObjects(MacroAssembler* masm);
445 void GenerateMiss(MacroAssembler* masm);
446
447 bool strict() const { return op_ == Token::EQ_STRICT; }
448 Condition GetCondition() const { return CompareIC::ComputeCondition(op_); }
449
450 Token::Value op_;
451 CompareIC::State state_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100452};
453
454
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100455// Flags that control the compare stub code generation.
456enum CompareFlags {
457 NO_COMPARE_FLAGS = 0,
458 NO_SMI_COMPARE_IN_STUB = 1 << 0,
459 NO_NUMBER_COMPARE_IN_STUB = 1 << 1,
460 CANT_BOTH_BE_NAN = 1 << 2
461};
462
463
Ben Murdochb0fe1622011-05-05 13:52:32 +0100464enum NaNInformation {
465 kBothCouldBeNaN,
466 kCantBothBeNaN
467};
468
469
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100470class CompareStub: public CodeStub {
471 public:
472 CompareStub(Condition cc,
473 bool strict,
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100474 CompareFlags flags,
475 Register lhs,
476 Register rhs) :
Ben Murdochb0fe1622011-05-05 13:52:32 +0100477 cc_(cc),
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100478 strict_(strict),
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100479 never_nan_nan_((flags & CANT_BOTH_BE_NAN) != 0),
480 include_number_compare_((flags & NO_NUMBER_COMPARE_IN_STUB) == 0),
481 include_smi_compare_((flags & NO_SMI_COMPARE_IN_STUB) == 0),
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100482 lhs_(lhs),
483 rhs_(rhs),
484 name_(NULL) { }
485
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100486 CompareStub(Condition cc,
487 bool strict,
488 CompareFlags flags) :
489 cc_(cc),
490 strict_(strict),
491 never_nan_nan_((flags & CANT_BOTH_BE_NAN) != 0),
492 include_number_compare_((flags & NO_NUMBER_COMPARE_IN_STUB) == 0),
493 include_smi_compare_((flags & NO_SMI_COMPARE_IN_STUB) == 0),
494 lhs_(no_reg),
495 rhs_(no_reg),
496 name_(NULL) { }
497
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100498 void Generate(MacroAssembler* masm);
499
500 private:
501 Condition cc_;
502 bool strict_;
503 // Only used for 'equal' comparisons. Tells the stub that we already know
504 // that at least one side of the comparison is not NaN. This allows the
505 // stub to use object identity in the positive case. We ignore it when
506 // generating the minor key for other comparisons to avoid creating more
507 // stubs.
508 bool never_nan_nan_;
509 // Do generate the number comparison code in the stub. Stubs without number
510 // comparison code is used when the number comparison has been inlined, and
511 // the stub will be called if one of the operands is not a number.
512 bool include_number_compare_;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100513
514 // Generate the comparison code for two smi operands in the stub.
515 bool include_smi_compare_;
516
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100517 // Register holding the left hand side of the comparison if the stub gives
518 // a choice, no_reg otherwise.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100519
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100520 Register lhs_;
521 // Register holding the right hand side of the comparison if the stub gives
522 // a choice, no_reg otherwise.
523 Register rhs_;
524
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100525 // Encoding of the minor key in 16 bits.
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100526 class StrictField: public BitField<bool, 0, 1> {};
527 class NeverNanNanField: public BitField<bool, 1, 1> {};
528 class IncludeNumberCompareField: public BitField<bool, 2, 1> {};
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100529 class IncludeSmiCompareField: public BitField<bool, 3, 1> {};
530 class RegisterField: public BitField<bool, 4, 1> {};
531 class ConditionField: public BitField<int, 5, 11> {};
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100532
533 Major MajorKey() { return Compare; }
534
535 int MinorKey();
536
Ben Murdochb0fe1622011-05-05 13:52:32 +0100537 virtual int GetCodeKind() { return Code::COMPARE_IC; }
538 virtual void FinishCode(Code* code) {
539 code->set_compare_state(CompareIC::GENERIC);
540 }
541
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100542 // Branch to the label if the given object isn't a symbol.
543 void BranchIfNonSymbol(MacroAssembler* masm,
544 Label* label,
545 Register object,
546 Register scratch);
547
548 // Unfortunately you have to run without snapshots to see most of these
549 // names in the profile since most compare stubs end up in the snapshot.
550 char* name_;
551 const char* GetName();
552#ifdef DEBUG
553 void Print() {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100554 PrintF("CompareStub (minor %d) (cc %d), (strict %s), "
555 "(never_nan_nan %s), (smi_compare %s) (number_compare %s) ",
556 MinorKey(),
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100557 static_cast<int>(cc_),
558 strict_ ? "true" : "false",
559 never_nan_nan_ ? "true" : "false",
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100560 include_smi_compare_ ? "inluded" : "not included",
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100561 include_number_compare_ ? "included" : "not included");
562
563 if (!lhs_.is(no_reg) && !rhs_.is(no_reg)) {
564 PrintF("(lhs r%d), (rhs r%d)\n", lhs_.code(), rhs_.code());
565 } else {
566 PrintF("\n");
567 }
568 }
569#endif
570};
571
572
573class CEntryStub : public CodeStub {
574 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100575 explicit CEntryStub(int result_size)
576 : result_size_(result_size), save_doubles_(false) { }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100577
578 void Generate(MacroAssembler* masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100579 void SaveDoubles() { save_doubles_ = true; }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100580
581 private:
582 void GenerateCore(MacroAssembler* masm,
583 Label* throw_normal_exception,
584 Label* throw_termination_exception,
585 Label* throw_out_of_memory_exception,
586 bool do_gc,
587 bool always_allocate_scope,
588 int alignment_skew = 0);
589 void GenerateThrowTOS(MacroAssembler* masm);
590 void GenerateThrowUncatchable(MacroAssembler* masm,
591 UncatchableExceptionType type);
592
593 // Number of pointers/values returned.
594 const int result_size_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100595 bool save_doubles_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100596
597 Major MajorKey() { return CEntry; }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100598 int MinorKey();
599
600 const char* GetName() { return "CEntryStub"; }
601};
602
603
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100604class JSEntryStub : public CodeStub {
605 public:
606 JSEntryStub() { }
607
608 void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
609
610 protected:
611 void GenerateBody(MacroAssembler* masm, bool is_construct);
612
613 private:
614 Major MajorKey() { return JSEntry; }
615 int MinorKey() { return 0; }
616
617 const char* GetName() { return "JSEntryStub"; }
618};
619
620
621class JSConstructEntryStub : public JSEntryStub {
622 public:
623 JSConstructEntryStub() { }
624
625 void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
626
627 private:
628 int MinorKey() { return 1; }
629
630 const char* GetName() { return "JSConstructEntryStub"; }
631};
632
633
634class ArgumentsAccessStub: public CodeStub {
635 public:
636 enum Type {
637 READ_ELEMENT,
638 NEW_OBJECT
639 };
640
641 explicit ArgumentsAccessStub(Type type) : type_(type) { }
642
643 private:
644 Type type_;
645
646 Major MajorKey() { return ArgumentsAccess; }
647 int MinorKey() { return type_; }
648
649 void Generate(MacroAssembler* masm);
650 void GenerateReadElement(MacroAssembler* masm);
651 void GenerateNewObject(MacroAssembler* masm);
652
653 const char* GetName() { return "ArgumentsAccessStub"; }
654
655#ifdef DEBUG
656 void Print() {
657 PrintF("ArgumentsAccessStub (type %d)\n", type_);
658 }
659#endif
660};
661
662
663class RegExpExecStub: public CodeStub {
664 public:
665 RegExpExecStub() { }
666
667 private:
668 Major MajorKey() { return RegExpExec; }
669 int MinorKey() { return 0; }
670
671 void Generate(MacroAssembler* masm);
672
673 const char* GetName() { return "RegExpExecStub"; }
674
675#ifdef DEBUG
676 void Print() {
677 PrintF("RegExpExecStub\n");
678 }
679#endif
680};
681
682
Ben Murdochb0fe1622011-05-05 13:52:32 +0100683class RegExpConstructResultStub: public CodeStub {
684 public:
685 RegExpConstructResultStub() { }
686
687 private:
688 Major MajorKey() { return RegExpConstructResult; }
689 int MinorKey() { return 0; }
690
691 void Generate(MacroAssembler* masm);
692
693 const char* GetName() { return "RegExpConstructResultStub"; }
694
695#ifdef DEBUG
696 void Print() {
697 PrintF("RegExpConstructResultStub\n");
698 }
699#endif
700};
701
702
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100703class CallFunctionStub: public CodeStub {
704 public:
705 CallFunctionStub(int argc, InLoopFlag in_loop, CallFunctionFlags flags)
706 : argc_(argc), in_loop_(in_loop), flags_(flags) { }
707
708 void Generate(MacroAssembler* masm);
709
710 private:
711 int argc_;
712 InLoopFlag in_loop_;
713 CallFunctionFlags flags_;
714
715#ifdef DEBUG
716 void Print() {
717 PrintF("CallFunctionStub (args %d, in_loop %d, flags %d)\n",
718 argc_,
719 static_cast<int>(in_loop_),
720 static_cast<int>(flags_));
721 }
722#endif
723
724 // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
725 class InLoopBits: public BitField<InLoopFlag, 0, 1> {};
726 class FlagBits: public BitField<CallFunctionFlags, 1, 1> {};
727 class ArgcBits: public BitField<int, 2, 32 - 2> {};
728
729 Major MajorKey() { return CallFunction; }
730 int MinorKey() {
731 // Encode the parameters in a unique 32 bit value.
732 return InLoopBits::encode(in_loop_)
733 | FlagBits::encode(flags_)
734 | ArgcBits::encode(argc_);
735 }
736
737 InLoopFlag InLoop() { return in_loop_; }
738 bool ReceiverMightBeValue() {
739 return (flags_ & RECEIVER_MIGHT_BE_VALUE) != 0;
740 }
741
742 public:
743 static int ExtractArgcFromMinorKey(int minor_key) {
744 return ArgcBits::decode(minor_key);
745 }
746};
747
748
749enum StringIndexFlags {
750 // Accepts smis or heap numbers.
751 STRING_INDEX_IS_NUMBER,
752
753 // Accepts smis or heap numbers that are valid array indices
754 // (ECMA-262 15.4). Invalid indices are reported as being out of
755 // range.
756 STRING_INDEX_IS_ARRAY_INDEX
757};
758
759
760// Generates code implementing String.prototype.charCodeAt.
761//
762// Only supports the case when the receiver is a string and the index
763// is a number (smi or heap number) that is a valid index into the
764// string. Additional index constraints are specified by the
765// flags. Otherwise, bails out to the provided labels.
766//
767// Register usage: |object| may be changed to another string in a way
768// that doesn't affect charCodeAt/charAt semantics, |index| is
769// preserved, |scratch| and |result| are clobbered.
770class StringCharCodeAtGenerator {
771 public:
772 StringCharCodeAtGenerator(Register object,
773 Register index,
774 Register scratch,
775 Register result,
776 Label* receiver_not_string,
777 Label* index_not_number,
778 Label* index_out_of_range,
779 StringIndexFlags index_flags)
780 : object_(object),
781 index_(index),
782 scratch_(scratch),
783 result_(result),
784 receiver_not_string_(receiver_not_string),
785 index_not_number_(index_not_number),
786 index_out_of_range_(index_out_of_range),
787 index_flags_(index_flags) {
788 ASSERT(!scratch_.is(object_));
789 ASSERT(!scratch_.is(index_));
790 ASSERT(!scratch_.is(result_));
791 ASSERT(!result_.is(object_));
792 ASSERT(!result_.is(index_));
793 }
794
795 // Generates the fast case code. On the fallthrough path |result|
796 // register contains the result.
797 void GenerateFast(MacroAssembler* masm);
798
799 // Generates the slow case code. Must not be naturally
800 // reachable. Expected to be put after a ret instruction (e.g., in
801 // deferred code). Always jumps back to the fast case.
802 void GenerateSlow(MacroAssembler* masm,
803 const RuntimeCallHelper& call_helper);
804
805 private:
806 Register object_;
807 Register index_;
808 Register scratch_;
809 Register result_;
810
811 Label* receiver_not_string_;
812 Label* index_not_number_;
813 Label* index_out_of_range_;
814
815 StringIndexFlags index_flags_;
816
817 Label call_runtime_;
818 Label index_not_smi_;
819 Label got_smi_index_;
820 Label exit_;
821
822 DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
823};
824
825
826// Generates code for creating a one-char string from a char code.
827class StringCharFromCodeGenerator {
828 public:
829 StringCharFromCodeGenerator(Register code,
830 Register result)
831 : code_(code),
832 result_(result) {
833 ASSERT(!code_.is(result_));
834 }
835
836 // Generates the fast case code. On the fallthrough path |result|
837 // register contains the result.
838 void GenerateFast(MacroAssembler* masm);
839
840 // Generates the slow case code. Must not be naturally
841 // reachable. Expected to be put after a ret instruction (e.g., in
842 // deferred code). Always jumps back to the fast case.
843 void GenerateSlow(MacroAssembler* masm,
844 const RuntimeCallHelper& call_helper);
845
846 private:
847 Register code_;
848 Register result_;
849
850 Label slow_case_;
851 Label exit_;
852
853 DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
854};
855
856
857// Generates code implementing String.prototype.charAt.
858//
859// Only supports the case when the receiver is a string and the index
860// is a number (smi or heap number) that is a valid index into the
861// string. Additional index constraints are specified by the
862// flags. Otherwise, bails out to the provided labels.
863//
864// Register usage: |object| may be changed to another string in a way
865// that doesn't affect charCodeAt/charAt semantics, |index| is
866// preserved, |scratch1|, |scratch2|, and |result| are clobbered.
867class StringCharAtGenerator {
868 public:
869 StringCharAtGenerator(Register object,
870 Register index,
871 Register scratch1,
872 Register scratch2,
873 Register result,
874 Label* receiver_not_string,
875 Label* index_not_number,
876 Label* index_out_of_range,
877 StringIndexFlags index_flags)
878 : char_code_at_generator_(object,
879 index,
880 scratch1,
881 scratch2,
882 receiver_not_string,
883 index_not_number,
884 index_out_of_range,
885 index_flags),
886 char_from_code_generator_(scratch2, result) {}
887
888 // Generates the fast case code. On the fallthrough path |result|
889 // register contains the result.
890 void GenerateFast(MacroAssembler* masm);
891
892 // Generates the slow case code. Must not be naturally
893 // reachable. Expected to be put after a ret instruction (e.g., in
894 // deferred code). Always jumps back to the fast case.
895 void GenerateSlow(MacroAssembler* masm,
896 const RuntimeCallHelper& call_helper);
897
898 private:
899 StringCharCodeAtGenerator char_code_at_generator_;
900 StringCharFromCodeGenerator char_from_code_generator_;
901
902 DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
903};
904
Steve Blocka7e24c12009-10-30 11:49:00 +0000905} } // namespace v8::internal
906
907#endif // V8_CODE_STUBS_H_