9188b58c326329fac4c145be016a866fcb1b758e
[platform/upstream/nodejs.git] / deps / v8 / src / arm / code-stubs-arm.cc
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/v8.h"
6
7 #if V8_TARGET_ARCH_ARM
8
9 #include "src/base/bits.h"
10 #include "src/bootstrapper.h"
11 #include "src/code-stubs.h"
12 #include "src/codegen.h"
13 #include "src/ic/handler-compiler.h"
14 #include "src/ic/ic.h"
15 #include "src/isolate.h"
16 #include "src/jsregexp.h"
17 #include "src/regexp-macro-assembler.h"
18 #include "src/runtime/runtime.h"
19
20 namespace v8 {
21 namespace internal {
22
23
24 static void InitializeArrayConstructorDescriptor(
25     Isolate* isolate, CodeStubDescriptor* descriptor,
26     int constant_stack_parameter_count) {
27   Address deopt_handler = Runtime::FunctionForId(
28       Runtime::kArrayConstructor)->entry;
29
30   if (constant_stack_parameter_count == 0) {
31     descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
32                            JS_FUNCTION_STUB_MODE);
33   } else {
34     descriptor->Initialize(r0, deopt_handler, constant_stack_parameter_count,
35                            JS_FUNCTION_STUB_MODE, PASS_ARGUMENTS);
36   }
37 }
38
39
40 static void InitializeInternalArrayConstructorDescriptor(
41     Isolate* isolate, CodeStubDescriptor* descriptor,
42     int constant_stack_parameter_count) {
43   Address deopt_handler = Runtime::FunctionForId(
44       Runtime::kInternalArrayConstructor)->entry;
45
46   if (constant_stack_parameter_count == 0) {
47     descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
48                            JS_FUNCTION_STUB_MODE);
49   } else {
50     descriptor->Initialize(r0, deopt_handler, constant_stack_parameter_count,
51                            JS_FUNCTION_STUB_MODE, PASS_ARGUMENTS);
52   }
53 }
54
55
56 void ArrayNoArgumentConstructorStub::InitializeDescriptor(
57     CodeStubDescriptor* descriptor) {
58   InitializeArrayConstructorDescriptor(isolate(), descriptor, 0);
59 }
60
61
62 void ArraySingleArgumentConstructorStub::InitializeDescriptor(
63     CodeStubDescriptor* descriptor) {
64   InitializeArrayConstructorDescriptor(isolate(), descriptor, 1);
65 }
66
67
68 void ArrayNArgumentsConstructorStub::InitializeDescriptor(
69     CodeStubDescriptor* descriptor) {
70   InitializeArrayConstructorDescriptor(isolate(), descriptor, -1);
71 }
72
73
74 void InternalArrayNoArgumentConstructorStub::InitializeDescriptor(
75     CodeStubDescriptor* descriptor) {
76   InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 0);
77 }
78
79
80 void InternalArraySingleArgumentConstructorStub::InitializeDescriptor(
81     CodeStubDescriptor* descriptor) {
82   InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 1);
83 }
84
85
86 void InternalArrayNArgumentsConstructorStub::InitializeDescriptor(
87     CodeStubDescriptor* descriptor) {
88   InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1);
89 }
90
91
92 #define __ ACCESS_MASM(masm)
93
94
95 static void EmitIdenticalObjectComparison(MacroAssembler* masm,
96                                           Label* slow,
97                                           Condition cond);
98 static void EmitSmiNonsmiComparison(MacroAssembler* masm,
99                                     Register lhs,
100                                     Register rhs,
101                                     Label* lhs_not_nan,
102                                     Label* slow,
103                                     bool strict);
104 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
105                                            Register lhs,
106                                            Register rhs);
107
108
109 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm,
110                                                ExternalReference miss) {
111   // Update the static counter each time a new code stub is generated.
112   isolate()->counters()->code_stubs()->Increment();
113
114   CallInterfaceDescriptor descriptor = GetCallInterfaceDescriptor();
115   int param_count = descriptor.GetEnvironmentParameterCount();
116   {
117     // Call the runtime system in a fresh internal frame.
118     FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
119     DCHECK(param_count == 0 ||
120            r0.is(descriptor.GetEnvironmentParameterRegister(param_count - 1)));
121     // Push arguments
122     for (int i = 0; i < param_count; ++i) {
123       __ push(descriptor.GetEnvironmentParameterRegister(i));
124     }
125     __ CallExternalReference(miss, param_count);
126   }
127
128   __ Ret();
129 }
130
131
132 void DoubleToIStub::Generate(MacroAssembler* masm) {
133   Label out_of_range, only_low, negate, done;
134   Register input_reg = source();
135   Register result_reg = destination();
136   DCHECK(is_truncating());
137
138   int double_offset = offset();
139   // Account for saved regs if input is sp.
140   if (input_reg.is(sp)) double_offset += 3 * kPointerSize;
141
142   Register scratch = GetRegisterThatIsNotOneOf(input_reg, result_reg);
143   Register scratch_low =
144       GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch);
145   Register scratch_high =
146       GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch, scratch_low);
147   LowDwVfpRegister double_scratch = kScratchDoubleReg;
148
149   __ Push(scratch_high, scratch_low, scratch);
150
151   if (!skip_fastpath()) {
152     // Load double input.
153     __ vldr(double_scratch, MemOperand(input_reg, double_offset));
154     __ vmov(scratch_low, scratch_high, double_scratch);
155
156     // Do fast-path convert from double to int.
157     __ vcvt_s32_f64(double_scratch.low(), double_scratch);
158     __ vmov(result_reg, double_scratch.low());
159
160     // If result is not saturated (0x7fffffff or 0x80000000), we are done.
161     __ sub(scratch, result_reg, Operand(1));
162     __ cmp(scratch, Operand(0x7ffffffe));
163     __ b(lt, &done);
164   } else {
165     // We've already done MacroAssembler::TryFastTruncatedDoubleToILoad, so we
166     // know exponent > 31, so we can skip the vcvt_s32_f64 which will saturate.
167     if (double_offset == 0) {
168       __ ldm(ia, input_reg, scratch_low.bit() | scratch_high.bit());
169     } else {
170       __ ldr(scratch_low, MemOperand(input_reg, double_offset));
171       __ ldr(scratch_high, MemOperand(input_reg, double_offset + kIntSize));
172     }
173   }
174
175   __ Ubfx(scratch, scratch_high,
176          HeapNumber::kExponentShift, HeapNumber::kExponentBits);
177   // Load scratch with exponent - 1. This is faster than loading
178   // with exponent because Bias + 1 = 1024 which is an *ARM* immediate value.
179   STATIC_ASSERT(HeapNumber::kExponentBias + 1 == 1024);
180   __ sub(scratch, scratch, Operand(HeapNumber::kExponentBias + 1));
181   // If exponent is greater than or equal to 84, the 32 less significant
182   // bits are 0s (2^84 = 1, 52 significant bits, 32 uncoded bits),
183   // the result is 0.
184   // Compare exponent with 84 (compare exponent - 1 with 83).
185   __ cmp(scratch, Operand(83));
186   __ b(ge, &out_of_range);
187
188   // If we reach this code, 31 <= exponent <= 83.
189   // So, we don't have to handle cases where 0 <= exponent <= 20 for
190   // which we would need to shift right the high part of the mantissa.
191   // Scratch contains exponent - 1.
192   // Load scratch with 52 - exponent (load with 51 - (exponent - 1)).
193   __ rsb(scratch, scratch, Operand(51), SetCC);
194   __ b(ls, &only_low);
195   // 21 <= exponent <= 51, shift scratch_low and scratch_high
196   // to generate the result.
197   __ mov(scratch_low, Operand(scratch_low, LSR, scratch));
198   // Scratch contains: 52 - exponent.
199   // We needs: exponent - 20.
200   // So we use: 32 - scratch = 32 - 52 + exponent = exponent - 20.
201   __ rsb(scratch, scratch, Operand(32));
202   __ Ubfx(result_reg, scratch_high,
203           0, HeapNumber::kMantissaBitsInTopWord);
204   // Set the implicit 1 before the mantissa part in scratch_high.
205   __ orr(result_reg, result_reg,
206          Operand(1 << HeapNumber::kMantissaBitsInTopWord));
207   __ orr(result_reg, scratch_low, Operand(result_reg, LSL, scratch));
208   __ b(&negate);
209
210   __ bind(&out_of_range);
211   __ mov(result_reg, Operand::Zero());
212   __ b(&done);
213
214   __ bind(&only_low);
215   // 52 <= exponent <= 83, shift only scratch_low.
216   // On entry, scratch contains: 52 - exponent.
217   __ rsb(scratch, scratch, Operand::Zero());
218   __ mov(result_reg, Operand(scratch_low, LSL, scratch));
219
220   __ bind(&negate);
221   // If input was positive, scratch_high ASR 31 equals 0 and
222   // scratch_high LSR 31 equals zero.
223   // New result = (result eor 0) + 0 = result.
224   // If the input was negative, we have to negate the result.
225   // Input_high ASR 31 equals 0xffffffff and scratch_high LSR 31 equals 1.
226   // New result = (result eor 0xffffffff) + 1 = 0 - result.
227   __ eor(result_reg, result_reg, Operand(scratch_high, ASR, 31));
228   __ add(result_reg, result_reg, Operand(scratch_high, LSR, 31));
229
230   __ bind(&done);
231
232   __ Pop(scratch_high, scratch_low, scratch);
233   __ Ret();
234 }
235
236
237 // Handle the case where the lhs and rhs are the same object.
238 // Equality is almost reflexive (everything but NaN), so this is a test
239 // for "identity and not NaN".
240 static void EmitIdenticalObjectComparison(MacroAssembler* masm,
241                                           Label* slow,
242                                           Condition cond) {
243   Label not_identical;
244   Label heap_number, return_equal;
245   __ cmp(r0, r1);
246   __ b(ne, &not_identical);
247
248   // Test for NaN. Sadly, we can't just compare to Factory::nan_value(),
249   // so we do the second best thing - test it ourselves.
250   // They are both equal and they are not both Smis so both of them are not
251   // Smis.  If it's not a heap number, then return equal.
252   if (cond == lt || cond == gt) {
253     __ CompareObjectType(r0, r4, r4, FIRST_SPEC_OBJECT_TYPE);
254     __ b(ge, slow);
255   } else {
256     __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE);
257     __ b(eq, &heap_number);
258     // Comparing JS objects with <=, >= is complicated.
259     if (cond != eq) {
260       __ cmp(r4, Operand(FIRST_SPEC_OBJECT_TYPE));
261       __ b(ge, slow);
262       // Normally here we fall through to return_equal, but undefined is
263       // special: (undefined == undefined) == true, but
264       // (undefined <= undefined) == false!  See ECMAScript 11.8.5.
265       if (cond == le || cond == ge) {
266         __ cmp(r4, Operand(ODDBALL_TYPE));
267         __ b(ne, &return_equal);
268         __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
269         __ cmp(r0, r2);
270         __ b(ne, &return_equal);
271         if (cond == le) {
272           // undefined <= undefined should fail.
273           __ mov(r0, Operand(GREATER));
274         } else  {
275           // undefined >= undefined should fail.
276           __ mov(r0, Operand(LESS));
277         }
278         __ Ret();
279       }
280     }
281   }
282
283   __ bind(&return_equal);
284   if (cond == lt) {
285     __ mov(r0, Operand(GREATER));  // Things aren't less than themselves.
286   } else if (cond == gt) {
287     __ mov(r0, Operand(LESS));     // Things aren't greater than themselves.
288   } else {
289     __ mov(r0, Operand(EQUAL));    // Things are <=, >=, ==, === themselves.
290   }
291   __ Ret();
292
293   // For less and greater we don't have to check for NaN since the result of
294   // x < x is false regardless.  For the others here is some code to check
295   // for NaN.
296   if (cond != lt && cond != gt) {
297     __ bind(&heap_number);
298     // It is a heap number, so return non-equal if it's NaN and equal if it's
299     // not NaN.
300
301     // The representation of NaN values has all exponent bits (52..62) set,
302     // and not all mantissa bits (0..51) clear.
303     // Read top bits of double representation (second word of value).
304     __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
305     // Test that exponent bits are all set.
306     __ Sbfx(r3, r2, HeapNumber::kExponentShift, HeapNumber::kExponentBits);
307     // NaNs have all-one exponents so they sign extend to -1.
308     __ cmp(r3, Operand(-1));
309     __ b(ne, &return_equal);
310
311     // Shift out flag and all exponent bits, retaining only mantissa.
312     __ mov(r2, Operand(r2, LSL, HeapNumber::kNonMantissaBitsInTopWord));
313     // Or with all low-bits of mantissa.
314     __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
315     __ orr(r0, r3, Operand(r2), SetCC);
316     // For equal we already have the right value in r0:  Return zero (equal)
317     // if all bits in mantissa are zero (it's an Infinity) and non-zero if
318     // not (it's a NaN).  For <= and >= we need to load r0 with the failing
319     // value if it's a NaN.
320     if (cond != eq) {
321       // All-zero means Infinity means equal.
322       __ Ret(eq);
323       if (cond == le) {
324         __ mov(r0, Operand(GREATER));  // NaN <= NaN should fail.
325       } else {
326         __ mov(r0, Operand(LESS));     // NaN >= NaN should fail.
327       }
328     }
329     __ Ret();
330   }
331   // No fall through here.
332
333   __ bind(&not_identical);
334 }
335
336
337 // See comment at call site.
338 static void EmitSmiNonsmiComparison(MacroAssembler* masm,
339                                     Register lhs,
340                                     Register rhs,
341                                     Label* lhs_not_nan,
342                                     Label* slow,
343                                     bool strict) {
344   DCHECK((lhs.is(r0) && rhs.is(r1)) ||
345          (lhs.is(r1) && rhs.is(r0)));
346
347   Label rhs_is_smi;
348   __ JumpIfSmi(rhs, &rhs_is_smi);
349
350   // Lhs is a Smi.  Check whether the rhs is a heap number.
351   __ CompareObjectType(rhs, r4, r4, HEAP_NUMBER_TYPE);
352   if (strict) {
353     // If rhs is not a number and lhs is a Smi then strict equality cannot
354     // succeed.  Return non-equal
355     // If rhs is r0 then there is already a non zero value in it.
356     if (!rhs.is(r0)) {
357       __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne);
358     }
359     __ Ret(ne);
360   } else {
361     // Smi compared non-strictly with a non-Smi non-heap-number.  Call
362     // the runtime.
363     __ b(ne, slow);
364   }
365
366   // Lhs is a smi, rhs is a number.
367   // Convert lhs to a double in d7.
368   __ SmiToDouble(d7, lhs);
369   // Load the double from rhs, tagged HeapNumber r0, to d6.
370   __ vldr(d6, rhs, HeapNumber::kValueOffset - kHeapObjectTag);
371
372   // We now have both loaded as doubles but we can skip the lhs nan check
373   // since it's a smi.
374   __ jmp(lhs_not_nan);
375
376   __ bind(&rhs_is_smi);
377   // Rhs is a smi.  Check whether the non-smi lhs is a heap number.
378   __ CompareObjectType(lhs, r4, r4, HEAP_NUMBER_TYPE);
379   if (strict) {
380     // If lhs is not a number and rhs is a smi then strict equality cannot
381     // succeed.  Return non-equal.
382     // If lhs is r0 then there is already a non zero value in it.
383     if (!lhs.is(r0)) {
384       __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne);
385     }
386     __ Ret(ne);
387   } else {
388     // Smi compared non-strictly with a non-smi non-heap-number.  Call
389     // the runtime.
390     __ b(ne, slow);
391   }
392
393   // Rhs is a smi, lhs is a heap number.
394   // Load the double from lhs, tagged HeapNumber r1, to d7.
395   __ vldr(d7, lhs, HeapNumber::kValueOffset - kHeapObjectTag);
396   // Convert rhs to a double in d6              .
397   __ SmiToDouble(d6, rhs);
398   // Fall through to both_loaded_as_doubles.
399 }
400
401
402 // See comment at call site.
403 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
404                                            Register lhs,
405                                            Register rhs) {
406     DCHECK((lhs.is(r0) && rhs.is(r1)) ||
407            (lhs.is(r1) && rhs.is(r0)));
408
409     // If either operand is a JS object or an oddball value, then they are
410     // not equal since their pointers are different.
411     // There is no test for undetectability in strict equality.
412     STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE);
413     Label first_non_object;
414     // Get the type of the first operand into r2 and compare it with
415     // FIRST_SPEC_OBJECT_TYPE.
416     __ CompareObjectType(rhs, r2, r2, FIRST_SPEC_OBJECT_TYPE);
417     __ b(lt, &first_non_object);
418
419     // Return non-zero (r0 is not zero)
420     Label return_not_equal;
421     __ bind(&return_not_equal);
422     __ Ret();
423
424     __ bind(&first_non_object);
425     // Check for oddballs: true, false, null, undefined.
426     __ cmp(r2, Operand(ODDBALL_TYPE));
427     __ b(eq, &return_not_equal);
428
429     __ CompareObjectType(lhs, r3, r3, FIRST_SPEC_OBJECT_TYPE);
430     __ b(ge, &return_not_equal);
431
432     // Check for oddballs: true, false, null, undefined.
433     __ cmp(r3, Operand(ODDBALL_TYPE));
434     __ b(eq, &return_not_equal);
435
436     // Now that we have the types we might as well check for
437     // internalized-internalized.
438     STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
439     __ orr(r2, r2, Operand(r3));
440     __ tst(r2, Operand(kIsNotStringMask | kIsNotInternalizedMask));
441     __ b(eq, &return_not_equal);
442 }
443
444
445 // See comment at call site.
446 static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm,
447                                        Register lhs,
448                                        Register rhs,
449                                        Label* both_loaded_as_doubles,
450                                        Label* not_heap_numbers,
451                                        Label* slow) {
452   DCHECK((lhs.is(r0) && rhs.is(r1)) ||
453          (lhs.is(r1) && rhs.is(r0)));
454
455   __ CompareObjectType(rhs, r3, r2, HEAP_NUMBER_TYPE);
456   __ b(ne, not_heap_numbers);
457   __ ldr(r2, FieldMemOperand(lhs, HeapObject::kMapOffset));
458   __ cmp(r2, r3);
459   __ b(ne, slow);  // First was a heap number, second wasn't.  Go slow case.
460
461   // Both are heap numbers.  Load them up then jump to the code we have
462   // for that.
463   __ vldr(d6, rhs, HeapNumber::kValueOffset - kHeapObjectTag);
464   __ vldr(d7, lhs, HeapNumber::kValueOffset - kHeapObjectTag);
465   __ jmp(both_loaded_as_doubles);
466 }
467
468
469 // Fast negative check for internalized-to-internalized equality.
470 static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm,
471                                                      Register lhs,
472                                                      Register rhs,
473                                                      Label* possible_strings,
474                                                      Label* not_both_strings) {
475   DCHECK((lhs.is(r0) && rhs.is(r1)) ||
476          (lhs.is(r1) && rhs.is(r0)));
477
478   // r2 is object type of rhs.
479   Label object_test;
480   STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
481   __ tst(r2, Operand(kIsNotStringMask));
482   __ b(ne, &object_test);
483   __ tst(r2, Operand(kIsNotInternalizedMask));
484   __ b(ne, possible_strings);
485   __ CompareObjectType(lhs, r3, r3, FIRST_NONSTRING_TYPE);
486   __ b(ge, not_both_strings);
487   __ tst(r3, Operand(kIsNotInternalizedMask));
488   __ b(ne, possible_strings);
489
490   // Both are internalized.  We already checked they weren't the same pointer
491   // so they are not equal.
492   __ mov(r0, Operand(NOT_EQUAL));
493   __ Ret();
494
495   __ bind(&object_test);
496   __ cmp(r2, Operand(FIRST_SPEC_OBJECT_TYPE));
497   __ b(lt, not_both_strings);
498   __ CompareObjectType(lhs, r2, r3, FIRST_SPEC_OBJECT_TYPE);
499   __ b(lt, not_both_strings);
500   // If both objects are undetectable, they are equal. Otherwise, they
501   // are not equal, since they are different objects and an object is not
502   // equal to undefined.
503   __ ldr(r3, FieldMemOperand(rhs, HeapObject::kMapOffset));
504   __ ldrb(r2, FieldMemOperand(r2, Map::kBitFieldOffset));
505   __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset));
506   __ and_(r0, r2, Operand(r3));
507   __ and_(r0, r0, Operand(1 << Map::kIsUndetectable));
508   __ eor(r0, r0, Operand(1 << Map::kIsUndetectable));
509   __ Ret();
510 }
511
512
513 static void CompareICStub_CheckInputType(MacroAssembler* masm, Register input,
514                                          Register scratch,
515                                          CompareICState::State expected,
516                                          Label* fail) {
517   Label ok;
518   if (expected == CompareICState::SMI) {
519     __ JumpIfNotSmi(input, fail);
520   } else if (expected == CompareICState::NUMBER) {
521     __ JumpIfSmi(input, &ok);
522     __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail,
523                 DONT_DO_SMI_CHECK);
524   }
525   // We could be strict about internalized/non-internalized here, but as long as
526   // hydrogen doesn't care, the stub doesn't have to care either.
527   __ bind(&ok);
528 }
529
530
531 // On entry r1 and r2 are the values to be compared.
532 // On exit r0 is 0, positive or negative to indicate the result of
533 // the comparison.
534 void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
535   Register lhs = r1;
536   Register rhs = r0;
537   Condition cc = GetCondition();
538
539   Label miss;
540   CompareICStub_CheckInputType(masm, lhs, r2, left(), &miss);
541   CompareICStub_CheckInputType(masm, rhs, r3, right(), &miss);
542
543   Label slow;  // Call builtin.
544   Label not_smis, both_loaded_as_doubles, lhs_not_nan;
545
546   Label not_two_smis, smi_done;
547   __ orr(r2, r1, r0);
548   __ JumpIfNotSmi(r2, &not_two_smis);
549   __ mov(r1, Operand(r1, ASR, 1));
550   __ sub(r0, r1, Operand(r0, ASR, 1));
551   __ Ret();
552   __ bind(&not_two_smis);
553
554   // NOTICE! This code is only reached after a smi-fast-case check, so
555   // it is certain that at least one operand isn't a smi.
556
557   // Handle the case where the objects are identical.  Either returns the answer
558   // or goes to slow.  Only falls through if the objects were not identical.
559   EmitIdenticalObjectComparison(masm, &slow, cc);
560
561   // If either is a Smi (we know that not both are), then they can only
562   // be strictly equal if the other is a HeapNumber.
563   STATIC_ASSERT(kSmiTag == 0);
564   DCHECK_EQ(static_cast<Smi*>(0), Smi::FromInt(0));
565   __ and_(r2, lhs, Operand(rhs));
566   __ JumpIfNotSmi(r2, &not_smis);
567   // One operand is a smi.  EmitSmiNonsmiComparison generates code that can:
568   // 1) Return the answer.
569   // 2) Go to slow.
570   // 3) Fall through to both_loaded_as_doubles.
571   // 4) Jump to lhs_not_nan.
572   // In cases 3 and 4 we have found out we were dealing with a number-number
573   // comparison.  If VFP3 is supported the double values of the numbers have
574   // been loaded into d7 and d6.  Otherwise, the double values have been loaded
575   // into r0, r1, r2, and r3.
576   EmitSmiNonsmiComparison(masm, lhs, rhs, &lhs_not_nan, &slow, strict());
577
578   __ bind(&both_loaded_as_doubles);
579   // The arguments have been converted to doubles and stored in d6 and d7, if
580   // VFP3 is supported, or in r0, r1, r2, and r3.
581   __ bind(&lhs_not_nan);
582   Label no_nan;
583   // ARMv7 VFP3 instructions to implement double precision comparison.
584   __ VFPCompareAndSetFlags(d7, d6);
585   Label nan;
586   __ b(vs, &nan);
587   __ mov(r0, Operand(EQUAL), LeaveCC, eq);
588   __ mov(r0, Operand(LESS), LeaveCC, lt);
589   __ mov(r0, Operand(GREATER), LeaveCC, gt);
590   __ Ret();
591
592   __ bind(&nan);
593   // If one of the sides was a NaN then the v flag is set.  Load r0 with
594   // whatever it takes to make the comparison fail, since comparisons with NaN
595   // always fail.
596   if (cc == lt || cc == le) {
597     __ mov(r0, Operand(GREATER));
598   } else {
599     __ mov(r0, Operand(LESS));
600   }
601   __ Ret();
602
603   __ bind(&not_smis);
604   // At this point we know we are dealing with two different objects,
605   // and neither of them is a Smi.  The objects are in rhs_ and lhs_.
606   if (strict()) {
607     // This returns non-equal for some object types, or falls through if it
608     // was not lucky.
609     EmitStrictTwoHeapObjectCompare(masm, lhs, rhs);
610   }
611
612   Label check_for_internalized_strings;
613   Label flat_string_check;
614   // Check for heap-number-heap-number comparison.  Can jump to slow case,
615   // or load both doubles into r0, r1, r2, r3 and jump to the code that handles
616   // that case.  If the inputs are not doubles then jumps to
617   // check_for_internalized_strings.
618   // In this case r2 will contain the type of rhs_.  Never falls through.
619   EmitCheckForTwoHeapNumbers(masm,
620                              lhs,
621                              rhs,
622                              &both_loaded_as_doubles,
623                              &check_for_internalized_strings,
624                              &flat_string_check);
625
626   __ bind(&check_for_internalized_strings);
627   // In the strict case the EmitStrictTwoHeapObjectCompare already took care of
628   // internalized strings.
629   if (cc == eq && !strict()) {
630     // Returns an answer for two internalized strings or two detectable objects.
631     // Otherwise jumps to string case or not both strings case.
632     // Assumes that r2 is the type of rhs_ on entry.
633     EmitCheckForInternalizedStringsOrObjects(
634         masm, lhs, rhs, &flat_string_check, &slow);
635   }
636
637   // Check for both being sequential one-byte strings,
638   // and inline if that is the case.
639   __ bind(&flat_string_check);
640
641   __ JumpIfNonSmisNotBothSequentialOneByteStrings(lhs, rhs, r2, r3, &slow);
642
643   __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, r2,
644                       r3);
645   if (cc == eq) {
646     StringHelper::GenerateFlatOneByteStringEquals(masm, lhs, rhs, r2, r3, r4);
647   } else {
648     StringHelper::GenerateCompareFlatOneByteStrings(masm, lhs, rhs, r2, r3, r4,
649                                                     r5);
650   }
651   // Never falls through to here.
652
653   __ bind(&slow);
654
655   __ Push(lhs, rhs);
656   // Figure out which native to call and setup the arguments.
657   Builtins::JavaScript native;
658   if (cc == eq) {
659     native = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS;
660   } else {
661     native = Builtins::COMPARE;
662     int ncr;  // NaN compare result
663     if (cc == lt || cc == le) {
664       ncr = GREATER;
665     } else {
666       DCHECK(cc == gt || cc == ge);  // remaining cases
667       ncr = LESS;
668     }
669     __ mov(r0, Operand(Smi::FromInt(ncr)));
670     __ push(r0);
671   }
672
673   // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
674   // tagged as a small integer.
675   __ InvokeBuiltin(native, JUMP_FUNCTION);
676
677   __ bind(&miss);
678   GenerateMiss(masm);
679 }
680
681
682 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
683   // We don't allow a GC during a store buffer overflow so there is no need to
684   // store the registers in any particular way, but we do have to store and
685   // restore them.
686   __ stm(db_w, sp, kCallerSaved | lr.bit());
687
688   const Register scratch = r1;
689
690   if (save_doubles()) {
691     __ SaveFPRegs(sp, scratch);
692   }
693   const int argument_count = 1;
694   const int fp_argument_count = 0;
695
696   AllowExternalCallThatCantCauseGC scope(masm);
697   __ PrepareCallCFunction(argument_count, fp_argument_count, scratch);
698   __ mov(r0, Operand(ExternalReference::isolate_address(isolate())));
699   __ CallCFunction(
700       ExternalReference::store_buffer_overflow_function(isolate()),
701       argument_count);
702   if (save_doubles()) {
703     __ RestoreFPRegs(sp, scratch);
704   }
705   __ ldm(ia_w, sp, kCallerSaved | pc.bit());  // Also pop pc to get Ret(0).
706 }
707
708
709 void MathPowStub::Generate(MacroAssembler* masm) {
710   const Register base = r1;
711   const Register exponent = MathPowTaggedDescriptor::exponent();
712   DCHECK(exponent.is(r2));
713   const Register heapnumbermap = r5;
714   const Register heapnumber = r0;
715   const DwVfpRegister double_base = d0;
716   const DwVfpRegister double_exponent = d1;
717   const DwVfpRegister double_result = d2;
718   const DwVfpRegister double_scratch = d3;
719   const SwVfpRegister single_scratch = s6;
720   const Register scratch = r9;
721   const Register scratch2 = r4;
722
723   Label call_runtime, done, int_exponent;
724   if (exponent_type() == ON_STACK) {
725     Label base_is_smi, unpack_exponent;
726     // The exponent and base are supplied as arguments on the stack.
727     // This can only happen if the stub is called from non-optimized code.
728     // Load input parameters from stack to double registers.
729     __ ldr(base, MemOperand(sp, 1 * kPointerSize));
730     __ ldr(exponent, MemOperand(sp, 0 * kPointerSize));
731
732     __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex);
733
734     __ UntagAndJumpIfSmi(scratch, base, &base_is_smi);
735     __ ldr(scratch, FieldMemOperand(base, JSObject::kMapOffset));
736     __ cmp(scratch, heapnumbermap);
737     __ b(ne, &call_runtime);
738
739     __ vldr(double_base, FieldMemOperand(base, HeapNumber::kValueOffset));
740     __ jmp(&unpack_exponent);
741
742     __ bind(&base_is_smi);
743     __ vmov(single_scratch, scratch);
744     __ vcvt_f64_s32(double_base, single_scratch);
745     __ bind(&unpack_exponent);
746
747     __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent);
748
749     __ ldr(scratch, FieldMemOperand(exponent, JSObject::kMapOffset));
750     __ cmp(scratch, heapnumbermap);
751     __ b(ne, &call_runtime);
752     __ vldr(double_exponent,
753             FieldMemOperand(exponent, HeapNumber::kValueOffset));
754   } else if (exponent_type() == TAGGED) {
755     // Base is already in double_base.
756     __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent);
757
758     __ vldr(double_exponent,
759             FieldMemOperand(exponent, HeapNumber::kValueOffset));
760   }
761
762   if (exponent_type() != INTEGER) {
763     Label int_exponent_convert;
764     // Detect integer exponents stored as double.
765     __ vcvt_u32_f64(single_scratch, double_exponent);
766     // We do not check for NaN or Infinity here because comparing numbers on
767     // ARM correctly distinguishes NaNs.  We end up calling the built-in.
768     __ vcvt_f64_u32(double_scratch, single_scratch);
769     __ VFPCompareAndSetFlags(double_scratch, double_exponent);
770     __ b(eq, &int_exponent_convert);
771
772     if (exponent_type() == ON_STACK) {
773       // Detect square root case.  Crankshaft detects constant +/-0.5 at
774       // compile time and uses DoMathPowHalf instead.  We then skip this check
775       // for non-constant cases of +/-0.5 as these hardly occur.
776       Label not_plus_half;
777
778       // Test for 0.5.
779       __ vmov(double_scratch, 0.5, scratch);
780       __ VFPCompareAndSetFlags(double_exponent, double_scratch);
781       __ b(ne, &not_plus_half);
782
783       // Calculates square root of base.  Check for the special case of
784       // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13).
785       __ vmov(double_scratch, -V8_INFINITY, scratch);
786       __ VFPCompareAndSetFlags(double_base, double_scratch);
787       __ vneg(double_result, double_scratch, eq);
788       __ b(eq, &done);
789
790       // Add +0 to convert -0 to +0.
791       __ vadd(double_scratch, double_base, kDoubleRegZero);
792       __ vsqrt(double_result, double_scratch);
793       __ jmp(&done);
794
795       __ bind(&not_plus_half);
796       __ vmov(double_scratch, -0.5, scratch);
797       __ VFPCompareAndSetFlags(double_exponent, double_scratch);
798       __ b(ne, &call_runtime);
799
800       // Calculates square root of base.  Check for the special case of
801       // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13).
802       __ vmov(double_scratch, -V8_INFINITY, scratch);
803       __ VFPCompareAndSetFlags(double_base, double_scratch);
804       __ vmov(double_result, kDoubleRegZero, eq);
805       __ b(eq, &done);
806
807       // Add +0 to convert -0 to +0.
808       __ vadd(double_scratch, double_base, kDoubleRegZero);
809       __ vmov(double_result, 1.0, scratch);
810       __ vsqrt(double_scratch, double_scratch);
811       __ vdiv(double_result, double_result, double_scratch);
812       __ jmp(&done);
813     }
814
815     __ push(lr);
816     {
817       AllowExternalCallThatCantCauseGC scope(masm);
818       __ PrepareCallCFunction(0, 2, scratch);
819       __ MovToFloatParameters(double_base, double_exponent);
820       __ CallCFunction(
821           ExternalReference::power_double_double_function(isolate()),
822           0, 2);
823     }
824     __ pop(lr);
825     __ MovFromFloatResult(double_result);
826     __ jmp(&done);
827
828     __ bind(&int_exponent_convert);
829     __ vcvt_u32_f64(single_scratch, double_exponent);
830     __ vmov(scratch, single_scratch);
831   }
832
833   // Calculate power with integer exponent.
834   __ bind(&int_exponent);
835
836   // Get two copies of exponent in the registers scratch and exponent.
837   if (exponent_type() == INTEGER) {
838     __ mov(scratch, exponent);
839   } else {
840     // Exponent has previously been stored into scratch as untagged integer.
841     __ mov(exponent, scratch);
842   }
843   __ vmov(double_scratch, double_base);  // Back up base.
844   __ vmov(double_result, 1.0, scratch2);
845
846   // Get absolute value of exponent.
847   __ cmp(scratch, Operand::Zero());
848   __ mov(scratch2, Operand::Zero(), LeaveCC, mi);
849   __ sub(scratch, scratch2, scratch, LeaveCC, mi);
850
851   Label while_true;
852   __ bind(&while_true);
853   __ mov(scratch, Operand(scratch, ASR, 1), SetCC);
854   __ vmul(double_result, double_result, double_scratch, cs);
855   __ vmul(double_scratch, double_scratch, double_scratch, ne);
856   __ b(ne, &while_true);
857
858   __ cmp(exponent, Operand::Zero());
859   __ b(ge, &done);
860   __ vmov(double_scratch, 1.0, scratch);
861   __ vdiv(double_result, double_scratch, double_result);
862   // Test whether result is zero.  Bail out to check for subnormal result.
863   // Due to subnormals, x^-y == (1/x)^y does not hold in all cases.
864   __ VFPCompareAndSetFlags(double_result, 0.0);
865   __ b(ne, &done);
866   // double_exponent may not containe the exponent value if the input was a
867   // smi.  We set it with exponent value before bailing out.
868   __ vmov(single_scratch, exponent);
869   __ vcvt_f64_s32(double_exponent, single_scratch);
870
871   // Returning or bailing out.
872   Counters* counters = isolate()->counters();
873   if (exponent_type() == ON_STACK) {
874     // The arguments are still on the stack.
875     __ bind(&call_runtime);
876     __ TailCallRuntime(Runtime::kMathPowRT, 2, 1);
877
878     // The stub is called from non-optimized code, which expects the result
879     // as heap number in exponent.
880     __ bind(&done);
881     __ AllocateHeapNumber(
882         heapnumber, scratch, scratch2, heapnumbermap, &call_runtime);
883     __ vstr(double_result,
884             FieldMemOperand(heapnumber, HeapNumber::kValueOffset));
885     DCHECK(heapnumber.is(r0));
886     __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2);
887     __ Ret(2);
888   } else {
889     __ push(lr);
890     {
891       AllowExternalCallThatCantCauseGC scope(masm);
892       __ PrepareCallCFunction(0, 2, scratch);
893       __ MovToFloatParameters(double_base, double_exponent);
894       __ CallCFunction(
895           ExternalReference::power_double_double_function(isolate()),
896           0, 2);
897     }
898     __ pop(lr);
899     __ MovFromFloatResult(double_result);
900
901     __ bind(&done);
902     __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2);
903     __ Ret();
904   }
905 }
906
907
908 bool CEntryStub::NeedsImmovableCode() {
909   return true;
910 }
911
912
913 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
914   CEntryStub::GenerateAheadOfTime(isolate);
915   StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
916   StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
917   ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
918   CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
919   CreateWeakCellStub::GenerateAheadOfTime(isolate);
920   BinaryOpICStub::GenerateAheadOfTime(isolate);
921   BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate);
922 }
923
924
925 void CodeStub::GenerateFPStubs(Isolate* isolate) {
926   // Generate if not already in cache.
927   SaveFPRegsMode mode = kSaveFPRegs;
928   CEntryStub(isolate, 1, mode).GetCode();
929   StoreBufferOverflowStub(isolate, mode).GetCode();
930   isolate->set_fp_stubs_generated(true);
931 }
932
933
934 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
935   CEntryStub stub(isolate, 1, kDontSaveFPRegs);
936   stub.GetCode();
937 }
938
939
940 void CEntryStub::Generate(MacroAssembler* masm) {
941   // Called from JavaScript; parameters are on stack as if calling JS function.
942   // r0: number of arguments including receiver
943   // r1: pointer to builtin function
944   // fp: frame pointer  (restored after C call)
945   // sp: stack pointer  (restored as callee's sp after C call)
946   // cp: current context  (C callee-saved)
947
948   ProfileEntryHookStub::MaybeCallEntryHook(masm);
949
950   __ mov(r5, Operand(r1));
951
952   // Compute the argv pointer in a callee-saved register.
953   __ add(r1, sp, Operand(r0, LSL, kPointerSizeLog2));
954   __ sub(r1, r1, Operand(kPointerSize));
955
956   // Enter the exit frame that transitions from JavaScript to C++.
957   FrameScope scope(masm, StackFrame::MANUAL);
958   __ EnterExitFrame(save_doubles());
959
960   // Store a copy of argc in callee-saved registers for later.
961   __ mov(r4, Operand(r0));
962
963   // r0, r4: number of arguments including receiver  (C callee-saved)
964   // r1: pointer to the first argument (C callee-saved)
965   // r5: pointer to builtin function  (C callee-saved)
966
967   // Result returned in r0 or r0+r1 by default.
968
969 #if V8_HOST_ARCH_ARM
970   int frame_alignment = MacroAssembler::ActivationFrameAlignment();
971   int frame_alignment_mask = frame_alignment - 1;
972   if (FLAG_debug_code) {
973     if (frame_alignment > kPointerSize) {
974       Label alignment_as_expected;
975       DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
976       __ tst(sp, Operand(frame_alignment_mask));
977       __ b(eq, &alignment_as_expected);
978       // Don't use Check here, as it will call Runtime_Abort re-entering here.
979       __ stop("Unexpected alignment");
980       __ bind(&alignment_as_expected);
981     }
982   }
983 #endif
984
985   // Call C built-in.
986   // r0 = argc, r1 = argv
987   __ mov(r2, Operand(ExternalReference::isolate_address(isolate())));
988
989   // To let the GC traverse the return address of the exit frames, we need to
990   // know where the return address is. The CEntryStub is unmovable, so
991   // we can store the address on the stack to be able to find it again and
992   // we never have to restore it, because it will not change.
993   // Compute the return address in lr to return to after the jump below. Pc is
994   // already at '+ 8' from the current instruction but return is after three
995   // instructions so add another 4 to pc to get the return address.
996   {
997     // Prevent literal pool emission before return address.
998     Assembler::BlockConstPoolScope block_const_pool(masm);
999     __ add(lr, pc, Operand(4));
1000     __ str(lr, MemOperand(sp, 0));
1001     __ Call(r5);
1002   }
1003
1004   __ VFPEnsureFPSCRState(r2);
1005
1006   // Runtime functions should not return 'the hole'.  Allowing it to escape may
1007   // lead to crashes in the IC code later.
1008   if (FLAG_debug_code) {
1009     Label okay;
1010     __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
1011     __ b(ne, &okay);
1012     __ stop("The hole escaped");
1013     __ bind(&okay);
1014   }
1015
1016   // Check result for exception sentinel.
1017   Label exception_returned;
1018   __ CompareRoot(r0, Heap::kExceptionRootIndex);
1019   __ b(eq, &exception_returned);
1020
1021   ExternalReference pending_exception_address(
1022       Isolate::kPendingExceptionAddress, isolate());
1023
1024   // Check that there is no pending exception, otherwise we
1025   // should have returned the exception sentinel.
1026   if (FLAG_debug_code) {
1027     Label okay;
1028     __ mov(r2, Operand(pending_exception_address));
1029     __ ldr(r2, MemOperand(r2));
1030     __ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
1031     // Cannot use check here as it attempts to generate call into runtime.
1032     __ b(eq, &okay);
1033     __ stop("Unexpected pending exception");
1034     __ bind(&okay);
1035   }
1036
1037   // Exit C frame and return.
1038   // r0:r1: result
1039   // sp: stack pointer
1040   // fp: frame pointer
1041   // Callee-saved register r4 still holds argc.
1042   __ LeaveExitFrame(save_doubles(), r4, true);
1043   __ mov(pc, lr);
1044
1045   // Handling of exception.
1046   __ bind(&exception_returned);
1047
1048   // Retrieve the pending exception.
1049   __ mov(r2, Operand(pending_exception_address));
1050   __ ldr(r0, MemOperand(r2));
1051
1052   // Clear the pending exception.
1053   __ LoadRoot(r3, Heap::kTheHoleValueRootIndex);
1054   __ str(r3, MemOperand(r2));
1055
1056   // Special handling of termination exceptions which are uncatchable
1057   // by javascript code.
1058   Label throw_termination_exception;
1059   __ CompareRoot(r0, Heap::kTerminationExceptionRootIndex);
1060   __ b(eq, &throw_termination_exception);
1061
1062   // Handle normal exception.
1063   __ Throw(r0);
1064
1065   __ bind(&throw_termination_exception);
1066   __ ThrowUncatchable(r0);
1067 }
1068
1069
1070 void JSEntryStub::Generate(MacroAssembler* masm) {
1071   // r0: code entry
1072   // r1: function
1073   // r2: receiver
1074   // r3: argc
1075   // [sp+0]: argv
1076
1077   Label invoke, handler_entry, exit;
1078
1079   ProfileEntryHookStub::MaybeCallEntryHook(masm);
1080
1081   // Called from C, so do not pop argc and args on exit (preserve sp)
1082   // No need to save register-passed args
1083   // Save callee-saved registers (incl. cp and fp), sp, and lr
1084   __ stm(db_w, sp, kCalleeSaved | lr.bit());
1085
1086   // Save callee-saved vfp registers.
1087   __ vstm(db_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg);
1088   // Set up the reserved register for 0.0.
1089   __ vmov(kDoubleRegZero, 0.0);
1090   __ VFPEnsureFPSCRState(r4);
1091
1092   // Get address of argv, see stm above.
1093   // r0: code entry
1094   // r1: function
1095   // r2: receiver
1096   // r3: argc
1097
1098   // Set up argv in r4.
1099   int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize;
1100   offset_to_argv += kNumDoubleCalleeSaved * kDoubleSize;
1101   __ ldr(r4, MemOperand(sp, offset_to_argv));
1102
1103   // Push a frame with special values setup to mark it as an entry frame.
1104   // r0: code entry
1105   // r1: function
1106   // r2: receiver
1107   // r3: argc
1108   // r4: argv
1109   int marker = type();
1110   if (FLAG_enable_ool_constant_pool) {
1111     __ mov(r8, Operand(isolate()->factory()->empty_constant_pool_array()));
1112   }
1113   __ mov(r7, Operand(Smi::FromInt(marker)));
1114   __ mov(r6, Operand(Smi::FromInt(marker)));
1115   __ mov(r5,
1116          Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
1117   __ ldr(r5, MemOperand(r5));
1118   __ mov(ip, Operand(-1));  // Push a bad frame pointer to fail if it is used.
1119   __ stm(db_w, sp, r5.bit() | r6.bit() | r7.bit() |
1120                    (FLAG_enable_ool_constant_pool ? r8.bit() : 0) |
1121                    ip.bit());
1122
1123   // Set up frame pointer for the frame to be pushed.
1124   __ add(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
1125
1126   // If this is the outermost JS call, set js_entry_sp value.
1127   Label non_outermost_js;
1128   ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate());
1129   __ mov(r5, Operand(ExternalReference(js_entry_sp)));
1130   __ ldr(r6, MemOperand(r5));
1131   __ cmp(r6, Operand::Zero());
1132   __ b(ne, &non_outermost_js);
1133   __ str(fp, MemOperand(r5));
1134   __ mov(ip, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
1135   Label cont;
1136   __ b(&cont);
1137   __ bind(&non_outermost_js);
1138   __ mov(ip, Operand(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME)));
1139   __ bind(&cont);
1140   __ push(ip);
1141
1142   // Jump to a faked try block that does the invoke, with a faked catch
1143   // block that sets the pending exception.
1144   __ jmp(&invoke);
1145
1146   // Block literal pool emission whilst taking the position of the handler
1147   // entry. This avoids making the assumption that literal pools are always
1148   // emitted after an instruction is emitted, rather than before.
1149   {
1150     Assembler::BlockConstPoolScope block_const_pool(masm);
1151     __ bind(&handler_entry);
1152     handler_offset_ = handler_entry.pos();
1153     // Caught exception: Store result (exception) in the pending exception
1154     // field in the JSEnv and return a failure sentinel.  Coming in here the
1155     // fp will be invalid because the PushTryHandler below sets it to 0 to
1156     // signal the existence of the JSEntry frame.
1157     __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
1158                                          isolate())));
1159   }
1160   __ str(r0, MemOperand(ip));
1161   __ LoadRoot(r0, Heap::kExceptionRootIndex);
1162   __ b(&exit);
1163
1164   // Invoke: Link this frame into the handler chain.  There's only one
1165   // handler block in this code object, so its index is 0.
1166   __ bind(&invoke);
1167   // Must preserve r0-r4, r5-r6 are available.
1168   __ PushTryHandler(StackHandler::JS_ENTRY, 0);
1169   // If an exception not caught by another handler occurs, this handler
1170   // returns control to the code after the bl(&invoke) above, which
1171   // restores all kCalleeSaved registers (including cp and fp) to their
1172   // saved values before returning a failure to C.
1173
1174   // Clear any pending exceptions.
1175   __ mov(r5, Operand(isolate()->factory()->the_hole_value()));
1176   __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
1177                                        isolate())));
1178   __ str(r5, MemOperand(ip));
1179
1180   // Invoke the function by calling through JS entry trampoline builtin.
1181   // Notice that we cannot store a reference to the trampoline code directly in
1182   // this stub, because runtime stubs are not traversed when doing GC.
1183
1184   // Expected registers by Builtins::JSEntryTrampoline
1185   // r0: code entry
1186   // r1: function
1187   // r2: receiver
1188   // r3: argc
1189   // r4: argv
1190   if (type() == StackFrame::ENTRY_CONSTRUCT) {
1191     ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline,
1192                                       isolate());
1193     __ mov(ip, Operand(construct_entry));
1194   } else {
1195     ExternalReference entry(Builtins::kJSEntryTrampoline, isolate());
1196     __ mov(ip, Operand(entry));
1197   }
1198   __ ldr(ip, MemOperand(ip));  // deref address
1199   __ add(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
1200
1201   // Branch and link to JSEntryTrampoline.
1202   __ Call(ip);
1203
1204   // Unlink this frame from the handler chain.
1205   __ PopTryHandler();
1206
1207   __ bind(&exit);  // r0 holds result
1208   // Check if the current stack frame is marked as the outermost JS frame.
1209   Label non_outermost_js_2;
1210   __ pop(r5);
1211   __ cmp(r5, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
1212   __ b(ne, &non_outermost_js_2);
1213   __ mov(r6, Operand::Zero());
1214   __ mov(r5, Operand(ExternalReference(js_entry_sp)));
1215   __ str(r6, MemOperand(r5));
1216   __ bind(&non_outermost_js_2);
1217
1218   // Restore the top frame descriptors from the stack.
1219   __ pop(r3);
1220   __ mov(ip,
1221          Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
1222   __ str(r3, MemOperand(ip));
1223
1224   // Reset the stack to the callee saved registers.
1225   __ add(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
1226
1227   // Restore callee-saved registers and return.
1228 #ifdef DEBUG
1229   if (FLAG_debug_code) {
1230     __ mov(lr, Operand(pc));
1231   }
1232 #endif
1233
1234   // Restore callee-saved vfp registers.
1235   __ vldm(ia_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg);
1236
1237   __ ldm(ia_w, sp, kCalleeSaved | pc.bit());
1238 }
1239
1240
1241 // Uses registers r0 to r4.
1242 // Expected input (depending on whether args are in registers or on the stack):
1243 // * object: r0 or at sp + 1 * kPointerSize.
1244 // * function: r1 or at sp.
1245 //
1246 // An inlined call site may have been generated before calling this stub.
1247 // In this case the offset to the inline sites to patch are passed in r5 and r6.
1248 // (See LCodeGen::DoInstanceOfKnownGlobal)
1249 void InstanceofStub::Generate(MacroAssembler* masm) {
1250   // Call site inlining and patching implies arguments in registers.
1251   DCHECK(HasArgsInRegisters() || !HasCallSiteInlineCheck());
1252
1253   // Fixed register usage throughout the stub:
1254   const Register object = r0;  // Object (lhs).
1255   Register map = r3;  // Map of the object.
1256   const Register function = r1;  // Function (rhs).
1257   const Register prototype = r4;  // Prototype of the function.
1258   const Register scratch = r2;
1259
1260   Label slow, loop, is_instance, is_not_instance, not_js_object;
1261
1262   if (!HasArgsInRegisters()) {
1263     __ ldr(object, MemOperand(sp, 1 * kPointerSize));
1264     __ ldr(function, MemOperand(sp, 0));
1265   }
1266
1267   // Check that the left hand is a JS object and load map.
1268   __ JumpIfSmi(object, &not_js_object);
1269   __ IsObjectJSObjectType(object, map, scratch, &not_js_object);
1270
1271   // If there is a call site cache don't look in the global cache, but do the
1272   // real lookup and update the call site cache.
1273   if (!HasCallSiteInlineCheck() && !ReturnTrueFalseObject()) {
1274     Label miss;
1275     __ CompareRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
1276     __ b(ne, &miss);
1277     __ CompareRoot(map, Heap::kInstanceofCacheMapRootIndex);
1278     __ b(ne, &miss);
1279     __ LoadRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
1280     __ Ret(HasArgsInRegisters() ? 0 : 2);
1281
1282     __ bind(&miss);
1283   }
1284
1285   // Get the prototype of the function.
1286   __ TryGetFunctionPrototype(function, prototype, scratch, &slow, true);
1287
1288   // Check that the function prototype is a JS object.
1289   __ JumpIfSmi(prototype, &slow);
1290   __ IsObjectJSObjectType(prototype, scratch, scratch, &slow);
1291
1292   // Update the global instanceof or call site inlined cache with the current
1293   // map and function. The cached answer will be set when it is known below.
1294   if (!HasCallSiteInlineCheck()) {
1295     __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
1296     __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex);
1297   } else {
1298     DCHECK(HasArgsInRegisters());
1299     // Patch the (relocated) inlined map check.
1300
1301     // The map_load_offset was stored in r5
1302     //   (See LCodeGen::DoDeferredLInstanceOfKnownGlobal).
1303     const Register map_load_offset = r5;
1304     __ sub(r9, lr, map_load_offset);
1305     // Get the map location in r5 and patch it.
1306     __ GetRelocatedValueLocation(r9, map_load_offset, scratch);
1307     __ ldr(map_load_offset, MemOperand(map_load_offset));
1308     __ str(map, FieldMemOperand(map_load_offset, Cell::kValueOffset));
1309   }
1310
1311   // Register mapping: r3 is object map and r4 is function prototype.
1312   // Get prototype of object into r2.
1313   __ ldr(scratch, FieldMemOperand(map, Map::kPrototypeOffset));
1314
1315   // We don't need map any more. Use it as a scratch register.
1316   Register scratch2 = map;
1317   map = no_reg;
1318
1319   // Loop through the prototype chain looking for the function prototype.
1320   __ LoadRoot(scratch2, Heap::kNullValueRootIndex);
1321   __ bind(&loop);
1322   __ cmp(scratch, Operand(prototype));
1323   __ b(eq, &is_instance);
1324   __ cmp(scratch, scratch2);
1325   __ b(eq, &is_not_instance);
1326   __ ldr(scratch, FieldMemOperand(scratch, HeapObject::kMapOffset));
1327   __ ldr(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset));
1328   __ jmp(&loop);
1329   Factory* factory = isolate()->factory();
1330
1331   __ bind(&is_instance);
1332   if (!HasCallSiteInlineCheck()) {
1333     __ mov(r0, Operand(Smi::FromInt(0)));
1334     __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
1335     if (ReturnTrueFalseObject()) {
1336       __ Move(r0, factory->true_value());
1337     }
1338   } else {
1339     // Patch the call site to return true.
1340     __ LoadRoot(r0, Heap::kTrueValueRootIndex);
1341     // The bool_load_offset was stored in r6
1342     //   (See LCodeGen::DoDeferredLInstanceOfKnownGlobal).
1343     const Register bool_load_offset = r6;
1344     __ sub(r9, lr, bool_load_offset);
1345     // Get the boolean result location in scratch and patch it.
1346     __ GetRelocatedValueLocation(r9, scratch, scratch2);
1347     __ str(r0, MemOperand(scratch));
1348
1349     if (!ReturnTrueFalseObject()) {
1350       __ mov(r0, Operand(Smi::FromInt(0)));
1351     }
1352   }
1353   __ Ret(HasArgsInRegisters() ? 0 : 2);
1354
1355   __ bind(&is_not_instance);
1356   if (!HasCallSiteInlineCheck()) {
1357     __ mov(r0, Operand(Smi::FromInt(1)));
1358     __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
1359     if (ReturnTrueFalseObject()) {
1360       __ Move(r0, factory->false_value());
1361     }
1362   } else {
1363     // Patch the call site to return false.
1364     __ LoadRoot(r0, Heap::kFalseValueRootIndex);
1365     // The bool_load_offset was stored in r6
1366     //   (See LCodeGen::DoDeferredLInstanceOfKnownGlobal).
1367     const Register bool_load_offset = r6;
1368     __ sub(r9, lr, bool_load_offset);
1369     ;
1370     // Get the boolean result location in scratch and patch it.
1371     __ GetRelocatedValueLocation(r9, scratch, scratch2);
1372     __ str(r0, MemOperand(scratch));
1373
1374     if (!ReturnTrueFalseObject()) {
1375       __ mov(r0, Operand(Smi::FromInt(1)));
1376     }
1377   }
1378   __ Ret(HasArgsInRegisters() ? 0 : 2);
1379
1380   Label object_not_null, object_not_null_or_smi;
1381   __ bind(&not_js_object);
1382   // Before null, smi and string value checks, check that the rhs is a function
1383   // as for a non-function rhs an exception needs to be thrown.
1384   __ JumpIfSmi(function, &slow);
1385   __ CompareObjectType(function, scratch2, scratch, JS_FUNCTION_TYPE);
1386   __ b(ne, &slow);
1387
1388   // Null is not instance of anything.
1389   __ cmp(object, Operand(isolate()->factory()->null_value()));
1390   __ b(ne, &object_not_null);
1391   if (ReturnTrueFalseObject()) {
1392     __ Move(r0, factory->false_value());
1393   } else {
1394     __ mov(r0, Operand(Smi::FromInt(1)));
1395   }
1396   __ Ret(HasArgsInRegisters() ? 0 : 2);
1397
1398   __ bind(&object_not_null);
1399   // Smi values are not instances of anything.
1400   __ JumpIfNotSmi(object, &object_not_null_or_smi);
1401   if (ReturnTrueFalseObject()) {
1402     __ Move(r0, factory->false_value());
1403   } else {
1404     __ mov(r0, Operand(Smi::FromInt(1)));
1405   }
1406   __ Ret(HasArgsInRegisters() ? 0 : 2);
1407
1408   __ bind(&object_not_null_or_smi);
1409   // String values are not instances of anything.
1410   __ IsObjectJSStringType(object, scratch, &slow);
1411   if (ReturnTrueFalseObject()) {
1412     __ Move(r0, factory->false_value());
1413   } else {
1414     __ mov(r0, Operand(Smi::FromInt(1)));
1415   }
1416   __ Ret(HasArgsInRegisters() ? 0 : 2);
1417
1418   // Slow-case.  Tail call builtin.
1419   __ bind(&slow);
1420   if (!ReturnTrueFalseObject()) {
1421     if (HasArgsInRegisters()) {
1422       __ Push(r0, r1);
1423     }
1424   __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
1425   } else {
1426     {
1427       FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
1428       __ Push(r0, r1);
1429       __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION);
1430     }
1431     __ cmp(r0, Operand::Zero());
1432     __ LoadRoot(r0, Heap::kTrueValueRootIndex, eq);
1433     __ LoadRoot(r0, Heap::kFalseValueRootIndex, ne);
1434     __ Ret(HasArgsInRegisters() ? 0 : 2);
1435   }
1436 }
1437
1438
1439 void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
1440   Label miss;
1441   Register receiver = LoadDescriptor::ReceiverRegister();
1442   // Ensure that the vector and slot registers won't be clobbered before
1443   // calling the miss handler.
1444   DCHECK(!FLAG_vector_ics ||
1445          !AreAliased(r4, r5, VectorLoadICDescriptor::VectorRegister(),
1446                      VectorLoadICDescriptor::SlotRegister()));
1447
1448   NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, r4,
1449                                                           r5, &miss);
1450   __ bind(&miss);
1451   PropertyAccessCompiler::TailCallBuiltin(
1452       masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC));
1453 }
1454
1455
1456 void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
1457   // Return address is in lr.
1458   Label miss;
1459
1460   Register receiver = LoadDescriptor::ReceiverRegister();
1461   Register index = LoadDescriptor::NameRegister();
1462   Register scratch = r5;
1463   Register result = r0;
1464   DCHECK(!scratch.is(receiver) && !scratch.is(index));
1465   DCHECK(!FLAG_vector_ics ||
1466          (!scratch.is(VectorLoadICDescriptor::VectorRegister()) &&
1467           result.is(VectorLoadICDescriptor::SlotRegister())));
1468
1469   // StringCharAtGenerator doesn't use the result register until it's passed
1470   // the different miss possibilities. If it did, we would have a conflict
1471   // when FLAG_vector_ics is true.
1472   StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
1473                                           &miss,  // When not a string.
1474                                           &miss,  // When not a number.
1475                                           &miss,  // When index out of range.
1476                                           STRING_INDEX_IS_ARRAY_INDEX,
1477                                           RECEIVER_IS_STRING);
1478   char_at_generator.GenerateFast(masm);
1479   __ Ret();
1480
1481   StubRuntimeCallHelper call_helper;
1482   char_at_generator.GenerateSlow(masm, call_helper);
1483
1484   __ bind(&miss);
1485   PropertyAccessCompiler::TailCallBuiltin(
1486       masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
1487 }
1488
1489
1490 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
1491   CHECK(!has_new_target());
1492   // The displacement is the offset of the last parameter (if any)
1493   // relative to the frame pointer.
1494   const int kDisplacement =
1495       StandardFrameConstants::kCallerSPOffset - kPointerSize;
1496   DCHECK(r1.is(ArgumentsAccessReadDescriptor::index()));
1497   DCHECK(r0.is(ArgumentsAccessReadDescriptor::parameter_count()));
1498
1499   // Check that the key is a smi.
1500   Label slow;
1501   __ JumpIfNotSmi(r1, &slow);
1502
1503   // Check if the calling frame is an arguments adaptor frame.
1504   Label adaptor;
1505   __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
1506   __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
1507   __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1508   __ b(eq, &adaptor);
1509
1510   // Check index against formal parameters count limit passed in
1511   // through register r0. Use unsigned comparison to get negative
1512   // check for free.
1513   __ cmp(r1, r0);
1514   __ b(hs, &slow);
1515
1516   // Read the argument from the stack and return it.
1517   __ sub(r3, r0, r1);
1518   __ add(r3, fp, Operand::PointerOffsetFromSmiKey(r3));
1519   __ ldr(r0, MemOperand(r3, kDisplacement));
1520   __ Jump(lr);
1521
1522   // Arguments adaptor case: Check index against actual arguments
1523   // limit found in the arguments adaptor frame. Use unsigned
1524   // comparison to get negative check for free.
1525   __ bind(&adaptor);
1526   __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
1527   __ cmp(r1, r0);
1528   __ b(cs, &slow);
1529
1530   // Read the argument from the adaptor frame and return it.
1531   __ sub(r3, r0, r1);
1532   __ add(r3, r2, Operand::PointerOffsetFromSmiKey(r3));
1533   __ ldr(r0, MemOperand(r3, kDisplacement));
1534   __ Jump(lr);
1535
1536   // Slow-case: Handle non-smi or out-of-bounds access to arguments
1537   // by calling the runtime system.
1538   __ bind(&slow);
1539   __ push(r1);
1540   __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1);
1541 }
1542
1543
1544 void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) {
1545   // sp[0] : number of parameters
1546   // sp[4] : receiver displacement
1547   // sp[8] : function
1548
1549   CHECK(!has_new_target());
1550
1551   // Check if the calling frame is an arguments adaptor frame.
1552   Label runtime;
1553   __ ldr(r3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
1554   __ ldr(r2, MemOperand(r3, StandardFrameConstants::kContextOffset));
1555   __ cmp(r2, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1556   __ b(ne, &runtime);
1557
1558   // Patch the arguments.length and the parameters pointer in the current frame.
1559   __ ldr(r2, MemOperand(r3, ArgumentsAdaptorFrameConstants::kLengthOffset));
1560   __ str(r2, MemOperand(sp, 0 * kPointerSize));
1561   __ add(r3, r3, Operand(r2, LSL, 1));
1562   __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset));
1563   __ str(r3, MemOperand(sp, 1 * kPointerSize));
1564
1565   __ bind(&runtime);
1566   __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1);
1567 }
1568
1569
1570 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
1571   // Stack layout:
1572   //  sp[0] : number of parameters (tagged)
1573   //  sp[4] : address of receiver argument
1574   //  sp[8] : function
1575   // Registers used over whole function:
1576   //  r6 : allocated object (tagged)
1577   //  r9 : mapped parameter count (tagged)
1578
1579   CHECK(!has_new_target());
1580
1581   __ ldr(r1, MemOperand(sp, 0 * kPointerSize));
1582   // r1 = parameter count (tagged)
1583
1584   // Check if the calling frame is an arguments adaptor frame.
1585   Label runtime;
1586   Label adaptor_frame, try_allocate;
1587   __ ldr(r3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
1588   __ ldr(r2, MemOperand(r3, StandardFrameConstants::kContextOffset));
1589   __ cmp(r2, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1590   __ b(eq, &adaptor_frame);
1591
1592   // No adaptor, parameter count = argument count.
1593   __ mov(r2, r1);
1594   __ b(&try_allocate);
1595
1596   // We have an adaptor frame. Patch the parameters pointer.
1597   __ bind(&adaptor_frame);
1598   __ ldr(r2, MemOperand(r3, ArgumentsAdaptorFrameConstants::kLengthOffset));
1599   __ add(r3, r3, Operand(r2, LSL, 1));
1600   __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset));
1601   __ str(r3, MemOperand(sp, 1 * kPointerSize));
1602
1603   // r1 = parameter count (tagged)
1604   // r2 = argument count (tagged)
1605   // Compute the mapped parameter count = min(r1, r2) in r1.
1606   __ cmp(r1, Operand(r2));
1607   __ mov(r1, Operand(r2), LeaveCC, gt);
1608
1609   __ bind(&try_allocate);
1610
1611   // Compute the sizes of backing store, parameter map, and arguments object.
1612   // 1. Parameter map, has 2 extra words containing context and backing store.
1613   const int kParameterMapHeaderSize =
1614       FixedArray::kHeaderSize + 2 * kPointerSize;
1615   // If there are no mapped parameters, we do not need the parameter_map.
1616   __ cmp(r1, Operand(Smi::FromInt(0)));
1617   __ mov(r9, Operand::Zero(), LeaveCC, eq);
1618   __ mov(r9, Operand(r1, LSL, 1), LeaveCC, ne);
1619   __ add(r9, r9, Operand(kParameterMapHeaderSize), LeaveCC, ne);
1620
1621   // 2. Backing store.
1622   __ add(r9, r9, Operand(r2, LSL, 1));
1623   __ add(r9, r9, Operand(FixedArray::kHeaderSize));
1624
1625   // 3. Arguments object.
1626   __ add(r9, r9, Operand(Heap::kSloppyArgumentsObjectSize));
1627
1628   // Do the allocation of all three objects in one go.
1629   __ Allocate(r9, r0, r3, r4, &runtime, TAG_OBJECT);
1630
1631   // r0 = address of new object(s) (tagged)
1632   // r2 = argument count (smi-tagged)
1633   // Get the arguments boilerplate from the current native context into r4.
1634   const int kNormalOffset =
1635       Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX);
1636   const int kAliasedOffset =
1637       Context::SlotOffset(Context::ALIASED_ARGUMENTS_MAP_INDEX);
1638
1639   __ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
1640   __ ldr(r4, FieldMemOperand(r4, GlobalObject::kNativeContextOffset));
1641   __ cmp(r1, Operand::Zero());
1642   __ ldr(r4, MemOperand(r4, kNormalOffset), eq);
1643   __ ldr(r4, MemOperand(r4, kAliasedOffset), ne);
1644
1645   // r0 = address of new object (tagged)
1646   // r1 = mapped parameter count (tagged)
1647   // r2 = argument count (smi-tagged)
1648   // r4 = address of arguments map (tagged)
1649   __ str(r4, FieldMemOperand(r0, JSObject::kMapOffset));
1650   __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex);
1651   __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset));
1652   __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset));
1653
1654   // Set up the callee in-object property.
1655   STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
1656   __ ldr(r3, MemOperand(sp, 2 * kPointerSize));
1657   __ AssertNotSmi(r3);
1658   const int kCalleeOffset = JSObject::kHeaderSize +
1659       Heap::kArgumentsCalleeIndex * kPointerSize;
1660   __ str(r3, FieldMemOperand(r0, kCalleeOffset));
1661
1662   // Use the length (smi tagged) and set that as an in-object property too.
1663   __ AssertSmi(r2);
1664   STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
1665   const int kLengthOffset = JSObject::kHeaderSize +
1666       Heap::kArgumentsLengthIndex * kPointerSize;
1667   __ str(r2, FieldMemOperand(r0, kLengthOffset));
1668
1669   // Set up the elements pointer in the allocated arguments object.
1670   // If we allocated a parameter map, r4 will point there, otherwise
1671   // it will point to the backing store.
1672   __ add(r4, r0, Operand(Heap::kSloppyArgumentsObjectSize));
1673   __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
1674
1675   // r0 = address of new object (tagged)
1676   // r1 = mapped parameter count (tagged)
1677   // r2 = argument count (tagged)
1678   // r4 = address of parameter map or backing store (tagged)
1679   // Initialize parameter map. If there are no mapped arguments, we're done.
1680   Label skip_parameter_map;
1681   __ cmp(r1, Operand(Smi::FromInt(0)));
1682   // Move backing store address to r3, because it is
1683   // expected there when filling in the unmapped arguments.
1684   __ mov(r3, r4, LeaveCC, eq);
1685   __ b(eq, &skip_parameter_map);
1686
1687   __ LoadRoot(r6, Heap::kSloppyArgumentsElementsMapRootIndex);
1688   __ str(r6, FieldMemOperand(r4, FixedArray::kMapOffset));
1689   __ add(r6, r1, Operand(Smi::FromInt(2)));
1690   __ str(r6, FieldMemOperand(r4, FixedArray::kLengthOffset));
1691   __ str(cp, FieldMemOperand(r4, FixedArray::kHeaderSize + 0 * kPointerSize));
1692   __ add(r6, r4, Operand(r1, LSL, 1));
1693   __ add(r6, r6, Operand(kParameterMapHeaderSize));
1694   __ str(r6, FieldMemOperand(r4, FixedArray::kHeaderSize + 1 * kPointerSize));
1695
1696   // Copy the parameter slots and the holes in the arguments.
1697   // We need to fill in mapped_parameter_count slots. They index the context,
1698   // where parameters are stored in reverse order, at
1699   //   MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1
1700   // The mapped parameter thus need to get indices
1701   //   MIN_CONTEXT_SLOTS+parameter_count-1 ..
1702   //       MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count
1703   // We loop from right to left.
1704   Label parameters_loop, parameters_test;
1705   __ mov(r6, r1);
1706   __ ldr(r9, MemOperand(sp, 0 * kPointerSize));
1707   __ add(r9, r9, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS)));
1708   __ sub(r9, r9, Operand(r1));
1709   __ LoadRoot(r5, Heap::kTheHoleValueRootIndex);
1710   __ add(r3, r4, Operand(r6, LSL, 1));
1711   __ add(r3, r3, Operand(kParameterMapHeaderSize));
1712
1713   // r6 = loop variable (tagged)
1714   // r1 = mapping index (tagged)
1715   // r3 = address of backing store (tagged)
1716   // r4 = address of parameter map (tagged), which is also the address of new
1717   //      object + Heap::kSloppyArgumentsObjectSize (tagged)
1718   // r0 = temporary scratch (a.o., for address calculation)
1719   // r5 = the hole value
1720   __ jmp(&parameters_test);
1721
1722   __ bind(&parameters_loop);
1723   __ sub(r6, r6, Operand(Smi::FromInt(1)));
1724   __ mov(r0, Operand(r6, LSL, 1));
1725   __ add(r0, r0, Operand(kParameterMapHeaderSize - kHeapObjectTag));
1726   __ str(r9, MemOperand(r4, r0));
1727   __ sub(r0, r0, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize));
1728   __ str(r5, MemOperand(r3, r0));
1729   __ add(r9, r9, Operand(Smi::FromInt(1)));
1730   __ bind(&parameters_test);
1731   __ cmp(r6, Operand(Smi::FromInt(0)));
1732   __ b(ne, &parameters_loop);
1733
1734   // Restore r0 = new object (tagged)
1735   __ sub(r0, r4, Operand(Heap::kSloppyArgumentsObjectSize));
1736
1737   __ bind(&skip_parameter_map);
1738   // r0 = address of new object (tagged)
1739   // r2 = argument count (tagged)
1740   // r3 = address of backing store (tagged)
1741   // r5 = scratch
1742   // Copy arguments header and remaining slots (if there are any).
1743   __ LoadRoot(r5, Heap::kFixedArrayMapRootIndex);
1744   __ str(r5, FieldMemOperand(r3, FixedArray::kMapOffset));
1745   __ str(r2, FieldMemOperand(r3, FixedArray::kLengthOffset));
1746
1747   Label arguments_loop, arguments_test;
1748   __ mov(r9, r1);
1749   __ ldr(r4, MemOperand(sp, 1 * kPointerSize));
1750   __ sub(r4, r4, Operand(r9, LSL, 1));
1751   __ jmp(&arguments_test);
1752
1753   __ bind(&arguments_loop);
1754   __ sub(r4, r4, Operand(kPointerSize));
1755   __ ldr(r6, MemOperand(r4, 0));
1756   __ add(r5, r3, Operand(r9, LSL, 1));
1757   __ str(r6, FieldMemOperand(r5, FixedArray::kHeaderSize));
1758   __ add(r9, r9, Operand(Smi::FromInt(1)));
1759
1760   __ bind(&arguments_test);
1761   __ cmp(r9, Operand(r2));
1762   __ b(lt, &arguments_loop);
1763
1764   // Return and remove the on-stack parameters.
1765   __ add(sp, sp, Operand(3 * kPointerSize));
1766   __ Ret();
1767
1768   // Do the runtime call to allocate the arguments object.
1769   // r0 = address of new object (tagged)
1770   // r2 = argument count (tagged)
1771   __ bind(&runtime);
1772   __ str(r2, MemOperand(sp, 0 * kPointerSize));  // Patch argument count.
1773   __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1);
1774 }
1775
1776
1777 void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) {
1778   // Return address is in lr.
1779   Label slow;
1780
1781   Register receiver = LoadDescriptor::ReceiverRegister();
1782   Register key = LoadDescriptor::NameRegister();
1783
1784   // Check that the key is an array index, that is Uint32.
1785   __ NonNegativeSmiTst(key);
1786   __ b(ne, &slow);
1787
1788   // Everything is fine, call runtime.
1789   __ Push(receiver, key);  // Receiver, key.
1790
1791   // Perform tail call to the entry.
1792   __ TailCallExternalReference(
1793       ExternalReference(IC_Utility(IC::kLoadElementWithInterceptor),
1794                         masm->isolate()),
1795       2, 1);
1796
1797   __ bind(&slow);
1798   PropertyAccessCompiler::TailCallBuiltin(
1799       masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
1800 }
1801
1802
1803 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
1804   // sp[0] : number of parameters
1805   // sp[4] : receiver displacement
1806   // sp[8] : function
1807   // Check if the calling frame is an arguments adaptor frame.
1808   Label adaptor_frame, try_allocate, runtime;
1809   __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
1810   __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
1811   __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1812   __ b(eq, &adaptor_frame);
1813
1814   // Get the length from the frame.
1815   __ ldr(r1, MemOperand(sp, 0));
1816   __ b(&try_allocate);
1817
1818   // Patch the arguments.length and the parameters pointer.
1819   __ bind(&adaptor_frame);
1820   __ ldr(r1, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
1821   if (has_new_target()) {
1822     // Subtract 1 from smi-tagged arguments count.
1823     __ sub(r1, r1, Operand(2));
1824   }
1825   __ str(r1, MemOperand(sp, 0));
1826   __ add(r3, r2, Operand::PointerOffsetFromSmiKey(r1));
1827   __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset));
1828   __ str(r3, MemOperand(sp, 1 * kPointerSize));
1829
1830   // Try the new space allocation. Start out with computing the size
1831   // of the arguments object and the elements array in words.
1832   Label add_arguments_object;
1833   __ bind(&try_allocate);
1834   __ SmiUntag(r1, SetCC);
1835   __ b(eq, &add_arguments_object);
1836   __ add(r1, r1, Operand(FixedArray::kHeaderSize / kPointerSize));
1837   __ bind(&add_arguments_object);
1838   __ add(r1, r1, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize));
1839
1840   // Do the allocation of both objects in one go.
1841   __ Allocate(r1, r0, r2, r3, &runtime,
1842               static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
1843
1844   // Get the arguments boilerplate from the current native context.
1845   __ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
1846   __ ldr(r4, FieldMemOperand(r4, GlobalObject::kNativeContextOffset));
1847   __ ldr(r4, MemOperand(
1848                  r4, Context::SlotOffset(Context::STRICT_ARGUMENTS_MAP_INDEX)));
1849
1850   __ str(r4, FieldMemOperand(r0, JSObject::kMapOffset));
1851   __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex);
1852   __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset));
1853   __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset));
1854
1855   // Get the length (smi tagged) and set that as an in-object property too.
1856   STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
1857   __ ldr(r1, MemOperand(sp, 0 * kPointerSize));
1858   __ AssertSmi(r1);
1859   __ str(r1, FieldMemOperand(r0, JSObject::kHeaderSize +
1860       Heap::kArgumentsLengthIndex * kPointerSize));
1861
1862   // If there are no actual arguments, we're done.
1863   Label done;
1864   __ cmp(r1, Operand::Zero());
1865   __ b(eq, &done);
1866
1867   // Get the parameters pointer from the stack.
1868   __ ldr(r2, MemOperand(sp, 1 * kPointerSize));
1869
1870   // Set up the elements pointer in the allocated arguments object and
1871   // initialize the header in the elements fixed array.
1872   __ add(r4, r0, Operand(Heap::kStrictArgumentsObjectSize));
1873   __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
1874   __ LoadRoot(r3, Heap::kFixedArrayMapRootIndex);
1875   __ str(r3, FieldMemOperand(r4, FixedArray::kMapOffset));
1876   __ str(r1, FieldMemOperand(r4, FixedArray::kLengthOffset));
1877   __ SmiUntag(r1);
1878
1879   // Copy the fixed array slots.
1880   Label loop;
1881   // Set up r4 to point to the first array slot.
1882   __ add(r4, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
1883   __ bind(&loop);
1884   // Pre-decrement r2 with kPointerSize on each iteration.
1885   // Pre-decrement in order to skip receiver.
1886   __ ldr(r3, MemOperand(r2, kPointerSize, NegPreIndex));
1887   // Post-increment r4 with kPointerSize on each iteration.
1888   __ str(r3, MemOperand(r4, kPointerSize, PostIndex));
1889   __ sub(r1, r1, Operand(1));
1890   __ cmp(r1, Operand::Zero());
1891   __ b(ne, &loop);
1892
1893   // Return and remove the on-stack parameters.
1894   __ bind(&done);
1895   __ add(sp, sp, Operand(3 * kPointerSize));
1896   __ Ret();
1897
1898   // Do the runtime call to allocate the arguments object.
1899   __ bind(&runtime);
1900   __ TailCallRuntime(Runtime::kNewStrictArguments, 3, 1);
1901 }
1902
1903
1904 void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
1905   // Stack layout on entry.
1906   //  sp[0] : index of rest parameter
1907   //  sp[4] : number of parameters
1908   //  sp[8] : receiver displacement
1909
1910   Label runtime;
1911   __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
1912   __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
1913   __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1914   __ b(ne, &runtime);
1915
1916   // Patch the arguments.length and the parameters pointer.
1917   __ ldr(r1, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
1918   __ str(r1, MemOperand(sp, 1 * kPointerSize));
1919   __ add(r3, r2, Operand::PointerOffsetFromSmiKey(r1));
1920   __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset));
1921   __ str(r3, MemOperand(sp, 2 * kPointerSize));
1922
1923   __ bind(&runtime);
1924   __ TailCallRuntime(Runtime::kNewRestParam, 3, 1);
1925 }
1926
1927
1928 void RegExpExecStub::Generate(MacroAssembler* masm) {
1929   // Just jump directly to runtime if native RegExp is not selected at compile
1930   // time or if regexp entry in generated code is turned off runtime switch or
1931   // at compilation.
1932 #ifdef V8_INTERPRETED_REGEXP
1933   __ TailCallRuntime(Runtime::kRegExpExecRT, 4, 1);
1934 #else  // V8_INTERPRETED_REGEXP
1935
1936   // Stack frame on entry.
1937   //  sp[0]: last_match_info (expected JSArray)
1938   //  sp[4]: previous index
1939   //  sp[8]: subject string
1940   //  sp[12]: JSRegExp object
1941
1942   const int kLastMatchInfoOffset = 0 * kPointerSize;
1943   const int kPreviousIndexOffset = 1 * kPointerSize;
1944   const int kSubjectOffset = 2 * kPointerSize;
1945   const int kJSRegExpOffset = 3 * kPointerSize;
1946
1947   Label runtime;
1948   // Allocation of registers for this function. These are in callee save
1949   // registers and will be preserved by the call to the native RegExp code, as
1950   // this code is called using the normal C calling convention. When calling
1951   // directly from generated code the native RegExp code will not do a GC and
1952   // therefore the content of these registers are safe to use after the call.
1953   Register subject = r4;
1954   Register regexp_data = r5;
1955   Register last_match_info_elements = no_reg;  // will be r6;
1956
1957   // Ensure that a RegExp stack is allocated.
1958   ExternalReference address_of_regexp_stack_memory_address =
1959       ExternalReference::address_of_regexp_stack_memory_address(isolate());
1960   ExternalReference address_of_regexp_stack_memory_size =
1961       ExternalReference::address_of_regexp_stack_memory_size(isolate());
1962   __ mov(r0, Operand(address_of_regexp_stack_memory_size));
1963   __ ldr(r0, MemOperand(r0, 0));
1964   __ cmp(r0, Operand::Zero());
1965   __ b(eq, &runtime);
1966
1967   // Check that the first argument is a JSRegExp object.
1968   __ ldr(r0, MemOperand(sp, kJSRegExpOffset));
1969   __ JumpIfSmi(r0, &runtime);
1970   __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
1971   __ b(ne, &runtime);
1972
1973   // Check that the RegExp has been compiled (data contains a fixed array).
1974   __ ldr(regexp_data, FieldMemOperand(r0, JSRegExp::kDataOffset));
1975   if (FLAG_debug_code) {
1976     __ SmiTst(regexp_data);
1977     __ Check(ne, kUnexpectedTypeForRegExpDataFixedArrayExpected);
1978     __ CompareObjectType(regexp_data, r0, r0, FIXED_ARRAY_TYPE);
1979     __ Check(eq, kUnexpectedTypeForRegExpDataFixedArrayExpected);
1980   }
1981
1982   // regexp_data: RegExp data (FixedArray)
1983   // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
1984   __ ldr(r0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset));
1985   __ cmp(r0, Operand(Smi::FromInt(JSRegExp::IRREGEXP)));
1986   __ b(ne, &runtime);
1987
1988   // regexp_data: RegExp data (FixedArray)
1989   // Check that the number of captures fit in the static offsets vector buffer.
1990   __ ldr(r2,
1991          FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
1992   // Check (number_of_captures + 1) * 2 <= offsets vector size
1993   // Or          number_of_captures * 2 <= offsets vector size - 2
1994   // Multiplying by 2 comes for free since r2 is smi-tagged.
1995   STATIC_ASSERT(kSmiTag == 0);
1996   STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
1997   STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2);
1998   __ cmp(r2, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize - 2));
1999   __ b(hi, &runtime);
2000
2001   // Reset offset for possibly sliced string.
2002   __ mov(r9, Operand::Zero());
2003   __ ldr(subject, MemOperand(sp, kSubjectOffset));
2004   __ JumpIfSmi(subject, &runtime);
2005   __ mov(r3, subject);  // Make a copy of the original subject string.
2006   __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
2007   __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
2008   // subject: subject string
2009   // r3: subject string
2010   // r0: subject string instance type
2011   // regexp_data: RegExp data (FixedArray)
2012   // Handle subject string according to its encoding and representation:
2013   // (1) Sequential string?  If yes, go to (5).
2014   // (2) Anything but sequential or cons?  If yes, go to (6).
2015   // (3) Cons string.  If the string is flat, replace subject with first string.
2016   //     Otherwise bailout.
2017   // (4) Is subject external?  If yes, go to (7).
2018   // (5) Sequential string.  Load regexp code according to encoding.
2019   // (E) Carry on.
2020   /// [...]
2021
2022   // Deferred code at the end of the stub:
2023   // (6) Not a long external string?  If yes, go to (8).
2024   // (7) External string.  Make it, offset-wise, look like a sequential string.
2025   //     Go to (5).
2026   // (8) Short external string or not a string?  If yes, bail out to runtime.
2027   // (9) Sliced string.  Replace subject with parent.  Go to (4).
2028
2029   Label seq_string /* 5 */, external_string /* 7 */,
2030         check_underlying /* 4 */, not_seq_nor_cons /* 6 */,
2031         not_long_external /* 8 */;
2032
2033   // (1) Sequential string?  If yes, go to (5).
2034   __ and_(r1,
2035           r0,
2036           Operand(kIsNotStringMask |
2037                   kStringRepresentationMask |
2038                   kShortExternalStringMask),
2039           SetCC);
2040   STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
2041   __ b(eq, &seq_string);  // Go to (5).
2042
2043   // (2) Anything but sequential or cons?  If yes, go to (6).
2044   STATIC_ASSERT(kConsStringTag < kExternalStringTag);
2045   STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
2046   STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
2047   STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
2048   __ cmp(r1, Operand(kExternalStringTag));
2049   __ b(ge, &not_seq_nor_cons);  // Go to (6).
2050
2051   // (3) Cons string.  Check that it's flat.
2052   // Replace subject with first string and reload instance type.
2053   __ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset));
2054   __ CompareRoot(r0, Heap::kempty_stringRootIndex);
2055   __ b(ne, &runtime);
2056   __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
2057
2058   // (4) Is subject external?  If yes, go to (7).
2059   __ bind(&check_underlying);
2060   __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
2061   __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
2062   STATIC_ASSERT(kSeqStringTag == 0);
2063   __ tst(r0, Operand(kStringRepresentationMask));
2064   // The underlying external string is never a short external string.
2065   STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
2066   STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
2067   __ b(ne, &external_string);  // Go to (7).
2068
2069   // (5) Sequential string.  Load regexp code according to encoding.
2070   __ bind(&seq_string);
2071   // subject: sequential subject string (or look-alike, external string)
2072   // r3: original subject string
2073   // Load previous index and check range before r3 is overwritten.  We have to
2074   // use r3 instead of subject here because subject might have been only made
2075   // to look like a sequential string when it actually is an external string.
2076   __ ldr(r1, MemOperand(sp, kPreviousIndexOffset));
2077   __ JumpIfNotSmi(r1, &runtime);
2078   __ ldr(r3, FieldMemOperand(r3, String::kLengthOffset));
2079   __ cmp(r3, Operand(r1));
2080   __ b(ls, &runtime);
2081   __ SmiUntag(r1);
2082
2083   STATIC_ASSERT(4 == kOneByteStringTag);
2084   STATIC_ASSERT(kTwoByteStringTag == 0);
2085   __ and_(r0, r0, Operand(kStringEncodingMask));
2086   __ mov(r3, Operand(r0, ASR, 2), SetCC);
2087   __ ldr(r6, FieldMemOperand(regexp_data, JSRegExp::kDataOneByteCodeOffset),
2088          ne);
2089   __ ldr(r6, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq);
2090
2091   // (E) Carry on.  String handling is done.
2092   // r6: irregexp code
2093   // Check that the irregexp code has been generated for the actual string
2094   // encoding. If it has, the field contains a code object otherwise it contains
2095   // a smi (code flushing support).
2096   __ JumpIfSmi(r6, &runtime);
2097
2098   // r1: previous index
2099   // r3: encoding of subject string (1 if one_byte, 0 if two_byte);
2100   // r6: code
2101   // subject: Subject string
2102   // regexp_data: RegExp data (FixedArray)
2103   // All checks done. Now push arguments for native regexp code.
2104   __ IncrementCounter(isolate()->counters()->regexp_entry_native(), 1, r0, r2);
2105
2106   // Isolates: note we add an additional parameter here (isolate pointer).
2107   const int kRegExpExecuteArguments = 9;
2108   const int kParameterRegisters = 4;
2109   __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters);
2110
2111   // Stack pointer now points to cell where return address is to be written.
2112   // Arguments are before that on the stack or in registers.
2113
2114   // Argument 9 (sp[20]): Pass current isolate address.
2115   __ mov(r0, Operand(ExternalReference::isolate_address(isolate())));
2116   __ str(r0, MemOperand(sp, 5 * kPointerSize));
2117
2118   // Argument 8 (sp[16]): Indicate that this is a direct call from JavaScript.
2119   __ mov(r0, Operand(1));
2120   __ str(r0, MemOperand(sp, 4 * kPointerSize));
2121
2122   // Argument 7 (sp[12]): Start (high end) of backtracking stack memory area.
2123   __ mov(r0, Operand(address_of_regexp_stack_memory_address));
2124   __ ldr(r0, MemOperand(r0, 0));
2125   __ mov(r2, Operand(address_of_regexp_stack_memory_size));
2126   __ ldr(r2, MemOperand(r2, 0));
2127   __ add(r0, r0, Operand(r2));
2128   __ str(r0, MemOperand(sp, 3 * kPointerSize));
2129
2130   // Argument 6: Set the number of capture registers to zero to force global
2131   // regexps to behave as non-global.  This does not affect non-global regexps.
2132   __ mov(r0, Operand::Zero());
2133   __ str(r0, MemOperand(sp, 2 * kPointerSize));
2134
2135   // Argument 5 (sp[4]): static offsets vector buffer.
2136   __ mov(r0,
2137          Operand(ExternalReference::address_of_static_offsets_vector(
2138              isolate())));
2139   __ str(r0, MemOperand(sp, 1 * kPointerSize));
2140
2141   // For arguments 4 and 3 get string length, calculate start of string data and
2142   // calculate the shift of the index (0 for one-byte and 1 for two-byte).
2143   __ add(r7, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag));
2144   __ eor(r3, r3, Operand(1));
2145   // Load the length from the original subject string from the previous stack
2146   // frame. Therefore we have to use fp, which points exactly to two pointer
2147   // sizes below the previous sp. (Because creating a new stack frame pushes
2148   // the previous fp onto the stack and moves up sp by 2 * kPointerSize.)
2149   __ ldr(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize));
2150   // If slice offset is not 0, load the length from the original sliced string.
2151   // Argument 4, r3: End of string data
2152   // Argument 3, r2: Start of string data
2153   // Prepare start and end index of the input.
2154   __ add(r9, r7, Operand(r9, LSL, r3));
2155   __ add(r2, r9, Operand(r1, LSL, r3));
2156
2157   __ ldr(r7, FieldMemOperand(subject, String::kLengthOffset));
2158   __ SmiUntag(r7);
2159   __ add(r3, r9, Operand(r7, LSL, r3));
2160
2161   // Argument 2 (r1): Previous index.
2162   // Already there
2163
2164   // Argument 1 (r0): Subject string.
2165   __ mov(r0, subject);
2166
2167   // Locate the code entry and call it.
2168   __ add(r6, r6, Operand(Code::kHeaderSize - kHeapObjectTag));
2169   DirectCEntryStub stub(isolate());
2170   stub.GenerateCall(masm, r6);
2171
2172   __ LeaveExitFrame(false, no_reg, true);
2173
2174   last_match_info_elements = r6;
2175
2176   // r0: result
2177   // subject: subject string (callee saved)
2178   // regexp_data: RegExp data (callee saved)
2179   // last_match_info_elements: Last match info elements (callee saved)
2180   // Check the result.
2181   Label success;
2182   __ cmp(r0, Operand(1));
2183   // We expect exactly one result since we force the called regexp to behave
2184   // as non-global.
2185   __ b(eq, &success);
2186   Label failure;
2187   __ cmp(r0, Operand(NativeRegExpMacroAssembler::FAILURE));
2188   __ b(eq, &failure);
2189   __ cmp(r0, Operand(NativeRegExpMacroAssembler::EXCEPTION));
2190   // If not exception it can only be retry. Handle that in the runtime system.
2191   __ b(ne, &runtime);
2192   // Result must now be exception. If there is no pending exception already a
2193   // stack overflow (on the backtrack stack) was detected in RegExp code but
2194   // haven't created the exception yet. Handle that in the runtime system.
2195   // TODO(592): Rerunning the RegExp to get the stack overflow exception.
2196   __ mov(r1, Operand(isolate()->factory()->the_hole_value()));
2197   __ mov(r2, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
2198                                        isolate())));
2199   __ ldr(r0, MemOperand(r2, 0));
2200   __ cmp(r0, r1);
2201   __ b(eq, &runtime);
2202
2203   __ str(r1, MemOperand(r2, 0));  // Clear pending exception.
2204
2205   // Check if the exception is a termination. If so, throw as uncatchable.
2206   __ CompareRoot(r0, Heap::kTerminationExceptionRootIndex);
2207
2208   Label termination_exception;
2209   __ b(eq, &termination_exception);
2210
2211   __ Throw(r0);
2212
2213   __ bind(&termination_exception);
2214   __ ThrowUncatchable(r0);
2215
2216   __ bind(&failure);
2217   // For failure and exception return null.
2218   __ mov(r0, Operand(isolate()->factory()->null_value()));
2219   __ add(sp, sp, Operand(4 * kPointerSize));
2220   __ Ret();
2221
2222   // Process the result from the native regexp code.
2223   __ bind(&success);
2224   __ ldr(r1,
2225          FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
2226   // Calculate number of capture registers (number_of_captures + 1) * 2.
2227   // Multiplying by 2 comes for free since r1 is smi-tagged.
2228   STATIC_ASSERT(kSmiTag == 0);
2229   STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
2230   __ add(r1, r1, Operand(2));  // r1 was a smi.
2231
2232   __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset));
2233   __ JumpIfSmi(r0, &runtime);
2234   __ CompareObjectType(r0, r2, r2, JS_ARRAY_TYPE);
2235   __ b(ne, &runtime);
2236   // Check that the JSArray is in fast case.
2237   __ ldr(last_match_info_elements,
2238          FieldMemOperand(r0, JSArray::kElementsOffset));
2239   __ ldr(r0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset));
2240   __ CompareRoot(r0, Heap::kFixedArrayMapRootIndex);
2241   __ b(ne, &runtime);
2242   // Check that the last match info has space for the capture registers and the
2243   // additional information.
2244   __ ldr(r0,
2245          FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset));
2246   __ add(r2, r1, Operand(RegExpImpl::kLastMatchOverhead));
2247   __ cmp(r2, Operand::SmiUntag(r0));
2248   __ b(gt, &runtime);
2249
2250   // r1: number of capture registers
2251   // r4: subject string
2252   // Store the capture count.
2253   __ SmiTag(r2, r1);
2254   __ str(r2, FieldMemOperand(last_match_info_elements,
2255                              RegExpImpl::kLastCaptureCountOffset));
2256   // Store last subject and last input.
2257   __ str(subject,
2258          FieldMemOperand(last_match_info_elements,
2259                          RegExpImpl::kLastSubjectOffset));
2260   __ mov(r2, subject);
2261   __ RecordWriteField(last_match_info_elements,
2262                       RegExpImpl::kLastSubjectOffset,
2263                       subject,
2264                       r3,
2265                       kLRHasNotBeenSaved,
2266                       kDontSaveFPRegs);
2267   __ mov(subject, r2);
2268   __ str(subject,
2269          FieldMemOperand(last_match_info_elements,
2270                          RegExpImpl::kLastInputOffset));
2271   __ RecordWriteField(last_match_info_elements,
2272                       RegExpImpl::kLastInputOffset,
2273                       subject,
2274                       r3,
2275                       kLRHasNotBeenSaved,
2276                       kDontSaveFPRegs);
2277
2278   // Get the static offsets vector filled by the native regexp code.
2279   ExternalReference address_of_static_offsets_vector =
2280       ExternalReference::address_of_static_offsets_vector(isolate());
2281   __ mov(r2, Operand(address_of_static_offsets_vector));
2282
2283   // r1: number of capture registers
2284   // r2: offsets vector
2285   Label next_capture, done;
2286   // Capture register counter starts from number of capture registers and
2287   // counts down until wraping after zero.
2288   __ add(r0,
2289          last_match_info_elements,
2290          Operand(RegExpImpl::kFirstCaptureOffset - kHeapObjectTag));
2291   __ bind(&next_capture);
2292   __ sub(r1, r1, Operand(1), SetCC);
2293   __ b(mi, &done);
2294   // Read the value from the static offsets vector buffer.
2295   __ ldr(r3, MemOperand(r2, kPointerSize, PostIndex));
2296   // Store the smi value in the last match info.
2297   __ SmiTag(r3);
2298   __ str(r3, MemOperand(r0, kPointerSize, PostIndex));
2299   __ jmp(&next_capture);
2300   __ bind(&done);
2301
2302   // Return last match info.
2303   __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset));
2304   __ add(sp, sp, Operand(4 * kPointerSize));
2305   __ Ret();
2306
2307   // Do the runtime call to execute the regexp.
2308   __ bind(&runtime);
2309   __ TailCallRuntime(Runtime::kRegExpExecRT, 4, 1);
2310
2311   // Deferred code for string handling.
2312   // (6) Not a long external string?  If yes, go to (8).
2313   __ bind(&not_seq_nor_cons);
2314   // Compare flags are still set.
2315   __ b(gt, &not_long_external);  // Go to (8).
2316
2317   // (7) External string.  Make it, offset-wise, look like a sequential string.
2318   __ bind(&external_string);
2319   __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
2320   __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
2321   if (FLAG_debug_code) {
2322     // Assert that we do not have a cons or slice (indirect strings) here.
2323     // Sequential strings have already been ruled out.
2324     __ tst(r0, Operand(kIsIndirectStringMask));
2325     __ Assert(eq, kExternalStringExpectedButNotFound);
2326   }
2327   __ ldr(subject,
2328          FieldMemOperand(subject, ExternalString::kResourceDataOffset));
2329   // Move the pointer so that offset-wise, it looks like a sequential string.
2330   STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
2331   __ sub(subject,
2332          subject,
2333          Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
2334   __ jmp(&seq_string);    // Go to (5).
2335
2336   // (8) Short external string or not a string?  If yes, bail out to runtime.
2337   __ bind(&not_long_external);
2338   STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
2339   __ tst(r1, Operand(kIsNotStringMask | kShortExternalStringMask));
2340   __ b(ne, &runtime);
2341
2342   // (9) Sliced string.  Replace subject with parent.  Go to (4).
2343   // Load offset into r9 and replace subject string with parent.
2344   __ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset));
2345   __ SmiUntag(r9);
2346   __ ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
2347   __ jmp(&check_underlying);  // Go to (4).
2348 #endif  // V8_INTERPRETED_REGEXP
2349 }
2350
2351
2352 static void GenerateRecordCallTarget(MacroAssembler* masm) {
2353   // Cache the called function in a feedback vector slot.  Cache states
2354   // are uninitialized, monomorphic (indicated by a JSFunction), and
2355   // megamorphic.
2356   // r0 : number of arguments to the construct function
2357   // r1 : the function to call
2358   // r2 : Feedback vector
2359   // r3 : slot in feedback vector (Smi)
2360   Label initialize, done, miss, megamorphic, not_array_function;
2361
2362   DCHECK_EQ(*TypeFeedbackVector::MegamorphicSentinel(masm->isolate()),
2363             masm->isolate()->heap()->megamorphic_symbol());
2364   DCHECK_EQ(*TypeFeedbackVector::UninitializedSentinel(masm->isolate()),
2365             masm->isolate()->heap()->uninitialized_symbol());
2366
2367   // Load the cache state into r4.
2368   __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
2369   __ ldr(r4, FieldMemOperand(r4, FixedArray::kHeaderSize));
2370
2371   // A monomorphic cache hit or an already megamorphic state: invoke the
2372   // function without changing the state.
2373   __ cmp(r4, r1);
2374   __ b(eq, &done);
2375
2376   if (!FLAG_pretenuring_call_new) {
2377     // If we came here, we need to see if we are the array function.
2378     // If we didn't have a matching function, and we didn't find the megamorph
2379     // sentinel, then we have in the slot either some other function or an
2380     // AllocationSite. Do a map check on the object in ecx.
2381     __ ldr(r5, FieldMemOperand(r4, 0));
2382     __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex);
2383     __ b(ne, &miss);
2384
2385     // Make sure the function is the Array() function
2386     __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4);
2387     __ cmp(r1, r4);
2388     __ b(ne, &megamorphic);
2389     __ jmp(&done);
2390   }
2391
2392   __ bind(&miss);
2393
2394   // A monomorphic miss (i.e, here the cache is not uninitialized) goes
2395   // megamorphic.
2396   __ CompareRoot(r4, Heap::kuninitialized_symbolRootIndex);
2397   __ b(eq, &initialize);
2398   // MegamorphicSentinel is an immortal immovable object (undefined) so no
2399   // write-barrier is needed.
2400   __ bind(&megamorphic);
2401   __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
2402   __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex);
2403   __ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize));
2404   __ jmp(&done);
2405
2406   // An uninitialized cache is patched with the function
2407   __ bind(&initialize);
2408
2409   if (!FLAG_pretenuring_call_new) {
2410     // Make sure the function is the Array() function
2411     __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4);
2412     __ cmp(r1, r4);
2413     __ b(ne, &not_array_function);
2414
2415     // The target function is the Array constructor,
2416     // Create an AllocationSite if we don't already have it, store it in the
2417     // slot.
2418     {
2419       FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
2420
2421       // Arguments register must be smi-tagged to call out.
2422       __ SmiTag(r0);
2423       __ Push(r3, r2, r1, r0);
2424
2425       CreateAllocationSiteStub create_stub(masm->isolate());
2426       __ CallStub(&create_stub);
2427
2428       __ Pop(r3, r2, r1, r0);
2429       __ SmiUntag(r0);
2430     }
2431     __ b(&done);
2432
2433     __ bind(&not_array_function);
2434   }
2435
2436   __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
2437   __ add(r4, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
2438   __ str(r1, MemOperand(r4, 0));
2439
2440   __ Push(r4, r2, r1);
2441   __ RecordWrite(r2, r4, r1, kLRHasNotBeenSaved, kDontSaveFPRegs,
2442                  EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
2443   __ Pop(r4, r2, r1);
2444
2445   __ bind(&done);
2446 }
2447
2448
2449 static void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) {
2450   // Do not transform the receiver for strict mode functions.
2451   __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
2452   __ ldr(r4, FieldMemOperand(r3, SharedFunctionInfo::kCompilerHintsOffset));
2453   __ tst(r4, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
2454                            kSmiTagSize)));
2455   __ b(ne, cont);
2456
2457   // Do not transform the receiver for native (Compilerhints already in r3).
2458   __ tst(r4, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
2459   __ b(ne, cont);
2460 }
2461
2462
2463 static void EmitSlowCase(MacroAssembler* masm,
2464                          int argc,
2465                          Label* non_function) {
2466   // Check for function proxy.
2467   __ cmp(r4, Operand(JS_FUNCTION_PROXY_TYPE));
2468   __ b(ne, non_function);
2469   __ push(r1);  // put proxy as additional argument
2470   __ mov(r0, Operand(argc + 1, RelocInfo::NONE32));
2471   __ mov(r2, Operand::Zero());
2472   __ GetBuiltinFunction(r1, Builtins::CALL_FUNCTION_PROXY);
2473   {
2474     Handle<Code> adaptor =
2475         masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();
2476     __ Jump(adaptor, RelocInfo::CODE_TARGET);
2477   }
2478
2479   // CALL_NON_FUNCTION expects the non-function callee as receiver (instead
2480   // of the original receiver from the call site).
2481   __ bind(non_function);
2482   __ str(r1, MemOperand(sp, argc * kPointerSize));
2483   __ mov(r0, Operand(argc));  // Set up the number of arguments.
2484   __ mov(r2, Operand::Zero());
2485   __ GetBuiltinFunction(r1, Builtins::CALL_NON_FUNCTION);
2486   __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
2487           RelocInfo::CODE_TARGET);
2488 }
2489
2490
2491 static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
2492   // Wrap the receiver and patch it back onto the stack.
2493   { FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL);
2494     __ Push(r1, r3);
2495     __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
2496     __ pop(r1);
2497   }
2498   __ str(r0, MemOperand(sp, argc * kPointerSize));
2499   __ jmp(cont);
2500 }
2501
2502
2503 static void CallFunctionNoFeedback(MacroAssembler* masm,
2504                                    int argc, bool needs_checks,
2505                                    bool call_as_method) {
2506   // r1 : the function to call
2507   Label slow, non_function, wrap, cont;
2508
2509   if (needs_checks) {
2510     // Check that the function is really a JavaScript function.
2511     // r1: pushed function (to be verified)
2512     __ JumpIfSmi(r1, &non_function);
2513
2514     // Goto slow case if we do not have a function.
2515     __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE);
2516     __ b(ne, &slow);
2517   }
2518
2519   // Fast-case: Invoke the function now.
2520   // r1: pushed function
2521   ParameterCount actual(argc);
2522
2523   if (call_as_method) {
2524     if (needs_checks) {
2525       EmitContinueIfStrictOrNative(masm, &cont);
2526     }
2527
2528     // Compute the receiver in sloppy mode.
2529     __ ldr(r3, MemOperand(sp, argc * kPointerSize));
2530
2531     if (needs_checks) {
2532       __ JumpIfSmi(r3, &wrap);
2533       __ CompareObjectType(r3, r4, r4, FIRST_SPEC_OBJECT_TYPE);
2534       __ b(lt, &wrap);
2535     } else {
2536       __ jmp(&wrap);
2537     }
2538
2539     __ bind(&cont);
2540   }
2541
2542   __ InvokeFunction(r1, actual, JUMP_FUNCTION, NullCallWrapper());
2543
2544   if (needs_checks) {
2545     // Slow-case: Non-function called.
2546     __ bind(&slow);
2547     EmitSlowCase(masm, argc, &non_function);
2548   }
2549
2550   if (call_as_method) {
2551     __ bind(&wrap);
2552     EmitWrapCase(masm, argc, &cont);
2553   }
2554 }
2555
2556
2557 void CallFunctionStub::Generate(MacroAssembler* masm) {
2558   CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod());
2559 }
2560
2561
2562 void CallConstructStub::Generate(MacroAssembler* masm) {
2563   // r0 : number of arguments
2564   // r1 : the function to call
2565   // r2 : feedback vector
2566   // r3 : (only if r2 is not the megamorphic symbol) slot in feedback
2567   //      vector (Smi)
2568   Label slow, non_function_call;
2569
2570   // Check that the function is not a smi.
2571   __ JumpIfSmi(r1, &non_function_call);
2572   // Check that the function is a JSFunction.
2573   __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE);
2574   __ b(ne, &slow);
2575
2576   if (RecordCallTarget()) {
2577     GenerateRecordCallTarget(masm);
2578
2579     __ add(r5, r2, Operand::PointerOffsetFromSmiKey(r3));
2580     if (FLAG_pretenuring_call_new) {
2581       // Put the AllocationSite from the feedback vector into r2.
2582       // By adding kPointerSize we encode that we know the AllocationSite
2583       // entry is at the feedback vector slot given by r3 + 1.
2584       __ ldr(r2, FieldMemOperand(r5, FixedArray::kHeaderSize + kPointerSize));
2585     } else {
2586       Label feedback_register_initialized;
2587       // Put the AllocationSite from the feedback vector into r2, or undefined.
2588       __ ldr(r2, FieldMemOperand(r5, FixedArray::kHeaderSize));
2589       __ ldr(r5, FieldMemOperand(r2, AllocationSite::kMapOffset));
2590       __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex);
2591       __ b(eq, &feedback_register_initialized);
2592       __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
2593       __ bind(&feedback_register_initialized);
2594     }
2595
2596     __ AssertUndefinedOrAllocationSite(r2, r5);
2597   }
2598
2599   // Pass function as original constructor.
2600   if (IsSuperConstructorCall()) {
2601     __ mov(r4, Operand(1 * kPointerSize));
2602     __ add(r4, r4, Operand(r0, LSL, kPointerSizeLog2));
2603     __ ldr(r3, MemOperand(sp, r4));
2604   } else {
2605     __ mov(r3, r1);
2606   }
2607
2608   // Jump to the function-specific construct stub.
2609   Register jmp_reg = r4;
2610   __ ldr(jmp_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
2611   __ ldr(jmp_reg, FieldMemOperand(jmp_reg,
2612                                   SharedFunctionInfo::kConstructStubOffset));
2613   __ add(pc, jmp_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
2614
2615   // r0: number of arguments
2616   // r1: called object
2617   // r4: object type
2618   Label do_call;
2619   __ bind(&slow);
2620   __ cmp(r4, Operand(JS_FUNCTION_PROXY_TYPE));
2621   __ b(ne, &non_function_call);
2622   __ GetBuiltinFunction(r1, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
2623   __ jmp(&do_call);
2624
2625   __ bind(&non_function_call);
2626   __ GetBuiltinFunction(r1, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
2627   __ bind(&do_call);
2628   // Set expected number of arguments to zero (not changing r0).
2629   __ mov(r2, Operand::Zero());
2630   __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
2631           RelocInfo::CODE_TARGET);
2632 }
2633
2634
2635 static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) {
2636   __ ldr(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
2637   __ ldr(vector, FieldMemOperand(vector,
2638                                  JSFunction::kSharedFunctionInfoOffset));
2639   __ ldr(vector, FieldMemOperand(vector,
2640                                  SharedFunctionInfo::kFeedbackVectorOffset));
2641 }
2642
2643
2644 void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
2645   // r1 - function
2646   // r3 - slot id
2647   // r2 - vector
2648   Label miss;
2649   int argc = arg_count();
2650   ParameterCount actual(argc);
2651
2652   __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4);
2653   __ cmp(r1, r4);
2654   __ b(ne, &miss);
2655
2656   __ mov(r0, Operand(arg_count()));
2657   __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
2658   __ ldr(r4, FieldMemOperand(r4, FixedArray::kHeaderSize));
2659
2660   // Verify that r4 contains an AllocationSite
2661   __ ldr(r5, FieldMemOperand(r4, HeapObject::kMapOffset));
2662   __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex);
2663   __ b(ne, &miss);
2664
2665   __ mov(r2, r4);
2666   __ mov(r3, r1);
2667   ArrayConstructorStub stub(masm->isolate(), arg_count());
2668   __ TailCallStub(&stub);
2669
2670   __ bind(&miss);
2671   GenerateMiss(masm);
2672
2673   // The slow case, we need this no matter what to complete a call after a miss.
2674   CallFunctionNoFeedback(masm,
2675                          arg_count(),
2676                          true,
2677                          CallAsMethod());
2678
2679   // Unreachable.
2680   __ stop("Unexpected code address");
2681 }
2682
2683
2684 void CallICStub::Generate(MacroAssembler* masm) {
2685   // r1 - function
2686   // r3 - slot id (Smi)
2687   // r2 - vector
2688   const int with_types_offset =
2689       FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex);
2690   const int generic_offset =
2691       FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex);
2692   Label extra_checks_or_miss, slow_start;
2693   Label slow, non_function, wrap, cont;
2694   Label have_js_function;
2695   int argc = arg_count();
2696   ParameterCount actual(argc);
2697
2698   // The checks. First, does r1 match the recorded monomorphic target?
2699   __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
2700   __ ldr(r4, FieldMemOperand(r4, FixedArray::kHeaderSize));
2701
2702   // We don't know that we have a weak cell. We might have a private symbol
2703   // or an AllocationSite, but the memory is safe to examine.
2704   // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to
2705   // FixedArray.
2706   // WeakCell::kValueOffset - contains a JSFunction or Smi(0)
2707   // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not
2708   // computed, meaning that it can't appear to be a pointer. If the low bit is
2709   // 0, then hash is computed, but the 0 bit prevents the field from appearing
2710   // to be a pointer.
2711   STATIC_ASSERT(WeakCell::kSize >= kPointerSize);
2712   STATIC_ASSERT(AllocationSite::kTransitionInfoOffset ==
2713                     WeakCell::kValueOffset &&
2714                 WeakCell::kValueOffset == Symbol::kHashFieldSlot);
2715
2716   __ ldr(r5, FieldMemOperand(r4, WeakCell::kValueOffset));
2717   __ cmp(r1, r5);
2718   __ b(ne, &extra_checks_or_miss);
2719
2720   // The compare above could have been a SMI/SMI comparison. Guard against this
2721   // convincing us that we have a monomorphic JSFunction.
2722   __ JumpIfSmi(r1, &extra_checks_or_miss);
2723
2724   __ bind(&have_js_function);
2725   if (CallAsMethod()) {
2726     EmitContinueIfStrictOrNative(masm, &cont);
2727     // Compute the receiver in sloppy mode.
2728     __ ldr(r3, MemOperand(sp, argc * kPointerSize));
2729
2730     __ JumpIfSmi(r3, &wrap);
2731     __ CompareObjectType(r3, r4, r4, FIRST_SPEC_OBJECT_TYPE);
2732     __ b(lt, &wrap);
2733
2734     __ bind(&cont);
2735   }
2736
2737   __ InvokeFunction(r1, actual, JUMP_FUNCTION, NullCallWrapper());
2738
2739   __ bind(&slow);
2740   EmitSlowCase(masm, argc, &non_function);
2741
2742   if (CallAsMethod()) {
2743     __ bind(&wrap);
2744     EmitWrapCase(masm, argc, &cont);
2745   }
2746
2747   __ bind(&extra_checks_or_miss);
2748   Label uninitialized, miss;
2749
2750   __ CompareRoot(r4, Heap::kmegamorphic_symbolRootIndex);
2751   __ b(eq, &slow_start);
2752
2753   // The following cases attempt to handle MISS cases without going to the
2754   // runtime.
2755   if (FLAG_trace_ic) {
2756     __ jmp(&miss);
2757   }
2758
2759   __ CompareRoot(r4, Heap::kuninitialized_symbolRootIndex);
2760   __ b(eq, &uninitialized);
2761
2762   // We are going megamorphic. If the feedback is a JSFunction, it is fine
2763   // to handle it here. More complex cases are dealt with in the runtime.
2764   __ AssertNotSmi(r4);
2765   __ CompareObjectType(r4, r5, r5, JS_FUNCTION_TYPE);
2766   __ b(ne, &miss);
2767   __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
2768   __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex);
2769   __ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize));
2770   // We have to update statistics for runtime profiling.
2771   __ ldr(r4, FieldMemOperand(r2, with_types_offset));
2772   __ sub(r4, r4, Operand(Smi::FromInt(1)));
2773   __ str(r4, FieldMemOperand(r2, with_types_offset));
2774   __ ldr(r4, FieldMemOperand(r2, generic_offset));
2775   __ add(r4, r4, Operand(Smi::FromInt(1)));
2776   __ str(r4, FieldMemOperand(r2, generic_offset));
2777   __ jmp(&slow_start);
2778
2779   __ bind(&uninitialized);
2780
2781   // We are going monomorphic, provided we actually have a JSFunction.
2782   __ JumpIfSmi(r1, &miss);
2783
2784   // Goto miss case if we do not have a function.
2785   __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE);
2786   __ b(ne, &miss);
2787
2788   // Make sure the function is not the Array() function, which requires special
2789   // behavior on MISS.
2790   __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4);
2791   __ cmp(r1, r4);
2792   __ b(eq, &miss);
2793
2794   // Update stats.
2795   __ ldr(r4, FieldMemOperand(r2, with_types_offset));
2796   __ add(r4, r4, Operand(Smi::FromInt(1)));
2797   __ str(r4, FieldMemOperand(r2, with_types_offset));
2798
2799   // Store the function. Use a stub since we need a frame for allocation.
2800   // r2 - vector
2801   // r3 - slot
2802   // r1 - function
2803   {
2804     FrameScope scope(masm, StackFrame::INTERNAL);
2805     CreateWeakCellStub create_stub(masm->isolate());
2806     __ Push(r1);
2807     __ CallStub(&create_stub);
2808     __ Pop(r1);
2809   }
2810
2811   __ jmp(&have_js_function);
2812
2813   // We are here because tracing is on or we encountered a MISS case we can't
2814   // handle here.
2815   __ bind(&miss);
2816   GenerateMiss(masm);
2817
2818   // the slow case
2819   __ bind(&slow_start);
2820   // Check that the function is really a JavaScript function.
2821   // r1: pushed function (to be verified)
2822   __ JumpIfSmi(r1, &non_function);
2823
2824   // Goto slow case if we do not have a function.
2825   __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE);
2826   __ b(ne, &slow);
2827   __ jmp(&have_js_function);
2828 }
2829
2830
2831 void CallICStub::GenerateMiss(MacroAssembler* masm) {
2832   FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
2833
2834   // Push the receiver and the function and feedback info.
2835   __ Push(r1, r2, r3);
2836
2837   // Call the entry.
2838   IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss
2839                                              : IC::kCallIC_Customization_Miss;
2840
2841   ExternalReference miss = ExternalReference(IC_Utility(id), masm->isolate());
2842   __ CallExternalReference(miss, 3);
2843
2844   // Move result to edi and exit the internal frame.
2845   __ mov(r1, r0);
2846 }
2847
2848
2849 // StringCharCodeAtGenerator
2850 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
2851   // If the receiver is a smi trigger the non-string case.
2852   if (check_mode_ == RECEIVER_IS_UNKNOWN) {
2853     __ JumpIfSmi(object_, receiver_not_string_);
2854
2855     // Fetch the instance type of the receiver into result register.
2856     __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
2857     __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
2858     // If the receiver is not a string trigger the non-string case.
2859     __ tst(result_, Operand(kIsNotStringMask));
2860     __ b(ne, receiver_not_string_);
2861   }
2862
2863   // If the index is non-smi trigger the non-smi case.
2864   __ JumpIfNotSmi(index_, &index_not_smi_);
2865   __ bind(&got_smi_index_);
2866
2867   // Check for index out of range.
2868   __ ldr(ip, FieldMemOperand(object_, String::kLengthOffset));
2869   __ cmp(ip, Operand(index_));
2870   __ b(ls, index_out_of_range_);
2871
2872   __ SmiUntag(index_);
2873
2874   StringCharLoadGenerator::Generate(masm,
2875                                     object_,
2876                                     index_,
2877                                     result_,
2878                                     &call_runtime_);
2879
2880   __ SmiTag(result_);
2881   __ bind(&exit_);
2882 }
2883
2884
2885 void StringCharCodeAtGenerator::GenerateSlow(
2886     MacroAssembler* masm,
2887     const RuntimeCallHelper& call_helper) {
2888   __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase);
2889
2890   // Index is not a smi.
2891   __ bind(&index_not_smi_);
2892   // If index is a heap number, try converting it to an integer.
2893   __ CheckMap(index_,
2894               result_,
2895               Heap::kHeapNumberMapRootIndex,
2896               index_not_number_,
2897               DONT_DO_SMI_CHECK);
2898   call_helper.BeforeCall(masm);
2899   __ push(object_);
2900   __ push(index_);  // Consumed by runtime conversion function.
2901   if (index_flags_ == STRING_INDEX_IS_NUMBER) {
2902     __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
2903   } else {
2904     DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
2905     // NumberToSmi discards numbers that are not exact integers.
2906     __ CallRuntime(Runtime::kNumberToSmi, 1);
2907   }
2908   // Save the conversion result before the pop instructions below
2909   // have a chance to overwrite it.
2910   __ Move(index_, r0);
2911   __ pop(object_);
2912   // Reload the instance type.
2913   __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
2914   __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
2915   call_helper.AfterCall(masm);
2916   // If index is still not a smi, it must be out of range.
2917   __ JumpIfNotSmi(index_, index_out_of_range_);
2918   // Otherwise, return to the fast path.
2919   __ jmp(&got_smi_index_);
2920
2921   // Call runtime. We get here when the receiver is a string and the
2922   // index is a number, but the code of getting the actual character
2923   // is too complex (e.g., when the string needs to be flattened).
2924   __ bind(&call_runtime_);
2925   call_helper.BeforeCall(masm);
2926   __ SmiTag(index_);
2927   __ Push(object_, index_);
2928   __ CallRuntime(Runtime::kStringCharCodeAtRT, 2);
2929   __ Move(result_, r0);
2930   call_helper.AfterCall(masm);
2931   __ jmp(&exit_);
2932
2933   __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
2934 }
2935
2936
2937 // -------------------------------------------------------------------------
2938 // StringCharFromCodeGenerator
2939
2940 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
2941   // Fast case of Heap::LookupSingleCharacterStringFromCode.
2942   STATIC_ASSERT(kSmiTag == 0);
2943   STATIC_ASSERT(kSmiShiftSize == 0);
2944   DCHECK(base::bits::IsPowerOfTwo32(String::kMaxOneByteCharCode + 1));
2945   __ tst(code_,
2946          Operand(kSmiTagMask |
2947                  ((~String::kMaxOneByteCharCode) << kSmiTagSize)));
2948   __ b(ne, &slow_case_);
2949
2950   __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
2951   // At this point code register contains smi tagged one-byte char code.
2952   __ add(result_, result_, Operand::PointerOffsetFromSmiKey(code_));
2953   __ ldr(result_, FieldMemOperand(result_, FixedArray::kHeaderSize));
2954   __ CompareRoot(result_, Heap::kUndefinedValueRootIndex);
2955   __ b(eq, &slow_case_);
2956   __ bind(&exit_);
2957 }
2958
2959
2960 void StringCharFromCodeGenerator::GenerateSlow(
2961     MacroAssembler* masm,
2962     const RuntimeCallHelper& call_helper) {
2963   __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
2964
2965   __ bind(&slow_case_);
2966   call_helper.BeforeCall(masm);
2967   __ push(code_);
2968   __ CallRuntime(Runtime::kCharFromCode, 1);
2969   __ Move(result_, r0);
2970   call_helper.AfterCall(masm);
2971   __ jmp(&exit_);
2972
2973   __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
2974 }
2975
2976
2977 enum CopyCharactersFlags { COPY_ONE_BYTE = 1, DEST_ALWAYS_ALIGNED = 2 };
2978
2979
2980 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
2981                                           Register dest,
2982                                           Register src,
2983                                           Register count,
2984                                           Register scratch,
2985                                           String::Encoding encoding) {
2986   if (FLAG_debug_code) {
2987     // Check that destination is word aligned.
2988     __ tst(dest, Operand(kPointerAlignmentMask));
2989     __ Check(eq, kDestinationOfCopyNotAligned);
2990   }
2991
2992   // Assumes word reads and writes are little endian.
2993   // Nothing to do for zero characters.
2994   Label done;
2995   if (encoding == String::TWO_BYTE_ENCODING) {
2996     __ add(count, count, Operand(count), SetCC);
2997   }
2998
2999   Register limit = count;  // Read until dest equals this.
3000   __ add(limit, dest, Operand(count));
3001
3002   Label loop_entry, loop;
3003   // Copy bytes from src to dest until dest hits limit.
3004   __ b(&loop_entry);
3005   __ bind(&loop);
3006   __ ldrb(scratch, MemOperand(src, 1, PostIndex), lt);
3007   __ strb(scratch, MemOperand(dest, 1, PostIndex));
3008   __ bind(&loop_entry);
3009   __ cmp(dest, Operand(limit));
3010   __ b(lt, &loop);
3011
3012   __ bind(&done);
3013 }
3014
3015
3016 void SubStringStub::Generate(MacroAssembler* masm) {
3017   Label runtime;
3018
3019   // Stack frame on entry.
3020   //  lr: return address
3021   //  sp[0]: to
3022   //  sp[4]: from
3023   //  sp[8]: string
3024
3025   // This stub is called from the native-call %_SubString(...), so
3026   // nothing can be assumed about the arguments. It is tested that:
3027   //  "string" is a sequential string,
3028   //  both "from" and "to" are smis, and
3029   //  0 <= from <= to <= string.length.
3030   // If any of these assumptions fail, we call the runtime system.
3031
3032   const int kToOffset = 0 * kPointerSize;
3033   const int kFromOffset = 1 * kPointerSize;
3034   const int kStringOffset = 2 * kPointerSize;
3035
3036   __ Ldrd(r2, r3, MemOperand(sp, kToOffset));
3037   STATIC_ASSERT(kFromOffset == kToOffset + 4);
3038   STATIC_ASSERT(kSmiTag == 0);
3039   STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
3040
3041   // Arithmetic shift right by one un-smi-tags. In this case we rotate right
3042   // instead because we bail out on non-smi values: ROR and ASR are equivalent
3043   // for smis but they set the flags in a way that's easier to optimize.
3044   __ mov(r2, Operand(r2, ROR, 1), SetCC);
3045   __ mov(r3, Operand(r3, ROR, 1), SetCC, cc);
3046   // If either to or from had the smi tag bit set, then C is set now, and N
3047   // has the same value: we rotated by 1, so the bottom bit is now the top bit.
3048   // We want to bailout to runtime here if From is negative.  In that case, the
3049   // next instruction is not executed and we fall through to bailing out to
3050   // runtime.
3051   // Executed if both r2 and r3 are untagged integers.
3052   __ sub(r2, r2, Operand(r3), SetCC, cc);
3053   // One of the above un-smis or the above SUB could have set N==1.
3054   __ b(mi, &runtime);  // Either "from" or "to" is not an smi, or from > to.
3055
3056   // Make sure first argument is a string.
3057   __ ldr(r0, MemOperand(sp, kStringOffset));
3058   __ JumpIfSmi(r0, &runtime);
3059   Condition is_string = masm->IsObjectStringType(r0, r1);
3060   __ b(NegateCondition(is_string), &runtime);
3061
3062   Label single_char;
3063   __ cmp(r2, Operand(1));
3064   __ b(eq, &single_char);
3065
3066   // Short-cut for the case of trivial substring.
3067   Label return_r0;
3068   // r0: original string
3069   // r2: result string length
3070   __ ldr(r4, FieldMemOperand(r0, String::kLengthOffset));
3071   __ cmp(r2, Operand(r4, ASR, 1));
3072   // Return original string.
3073   __ b(eq, &return_r0);
3074   // Longer than original string's length or negative: unsafe arguments.
3075   __ b(hi, &runtime);
3076   // Shorter than original string's length: an actual substring.
3077
3078   // Deal with different string types: update the index if necessary
3079   // and put the underlying string into r5.
3080   // r0: original string
3081   // r1: instance type
3082   // r2: length
3083   // r3: from index (untagged)
3084   Label underlying_unpacked, sliced_string, seq_or_external_string;
3085   // If the string is not indirect, it can only be sequential or external.
3086   STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
3087   STATIC_ASSERT(kIsIndirectStringMask != 0);
3088   __ tst(r1, Operand(kIsIndirectStringMask));
3089   __ b(eq, &seq_or_external_string);
3090
3091   __ tst(r1, Operand(kSlicedNotConsMask));
3092   __ b(ne, &sliced_string);
3093   // Cons string.  Check whether it is flat, then fetch first part.
3094   __ ldr(r5, FieldMemOperand(r0, ConsString::kSecondOffset));
3095   __ CompareRoot(r5, Heap::kempty_stringRootIndex);
3096   __ b(ne, &runtime);
3097   __ ldr(r5, FieldMemOperand(r0, ConsString::kFirstOffset));
3098   // Update instance type.
3099   __ ldr(r1, FieldMemOperand(r5, HeapObject::kMapOffset));
3100   __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
3101   __ jmp(&underlying_unpacked);
3102
3103   __ bind(&sliced_string);
3104   // Sliced string.  Fetch parent and correct start index by offset.
3105   __ ldr(r5, FieldMemOperand(r0, SlicedString::kParentOffset));
3106   __ ldr(r4, FieldMemOperand(r0, SlicedString::kOffsetOffset));
3107   __ add(r3, r3, Operand(r4, ASR, 1));  // Add offset to index.
3108   // Update instance type.
3109   __ ldr(r1, FieldMemOperand(r5, HeapObject::kMapOffset));
3110   __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
3111   __ jmp(&underlying_unpacked);
3112
3113   __ bind(&seq_or_external_string);
3114   // Sequential or external string.  Just move string to the expected register.
3115   __ mov(r5, r0);
3116
3117   __ bind(&underlying_unpacked);
3118
3119   if (FLAG_string_slices) {
3120     Label copy_routine;
3121     // r5: underlying subject string
3122     // r1: instance type of underlying subject string
3123     // r2: length
3124     // r3: adjusted start index (untagged)
3125     __ cmp(r2, Operand(SlicedString::kMinLength));
3126     // Short slice.  Copy instead of slicing.
3127     __ b(lt, &copy_routine);
3128     // Allocate new sliced string.  At this point we do not reload the instance
3129     // type including the string encoding because we simply rely on the info
3130     // provided by the original string.  It does not matter if the original
3131     // string's encoding is wrong because we always have to recheck encoding of
3132     // the newly created string's parent anyways due to externalized strings.
3133     Label two_byte_slice, set_slice_header;
3134     STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
3135     STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
3136     __ tst(r1, Operand(kStringEncodingMask));
3137     __ b(eq, &two_byte_slice);
3138     __ AllocateOneByteSlicedString(r0, r2, r6, r4, &runtime);
3139     __ jmp(&set_slice_header);
3140     __ bind(&two_byte_slice);
3141     __ AllocateTwoByteSlicedString(r0, r2, r6, r4, &runtime);
3142     __ bind(&set_slice_header);
3143     __ mov(r3, Operand(r3, LSL, 1));
3144     __ str(r5, FieldMemOperand(r0, SlicedString::kParentOffset));
3145     __ str(r3, FieldMemOperand(r0, SlicedString::kOffsetOffset));
3146     __ jmp(&return_r0);
3147
3148     __ bind(&copy_routine);
3149   }
3150
3151   // r5: underlying subject string
3152   // r1: instance type of underlying subject string
3153   // r2: length
3154   // r3: adjusted start index (untagged)
3155   Label two_byte_sequential, sequential_string, allocate_result;
3156   STATIC_ASSERT(kExternalStringTag != 0);
3157   STATIC_ASSERT(kSeqStringTag == 0);
3158   __ tst(r1, Operand(kExternalStringTag));
3159   __ b(eq, &sequential_string);
3160
3161   // Handle external string.
3162   // Rule out short external strings.
3163   STATIC_ASSERT(kShortExternalStringTag != 0);
3164   __ tst(r1, Operand(kShortExternalStringTag));
3165   __ b(ne, &runtime);
3166   __ ldr(r5, FieldMemOperand(r5, ExternalString::kResourceDataOffset));
3167   // r5 already points to the first character of underlying string.
3168   __ jmp(&allocate_result);
3169
3170   __ bind(&sequential_string);
3171   // Locate first character of underlying subject string.
3172   STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
3173   __ add(r5, r5, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3174
3175   __ bind(&allocate_result);
3176   // Sequential acii string.  Allocate the result.
3177   STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0);
3178   __ tst(r1, Operand(kStringEncodingMask));
3179   __ b(eq, &two_byte_sequential);
3180
3181   // Allocate and copy the resulting one-byte string.
3182   __ AllocateOneByteString(r0, r2, r4, r6, r1, &runtime);
3183
3184   // Locate first character of substring to copy.
3185   __ add(r5, r5, r3);
3186   // Locate first character of result.
3187   __ add(r1, r0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3188
3189   // r0: result string
3190   // r1: first character of result string
3191   // r2: result string length
3192   // r5: first character of substring to copy
3193   STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
3194   StringHelper::GenerateCopyCharacters(
3195       masm, r1, r5, r2, r3, String::ONE_BYTE_ENCODING);
3196   __ jmp(&return_r0);
3197
3198   // Allocate and copy the resulting two-byte string.
3199   __ bind(&two_byte_sequential);
3200   __ AllocateTwoByteString(r0, r2, r4, r6, r1, &runtime);
3201
3202   // Locate first character of substring to copy.
3203   STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
3204   __ add(r5, r5, Operand(r3, LSL, 1));
3205   // Locate first character of result.
3206   __ add(r1, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
3207
3208   // r0: result string.
3209   // r1: first character of result.
3210   // r2: result length.
3211   // r5: first character of substring to copy.
3212   STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
3213   StringHelper::GenerateCopyCharacters(
3214       masm, r1, r5, r2, r3, String::TWO_BYTE_ENCODING);
3215
3216   __ bind(&return_r0);
3217   Counters* counters = isolate()->counters();
3218   __ IncrementCounter(counters->sub_string_native(), 1, r3, r4);
3219   __ Drop(3);
3220   __ Ret();
3221
3222   // Just jump to runtime to create the sub string.
3223   __ bind(&runtime);
3224   __ TailCallRuntime(Runtime::kSubString, 3, 1);
3225
3226   __ bind(&single_char);
3227   // r0: original string
3228   // r1: instance type
3229   // r2: length
3230   // r3: from index (untagged)
3231   __ SmiTag(r3, r3);
3232   StringCharAtGenerator generator(r0, r3, r2, r0, &runtime, &runtime, &runtime,
3233                                   STRING_INDEX_IS_NUMBER, RECEIVER_IS_STRING);
3234   generator.GenerateFast(masm);
3235   __ Drop(3);
3236   __ Ret();
3237   generator.SkipSlow(masm, &runtime);
3238 }
3239
3240
3241 void ToNumberStub::Generate(MacroAssembler* masm) {
3242   // The ToNumber stub takes one argument in r0.
3243   Label not_smi;
3244   __ JumpIfNotSmi(r0, &not_smi);
3245   __ Ret();
3246   __ bind(&not_smi);
3247
3248   Label not_heap_number;
3249   __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
3250   __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
3251   // r0: object
3252   // r1: instance type.
3253   __ cmp(r1, Operand(HEAP_NUMBER_TYPE));
3254   __ b(ne, &not_heap_number);
3255   __ Ret();
3256   __ bind(&not_heap_number);
3257
3258   Label not_string, slow_string;
3259   __ cmp(r1, Operand(FIRST_NONSTRING_TYPE));
3260   __ b(hs, &not_string);
3261   // Check if string has a cached array index.
3262   __ ldr(r2, FieldMemOperand(r0, String::kHashFieldOffset));
3263   __ tst(r2, Operand(String::kContainsCachedArrayIndexMask));
3264   __ b(ne, &slow_string);
3265   __ IndexFromHash(r2, r0);
3266   __ Ret();
3267   __ bind(&slow_string);
3268   __ push(r0);  // Push argument.
3269   __ TailCallRuntime(Runtime::kStringToNumber, 1, 1);
3270   __ bind(&not_string);
3271
3272   Label not_oddball;
3273   __ cmp(r1, Operand(ODDBALL_TYPE));
3274   __ b(ne, &not_oddball);
3275   __ ldr(r0, FieldMemOperand(r0, Oddball::kToNumberOffset));
3276   __ Ret();
3277   __ bind(&not_oddball);
3278
3279   __ push(r0);  // Push argument.
3280   __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION);
3281 }
3282
3283
3284 void StringHelper::GenerateFlatOneByteStringEquals(
3285     MacroAssembler* masm, Register left, Register right, Register scratch1,
3286     Register scratch2, Register scratch3) {
3287   Register length = scratch1;
3288
3289   // Compare lengths.
3290   Label strings_not_equal, check_zero_length;
3291   __ ldr(length, FieldMemOperand(left, String::kLengthOffset));
3292   __ ldr(scratch2, FieldMemOperand(right, String::kLengthOffset));
3293   __ cmp(length, scratch2);
3294   __ b(eq, &check_zero_length);
3295   __ bind(&strings_not_equal);
3296   __ mov(r0, Operand(Smi::FromInt(NOT_EQUAL)));
3297   __ Ret();
3298
3299   // Check if the length is zero.
3300   Label compare_chars;
3301   __ bind(&check_zero_length);
3302   STATIC_ASSERT(kSmiTag == 0);
3303   __ cmp(length, Operand::Zero());
3304   __ b(ne, &compare_chars);
3305   __ mov(r0, Operand(Smi::FromInt(EQUAL)));
3306   __ Ret();
3307
3308   // Compare characters.
3309   __ bind(&compare_chars);
3310   GenerateOneByteCharsCompareLoop(masm, left, right, length, scratch2, scratch3,
3311                                   &strings_not_equal);
3312
3313   // Characters are equal.
3314   __ mov(r0, Operand(Smi::FromInt(EQUAL)));
3315   __ Ret();
3316 }
3317
3318
3319 void StringHelper::GenerateCompareFlatOneByteStrings(
3320     MacroAssembler* masm, Register left, Register right, Register scratch1,
3321     Register scratch2, Register scratch3, Register scratch4) {
3322   Label result_not_equal, compare_lengths;
3323   // Find minimum length and length difference.
3324   __ ldr(scratch1, FieldMemOperand(left, String::kLengthOffset));
3325   __ ldr(scratch2, FieldMemOperand(right, String::kLengthOffset));
3326   __ sub(scratch3, scratch1, Operand(scratch2), SetCC);
3327   Register length_delta = scratch3;
3328   __ mov(scratch1, scratch2, LeaveCC, gt);
3329   Register min_length = scratch1;
3330   STATIC_ASSERT(kSmiTag == 0);
3331   __ cmp(min_length, Operand::Zero());
3332   __ b(eq, &compare_lengths);
3333
3334   // Compare loop.
3335   GenerateOneByteCharsCompareLoop(masm, left, right, min_length, scratch2,
3336                                   scratch4, &result_not_equal);
3337
3338   // Compare lengths - strings up to min-length are equal.
3339   __ bind(&compare_lengths);
3340   DCHECK(Smi::FromInt(EQUAL) == static_cast<Smi*>(0));
3341   // Use length_delta as result if it's zero.
3342   __ mov(r0, Operand(length_delta), SetCC);
3343   __ bind(&result_not_equal);
3344   // Conditionally update the result based either on length_delta or
3345   // the last comparion performed in the loop above.
3346   __ mov(r0, Operand(Smi::FromInt(GREATER)), LeaveCC, gt);
3347   __ mov(r0, Operand(Smi::FromInt(LESS)), LeaveCC, lt);
3348   __ Ret();
3349 }
3350
3351
3352 void StringHelper::GenerateOneByteCharsCompareLoop(
3353     MacroAssembler* masm, Register left, Register right, Register length,
3354     Register scratch1, Register scratch2, Label* chars_not_equal) {
3355   // Change index to run from -length to -1 by adding length to string
3356   // start. This means that loop ends when index reaches zero, which
3357   // doesn't need an additional compare.
3358   __ SmiUntag(length);
3359   __ add(scratch1, length,
3360          Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3361   __ add(left, left, Operand(scratch1));
3362   __ add(right, right, Operand(scratch1));
3363   __ rsb(length, length, Operand::Zero());
3364   Register index = length;  // index = -length;
3365
3366   // Compare loop.
3367   Label loop;
3368   __ bind(&loop);
3369   __ ldrb(scratch1, MemOperand(left, index));
3370   __ ldrb(scratch2, MemOperand(right, index));
3371   __ cmp(scratch1, scratch2);
3372   __ b(ne, chars_not_equal);
3373   __ add(index, index, Operand(1), SetCC);
3374   __ b(ne, &loop);
3375 }
3376
3377
3378 void StringCompareStub::Generate(MacroAssembler* masm) {
3379   Label runtime;
3380
3381   Counters* counters = isolate()->counters();
3382
3383   // Stack frame on entry.
3384   //  sp[0]: right string
3385   //  sp[4]: left string
3386   __ Ldrd(r0 , r1, MemOperand(sp));  // Load right in r0, left in r1.
3387
3388   Label not_same;
3389   __ cmp(r0, r1);
3390   __ b(ne, &not_same);
3391   STATIC_ASSERT(EQUAL == 0);
3392   STATIC_ASSERT(kSmiTag == 0);
3393   __ mov(r0, Operand(Smi::FromInt(EQUAL)));
3394   __ IncrementCounter(counters->string_compare_native(), 1, r1, r2);
3395   __ add(sp, sp, Operand(2 * kPointerSize));
3396   __ Ret();
3397
3398   __ bind(&not_same);
3399
3400   // Check that both objects are sequential one-byte strings.
3401   __ JumpIfNotBothSequentialOneByteStrings(r1, r0, r2, r3, &runtime);
3402
3403   // Compare flat one-byte strings natively. Remove arguments from stack first.
3404   __ IncrementCounter(counters->string_compare_native(), 1, r2, r3);
3405   __ add(sp, sp, Operand(2 * kPointerSize));
3406   StringHelper::GenerateCompareFlatOneByteStrings(masm, r1, r0, r2, r3, r4, r5);
3407
3408   // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
3409   // tagged as a small integer.
3410   __ bind(&runtime);
3411   __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
3412 }
3413
3414
3415 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) {
3416   // ----------- S t a t e -------------
3417   //  -- r1    : left
3418   //  -- r0    : right
3419   //  -- lr    : return address
3420   // -----------------------------------
3421
3422   // Load r2 with the allocation site.  We stick an undefined dummy value here
3423   // and replace it with the real allocation site later when we instantiate this
3424   // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate().
3425   __ Move(r2, handle(isolate()->heap()->undefined_value()));
3426
3427   // Make sure that we actually patched the allocation site.
3428   if (FLAG_debug_code) {
3429     __ tst(r2, Operand(kSmiTagMask));
3430     __ Assert(ne, kExpectedAllocationSite);
3431     __ push(r2);
3432     __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset));
3433     __ LoadRoot(ip, Heap::kAllocationSiteMapRootIndex);
3434     __ cmp(r2, ip);
3435     __ pop(r2);
3436     __ Assert(eq, kExpectedAllocationSite);
3437   }
3438
3439   // Tail call into the stub that handles binary operations with allocation
3440   // sites.
3441   BinaryOpWithAllocationSiteStub stub(isolate(), state());
3442   __ TailCallStub(&stub);
3443 }
3444
3445
3446 void CompareICStub::GenerateSmis(MacroAssembler* masm) {
3447   DCHECK(state() == CompareICState::SMI);
3448   Label miss;
3449   __ orr(r2, r1, r0);
3450   __ JumpIfNotSmi(r2, &miss);
3451
3452   if (GetCondition() == eq) {
3453     // For equality we do not care about the sign of the result.
3454     __ sub(r0, r0, r1, SetCC);
3455   } else {
3456     // Untag before subtracting to avoid handling overflow.
3457     __ SmiUntag(r1);
3458     __ sub(r0, r1, Operand::SmiUntag(r0));
3459   }
3460   __ Ret();
3461
3462   __ bind(&miss);
3463   GenerateMiss(masm);
3464 }
3465
3466
3467 void CompareICStub::GenerateNumbers(MacroAssembler* masm) {
3468   DCHECK(state() == CompareICState::NUMBER);
3469
3470   Label generic_stub;
3471   Label unordered, maybe_undefined1, maybe_undefined2;
3472   Label miss;
3473
3474   if (left() == CompareICState::SMI) {
3475     __ JumpIfNotSmi(r1, &miss);
3476   }
3477   if (right() == CompareICState::SMI) {
3478     __ JumpIfNotSmi(r0, &miss);
3479   }
3480
3481   // Inlining the double comparison and falling back to the general compare
3482   // stub if NaN is involved.
3483   // Load left and right operand.
3484   Label done, left, left_smi, right_smi;
3485   __ JumpIfSmi(r0, &right_smi);
3486   __ CheckMap(r0, r2, Heap::kHeapNumberMapRootIndex, &maybe_undefined1,
3487               DONT_DO_SMI_CHECK);
3488   __ sub(r2, r0, Operand(kHeapObjectTag));
3489   __ vldr(d1, r2, HeapNumber::kValueOffset);
3490   __ b(&left);
3491   __ bind(&right_smi);
3492   __ SmiToDouble(d1, r0);
3493
3494   __ bind(&left);
3495   __ JumpIfSmi(r1, &left_smi);
3496   __ CheckMap(r1, r2, Heap::kHeapNumberMapRootIndex, &maybe_undefined2,
3497               DONT_DO_SMI_CHECK);
3498   __ sub(r2, r1, Operand(kHeapObjectTag));
3499   __ vldr(d0, r2, HeapNumber::kValueOffset);
3500   __ b(&done);
3501   __ bind(&left_smi);
3502   __ SmiToDouble(d0, r1);
3503
3504   __ bind(&done);
3505   // Compare operands.
3506   __ VFPCompareAndSetFlags(d0, d1);
3507
3508   // Don't base result on status bits when a NaN is involved.
3509   __ b(vs, &unordered);
3510
3511   // Return a result of -1, 0, or 1, based on status bits.
3512   __ mov(r0, Operand(EQUAL), LeaveCC, eq);
3513   __ mov(r0, Operand(LESS), LeaveCC, lt);
3514   __ mov(r0, Operand(GREATER), LeaveCC, gt);
3515   __ Ret();
3516
3517   __ bind(&unordered);
3518   __ bind(&generic_stub);
3519   CompareICStub stub(isolate(), op(), CompareICState::GENERIC,
3520                      CompareICState::GENERIC, CompareICState::GENERIC);
3521   __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
3522
3523   __ bind(&maybe_undefined1);
3524   if (Token::IsOrderedRelationalCompareOp(op())) {
3525     __ CompareRoot(r0, Heap::kUndefinedValueRootIndex);
3526     __ b(ne, &miss);
3527     __ JumpIfSmi(r1, &unordered);
3528     __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE);
3529     __ b(ne, &maybe_undefined2);
3530     __ jmp(&unordered);
3531   }
3532
3533   __ bind(&maybe_undefined2);
3534   if (Token::IsOrderedRelationalCompareOp(op())) {
3535     __ CompareRoot(r1, Heap::kUndefinedValueRootIndex);
3536     __ b(eq, &unordered);
3537   }
3538
3539   __ bind(&miss);
3540   GenerateMiss(masm);
3541 }
3542
3543
3544 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) {
3545   DCHECK(state() == CompareICState::INTERNALIZED_STRING);
3546   Label miss;
3547
3548   // Registers containing left and right operands respectively.
3549   Register left = r1;
3550   Register right = r0;
3551   Register tmp1 = r2;
3552   Register tmp2 = r3;
3553
3554   // Check that both operands are heap objects.
3555   __ JumpIfEitherSmi(left, right, &miss);
3556
3557   // Check that both operands are internalized strings.
3558   __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
3559   __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
3560   __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
3561   __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
3562   STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
3563   __ orr(tmp1, tmp1, Operand(tmp2));
3564   __ tst(tmp1, Operand(kIsNotStringMask | kIsNotInternalizedMask));
3565   __ b(ne, &miss);
3566
3567   // Internalized strings are compared by identity.
3568   __ cmp(left, right);
3569   // Make sure r0 is non-zero. At this point input operands are
3570   // guaranteed to be non-zero.
3571   DCHECK(right.is(r0));
3572   STATIC_ASSERT(EQUAL == 0);
3573   STATIC_ASSERT(kSmiTag == 0);
3574   __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq);
3575   __ Ret();
3576
3577   __ bind(&miss);
3578   GenerateMiss(masm);
3579 }
3580
3581
3582 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) {
3583   DCHECK(state() == CompareICState::UNIQUE_NAME);
3584   DCHECK(GetCondition() == eq);
3585   Label miss;
3586
3587   // Registers containing left and right operands respectively.
3588   Register left = r1;
3589   Register right = r0;
3590   Register tmp1 = r2;
3591   Register tmp2 = r3;
3592
3593   // Check that both operands are heap objects.
3594   __ JumpIfEitherSmi(left, right, &miss);
3595
3596   // Check that both operands are unique names. This leaves the instance
3597   // types loaded in tmp1 and tmp2.
3598   __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
3599   __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
3600   __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
3601   __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
3602
3603   __ JumpIfNotUniqueNameInstanceType(tmp1, &miss);
3604   __ JumpIfNotUniqueNameInstanceType(tmp2, &miss);
3605
3606   // Unique names are compared by identity.
3607   __ cmp(left, right);
3608   // Make sure r0 is non-zero. At this point input operands are
3609   // guaranteed to be non-zero.
3610   DCHECK(right.is(r0));
3611   STATIC_ASSERT(EQUAL == 0);
3612   STATIC_ASSERT(kSmiTag == 0);
3613   __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq);
3614   __ Ret();
3615
3616   __ bind(&miss);
3617   GenerateMiss(masm);
3618 }
3619
3620
3621 void CompareICStub::GenerateStrings(MacroAssembler* masm) {
3622   DCHECK(state() == CompareICState::STRING);
3623   Label miss;
3624
3625   bool equality = Token::IsEqualityOp(op());
3626
3627   // Registers containing left and right operands respectively.
3628   Register left = r1;
3629   Register right = r0;
3630   Register tmp1 = r2;
3631   Register tmp2 = r3;
3632   Register tmp3 = r4;
3633   Register tmp4 = r5;
3634
3635   // Check that both operands are heap objects.
3636   __ JumpIfEitherSmi(left, right, &miss);
3637
3638   // Check that both operands are strings. This leaves the instance
3639   // types loaded in tmp1 and tmp2.
3640   __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
3641   __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
3642   __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
3643   __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
3644   STATIC_ASSERT(kNotStringTag != 0);
3645   __ orr(tmp3, tmp1, tmp2);
3646   __ tst(tmp3, Operand(kIsNotStringMask));
3647   __ b(ne, &miss);
3648
3649   // Fast check for identical strings.
3650   __ cmp(left, right);
3651   STATIC_ASSERT(EQUAL == 0);
3652   STATIC_ASSERT(kSmiTag == 0);
3653   __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq);
3654   __ Ret(eq);
3655
3656   // Handle not identical strings.
3657
3658   // Check that both strings are internalized strings. If they are, we're done
3659   // because we already know they are not identical. We know they are both
3660   // strings.
3661   if (equality) {
3662     DCHECK(GetCondition() == eq);
3663     STATIC_ASSERT(kInternalizedTag == 0);
3664     __ orr(tmp3, tmp1, Operand(tmp2));
3665     __ tst(tmp3, Operand(kIsNotInternalizedMask));
3666     // Make sure r0 is non-zero. At this point input operands are
3667     // guaranteed to be non-zero.
3668     DCHECK(right.is(r0));
3669     __ Ret(eq);
3670   }
3671
3672   // Check that both strings are sequential one-byte.
3673   Label runtime;
3674   __ JumpIfBothInstanceTypesAreNotSequentialOneByte(tmp1, tmp2, tmp3, tmp4,
3675                                                     &runtime);
3676
3677   // Compare flat one-byte strings. Returns when done.
3678   if (equality) {
3679     StringHelper::GenerateFlatOneByteStringEquals(masm, left, right, tmp1, tmp2,
3680                                                   tmp3);
3681   } else {
3682     StringHelper::GenerateCompareFlatOneByteStrings(masm, left, right, tmp1,
3683                                                     tmp2, tmp3, tmp4);
3684   }
3685
3686   // Handle more complex cases in runtime.
3687   __ bind(&runtime);
3688   __ Push(left, right);
3689   if (equality) {
3690     __ TailCallRuntime(Runtime::kStringEquals, 2, 1);
3691   } else {
3692     __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
3693   }
3694
3695   __ bind(&miss);
3696   GenerateMiss(masm);
3697 }
3698
3699
3700 void CompareICStub::GenerateObjects(MacroAssembler* masm) {
3701   DCHECK(state() == CompareICState::OBJECT);
3702   Label miss;
3703   __ and_(r2, r1, Operand(r0));
3704   __ JumpIfSmi(r2, &miss);
3705
3706   __ CompareObjectType(r0, r2, r2, JS_OBJECT_TYPE);
3707   __ b(ne, &miss);
3708   __ CompareObjectType(r1, r2, r2, JS_OBJECT_TYPE);
3709   __ b(ne, &miss);
3710
3711   DCHECK(GetCondition() == eq);
3712   __ sub(r0, r0, Operand(r1));
3713   __ Ret();
3714
3715   __ bind(&miss);
3716   GenerateMiss(masm);
3717 }
3718
3719
3720 void CompareICStub::GenerateKnownObjects(MacroAssembler* masm) {
3721   Label miss;
3722   Handle<WeakCell> cell = Map::WeakCellForMap(known_map_);
3723   __ and_(r2, r1, Operand(r0));
3724   __ JumpIfSmi(r2, &miss);
3725   __ GetWeakValue(r4, cell);
3726   __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
3727   __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
3728   __ cmp(r2, r4);
3729   __ b(ne, &miss);
3730   __ cmp(r3, r4);
3731   __ b(ne, &miss);
3732
3733   __ sub(r0, r0, Operand(r1));
3734   __ Ret();
3735
3736   __ bind(&miss);
3737   GenerateMiss(masm);
3738 }
3739
3740
3741 void CompareICStub::GenerateMiss(MacroAssembler* masm) {
3742   {
3743     // Call the runtime system in a fresh internal frame.
3744     ExternalReference miss =
3745         ExternalReference(IC_Utility(IC::kCompareIC_Miss), isolate());
3746
3747     FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
3748     __ Push(r1, r0);
3749     __ Push(lr, r1, r0);
3750     __ mov(ip, Operand(Smi::FromInt(op())));
3751     __ push(ip);
3752     __ CallExternalReference(miss, 3);
3753     // Compute the entry point of the rewritten stub.
3754     __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
3755     // Restore registers.
3756     __ pop(lr);
3757     __ Pop(r1, r0);
3758   }
3759
3760   __ Jump(r2);
3761 }
3762
3763
3764 void DirectCEntryStub::Generate(MacroAssembler* masm) {
3765   // Place the return address on the stack, making the call
3766   // GC safe. The RegExp backend also relies on this.
3767   __ str(lr, MemOperand(sp, 0));
3768   __ blx(ip);  // Call the C++ function.
3769   __ VFPEnsureFPSCRState(r2);
3770   __ ldr(pc, MemOperand(sp, 0));
3771 }
3772
3773
3774 void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
3775                                     Register target) {
3776   intptr_t code =
3777       reinterpret_cast<intptr_t>(GetCode().location());
3778   __ Move(ip, target);
3779   __ mov(lr, Operand(code, RelocInfo::CODE_TARGET));
3780   __ blx(lr);  // Call the stub.
3781 }
3782
3783
3784 void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
3785                                                       Label* miss,
3786                                                       Label* done,
3787                                                       Register receiver,
3788                                                       Register properties,
3789                                                       Handle<Name> name,
3790                                                       Register scratch0) {
3791   DCHECK(name->IsUniqueName());
3792   // If names of slots in range from 1 to kProbes - 1 for the hash value are
3793   // not equal to the name and kProbes-th slot is not used (its name is the
3794   // undefined value), it guarantees the hash table doesn't contain the
3795   // property. It's true even if some slots represent deleted properties
3796   // (their names are the hole value).
3797   for (int i = 0; i < kInlinedProbes; i++) {
3798     // scratch0 points to properties hash.
3799     // Compute the masked index: (hash + i + i * i) & mask.
3800     Register index = scratch0;
3801     // Capacity is smi 2^n.
3802     __ ldr(index, FieldMemOperand(properties, kCapacityOffset));
3803     __ sub(index, index, Operand(1));
3804     __ and_(index, index, Operand(
3805         Smi::FromInt(name->Hash() + NameDictionary::GetProbeOffset(i))));
3806
3807     // Scale the index by multiplying by the entry size.
3808     STATIC_ASSERT(NameDictionary::kEntrySize == 3);
3809     __ add(index, index, Operand(index, LSL, 1));  // index *= 3.
3810
3811     Register entity_name = scratch0;
3812     // Having undefined at this place means the name is not contained.
3813     DCHECK_EQ(kSmiTagSize, 1);
3814     Register tmp = properties;
3815     __ add(tmp, properties, Operand(index, LSL, 1));
3816     __ ldr(entity_name, FieldMemOperand(tmp, kElementsStartOffset));
3817
3818     DCHECK(!tmp.is(entity_name));
3819     __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex);
3820     __ cmp(entity_name, tmp);
3821     __ b(eq, done);
3822
3823     // Load the hole ready for use below:
3824     __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex);
3825
3826     // Stop if found the property.
3827     __ cmp(entity_name, Operand(Handle<Name>(name)));
3828     __ b(eq, miss);
3829
3830     Label good;
3831     __ cmp(entity_name, tmp);
3832     __ b(eq, &good);
3833
3834     // Check if the entry name is not a unique name.
3835     __ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
3836     __ ldrb(entity_name,
3837             FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
3838     __ JumpIfNotUniqueNameInstanceType(entity_name, miss);
3839     __ bind(&good);
3840
3841     // Restore the properties.
3842     __ ldr(properties,
3843            FieldMemOperand(receiver, JSObject::kPropertiesOffset));
3844   }
3845
3846   const int spill_mask =
3847       (lr.bit() | r6.bit() | r5.bit() | r4.bit() | r3.bit() |
3848        r2.bit() | r1.bit() | r0.bit());
3849
3850   __ stm(db_w, sp, spill_mask);
3851   __ ldr(r0, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
3852   __ mov(r1, Operand(Handle<Name>(name)));
3853   NameDictionaryLookupStub stub(masm->isolate(), NEGATIVE_LOOKUP);
3854   __ CallStub(&stub);
3855   __ cmp(r0, Operand::Zero());
3856   __ ldm(ia_w, sp, spill_mask);
3857
3858   __ b(eq, done);
3859   __ b(ne, miss);
3860 }
3861
3862
3863 // Probe the name dictionary in the |elements| register. Jump to the
3864 // |done| label if a property with the given name is found. Jump to
3865 // the |miss| label otherwise.
3866 // If lookup was successful |scratch2| will be equal to elements + 4 * index.
3867 void NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
3868                                                       Label* miss,
3869                                                       Label* done,
3870                                                       Register elements,
3871                                                       Register name,
3872                                                       Register scratch1,
3873                                                       Register scratch2) {
3874   DCHECK(!elements.is(scratch1));
3875   DCHECK(!elements.is(scratch2));
3876   DCHECK(!name.is(scratch1));
3877   DCHECK(!name.is(scratch2));
3878
3879   __ AssertName(name);
3880
3881   // Compute the capacity mask.
3882   __ ldr(scratch1, FieldMemOperand(elements, kCapacityOffset));
3883   __ SmiUntag(scratch1);
3884   __ sub(scratch1, scratch1, Operand(1));
3885
3886   // Generate an unrolled loop that performs a few probes before
3887   // giving up. Measurements done on Gmail indicate that 2 probes
3888   // cover ~93% of loads from dictionaries.
3889   for (int i = 0; i < kInlinedProbes; i++) {
3890     // Compute the masked index: (hash + i + i * i) & mask.
3891     __ ldr(scratch2, FieldMemOperand(name, Name::kHashFieldOffset));
3892     if (i > 0) {
3893       // Add the probe offset (i + i * i) left shifted to avoid right shifting
3894       // the hash in a separate instruction. The value hash + i + i * i is right
3895       // shifted in the following and instruction.
3896       DCHECK(NameDictionary::GetProbeOffset(i) <
3897              1 << (32 - Name::kHashFieldOffset));
3898       __ add(scratch2, scratch2, Operand(
3899           NameDictionary::GetProbeOffset(i) << Name::kHashShift));
3900     }
3901     __ and_(scratch2, scratch1, Operand(scratch2, LSR, Name::kHashShift));
3902
3903     // Scale the index by multiplying by the element size.
3904     DCHECK(NameDictionary::kEntrySize == 3);
3905     // scratch2 = scratch2 * 3.
3906     __ add(scratch2, scratch2, Operand(scratch2, LSL, 1));
3907
3908     // Check if the key is identical to the name.
3909     __ add(scratch2, elements, Operand(scratch2, LSL, 2));
3910     __ ldr(ip, FieldMemOperand(scratch2, kElementsStartOffset));
3911     __ cmp(name, Operand(ip));
3912     __ b(eq, done);
3913   }
3914
3915   const int spill_mask =
3916       (lr.bit() | r6.bit() | r5.bit() | r4.bit() |
3917        r3.bit() | r2.bit() | r1.bit() | r0.bit()) &
3918       ~(scratch1.bit() | scratch2.bit());
3919
3920   __ stm(db_w, sp, spill_mask);
3921   if (name.is(r0)) {
3922     DCHECK(!elements.is(r1));
3923     __ Move(r1, name);
3924     __ Move(r0, elements);
3925   } else {
3926     __ Move(r0, elements);
3927     __ Move(r1, name);
3928   }
3929   NameDictionaryLookupStub stub(masm->isolate(), POSITIVE_LOOKUP);
3930   __ CallStub(&stub);
3931   __ cmp(r0, Operand::Zero());
3932   __ mov(scratch2, Operand(r2));
3933   __ ldm(ia_w, sp, spill_mask);
3934
3935   __ b(ne, done);
3936   __ b(eq, miss);
3937 }
3938
3939
3940 void NameDictionaryLookupStub::Generate(MacroAssembler* masm) {
3941   // This stub overrides SometimesSetsUpAFrame() to return false.  That means
3942   // we cannot call anything that could cause a GC from this stub.
3943   // Registers:
3944   //  result: NameDictionary to probe
3945   //  r1: key
3946   //  dictionary: NameDictionary to probe.
3947   //  index: will hold an index of entry if lookup is successful.
3948   //         might alias with result_.
3949   // Returns:
3950   //  result_ is zero if lookup failed, non zero otherwise.
3951
3952   Register result = r0;
3953   Register dictionary = r0;
3954   Register key = r1;
3955   Register index = r2;
3956   Register mask = r3;
3957   Register hash = r4;
3958   Register undefined = r5;
3959   Register entry_key = r6;
3960
3961   Label in_dictionary, maybe_in_dictionary, not_in_dictionary;
3962
3963   __ ldr(mask, FieldMemOperand(dictionary, kCapacityOffset));
3964   __ SmiUntag(mask);
3965   __ sub(mask, mask, Operand(1));
3966
3967   __ ldr(hash, FieldMemOperand(key, Name::kHashFieldOffset));
3968
3969   __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
3970
3971   for (int i = kInlinedProbes; i < kTotalProbes; i++) {
3972     // Compute the masked index: (hash + i + i * i) & mask.
3973     // Capacity is smi 2^n.
3974     if (i > 0) {
3975       // Add the probe offset (i + i * i) left shifted to avoid right shifting
3976       // the hash in a separate instruction. The value hash + i + i * i is right
3977       // shifted in the following and instruction.
3978       DCHECK(NameDictionary::GetProbeOffset(i) <
3979              1 << (32 - Name::kHashFieldOffset));
3980       __ add(index, hash, Operand(
3981           NameDictionary::GetProbeOffset(i) << Name::kHashShift));
3982     } else {
3983       __ mov(index, Operand(hash));
3984     }
3985     __ and_(index, mask, Operand(index, LSR, Name::kHashShift));
3986
3987     // Scale the index by multiplying by the entry size.
3988     DCHECK(NameDictionary::kEntrySize == 3);
3989     __ add(index, index, Operand(index, LSL, 1));  // index *= 3.
3990
3991     DCHECK_EQ(kSmiTagSize, 1);
3992     __ add(index, dictionary, Operand(index, LSL, 2));
3993     __ ldr(entry_key, FieldMemOperand(index, kElementsStartOffset));
3994
3995     // Having undefined at this place means the name is not contained.
3996     __ cmp(entry_key, Operand(undefined));
3997     __ b(eq, &not_in_dictionary);
3998
3999     // Stop if found the property.
4000     __ cmp(entry_key, Operand(key));
4001     __ b(eq, &in_dictionary);
4002
4003     if (i != kTotalProbes - 1 && mode() == NEGATIVE_LOOKUP) {
4004       // Check if the entry name is not a unique name.
4005       __ ldr(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset));
4006       __ ldrb(entry_key,
4007               FieldMemOperand(entry_key, Map::kInstanceTypeOffset));
4008       __ JumpIfNotUniqueNameInstanceType(entry_key, &maybe_in_dictionary);
4009     }
4010   }
4011
4012   __ bind(&maybe_in_dictionary);
4013   // If we are doing negative lookup then probing failure should be
4014   // treated as a lookup success. For positive lookup probing failure
4015   // should be treated as lookup failure.
4016   if (mode() == POSITIVE_LOOKUP) {
4017     __ mov(result, Operand::Zero());
4018     __ Ret();
4019   }
4020
4021   __ bind(&in_dictionary);
4022   __ mov(result, Operand(1));
4023   __ Ret();
4024
4025   __ bind(&not_in_dictionary);
4026   __ mov(result, Operand::Zero());
4027   __ Ret();
4028 }
4029
4030
4031 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(
4032     Isolate* isolate) {
4033   StoreBufferOverflowStub stub1(isolate, kDontSaveFPRegs);
4034   stub1.GetCode();
4035   // Hydrogen code stubs need stub2 at snapshot time.
4036   StoreBufferOverflowStub stub2(isolate, kSaveFPRegs);
4037   stub2.GetCode();
4038 }
4039
4040
4041 // Takes the input in 3 registers: address_ value_ and object_.  A pointer to
4042 // the value has just been written into the object, now this stub makes sure
4043 // we keep the GC informed.  The word in the object where the value has been
4044 // written is in the address register.
4045 void RecordWriteStub::Generate(MacroAssembler* masm) {
4046   Label skip_to_incremental_noncompacting;
4047   Label skip_to_incremental_compacting;
4048
4049   // The first two instructions are generated with labels so as to get the
4050   // offset fixed up correctly by the bind(Label*) call.  We patch it back and
4051   // forth between a compare instructions (a nop in this position) and the
4052   // real branch when we start and stop incremental heap marking.
4053   // See RecordWriteStub::Patch for details.
4054   {
4055     // Block literal pool emission, as the position of these two instructions
4056     // is assumed by the patching code.
4057     Assembler::BlockConstPoolScope block_const_pool(masm);
4058     __ b(&skip_to_incremental_noncompacting);
4059     __ b(&skip_to_incremental_compacting);
4060   }
4061
4062   if (remembered_set_action() == EMIT_REMEMBERED_SET) {
4063     __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(),
4064                            MacroAssembler::kReturnAtEnd);
4065   }
4066   __ Ret();
4067
4068   __ bind(&skip_to_incremental_noncompacting);
4069   GenerateIncremental(masm, INCREMENTAL);
4070
4071   __ bind(&skip_to_incremental_compacting);
4072   GenerateIncremental(masm, INCREMENTAL_COMPACTION);
4073
4074   // Initial mode of the stub is expected to be STORE_BUFFER_ONLY.
4075   // Will be checked in IncrementalMarking::ActivateGeneratedStub.
4076   DCHECK(Assembler::GetBranchOffset(masm->instr_at(0)) < (1 << 12));
4077   DCHECK(Assembler::GetBranchOffset(masm->instr_at(4)) < (1 << 12));
4078   PatchBranchIntoNop(masm, 0);
4079   PatchBranchIntoNop(masm, Assembler::kInstrSize);
4080 }
4081
4082
4083 void RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) {
4084   regs_.Save(masm);
4085
4086   if (remembered_set_action() == EMIT_REMEMBERED_SET) {
4087     Label dont_need_remembered_set;
4088
4089     __ ldr(regs_.scratch0(), MemOperand(regs_.address(), 0));
4090     __ JumpIfNotInNewSpace(regs_.scratch0(),  // Value.
4091                            regs_.scratch0(),
4092                            &dont_need_remembered_set);
4093
4094     __ CheckPageFlag(regs_.object(),
4095                      regs_.scratch0(),
4096                      1 << MemoryChunk::SCAN_ON_SCAVENGE,
4097                      ne,
4098                      &dont_need_remembered_set);
4099
4100     // First notify the incremental marker if necessary, then update the
4101     // remembered set.
4102     CheckNeedsToInformIncrementalMarker(
4103         masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode);
4104     InformIncrementalMarker(masm);
4105     regs_.Restore(masm);
4106     __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(),
4107                            MacroAssembler::kReturnAtEnd);
4108
4109     __ bind(&dont_need_remembered_set);
4110   }
4111
4112   CheckNeedsToInformIncrementalMarker(
4113       masm, kReturnOnNoNeedToInformIncrementalMarker, mode);
4114   InformIncrementalMarker(masm);
4115   regs_.Restore(masm);
4116   __ Ret();
4117 }
4118
4119
4120 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) {
4121   regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode());
4122   int argument_count = 3;
4123   __ PrepareCallCFunction(argument_count, regs_.scratch0());
4124   Register address =
4125       r0.is(regs_.address()) ? regs_.scratch0() : regs_.address();
4126   DCHECK(!address.is(regs_.object()));
4127   DCHECK(!address.is(r0));
4128   __ Move(address, regs_.address());
4129   __ Move(r0, regs_.object());
4130   __ Move(r1, address);
4131   __ mov(r2, Operand(ExternalReference::isolate_address(isolate())));
4132
4133   AllowExternalCallThatCantCauseGC scope(masm);
4134   __ CallCFunction(
4135       ExternalReference::incremental_marking_record_write_function(isolate()),
4136       argument_count);
4137   regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode());
4138 }
4139
4140
4141 void RecordWriteStub::CheckNeedsToInformIncrementalMarker(
4142     MacroAssembler* masm,
4143     OnNoNeedToInformIncrementalMarker on_no_need,
4144     Mode mode) {
4145   Label on_black;
4146   Label need_incremental;
4147   Label need_incremental_pop_scratch;
4148
4149   __ and_(regs_.scratch0(), regs_.object(), Operand(~Page::kPageAlignmentMask));
4150   __ ldr(regs_.scratch1(),
4151          MemOperand(regs_.scratch0(),
4152                     MemoryChunk::kWriteBarrierCounterOffset));
4153   __ sub(regs_.scratch1(), regs_.scratch1(), Operand(1), SetCC);
4154   __ str(regs_.scratch1(),
4155          MemOperand(regs_.scratch0(),
4156                     MemoryChunk::kWriteBarrierCounterOffset));
4157   __ b(mi, &need_incremental);
4158
4159   // Let's look at the color of the object:  If it is not black we don't have
4160   // to inform the incremental marker.
4161   __ JumpIfBlack(regs_.object(), regs_.scratch0(), regs_.scratch1(), &on_black);
4162
4163   regs_.Restore(masm);
4164   if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
4165     __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(),
4166                            MacroAssembler::kReturnAtEnd);
4167   } else {
4168     __ Ret();
4169   }
4170
4171   __ bind(&on_black);
4172
4173   // Get the value from the slot.
4174   __ ldr(regs_.scratch0(), MemOperand(regs_.address(), 0));
4175
4176   if (mode == INCREMENTAL_COMPACTION) {
4177     Label ensure_not_white;
4178
4179     __ CheckPageFlag(regs_.scratch0(),  // Contains value.
4180                      regs_.scratch1(),  // Scratch.
4181                      MemoryChunk::kEvacuationCandidateMask,
4182                      eq,
4183                      &ensure_not_white);
4184
4185     __ CheckPageFlag(regs_.object(),
4186                      regs_.scratch1(),  // Scratch.
4187                      MemoryChunk::kSkipEvacuationSlotsRecordingMask,
4188                      eq,
4189                      &need_incremental);
4190
4191     __ bind(&ensure_not_white);
4192   }
4193
4194   // We need extra registers for this, so we push the object and the address
4195   // register temporarily.
4196   __ Push(regs_.object(), regs_.address());
4197   __ EnsureNotWhite(regs_.scratch0(),  // The value.
4198                     regs_.scratch1(),  // Scratch.
4199                     regs_.object(),  // Scratch.
4200                     regs_.address(),  // Scratch.
4201                     &need_incremental_pop_scratch);
4202   __ Pop(regs_.object(), regs_.address());
4203
4204   regs_.Restore(masm);
4205   if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
4206     __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(),
4207                            MacroAssembler::kReturnAtEnd);
4208   } else {
4209     __ Ret();
4210   }
4211
4212   __ bind(&need_incremental_pop_scratch);
4213   __ Pop(regs_.object(), regs_.address());
4214
4215   __ bind(&need_incremental);
4216
4217   // Fall through when we need to inform the incremental marker.
4218 }
4219
4220
4221 void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
4222   // ----------- S t a t e -------------
4223   //  -- r0    : element value to store
4224   //  -- r3    : element index as smi
4225   //  -- sp[0] : array literal index in function as smi
4226   //  -- sp[4] : array literal
4227   // clobbers r1, r2, r4
4228   // -----------------------------------
4229
4230   Label element_done;
4231   Label double_elements;
4232   Label smi_element;
4233   Label slow_elements;
4234   Label fast_elements;
4235
4236   // Get array literal index, array literal and its map.
4237   __ ldr(r4, MemOperand(sp, 0 * kPointerSize));
4238   __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
4239   __ ldr(r2, FieldMemOperand(r1, JSObject::kMapOffset));
4240
4241   __ CheckFastElements(r2, r5, &double_elements);
4242   // FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS
4243   __ JumpIfSmi(r0, &smi_element);
4244   __ CheckFastSmiElements(r2, r5, &fast_elements);
4245
4246   // Store into the array literal requires a elements transition. Call into
4247   // the runtime.
4248   __ bind(&slow_elements);
4249   // call.
4250   __ Push(r1, r3, r0);
4251   __ ldr(r5, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
4252   __ ldr(r5, FieldMemOperand(r5, JSFunction::kLiteralsOffset));
4253   __ Push(r5, r4);
4254   __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1);
4255
4256   // Array literal has ElementsKind of FAST_*_ELEMENTS and value is an object.
4257   __ bind(&fast_elements);
4258   __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset));
4259   __ add(r6, r5, Operand::PointerOffsetFromSmiKey(r3));
4260   __ add(r6, r6, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
4261   __ str(r0, MemOperand(r6, 0));
4262   // Update the write barrier for the array store.
4263   __ RecordWrite(r5, r6, r0, kLRHasNotBeenSaved, kDontSaveFPRegs,
4264                  EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
4265   __ Ret();
4266
4267   // Array literal has ElementsKind of FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS,
4268   // and value is Smi.
4269   __ bind(&smi_element);
4270   __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset));
4271   __ add(r6, r5, Operand::PointerOffsetFromSmiKey(r3));
4272   __ str(r0, FieldMemOperand(r6, FixedArray::kHeaderSize));
4273   __ Ret();
4274
4275   // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
4276   __ bind(&double_elements);
4277   __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset));
4278   __ StoreNumberToDoubleElements(r0, r3, r5, r6, d0, &slow_elements);
4279   __ Ret();
4280 }
4281
4282
4283 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
4284   CEntryStub ces(isolate(), 1, kSaveFPRegs);
4285   __ Call(ces.GetCode(), RelocInfo::CODE_TARGET);
4286   int parameter_count_offset =
4287       StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
4288   __ ldr(r1, MemOperand(fp, parameter_count_offset));
4289   if (function_mode() == JS_FUNCTION_STUB_MODE) {
4290     __ add(r1, r1, Operand(1));
4291   }
4292   masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
4293   __ mov(r1, Operand(r1, LSL, kPointerSizeLog2));
4294   __ add(sp, sp, r1);
4295   __ Ret();
4296 }
4297
4298
4299 void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
4300   EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister());
4301   VectorLoadStub stub(isolate(), state());
4302   __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
4303 }
4304
4305
4306 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
4307   EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister());
4308   VectorKeyedLoadStub stub(isolate());
4309   __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
4310 }
4311
4312
4313 void CallICTrampolineStub::Generate(MacroAssembler* masm) {
4314   EmitLoadTypeFeedbackVector(masm, r2);
4315   CallICStub stub(isolate(), state());
4316   __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
4317 }
4318
4319
4320 void CallIC_ArrayTrampolineStub::Generate(MacroAssembler* masm) {
4321   EmitLoadTypeFeedbackVector(masm, r2);
4322   CallIC_ArrayStub stub(isolate(), state());
4323   __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
4324 }
4325
4326
4327 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) {
4328   if (masm->isolate()->function_entry_hook() != NULL) {
4329     ProfileEntryHookStub stub(masm->isolate());
4330     int code_size = masm->CallStubSize(&stub) + 2 * Assembler::kInstrSize;
4331     PredictableCodeSizeScope predictable(masm, code_size);
4332     __ push(lr);
4333     __ CallStub(&stub);
4334     __ pop(lr);
4335   }
4336 }
4337
4338
4339 void ProfileEntryHookStub::Generate(MacroAssembler* masm) {
4340   // The entry hook is a "push lr" instruction, followed by a call.
4341   const int32_t kReturnAddressDistanceFromFunctionStart =
4342       3 * Assembler::kInstrSize;
4343
4344   // This should contain all kCallerSaved registers.
4345   const RegList kSavedRegs =
4346       1 <<  0 |  // r0
4347       1 <<  1 |  // r1
4348       1 <<  2 |  // r2
4349       1 <<  3 |  // r3
4350       1 <<  5 |  // r5
4351       1 <<  9;   // r9
4352   // We also save lr, so the count here is one higher than the mask indicates.
4353   const int32_t kNumSavedRegs = 7;
4354
4355   DCHECK((kCallerSaved & kSavedRegs) == kCallerSaved);
4356
4357   // Save all caller-save registers as this may be called from anywhere.
4358   __ stm(db_w, sp, kSavedRegs | lr.bit());
4359
4360   // Compute the function's address for the first argument.
4361   __ sub(r0, lr, Operand(kReturnAddressDistanceFromFunctionStart));
4362
4363   // The caller's return address is above the saved temporaries.
4364   // Grab that for the second argument to the hook.
4365   __ add(r1, sp, Operand(kNumSavedRegs * kPointerSize));
4366
4367   // Align the stack if necessary.
4368   int frame_alignment = masm->ActivationFrameAlignment();
4369   if (frame_alignment > kPointerSize) {
4370     __ mov(r5, sp);
4371     DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
4372     __ and_(sp, sp, Operand(-frame_alignment));
4373   }
4374
4375 #if V8_HOST_ARCH_ARM
4376   int32_t entry_hook =
4377       reinterpret_cast<int32_t>(isolate()->function_entry_hook());
4378   __ mov(ip, Operand(entry_hook));
4379 #else
4380   // Under the simulator we need to indirect the entry hook through a
4381   // trampoline function at a known address.
4382   // It additionally takes an isolate as a third parameter
4383   __ mov(r2, Operand(ExternalReference::isolate_address(isolate())));
4384
4385   ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline));
4386   __ mov(ip, Operand(ExternalReference(&dispatcher,
4387                                        ExternalReference::BUILTIN_CALL,
4388                                        isolate())));
4389 #endif
4390   __ Call(ip);
4391
4392   // Restore the stack pointer if needed.
4393   if (frame_alignment > kPointerSize) {
4394     __ mov(sp, r5);
4395   }
4396
4397   // Also pop pc to get Ret(0).
4398   __ ldm(ia_w, sp, kSavedRegs | pc.bit());
4399 }
4400
4401
4402 template<class T>
4403 static void CreateArrayDispatch(MacroAssembler* masm,
4404                                 AllocationSiteOverrideMode mode) {
4405   if (mode == DISABLE_ALLOCATION_SITES) {
4406     T stub(masm->isolate(), GetInitialFastElementsKind(), mode);
4407     __ TailCallStub(&stub);
4408   } else if (mode == DONT_OVERRIDE) {
4409     int last_index = GetSequenceIndexFromFastElementsKind(
4410         TERMINAL_FAST_ELEMENTS_KIND);
4411     for (int i = 0; i <= last_index; ++i) {
4412       ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
4413       __ cmp(r3, Operand(kind));
4414       T stub(masm->isolate(), kind);
4415       __ TailCallStub(&stub, eq);
4416     }
4417
4418     // If we reached this point there is a problem.
4419     __ Abort(kUnexpectedElementsKindInArrayConstructor);
4420   } else {
4421     UNREACHABLE();
4422   }
4423 }
4424
4425
4426 static void CreateArrayDispatchOneArgument(MacroAssembler* masm,
4427                                            AllocationSiteOverrideMode mode) {
4428   // r2 - allocation site (if mode != DISABLE_ALLOCATION_SITES)
4429   // r3 - kind (if mode != DISABLE_ALLOCATION_SITES)
4430   // r0 - number of arguments
4431   // r1 - constructor?
4432   // sp[0] - last argument
4433   Label normal_sequence;
4434   if (mode == DONT_OVERRIDE) {
4435     DCHECK(FAST_SMI_ELEMENTS == 0);
4436     DCHECK(FAST_HOLEY_SMI_ELEMENTS == 1);
4437     DCHECK(FAST_ELEMENTS == 2);
4438     DCHECK(FAST_HOLEY_ELEMENTS == 3);
4439     DCHECK(FAST_DOUBLE_ELEMENTS == 4);
4440     DCHECK(FAST_HOLEY_DOUBLE_ELEMENTS == 5);
4441
4442     // is the low bit set? If so, we are holey and that is good.
4443     __ tst(r3, Operand(1));
4444     __ b(ne, &normal_sequence);
4445   }
4446
4447   // look at the first argument
4448   __ ldr(r5, MemOperand(sp, 0));
4449   __ cmp(r5, Operand::Zero());
4450   __ b(eq, &normal_sequence);
4451
4452   if (mode == DISABLE_ALLOCATION_SITES) {
4453     ElementsKind initial = GetInitialFastElementsKind();
4454     ElementsKind holey_initial = GetHoleyElementsKind(initial);
4455
4456     ArraySingleArgumentConstructorStub stub_holey(masm->isolate(),
4457                                                   holey_initial,
4458                                                   DISABLE_ALLOCATION_SITES);
4459     __ TailCallStub(&stub_holey);
4460
4461     __ bind(&normal_sequence);
4462     ArraySingleArgumentConstructorStub stub(masm->isolate(),
4463                                             initial,
4464                                             DISABLE_ALLOCATION_SITES);
4465     __ TailCallStub(&stub);
4466   } else if (mode == DONT_OVERRIDE) {
4467     // We are going to create a holey array, but our kind is non-holey.
4468     // Fix kind and retry (only if we have an allocation site in the slot).
4469     __ add(r3, r3, Operand(1));
4470
4471     if (FLAG_debug_code) {
4472       __ ldr(r5, FieldMemOperand(r2, 0));
4473       __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex);
4474       __ Assert(eq, kExpectedAllocationSite);
4475     }
4476
4477     // Save the resulting elements kind in type info. We can't just store r3
4478     // in the AllocationSite::transition_info field because elements kind is
4479     // restricted to a portion of the field...upper bits need to be left alone.
4480     STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
4481     __ ldr(r4, FieldMemOperand(r2, AllocationSite::kTransitionInfoOffset));
4482     __ add(r4, r4, Operand(Smi::FromInt(kFastElementsKindPackedToHoley)));
4483     __ str(r4, FieldMemOperand(r2, AllocationSite::kTransitionInfoOffset));
4484
4485     __ bind(&normal_sequence);
4486     int last_index = GetSequenceIndexFromFastElementsKind(
4487         TERMINAL_FAST_ELEMENTS_KIND);
4488     for (int i = 0; i <= last_index; ++i) {
4489       ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
4490       __ cmp(r3, Operand(kind));
4491       ArraySingleArgumentConstructorStub stub(masm->isolate(), kind);
4492       __ TailCallStub(&stub, eq);
4493     }
4494
4495     // If we reached this point there is a problem.
4496     __ Abort(kUnexpectedElementsKindInArrayConstructor);
4497   } else {
4498     UNREACHABLE();
4499   }
4500 }
4501
4502
4503 template<class T>
4504 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) {
4505   int to_index = GetSequenceIndexFromFastElementsKind(
4506       TERMINAL_FAST_ELEMENTS_KIND);
4507   for (int i = 0; i <= to_index; ++i) {
4508     ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
4509     T stub(isolate, kind);
4510     stub.GetCode();
4511     if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) {
4512       T stub1(isolate, kind, DISABLE_ALLOCATION_SITES);
4513       stub1.GetCode();
4514     }
4515   }
4516 }
4517
4518
4519 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
4520   ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
4521       isolate);
4522   ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
4523       isolate);
4524   ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>(
4525       isolate);
4526 }
4527
4528
4529 void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(
4530     Isolate* isolate) {
4531   ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS };
4532   for (int i = 0; i < 2; i++) {
4533     // For internal arrays we only need a few things
4534     InternalArrayNoArgumentConstructorStub stubh1(isolate, kinds[i]);
4535     stubh1.GetCode();
4536     InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]);
4537     stubh2.GetCode();
4538     InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]);
4539     stubh3.GetCode();
4540   }
4541 }
4542
4543
4544 void ArrayConstructorStub::GenerateDispatchToArrayStub(
4545     MacroAssembler* masm,
4546     AllocationSiteOverrideMode mode) {
4547   if (argument_count() == ANY) {
4548     Label not_zero_case, not_one_case;
4549     __ tst(r0, r0);
4550     __ b(ne, &not_zero_case);
4551     CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
4552
4553     __ bind(&not_zero_case);
4554     __ cmp(r0, Operand(1));
4555     __ b(gt, &not_one_case);
4556     CreateArrayDispatchOneArgument(masm, mode);
4557
4558     __ bind(&not_one_case);
4559     CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
4560   } else if (argument_count() == NONE) {
4561     CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
4562   } else if (argument_count() == ONE) {
4563     CreateArrayDispatchOneArgument(masm, mode);
4564   } else if (argument_count() == MORE_THAN_ONE) {
4565     CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
4566   } else {
4567     UNREACHABLE();
4568   }
4569 }
4570
4571
4572 void ArrayConstructorStub::Generate(MacroAssembler* masm) {
4573   // ----------- S t a t e -------------
4574   //  -- r0 : argc (only if argument_count() == ANY)
4575   //  -- r1 : constructor
4576   //  -- r2 : AllocationSite or undefined
4577   //  -- r3 : original constructor
4578   //  -- sp[0] : return address
4579   //  -- sp[4] : last argument
4580   // -----------------------------------
4581
4582   if (FLAG_debug_code) {
4583     // The array construct code is only set for the global and natives
4584     // builtin Array functions which always have maps.
4585
4586     // Initial map for the builtin Array function should be a map.
4587     __ ldr(r4, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
4588     // Will both indicate a NULL and a Smi.
4589     __ tst(r4, Operand(kSmiTagMask));
4590     __ Assert(ne, kUnexpectedInitialMapForArrayFunction);
4591     __ CompareObjectType(r4, r4, r5, MAP_TYPE);
4592     __ Assert(eq, kUnexpectedInitialMapForArrayFunction);
4593
4594     // We should either have undefined in r2 or a valid AllocationSite
4595     __ AssertUndefinedOrAllocationSite(r2, r4);
4596   }
4597
4598   Label subclassing;
4599   __ cmp(r3, r1);
4600   __ b(ne, &subclassing);
4601
4602   Label no_info;
4603   // Get the elements kind and case on that.
4604   __ CompareRoot(r2, Heap::kUndefinedValueRootIndex);
4605   __ b(eq, &no_info);
4606
4607   __ ldr(r3, FieldMemOperand(r2, AllocationSite::kTransitionInfoOffset));
4608   __ SmiUntag(r3);
4609   STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
4610   __ and_(r3, r3, Operand(AllocationSite::ElementsKindBits::kMask));
4611   GenerateDispatchToArrayStub(masm, DONT_OVERRIDE);
4612
4613   __ bind(&no_info);
4614   GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES);
4615
4616   __ bind(&subclassing);
4617   __ push(r1);
4618   __ push(r3);
4619
4620   // Adjust argc.
4621   switch (argument_count()) {
4622     case ANY:
4623     case MORE_THAN_ONE:
4624       __ add(r0, r0, Operand(2));
4625       break;
4626     case NONE:
4627       __ mov(r0, Operand(2));
4628       break;
4629     case ONE:
4630       __ mov(r0, Operand(3));
4631       break;
4632   }
4633
4634   __ JumpToExternalReference(
4635       ExternalReference(Runtime::kArrayConstructorWithSubclassing, isolate()));
4636 }
4637
4638
4639 void InternalArrayConstructorStub::GenerateCase(
4640     MacroAssembler* masm, ElementsKind kind) {
4641   __ cmp(r0, Operand(1));
4642
4643   InternalArrayNoArgumentConstructorStub stub0(isolate(), kind);
4644   __ TailCallStub(&stub0, lo);
4645
4646   InternalArrayNArgumentsConstructorStub stubN(isolate(), kind);
4647   __ TailCallStub(&stubN, hi);
4648
4649   if (IsFastPackedElementsKind(kind)) {
4650     // We might need to create a holey array
4651     // look at the first argument
4652     __ ldr(r3, MemOperand(sp, 0));
4653     __ cmp(r3, Operand::Zero());
4654
4655     InternalArraySingleArgumentConstructorStub
4656         stub1_holey(isolate(), GetHoleyElementsKind(kind));
4657     __ TailCallStub(&stub1_holey, ne);
4658   }
4659
4660   InternalArraySingleArgumentConstructorStub stub1(isolate(), kind);
4661   __ TailCallStub(&stub1);
4662 }
4663
4664
4665 void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
4666   // ----------- S t a t e -------------
4667   //  -- r0 : argc
4668   //  -- r1 : constructor
4669   //  -- sp[0] : return address
4670   //  -- sp[4] : last argument
4671   // -----------------------------------
4672
4673   if (FLAG_debug_code) {
4674     // The array construct code is only set for the global and natives
4675     // builtin Array functions which always have maps.
4676
4677     // Initial map for the builtin Array function should be a map.
4678     __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
4679     // Will both indicate a NULL and a Smi.
4680     __ tst(r3, Operand(kSmiTagMask));
4681     __ Assert(ne, kUnexpectedInitialMapForArrayFunction);
4682     __ CompareObjectType(r3, r3, r4, MAP_TYPE);
4683     __ Assert(eq, kUnexpectedInitialMapForArrayFunction);
4684   }
4685
4686   // Figure out the right elements kind
4687   __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
4688   // Load the map's "bit field 2" into |result|. We only need the first byte,
4689   // but the following bit field extraction takes care of that anyway.
4690   __ ldr(r3, FieldMemOperand(r3, Map::kBitField2Offset));
4691   // Retrieve elements_kind from bit field 2.
4692   __ DecodeField<Map::ElementsKindBits>(r3);
4693
4694   if (FLAG_debug_code) {
4695     Label done;
4696     __ cmp(r3, Operand(FAST_ELEMENTS));
4697     __ b(eq, &done);
4698     __ cmp(r3, Operand(FAST_HOLEY_ELEMENTS));
4699     __ Assert(eq,
4700               kInvalidElementsKindForInternalArrayOrInternalPackedArray);
4701     __ bind(&done);
4702   }
4703
4704   Label fast_elements_case;
4705   __ cmp(r3, Operand(FAST_ELEMENTS));
4706   __ b(eq, &fast_elements_case);
4707   GenerateCase(masm, FAST_HOLEY_ELEMENTS);
4708
4709   __ bind(&fast_elements_case);
4710   GenerateCase(masm, FAST_ELEMENTS);
4711 }
4712
4713
4714 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
4715   return ref0.address() - ref1.address();
4716 }
4717
4718
4719 // Calls an API function.  Allocates HandleScope, extracts returned value
4720 // from handle and propagates exceptions.  Restores context.  stack_space
4721 // - space to be unwound on exit (includes the call JS arguments space and
4722 // the additional space allocated for the fast call).
4723 static void CallApiFunctionAndReturn(MacroAssembler* masm,
4724                                      Register function_address,
4725                                      ExternalReference thunk_ref,
4726                                      int stack_space,
4727                                      MemOperand* stack_space_operand,
4728                                      MemOperand return_value_operand,
4729                                      MemOperand* context_restore_operand) {
4730   Isolate* isolate = masm->isolate();
4731   ExternalReference next_address =
4732       ExternalReference::handle_scope_next_address(isolate);
4733   const int kNextOffset = 0;
4734   const int kLimitOffset = AddressOffset(
4735       ExternalReference::handle_scope_limit_address(isolate), next_address);
4736   const int kLevelOffset = AddressOffset(
4737       ExternalReference::handle_scope_level_address(isolate), next_address);
4738
4739   DCHECK(function_address.is(r1) || function_address.is(r2));
4740
4741   Label profiler_disabled;
4742   Label end_profiler_check;
4743   __ mov(r9, Operand(ExternalReference::is_profiling_address(isolate)));
4744   __ ldrb(r9, MemOperand(r9, 0));
4745   __ cmp(r9, Operand(0));
4746   __ b(eq, &profiler_disabled);
4747
4748   // Additional parameter is the address of the actual callback.
4749   __ mov(r3, Operand(thunk_ref));
4750   __ jmp(&end_profiler_check);
4751
4752   __ bind(&profiler_disabled);
4753   __ Move(r3, function_address);
4754   __ bind(&end_profiler_check);
4755
4756   // Allocate HandleScope in callee-save registers.
4757   __ mov(r9, Operand(next_address));
4758   __ ldr(r4, MemOperand(r9, kNextOffset));
4759   __ ldr(r5, MemOperand(r9, kLimitOffset));
4760   __ ldr(r6, MemOperand(r9, kLevelOffset));
4761   __ add(r6, r6, Operand(1));
4762   __ str(r6, MemOperand(r9, kLevelOffset));
4763
4764   if (FLAG_log_timer_events) {
4765     FrameScope frame(masm, StackFrame::MANUAL);
4766     __ PushSafepointRegisters();
4767     __ PrepareCallCFunction(1, r0);
4768     __ mov(r0, Operand(ExternalReference::isolate_address(isolate)));
4769     __ CallCFunction(ExternalReference::log_enter_external_function(isolate),
4770                      1);
4771     __ PopSafepointRegisters();
4772   }
4773
4774   // Native call returns to the DirectCEntry stub which redirects to the
4775   // return address pushed on stack (could have moved after GC).
4776   // DirectCEntry stub itself is generated early and never moves.
4777   DirectCEntryStub stub(isolate);
4778   stub.GenerateCall(masm, r3);
4779
4780   if (FLAG_log_timer_events) {
4781     FrameScope frame(masm, StackFrame::MANUAL);
4782     __ PushSafepointRegisters();
4783     __ PrepareCallCFunction(1, r0);
4784     __ mov(r0, Operand(ExternalReference::isolate_address(isolate)));
4785     __ CallCFunction(ExternalReference::log_leave_external_function(isolate),
4786                      1);
4787     __ PopSafepointRegisters();
4788   }
4789
4790   Label promote_scheduled_exception;
4791   Label exception_handled;
4792   Label delete_allocated_handles;
4793   Label leave_exit_frame;
4794   Label return_value_loaded;
4795
4796   // load value from ReturnValue
4797   __ ldr(r0, return_value_operand);
4798   __ bind(&return_value_loaded);
4799   // No more valid handles (the result handle was the last one). Restore
4800   // previous handle scope.
4801   __ str(r4, MemOperand(r9, kNextOffset));
4802   if (__ emit_debug_code()) {
4803     __ ldr(r1, MemOperand(r9, kLevelOffset));
4804     __ cmp(r1, r6);
4805     __ Check(eq, kUnexpectedLevelAfterReturnFromApiCall);
4806   }
4807   __ sub(r6, r6, Operand(1));
4808   __ str(r6, MemOperand(r9, kLevelOffset));
4809   __ ldr(ip, MemOperand(r9, kLimitOffset));
4810   __ cmp(r5, ip);
4811   __ b(ne, &delete_allocated_handles);
4812
4813   // Check if the function scheduled an exception.
4814   __ bind(&leave_exit_frame);
4815   __ LoadRoot(r4, Heap::kTheHoleValueRootIndex);
4816   __ mov(ip, Operand(ExternalReference::scheduled_exception_address(isolate)));
4817   __ ldr(r5, MemOperand(ip));
4818   __ cmp(r4, r5);
4819   __ b(ne, &promote_scheduled_exception);
4820   __ bind(&exception_handled);
4821
4822   bool restore_context = context_restore_operand != NULL;
4823   if (restore_context) {
4824     __ ldr(cp, *context_restore_operand);
4825   }
4826   // LeaveExitFrame expects unwind space to be in a register.
4827   if (stack_space_operand != NULL) {
4828     __ ldr(r4, *stack_space_operand);
4829   } else {
4830     __ mov(r4, Operand(stack_space));
4831   }
4832   __ LeaveExitFrame(false, r4, !restore_context, stack_space_operand != NULL);
4833   __ mov(pc, lr);
4834
4835   __ bind(&promote_scheduled_exception);
4836   {
4837     FrameScope frame(masm, StackFrame::INTERNAL);
4838     __ CallExternalReference(
4839         ExternalReference(Runtime::kPromoteScheduledException, isolate), 0);
4840   }
4841   __ jmp(&exception_handled);
4842
4843   // HandleScope limit has changed. Delete allocated extensions.
4844   __ bind(&delete_allocated_handles);
4845   __ str(r5, MemOperand(r9, kLimitOffset));
4846   __ mov(r4, r0);
4847   __ PrepareCallCFunction(1, r5);
4848   __ mov(r0, Operand(ExternalReference::isolate_address(isolate)));
4849   __ CallCFunction(ExternalReference::delete_handle_scope_extensions(isolate),
4850                    1);
4851   __ mov(r0, r4);
4852   __ jmp(&leave_exit_frame);
4853 }
4854
4855
4856 static void CallApiFunctionStubHelper(MacroAssembler* masm,
4857                                       const ParameterCount& argc,
4858                                       bool return_first_arg,
4859                                       bool call_data_undefined) {
4860   // ----------- S t a t e -------------
4861   //  -- r0                  : callee
4862   //  -- r4                  : call_data
4863   //  -- r2                  : holder
4864   //  -- r1                  : api_function_address
4865   //  -- r3                  : number of arguments if argc is a register
4866   //  -- cp                  : context
4867   //  --
4868   //  -- sp[0]               : last argument
4869   //  -- ...
4870   //  -- sp[(argc - 1)* 4]   : first argument
4871   //  -- sp[argc * 4]        : receiver
4872   // -----------------------------------
4873
4874   Register callee = r0;
4875   Register call_data = r4;
4876   Register holder = r2;
4877   Register api_function_address = r1;
4878   Register context = cp;
4879
4880   typedef FunctionCallbackArguments FCA;
4881
4882   STATIC_ASSERT(FCA::kContextSaveIndex == 6);
4883   STATIC_ASSERT(FCA::kCalleeIndex == 5);
4884   STATIC_ASSERT(FCA::kDataIndex == 4);
4885   STATIC_ASSERT(FCA::kReturnValueOffset == 3);
4886   STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
4887   STATIC_ASSERT(FCA::kIsolateIndex == 1);
4888   STATIC_ASSERT(FCA::kHolderIndex == 0);
4889   STATIC_ASSERT(FCA::kArgsLength == 7);
4890
4891   DCHECK(argc.is_immediate() || r3.is(argc.reg()));
4892
4893   // context save
4894   __ push(context);
4895   // load context from callee
4896   __ ldr(context, FieldMemOperand(callee, JSFunction::kContextOffset));
4897
4898   // callee
4899   __ push(callee);
4900
4901   // call data
4902   __ push(call_data);
4903
4904   Register scratch = call_data;
4905   if (!call_data_undefined) {
4906     __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
4907   }
4908   // return value
4909   __ push(scratch);
4910   // return value default
4911   __ push(scratch);
4912   // isolate
4913   __ mov(scratch, Operand(ExternalReference::isolate_address(masm->isolate())));
4914   __ push(scratch);
4915   // holder
4916   __ push(holder);
4917
4918   // Prepare arguments.
4919   __ mov(scratch, sp);
4920
4921   // Allocate the v8::Arguments structure in the arguments' space since
4922   // it's not controlled by GC.
4923   const int kApiStackSpace = 4;
4924
4925   FrameScope frame_scope(masm, StackFrame::MANUAL);
4926   __ EnterExitFrame(false, kApiStackSpace);
4927
4928   DCHECK(!api_function_address.is(r0) && !scratch.is(r0));
4929   // r0 = FunctionCallbackInfo&
4930   // Arguments is after the return address.
4931   __ add(r0, sp, Operand(1 * kPointerSize));
4932   // FunctionCallbackInfo::implicit_args_
4933   __ str(scratch, MemOperand(r0, 0 * kPointerSize));
4934   if (argc.is_immediate()) {
4935     // FunctionCallbackInfo::values_
4936     __ add(ip, scratch,
4937            Operand((FCA::kArgsLength - 1 + argc.immediate()) * kPointerSize));
4938     __ str(ip, MemOperand(r0, 1 * kPointerSize));
4939     // FunctionCallbackInfo::length_ = argc
4940     __ mov(ip, Operand(argc.immediate()));
4941     __ str(ip, MemOperand(r0, 2 * kPointerSize));
4942     // FunctionCallbackInfo::is_construct_call_ = 0
4943     __ mov(ip, Operand::Zero());
4944     __ str(ip, MemOperand(r0, 3 * kPointerSize));
4945   } else {
4946     // FunctionCallbackInfo::values_
4947     __ add(ip, scratch, Operand(argc.reg(), LSL, kPointerSizeLog2));
4948     __ add(ip, ip, Operand((FCA::kArgsLength - 1) * kPointerSize));
4949     __ str(ip, MemOperand(r0, 1 * kPointerSize));
4950     // FunctionCallbackInfo::length_ = argc
4951     __ str(argc.reg(), MemOperand(r0, 2 * kPointerSize));
4952     // FunctionCallbackInfo::is_construct_call_
4953     __ add(argc.reg(), argc.reg(), Operand(FCA::kArgsLength + 1));
4954     __ mov(ip, Operand(argc.reg(), LSL, kPointerSizeLog2));
4955     __ str(ip, MemOperand(r0, 3 * kPointerSize));
4956   }
4957
4958   ExternalReference thunk_ref =
4959       ExternalReference::invoke_function_callback(masm->isolate());
4960
4961   AllowExternalCallThatCantCauseGC scope(masm);
4962   MemOperand context_restore_operand(
4963       fp, (2 + FCA::kContextSaveIndex) * kPointerSize);
4964   // Stores return the first js argument
4965   int return_value_offset = 0;
4966   if (return_first_arg) {
4967     return_value_offset = 2 + FCA::kArgsLength;
4968   } else {
4969     return_value_offset = 2 + FCA::kReturnValueOffset;
4970   }
4971   MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
4972   int stack_space = 0;
4973   MemOperand is_construct_call_operand = MemOperand(sp, 4 * kPointerSize);
4974   MemOperand* stack_space_operand = &is_construct_call_operand;
4975   if (argc.is_immediate()) {
4976     stack_space = argc.immediate() + FCA::kArgsLength + 1;
4977     stack_space_operand = NULL;
4978   }
4979   CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space,
4980                            stack_space_operand, return_value_operand,
4981                            &context_restore_operand);
4982 }
4983
4984
4985 void CallApiFunctionStub::Generate(MacroAssembler* masm) {
4986   bool call_data_undefined = this->call_data_undefined();
4987   CallApiFunctionStubHelper(masm, ParameterCount(r3), false,
4988                             call_data_undefined);
4989 }
4990
4991
4992 void CallApiAccessorStub::Generate(MacroAssembler* masm) {
4993   bool is_store = this->is_store();
4994   int argc = this->argc();
4995   bool call_data_undefined = this->call_data_undefined();
4996   CallApiFunctionStubHelper(masm, ParameterCount(argc), is_store,
4997                             call_data_undefined);
4998 }
4999
5000
5001 void CallApiGetterStub::Generate(MacroAssembler* masm) {
5002   // ----------- S t a t e -------------
5003   //  -- sp[0]                  : name
5004   //  -- sp[4 - kArgsLength*4]  : PropertyCallbackArguments object
5005   //  -- ...
5006   //  -- r2                     : api_function_address
5007   // -----------------------------------
5008
5009   Register api_function_address = ApiGetterDescriptor::function_address();
5010   DCHECK(api_function_address.is(r2));
5011
5012   __ mov(r0, sp);  // r0 = Handle<Name>
5013   __ add(r1, r0, Operand(1 * kPointerSize));  // r1 = PCA
5014
5015   const int kApiStackSpace = 1;
5016   FrameScope frame_scope(masm, StackFrame::MANUAL);
5017   __ EnterExitFrame(false, kApiStackSpace);
5018
5019   // Create PropertyAccessorInfo instance on the stack above the exit frame with
5020   // r1 (internal::Object** args_) as the data.
5021   __ str(r1, MemOperand(sp, 1 * kPointerSize));
5022   __ add(r1, sp, Operand(1 * kPointerSize));  // r1 = AccessorInfo&
5023
5024   const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
5025
5026   ExternalReference thunk_ref =
5027       ExternalReference::invoke_accessor_getter_callback(isolate());
5028   CallApiFunctionAndReturn(masm, api_function_address, thunk_ref,
5029                            kStackUnwindSpace, NULL,
5030                            MemOperand(fp, 6 * kPointerSize), NULL);
5031 }
5032
5033
5034 #undef __
5035
5036 } }  // namespace v8::internal
5037
5038 #endif  // V8_TARGET_ARCH_ARM