[runtime] Initial step towards switching Execution::Call to callable.
[platform/upstream/v8.git] / src / arm / builtins-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 #if V8_TARGET_ARCH_ARM
6
7 #include "src/codegen.h"
8 #include "src/debug/debug.h"
9 #include "src/deoptimizer.h"
10 #include "src/full-codegen/full-codegen.h"
11 #include "src/runtime/runtime.h"
12
13 namespace v8 {
14 namespace internal {
15
16
17 #define __ ACCESS_MASM(masm)
18
19
20 void Builtins::Generate_Adaptor(MacroAssembler* masm,
21                                 CFunctionId id,
22                                 BuiltinExtraArguments extra_args) {
23   // ----------- S t a t e -------------
24   //  -- r0                 : number of arguments excluding receiver
25   //  -- r1                 : called function (only guaranteed when
26   //                          extra_args requires it)
27   //  -- cp                 : context
28   //  -- sp[0]              : last argument
29   //  -- ...
30   //  -- sp[4 * (argc - 1)] : first argument (argc == r0)
31   //  -- sp[4 * argc]       : receiver
32   // -----------------------------------
33
34   // Insert extra arguments.
35   int num_extra_args = 0;
36   if (extra_args == NEEDS_CALLED_FUNCTION) {
37     num_extra_args = 1;
38     __ push(r1);
39   } else {
40     DCHECK(extra_args == NO_EXTRA_ARGUMENTS);
41   }
42
43   // JumpToExternalReference expects r0 to contain the number of arguments
44   // including the receiver and the extra arguments.
45   __ add(r0, r0, Operand(num_extra_args + 1));
46   __ JumpToExternalReference(ExternalReference(id, masm->isolate()));
47 }
48
49
50 // Load the built-in InternalArray function from the current context.
51 static void GenerateLoadInternalArrayFunction(MacroAssembler* masm,
52                                               Register result) {
53   // Load the native context.
54
55   __ ldr(result,
56          MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
57   __ ldr(result,
58          FieldMemOperand(result, GlobalObject::kNativeContextOffset));
59   // Load the InternalArray function from the native context.
60   __ ldr(result,
61          MemOperand(result,
62                     Context::SlotOffset(
63                         Context::INTERNAL_ARRAY_FUNCTION_INDEX)));
64 }
65
66
67 // Load the built-in Array function from the current context.
68 static void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) {
69   // Load the native context.
70
71   __ ldr(result,
72          MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
73   __ ldr(result,
74          FieldMemOperand(result, GlobalObject::kNativeContextOffset));
75   // Load the Array function from the native context.
76   __ ldr(result,
77          MemOperand(result,
78                     Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
79 }
80
81
82 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
83   // ----------- S t a t e -------------
84   //  -- r0     : number of arguments
85   //  -- lr     : return address
86   //  -- sp[...]: constructor arguments
87   // -----------------------------------
88   Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
89
90   // Get the InternalArray function.
91   GenerateLoadInternalArrayFunction(masm, r1);
92
93   if (FLAG_debug_code) {
94     // Initial map for the builtin InternalArray functions should be maps.
95     __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
96     __ SmiTst(r2);
97     __ Assert(ne, kUnexpectedInitialMapForInternalArrayFunction);
98     __ CompareObjectType(r2, r3, r4, MAP_TYPE);
99     __ Assert(eq, kUnexpectedInitialMapForInternalArrayFunction);
100   }
101
102   // Run the native code for the InternalArray function called as a normal
103   // function.
104   // tail call a stub
105   InternalArrayConstructorStub stub(masm->isolate());
106   __ TailCallStub(&stub);
107 }
108
109
110 void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
111   // ----------- S t a t e -------------
112   //  -- r0     : number of arguments
113   //  -- lr     : return address
114   //  -- sp[...]: constructor arguments
115   // -----------------------------------
116   Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
117
118   // Get the Array function.
119   GenerateLoadArrayFunction(masm, r1);
120
121   if (FLAG_debug_code) {
122     // Initial map for the builtin Array functions should be maps.
123     __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
124     __ SmiTst(r2);
125     __ Assert(ne, kUnexpectedInitialMapForArrayFunction);
126     __ CompareObjectType(r2, r3, r4, MAP_TYPE);
127     __ Assert(eq, kUnexpectedInitialMapForArrayFunction);
128   }
129
130   __ mov(r3, r1);
131   // Run the native code for the Array function called as a normal function.
132   // tail call a stub
133   __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
134   ArrayConstructorStub stub(masm->isolate());
135   __ TailCallStub(&stub);
136 }
137
138
139 // static
140 void Builtins::Generate_StringConstructor(MacroAssembler* masm) {
141   // ----------- S t a t e -------------
142   //  -- r0                     : number of arguments
143   //  -- r1                     : constructor function
144   //  -- lr                     : return address
145   //  -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
146   //  -- sp[argc * 4]           : receiver
147   // -----------------------------------
148
149   // 1. Load the first argument into r0 and get rid of the rest (including the
150   // receiver).
151   Label no_arguments;
152   {
153     __ sub(r0, r0, Operand(1), SetCC);
154     __ b(lo, &no_arguments);
155     __ ldr(r0, MemOperand(sp, r0, LSL, kPointerSizeLog2, PreIndex));
156     __ Drop(2);
157   }
158
159   // 2a. At least one argument, return r0 if it's a string, otherwise
160   // dispatch to appropriate conversion.
161   Label to_string, symbol_descriptive_string;
162   {
163     __ JumpIfSmi(r0, &to_string);
164     STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE);
165     __ CompareObjectType(r0, r1, r1, FIRST_NONSTRING_TYPE);
166     __ b(hi, &to_string);
167     __ b(eq, &symbol_descriptive_string);
168     __ Ret();
169   }
170
171   // 2b. No arguments, return the empty string (and pop the receiver).
172   __ bind(&no_arguments);
173   {
174     __ LoadRoot(r0, Heap::kempty_stringRootIndex);
175     __ Ret(1);
176   }
177
178   // 3a. Convert r0 to a string.
179   __ bind(&to_string);
180   {
181     ToStringStub stub(masm->isolate());
182     __ TailCallStub(&stub);
183   }
184
185   // 3b. Convert symbol in r0 to a string.
186   __ bind(&symbol_descriptive_string);
187   {
188     __ Push(r0);
189     __ TailCallRuntime(Runtime::kSymbolDescriptiveString, 1, 1);
190   }
191 }
192
193
194 // static
195 void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
196   // ----------- S t a t e -------------
197   //  -- r0                     : number of arguments
198   //  -- r1                     : constructor function
199   //  -- lr                     : return address
200   //  -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
201   //  -- sp[argc * 4]           : receiver
202   // -----------------------------------
203
204   // 1. Load the first argument into r0 and get rid of the rest (including the
205   // receiver).
206   {
207     Label no_arguments, done;
208     __ sub(r0, r0, Operand(1), SetCC);
209     __ b(lo, &no_arguments);
210     __ ldr(r0, MemOperand(sp, r0, LSL, kPointerSizeLog2, PreIndex));
211     __ Drop(2);
212     __ b(&done);
213     __ bind(&no_arguments);
214     __ LoadRoot(r0, Heap::kempty_stringRootIndex);
215     __ Drop(1);
216     __ bind(&done);
217   }
218
219   // 2. Make sure r0 is a string.
220   {
221     Label convert, done_convert;
222     __ JumpIfSmi(r0, &convert);
223     __ CompareObjectType(r0, r2, r2, FIRST_NONSTRING_TYPE);
224     __ b(lo, &done_convert);
225     __ bind(&convert);
226     {
227       FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
228       ToStringStub stub(masm->isolate());
229       __ Push(r1);
230       __ CallStub(&stub);
231       __ Pop(r1);
232     }
233     __ bind(&done_convert);
234   }
235
236   // 3. Allocate a JSValue wrapper for the string.
237   {
238     // ----------- S t a t e -------------
239     //  -- r0 : the first argument
240     //  -- r1 : constructor function
241     //  -- lr : return address
242     // -----------------------------------
243
244     Label allocate, done_allocate;
245     __ Move(r2, r0);
246     __ Allocate(JSValue::kSize, r0, r3, r4, &allocate, TAG_OBJECT);
247     __ bind(&done_allocate);
248
249     // Initialize the JSValue in r0.
250     __ LoadGlobalFunctionInitialMap(r1, r3, r4);
251     __ str(r3, FieldMemOperand(r0, HeapObject::kMapOffset));
252     __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex);
253     __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset));
254     __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset));
255     __ str(r2, FieldMemOperand(r0, JSValue::kValueOffset));
256     STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
257     __ Ret();
258
259     // Fallback to the runtime to allocate in new space.
260     __ bind(&allocate);
261     {
262       FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
263       __ Move(r3, Smi::FromInt(JSValue::kSize));
264       __ Push(r1, r2, r3);
265       __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
266       __ Pop(r1, r2);
267     }
268     __ b(&done_allocate);
269   }
270 }
271
272
273 static void CallRuntimePassFunction(
274     MacroAssembler* masm, Runtime::FunctionId function_id) {
275   FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
276   // Push a copy of the function onto the stack.
277   __ push(r1);
278   // Push function as parameter to the runtime call.
279   __ Push(r1);
280
281   __ CallRuntime(function_id, 1);
282   // Restore receiver.
283   __ pop(r1);
284 }
285
286
287 static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
288   __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
289   __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCodeOffset));
290   __ add(r2, r2, Operand(Code::kHeaderSize - kHeapObjectTag));
291   __ Jump(r2);
292 }
293
294
295 static void GenerateTailCallToReturnedCode(MacroAssembler* masm) {
296   __ add(r0, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
297   __ Jump(r0);
298 }
299
300
301 void Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) {
302   // Checking whether the queued function is ready for install is optional,
303   // since we come across interrupts and stack checks elsewhere.  However,
304   // not checking may delay installing ready functions, and always checking
305   // would be quite expensive.  A good compromise is to first check against
306   // stack limit as a cue for an interrupt signal.
307   Label ok;
308   __ LoadRoot(ip, Heap::kStackLimitRootIndex);
309   __ cmp(sp, Operand(ip));
310   __ b(hs, &ok);
311
312   CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode);
313   GenerateTailCallToReturnedCode(masm);
314
315   __ bind(&ok);
316   GenerateTailCallToSharedCode(masm);
317 }
318
319
320 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
321                                            bool is_api_function) {
322   // ----------- S t a t e -------------
323   //  -- r0     : number of arguments
324   //  -- r1     : constructor function
325   //  -- r2     : allocation site or undefined
326   //  -- r3     : original constructor
327   //  -- lr     : return address
328   //  -- sp[...]: constructor arguments
329   // -----------------------------------
330
331   Isolate* isolate = masm->isolate();
332
333   // Enter a construct frame.
334   {
335     FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT);
336
337     // Preserve the incoming parameters on the stack.
338     __ AssertUndefinedOrAllocationSite(r2, r4);
339     __ push(r2);
340     __ SmiTag(r0);
341     __ push(r0);
342     __ push(r1);
343     __ push(r3);
344
345     // Try to allocate the object without transitioning into C code. If any of
346     // the preconditions is not met, the code bails out to the runtime call.
347     Label rt_call, allocated;
348     if (FLAG_inline_new) {
349       ExternalReference debug_step_in_fp =
350           ExternalReference::debug_step_in_fp_address(isolate);
351       __ mov(r2, Operand(debug_step_in_fp));
352       __ ldr(r2, MemOperand(r2));
353       __ tst(r2, r2);
354       __ b(ne, &rt_call);
355
356       // Fall back to runtime if the original constructor and function differ.
357       __ cmp(r1, r3);
358       __ b(ne, &rt_call);
359
360       // Load the initial map and verify that it is in fact a map.
361       // r1: constructor function
362       __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
363       __ JumpIfSmi(r2, &rt_call);
364       __ CompareObjectType(r2, r5, r4, MAP_TYPE);
365       __ b(ne, &rt_call);
366
367       // Check that the constructor is not constructing a JSFunction (see
368       // comments in Runtime_NewObject in runtime.cc). In which case the
369       // initial map's instance type would be JS_FUNCTION_TYPE.
370       // r1: constructor function
371       // r2: initial map
372       __ CompareInstanceType(r2, r5, JS_FUNCTION_TYPE);
373       __ b(eq, &rt_call);
374
375       if (!is_api_function) {
376         Label allocate;
377         MemOperand bit_field3 = FieldMemOperand(r2, Map::kBitField3Offset);
378         // Check if slack tracking is enabled.
379         __ ldr(r4, bit_field3);
380         __ DecodeField<Map::Counter>(r3, r4);
381         __ cmp(r3, Operand(Map::kSlackTrackingCounterEnd));
382         __ b(lt, &allocate);
383         // Decrease generous allocation count.
384         __ sub(r4, r4, Operand(1 << Map::Counter::kShift));
385         __ str(r4, bit_field3);
386         __ cmp(r3, Operand(Map::kSlackTrackingCounterEnd));
387         __ b(ne, &allocate);
388
389         __ push(r1);
390
391         __ Push(r2, r1);  // r1 = constructor
392         __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
393
394         __ pop(r2);
395         __ pop(r1);
396
397         __ bind(&allocate);
398       }
399
400       // Now allocate the JSObject on the heap.
401       // r1: constructor function
402       // r2: initial map
403       Label rt_call_reload_new_target;
404       __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
405
406       __ Allocate(r3, r4, r5, r6, &rt_call_reload_new_target, SIZE_IN_WORDS);
407
408       // Allocated the JSObject, now initialize the fields. Map is set to
409       // initial map and properties and elements are set to empty fixed array.
410       // r1: constructor function
411       // r2: initial map
412       // r3: object size
413       // r4: JSObject (not tagged)
414       __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
415       __ mov(r5, r4);
416       DCHECK_EQ(0 * kPointerSize, JSObject::kMapOffset);
417       __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
418       DCHECK_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
419       __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
420       DCHECK_EQ(2 * kPointerSize, JSObject::kElementsOffset);
421       __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
422
423       // Fill all the in-object properties with the appropriate filler.
424       // r1: constructor function
425       // r2: initial map
426       // r3: object size
427       // r4: JSObject (not tagged)
428       // r5: First in-object property of JSObject (not tagged)
429       DCHECK_EQ(3 * kPointerSize, JSObject::kHeaderSize);
430       __ LoadRoot(r6, Heap::kUndefinedValueRootIndex);
431
432       if (!is_api_function) {
433         Label no_inobject_slack_tracking;
434
435         // Check if slack tracking is enabled.
436         __ ldr(ip, FieldMemOperand(r2, Map::kBitField3Offset));
437         __ DecodeField<Map::Counter>(ip);
438         __ cmp(ip, Operand(Map::kSlackTrackingCounterEnd));
439         __ b(lt, &no_inobject_slack_tracking);
440
441         // Allocate object with a slack.
442         __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
443         __ Ubfx(r0, r0, Map::kInObjectPropertiesOrConstructorFunctionIndexByte *
444                             kBitsPerByte,
445                 kBitsPerByte);
446         __ ldr(r2, FieldMemOperand(r2, Map::kInstanceAttributesOffset));
447         __ Ubfx(r2, r2, Map::kUnusedPropertyFieldsByte * kBitsPerByte,
448                 kBitsPerByte);
449         __ sub(r0, r0, Operand(r2));
450         __ add(r0, r5, Operand(r0, LSL, kPointerSizeLog2));
451         // r0: offset of first field after pre-allocated fields
452         if (FLAG_debug_code) {
453           __ add(ip, r4, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
454           __ cmp(r0, ip);
455           __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields);
456         }
457         __ InitializeFieldsWithFiller(r5, r0, r6);
458         // To allow for truncation.
459         __ LoadRoot(r6, Heap::kOnePointerFillerMapRootIndex);
460         // Fill the remaining fields with one pointer filler map.
461
462         __ bind(&no_inobject_slack_tracking);
463       }
464
465       __ add(r0, r4, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
466       __ InitializeFieldsWithFiller(r5, r0, r6);
467
468       // Add the object tag to make the JSObject real, so that we can continue
469       // and jump into the continuation code at any time from now on.
470       __ add(r4, r4, Operand(kHeapObjectTag));
471
472       // Continue with JSObject being successfully allocated
473       // r4: JSObject
474       __ jmp(&allocated);
475
476       // Reload the original constructor and fall-through.
477       __ bind(&rt_call_reload_new_target);
478       __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
479     }
480
481     // Allocate the new receiver object using the runtime call.
482     // r1: constructor function
483     // r3: original constructor
484     __ bind(&rt_call);
485
486     __ push(r1);  // argument 2/1: constructor function
487     __ push(r3);  // argument 3/2: original constructor
488     __ CallRuntime(Runtime::kNewObject, 2);
489     __ mov(r4, r0);
490
491     // Receiver for constructor call allocated.
492     // r4: JSObject
493     __ bind(&allocated);
494
495     // Restore the parameters.
496     __ pop(r3);
497     __ pop(r1);
498
499     // Retrieve smi-tagged arguments count from the stack.
500     __ ldr(r0, MemOperand(sp));
501     __ SmiUntag(r0);
502
503     // Push new.target onto the construct frame. This is stored just below the
504     // receiver on the stack.
505     __ push(r3);
506     __ push(r4);
507     __ push(r4);
508
509     // Set up pointer to last argument.
510     __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
511
512     // Copy arguments and receiver to the expression stack.
513     // r0: number of arguments
514     // r1: constructor function
515     // r2: address of last argument (caller sp)
516     // r3: number of arguments (smi-tagged)
517     // sp[0]: receiver
518     // sp[1]: receiver
519     // sp[2]: new.target
520     // sp[3]: number of arguments (smi-tagged)
521     Label loop, entry;
522     __ SmiTag(r3, r0);
523     __ b(&entry);
524     __ bind(&loop);
525     __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1));
526     __ push(ip);
527     __ bind(&entry);
528     __ sub(r3, r3, Operand(2), SetCC);
529     __ b(ge, &loop);
530
531     // Call the function.
532     // r0: number of arguments
533     // r1: constructor function
534     if (is_api_function) {
535       __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
536       Handle<Code> code =
537           masm->isolate()->builtins()->HandleApiCallConstruct();
538       __ Call(code, RelocInfo::CODE_TARGET);
539     } else {
540       ParameterCount actual(r0);
541       __ InvokeFunction(r1, actual, CALL_FUNCTION, NullCallWrapper());
542     }
543
544     // Store offset of return address for deoptimizer.
545     if (!is_api_function) {
546       masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
547     }
548
549     // Restore context from the frame.
550     // r0: result
551     // sp[0]: receiver
552     // sp[1]: new.target
553     // sp[2]: number of arguments (smi-tagged)
554     __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
555
556     // If the result is an object (in the ECMA sense), we should get rid
557     // of the receiver and use the result; see ECMA-262 section 13.2.2-7
558     // on page 74.
559     Label use_receiver, exit;
560
561     // If the result is a smi, it is *not* an object in the ECMA sense.
562     // r0: result
563     // sp[0]: receiver
564     // sp[1]: new.target
565     // sp[2]: number of arguments (smi-tagged)
566     __ JumpIfSmi(r0, &use_receiver);
567
568     // If the type of the result (stored in its map) is less than
569     // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
570     __ CompareObjectType(r0, r1, r3, FIRST_SPEC_OBJECT_TYPE);
571     __ b(ge, &exit);
572
573     // Throw away the result of the constructor invocation and use the
574     // on-stack receiver as the result.
575     __ bind(&use_receiver);
576     __ ldr(r0, MemOperand(sp));
577
578     // Remove receiver from the stack, remove caller arguments, and
579     // return.
580     __ bind(&exit);
581     // r0: result
582     // sp[0]: receiver (newly allocated object)
583     // sp[1]: new.target (original constructor)
584     // sp[2]: number of arguments (smi-tagged)
585     __ ldr(r1, MemOperand(sp, 2 * kPointerSize));
586
587     // Leave construct frame.
588   }
589
590   __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
591   __ add(sp, sp, Operand(kPointerSize));
592   __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2);
593   __ Jump(lr);
594 }
595
596
597 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
598   Generate_JSConstructStubHelper(masm, false);
599 }
600
601
602 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
603   Generate_JSConstructStubHelper(masm, true);
604 }
605
606
607 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
608   // ----------- S t a t e -------------
609   //  -- r0     : number of arguments
610   //  -- r1     : constructor function
611   //  -- r2     : allocation site or undefined
612   //  -- r3     : original constructor
613   //  -- lr     : return address
614   //  -- sp[...]: constructor arguments
615   // -----------------------------------
616
617   {
618     FrameScope frame_scope(masm, StackFrame::CONSTRUCT);
619
620     __ AssertUndefinedOrAllocationSite(r2, r4);
621     __ push(r2);
622
623     __ mov(r4, r0);
624     __ SmiTag(r4);
625     __ push(r4);  // Smi-tagged arguments count.
626
627     // Push new.target.
628     __ push(r3);
629
630     // receiver is the hole.
631     __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
632     __ push(ip);
633
634     // Set up pointer to last argument.
635     __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
636
637     // Copy arguments and receiver to the expression stack.
638     // r0: number of arguments
639     // r1: constructor function
640     // r2: address of last argument (caller sp)
641     // r4: number of arguments (smi-tagged)
642     // sp[0]: receiver
643     // sp[1]: new.target
644     // sp[2]: number of arguments (smi-tagged)
645     Label loop, entry;
646     __ b(&entry);
647     __ bind(&loop);
648     __ ldr(ip, MemOperand(r2, r4, LSL, kPointerSizeLog2 - 1));
649     __ push(ip);
650     __ bind(&entry);
651     __ sub(r4, r4, Operand(2), SetCC);
652     __ b(ge, &loop);
653
654     // Handle step in.
655     Label skip_step_in;
656     ExternalReference debug_step_in_fp =
657         ExternalReference::debug_step_in_fp_address(masm->isolate());
658     __ mov(r2, Operand(debug_step_in_fp));
659     __ ldr(r2, MemOperand(r2));
660     __ tst(r2, r2);
661     __ b(eq, &skip_step_in);
662
663     __ Push(r0);
664     __ Push(r1);
665     __ Push(r1);
666     __ CallRuntime(Runtime::kHandleStepInForDerivedConstructors, 1);
667     __ Pop(r1);
668     __ Pop(r0);
669
670     __ bind(&skip_step_in);
671
672     // Call the function.
673     // r0: number of arguments
674     // r1: constructor function
675     ParameterCount actual(r0);
676     __ InvokeFunction(r1, actual, CALL_FUNCTION, NullCallWrapper());
677
678     // Restore context from the frame.
679     // r0: result
680     // sp[0]: number of arguments (smi-tagged)
681     __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
682     // Get arguments count, skipping over new.target.
683     __ ldr(r1, MemOperand(sp, kPointerSize));
684
685     // Leave construct frame.
686   }
687
688   __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
689   __ add(sp, sp, Operand(kPointerSize));
690   __ Jump(lr);
691 }
692
693
694 enum IsTagged { kArgcIsSmiTagged, kArgcIsUntaggedInt };
695
696
697 // Clobbers r2; preserves all other registers.
698 static void Generate_CheckStackOverflow(MacroAssembler* masm,
699                                         const int calleeOffset, Register argc,
700                                         IsTagged argc_is_tagged) {
701   // Check the stack for overflow. We are not trying to catch
702   // interruptions (e.g. debug break and preemption) here, so the "real stack
703   // limit" is checked.
704   Label okay;
705   __ LoadRoot(r2, Heap::kRealStackLimitRootIndex);
706   // Make r2 the space we have left. The stack might already be overflowed
707   // here which will cause r2 to become negative.
708   __ sub(r2, sp, r2);
709   // Check if the arguments will overflow the stack.
710   if (argc_is_tagged == kArgcIsSmiTagged) {
711     __ cmp(r2, Operand::PointerOffsetFromSmiKey(argc));
712   } else {
713     DCHECK(argc_is_tagged == kArgcIsUntaggedInt);
714     __ cmp(r2, Operand(argc, LSL, kPointerSizeLog2));
715   }
716   __ b(gt, &okay);  // Signed comparison.
717
718   // Out of stack space.
719   __ ldr(r1, MemOperand(fp, calleeOffset));
720   if (argc_is_tagged == kArgcIsUntaggedInt) {
721     __ SmiTag(argc);
722   }
723   __ Push(r1, argc);
724   __ CallRuntime(Runtime::kThrowStackOverflow, 0);
725
726   __ bind(&okay);
727 }
728
729
730 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
731                                              bool is_construct) {
732   // Called from Generate_JS_Entry
733   // r0: code entry
734   // r1: function
735   // r2: receiver
736   // r3: argc
737   // r4: argv
738   // r5-r6, r8 (if !FLAG_enable_embedded_constant_pool) and cp may be clobbered
739   ProfileEntryHookStub::MaybeCallEntryHook(masm);
740
741   // Clear the context before we push it when entering the internal frame.
742   __ mov(cp, Operand::Zero());
743
744   // Enter an internal frame.
745   {
746     FrameScope scope(masm, StackFrame::INTERNAL);
747
748     // Set up the context from the function argument.
749     __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
750
751     __ InitializeRootRegister();
752
753     // Push the function and the receiver onto the stack.
754     __ push(r1);
755     __ push(r2);
756
757     // Check if we have enough stack space to push all arguments.
758     // The function is the first thing that was pushed above after entering
759     // the internal frame.
760     const int kFunctionOffset =
761         InternalFrameConstants::kCodeOffset - kPointerSize;
762     // Clobbers r2.
763     Generate_CheckStackOverflow(masm, kFunctionOffset, r3, kArgcIsUntaggedInt);
764
765     // Copy arguments to the stack in a loop.
766     // r1: function
767     // r3: argc
768     // r4: argv, i.e. points to first arg
769     Label loop, entry;
770     __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2));
771     // r2 points past last arg.
772     __ b(&entry);
773     __ bind(&loop);
774     __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex));  // read next parameter
775     __ ldr(r0, MemOperand(r0));  // dereference handle
776     __ push(r0);  // push parameter
777     __ bind(&entry);
778     __ cmp(r4, r2);
779     __ b(ne, &loop);
780
781     // Initialize all JavaScript callee-saved registers, since they will be seen
782     // by the garbage collector as part of handlers.
783     __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
784     __ mov(r5, Operand(r4));
785     __ mov(r6, Operand(r4));
786     if (!FLAG_enable_embedded_constant_pool) {
787       __ mov(r8, Operand(r4));
788     }
789     if (kR9Available == 1) {
790       __ mov(r9, Operand(r4));
791     }
792
793     // Invoke the code and pass argc as r0.
794     __ mov(r0, Operand(r3));
795     if (is_construct) {
796       // No type feedback cell is available
797       __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
798       CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
799       __ CallStub(&stub);
800     } else {
801       __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
802     }
803     // Exit the JS frame and remove the parameters (except function), and
804     // return.
805     // Respect ABI stack constraint.
806   }
807   __ Jump(lr);
808
809   // r0: result
810 }
811
812
813 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
814   Generate_JSEntryTrampolineHelper(masm, false);
815 }
816
817
818 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
819   Generate_JSEntryTrampolineHelper(masm, true);
820 }
821
822
823 // Generate code for entering a JS function with the interpreter.
824 // On entry to the function the receiver and arguments have been pushed on the
825 // stack left to right.  The actual argument count matches the formal parameter
826 // count expected by the function.
827 //
828 // The live registers are:
829 //   o r1: the JS function object being called.
830 //   o cp: our context
831 //   o pp: the caller's constant pool pointer (if enabled)
832 //   o fp: the caller's frame pointer
833 //   o sp: stack pointer
834 //   o lr: return address
835 //
836 // The function builds a JS frame.  Please see JavaScriptFrameConstants in
837 // frames-arm.h for its layout.
838 // TODO(rmcilroy): We will need to include the current bytecode pointer in the
839 // frame.
840 void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
841   // Open a frame scope to indicate that there is a frame on the stack.  The
842   // MANUAL indicates that the scope shouldn't actually generate code to set up
843   // the frame (that is done below).
844   FrameScope frame_scope(masm, StackFrame::MANUAL);
845   __ PushFixedFrame(r1);
846   __ add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
847
848   // Get the bytecode array from the function object and load the pointer to the
849   // first entry into kInterpreterBytecodeRegister.
850   __ ldr(r0, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
851   __ ldr(kInterpreterBytecodeArrayRegister,
852          FieldMemOperand(r0, SharedFunctionInfo::kFunctionDataOffset));
853
854   if (FLAG_debug_code) {
855     // Check function data field is actually a BytecodeArray object.
856     __ SmiTst(kInterpreterBytecodeArrayRegister);
857     __ Assert(ne, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry);
858     __ CompareObjectType(kInterpreterBytecodeArrayRegister, r0, no_reg,
859                          BYTECODE_ARRAY_TYPE);
860     __ Assert(eq, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry);
861   }
862
863   // Allocate the local and temporary register file on the stack.
864   {
865     // Load frame size from the BytecodeArray object.
866     __ ldr(r4, FieldMemOperand(kInterpreterBytecodeArrayRegister,
867                                BytecodeArray::kFrameSizeOffset));
868
869     // Do a stack check to ensure we don't go over the limit.
870     Label ok;
871     __ sub(r9, sp, Operand(r4));
872     __ LoadRoot(r2, Heap::kRealStackLimitRootIndex);
873     __ cmp(r9, Operand(r2));
874     __ b(hs, &ok);
875     __ CallRuntime(Runtime::kThrowStackOverflow, 0);
876     __ bind(&ok);
877
878     // If ok, push undefined as the initial value for all register file entries.
879     Label loop_header;
880     Label loop_check;
881     __ LoadRoot(r9, Heap::kUndefinedValueRootIndex);
882     __ b(&loop_check, al);
883     __ bind(&loop_header);
884     // TODO(rmcilroy): Consider doing more than one push per loop iteration.
885     __ push(r9);
886     // Continue loop if not done.
887     __ bind(&loop_check);
888     __ sub(r4, r4, Operand(kPointerSize), SetCC);
889     __ b(&loop_header, ge);
890   }
891
892   // TODO(rmcilroy): List of things not currently dealt with here but done in
893   // fullcodegen's prologue:
894   //  - Support profiler (specifically profiling_counter).
895   //  - Call ProfileEntryHookStub when isolate has a function_entry_hook.
896   //  - Allow simulator stop operations if FLAG_stop_at is set.
897   //  - Deal with sloppy mode functions which need to replace the
898   //    receiver with the global proxy when called as functions (without an
899   //    explicit receiver object).
900   //  - Code aging of the BytecodeArray object.
901   //  - Supporting FLAG_trace.
902   //
903   // The following items are also not done here, and will probably be done using
904   // explicit bytecodes instead:
905   //  - Allocating a new local context if applicable.
906   //  - Setting up a local binding to the this function, which is used in
907   //    derived constructors with super calls.
908   //  - Setting new.target if required.
909   //  - Dealing with REST parameters (only if
910   //    https://codereview.chromium.org/1235153006 doesn't land by then).
911   //  - Dealing with argument objects.
912
913   // Perform stack guard check.
914   {
915     Label ok;
916     __ LoadRoot(ip, Heap::kStackLimitRootIndex);
917     __ cmp(sp, Operand(ip));
918     __ b(hs, &ok);
919     __ CallRuntime(Runtime::kStackGuard, 0);
920     __ bind(&ok);
921   }
922
923   // Load accumulator, register file, bytecode offset, dispatch table into
924   // registers.
925   __ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
926   __ sub(kInterpreterRegisterFileRegister, fp,
927          Operand(kPointerSize + StandardFrameConstants::kFixedFrameSizeFromFp));
928   __ mov(kInterpreterBytecodeOffsetRegister,
929          Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
930   __ LoadRoot(kInterpreterDispatchTableRegister,
931               Heap::kInterpreterTableRootIndex);
932   __ add(kInterpreterDispatchTableRegister, kInterpreterDispatchTableRegister,
933          Operand(FixedArray::kHeaderSize - kHeapObjectTag));
934
935   // Dispatch to the first bytecode handler for the function.
936   __ ldrb(r1, MemOperand(kInterpreterBytecodeArrayRegister,
937                          kInterpreterBytecodeOffsetRegister));
938   __ ldr(ip, MemOperand(kInterpreterDispatchTableRegister, r1, LSL,
939                         kPointerSizeLog2));
940   // TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging
941   // and header removal.
942   __ add(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
943   __ Call(ip);
944 }
945
946
947 void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
948   // TODO(rmcilroy): List of things not currently dealt with here but done in
949   // fullcodegen's EmitReturnSequence.
950   //  - Supporting FLAG_trace for Runtime::TraceExit.
951   //  - Support profiler (specifically decrementing profiling_counter
952   //    appropriately and calling out to HandleInterrupts if necessary).
953
954   // The return value is in accumulator, which is already in r0.
955
956   // Leave the frame (also dropping the register file).
957   __ LeaveFrame(StackFrame::JAVA_SCRIPT);
958
959   // Drop receiver + arguments and return.
960   __ ldr(ip, FieldMemOperand(kInterpreterBytecodeArrayRegister,
961                              BytecodeArray::kParameterSizeOffset));
962   __ add(sp, sp, ip, LeaveCC);
963   __ Jump(lr);
964 }
965
966
967 void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
968   CallRuntimePassFunction(masm, Runtime::kCompileLazy);
969   GenerateTailCallToReturnedCode(masm);
970 }
971
972
973 static void CallCompileOptimized(MacroAssembler* masm, bool concurrent) {
974   FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
975   // Push a copy of the function onto the stack.
976   __ push(r1);
977   // Push function as parameter to the runtime call.
978   __ Push(r1);
979   // Whether to compile in a background thread.
980   __ LoadRoot(
981       ip, concurrent ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex);
982   __ push(ip);
983
984   __ CallRuntime(Runtime::kCompileOptimized, 2);
985   // Restore receiver.
986   __ pop(r1);
987 }
988
989
990 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) {
991   CallCompileOptimized(masm, false);
992   GenerateTailCallToReturnedCode(masm);
993 }
994
995
996 void Builtins::Generate_CompileOptimizedConcurrent(MacroAssembler* masm) {
997   CallCompileOptimized(masm, true);
998   GenerateTailCallToReturnedCode(masm);
999 }
1000
1001
1002 static void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) {
1003   // For now, we are relying on the fact that make_code_young doesn't do any
1004   // garbage collection which allows us to save/restore the registers without
1005   // worrying about which of them contain pointers. We also don't build an
1006   // internal frame to make the code faster, since we shouldn't have to do stack
1007   // crawls in MakeCodeYoung. This seems a bit fragile.
1008
1009   // The following registers must be saved and restored when calling through to
1010   // the runtime:
1011   //   r0 - contains return address (beginning of patch sequence)
1012   //   r1 - isolate
1013   FrameScope scope(masm, StackFrame::MANUAL);
1014   __ stm(db_w, sp, r0.bit() | r1.bit() | fp.bit() | lr.bit());
1015   __ PrepareCallCFunction(2, 0, r2);
1016   __ mov(r1, Operand(ExternalReference::isolate_address(masm->isolate())));
1017   __ CallCFunction(
1018       ExternalReference::get_make_code_young_function(masm->isolate()), 2);
1019   __ ldm(ia_w, sp, r0.bit() | r1.bit() | fp.bit() | lr.bit());
1020   __ mov(pc, r0);
1021 }
1022
1023 #define DEFINE_CODE_AGE_BUILTIN_GENERATOR(C)                 \
1024 void Builtins::Generate_Make##C##CodeYoungAgainEvenMarking(  \
1025     MacroAssembler* masm) {                                  \
1026   GenerateMakeCodeYoungAgainCommon(masm);                    \
1027 }                                                            \
1028 void Builtins::Generate_Make##C##CodeYoungAgainOddMarking(   \
1029     MacroAssembler* masm) {                                  \
1030   GenerateMakeCodeYoungAgainCommon(masm);                    \
1031 }
1032 CODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR)
1033 #undef DEFINE_CODE_AGE_BUILTIN_GENERATOR
1034
1035
1036 void Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) {
1037   // For now, as in GenerateMakeCodeYoungAgainCommon, we are relying on the fact
1038   // that make_code_young doesn't do any garbage collection which allows us to
1039   // save/restore the registers without worrying about which of them contain
1040   // pointers.
1041
1042   // The following registers must be saved and restored when calling through to
1043   // the runtime:
1044   //   r0 - contains return address (beginning of patch sequence)
1045   //   r1 - isolate
1046   FrameScope scope(masm, StackFrame::MANUAL);
1047   __ stm(db_w, sp, r0.bit() | r1.bit() | fp.bit() | lr.bit());
1048   __ PrepareCallCFunction(2, 0, r2);
1049   __ mov(r1, Operand(ExternalReference::isolate_address(masm->isolate())));
1050   __ CallCFunction(ExternalReference::get_mark_code_as_executed_function(
1051         masm->isolate()), 2);
1052   __ ldm(ia_w, sp, r0.bit() | r1.bit() | fp.bit() | lr.bit());
1053
1054   // Perform prologue operations usually performed by the young code stub.
1055   __ PushFixedFrame(r1);
1056   __ add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
1057
1058   // Jump to point after the code-age stub.
1059   __ add(r0, r0, Operand(kNoCodeAgeSequenceLength));
1060   __ mov(pc, r0);
1061 }
1062
1063
1064 void Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) {
1065   GenerateMakeCodeYoungAgainCommon(masm);
1066 }
1067
1068
1069 void Builtins::Generate_MarkCodeAsToBeExecutedOnce(MacroAssembler* masm) {
1070   Generate_MarkCodeAsExecutedOnce(masm);
1071 }
1072
1073
1074 static void Generate_NotifyStubFailureHelper(MacroAssembler* masm,
1075                                              SaveFPRegsMode save_doubles) {
1076   {
1077     FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
1078
1079     // Preserve registers across notification, this is important for compiled
1080     // stubs that tail call the runtime on deopts passing their parameters in
1081     // registers.
1082     __ stm(db_w, sp, kJSCallerSaved | kCalleeSaved);
1083     // Pass the function and deoptimization type to the runtime system.
1084     __ CallRuntime(Runtime::kNotifyStubFailure, 0, save_doubles);
1085     __ ldm(ia_w, sp, kJSCallerSaved | kCalleeSaved);
1086   }
1087
1088   __ add(sp, sp, Operand(kPointerSize));  // Ignore state
1089   __ mov(pc, lr);  // Jump to miss handler
1090 }
1091
1092
1093 void Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) {
1094   Generate_NotifyStubFailureHelper(masm, kDontSaveFPRegs);
1095 }
1096
1097
1098 void Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) {
1099   Generate_NotifyStubFailureHelper(masm, kSaveFPRegs);
1100 }
1101
1102
1103 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
1104                                              Deoptimizer::BailoutType type) {
1105   {
1106     FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
1107     // Pass the function and deoptimization type to the runtime system.
1108     __ mov(r0, Operand(Smi::FromInt(static_cast<int>(type))));
1109     __ push(r0);
1110     __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
1111   }
1112
1113   // Get the full codegen state from the stack and untag it -> r6.
1114   __ ldr(r6, MemOperand(sp, 0 * kPointerSize));
1115   __ SmiUntag(r6);
1116   // Switch on the state.
1117   Label with_tos_register, unknown_state;
1118   __ cmp(r6, Operand(FullCodeGenerator::NO_REGISTERS));
1119   __ b(ne, &with_tos_register);
1120   __ add(sp, sp, Operand(1 * kPointerSize));  // Remove state.
1121   __ Ret();
1122
1123   __ bind(&with_tos_register);
1124   __ ldr(r0, MemOperand(sp, 1 * kPointerSize));
1125   __ cmp(r6, Operand(FullCodeGenerator::TOS_REG));
1126   __ b(ne, &unknown_state);
1127   __ add(sp, sp, Operand(2 * kPointerSize));  // Remove state.
1128   __ Ret();
1129
1130   __ bind(&unknown_state);
1131   __ stop("no cases left");
1132 }
1133
1134
1135 void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
1136   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
1137 }
1138
1139
1140 void Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) {
1141   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
1142 }
1143
1144
1145 void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
1146   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
1147 }
1148
1149
1150 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1151   // Lookup the function in the JavaScript frame.
1152   __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1153   {
1154     FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
1155     // Pass function as argument.
1156     __ push(r0);
1157     __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
1158   }
1159
1160   // If the code object is null, just return to the unoptimized code.
1161   Label skip;
1162   __ cmp(r0, Operand(Smi::FromInt(0)));
1163   __ b(ne, &skip);
1164   __ Ret();
1165
1166   __ bind(&skip);
1167
1168   // Load deoptimization data from the code object.
1169   // <deopt_data> = <code>[#deoptimization_data_offset]
1170   __ ldr(r1, FieldMemOperand(r0, Code::kDeoptimizationDataOffset));
1171
1172   { ConstantPoolUnavailableScope constant_pool_unavailable(masm);
1173     __ add(r0, r0, Operand(Code::kHeaderSize - kHeapObjectTag));  // Code start
1174
1175     if (FLAG_enable_embedded_constant_pool) {
1176       __ LoadConstantPoolPointerRegisterFromCodeTargetAddress(r0);
1177     }
1178
1179     // Load the OSR entrypoint offset from the deoptimization data.
1180     // <osr_offset> = <deopt_data>[#header_size + #osr_pc_offset]
1181     __ ldr(r1, FieldMemOperand(r1, FixedArray::OffsetOfElementAt(
1182         DeoptimizationInputData::kOsrPcOffsetIndex)));
1183
1184     // Compute the target address = code start + osr_offset
1185     __ add(lr, r0, Operand::SmiUntag(r1));
1186
1187     // And "return" to the OSR entry point of the function.
1188     __ Ret();
1189   }
1190 }
1191
1192
1193 void Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) {
1194   // We check the stack limit as indicator that recompilation might be done.
1195   Label ok;
1196   __ LoadRoot(ip, Heap::kStackLimitRootIndex);
1197   __ cmp(sp, Operand(ip));
1198   __ b(hs, &ok);
1199   {
1200     FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
1201     __ CallRuntime(Runtime::kStackGuard, 0);
1202   }
1203   __ Jump(masm->isolate()->builtins()->OnStackReplacement(),
1204           RelocInfo::CODE_TARGET);
1205
1206   __ bind(&ok);
1207   __ Ret();
1208 }
1209
1210
1211 // static
1212 void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
1213   // 1. Make sure we have at least one argument.
1214   // r0: actual number of arguments
1215   {
1216     Label done;
1217     __ cmp(r0, Operand::Zero());
1218     __ b(ne, &done);
1219     __ PushRoot(Heap::kUndefinedValueRootIndex);
1220     __ add(r0, r0, Operand(1));
1221     __ bind(&done);
1222   }
1223
1224   // 2. Get the callable to call (passed as receiver) from the stack.
1225   // r0: actual number of arguments
1226   __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
1227
1228   // 3. Shift arguments and return address one slot down on the stack
1229   //    (overwriting the original receiver).  Adjust argument count to make
1230   //    the original first argument the new receiver.
1231   // r0: actual number of arguments
1232   // r1: callable
1233   {
1234     Label loop;
1235     // Calculate the copy start address (destination). Copy end address is sp.
1236     __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
1237
1238     __ bind(&loop);
1239     __ ldr(ip, MemOperand(r2, -kPointerSize));
1240     __ str(ip, MemOperand(r2));
1241     __ sub(r2, r2, Operand(kPointerSize));
1242     __ cmp(r2, sp);
1243     __ b(ne, &loop);
1244     // Adjust the actual number of arguments and remove the top element
1245     // (which is a copy of the last argument).
1246     __ sub(r0, r0, Operand(1));
1247     __ pop();
1248   }
1249
1250   // 4. Call the callable.
1251   __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1252 }
1253
1254
1255 static void Generate_PushAppliedArguments(MacroAssembler* masm,
1256                                           const int vectorOffset,
1257                                           const int argumentsOffset,
1258                                           const int indexOffset,
1259                                           const int limitOffset) {
1260   Label entry, loop;
1261   Register receiver = LoadDescriptor::ReceiverRegister();
1262   Register key = LoadDescriptor::NameRegister();
1263   Register slot = LoadDescriptor::SlotRegister();
1264   Register vector = LoadWithVectorDescriptor::VectorRegister();
1265
1266   __ ldr(key, MemOperand(fp, indexOffset));
1267   __ b(&entry);
1268
1269   // Load the current argument from the arguments array.
1270   __ bind(&loop);
1271   __ ldr(receiver, MemOperand(fp, argumentsOffset));
1272
1273   // Use inline caching to speed up access to arguments.
1274   int slot_index = TypeFeedbackVector::PushAppliedArgumentsIndex();
1275   __ mov(slot, Operand(Smi::FromInt(slot_index)));
1276   __ ldr(vector, MemOperand(fp, vectorOffset));
1277   Handle<Code> ic =
1278       KeyedLoadICStub(masm->isolate(), LoadICState(kNoExtraICState)).GetCode();
1279   __ Call(ic, RelocInfo::CODE_TARGET);
1280
1281   // Push the nth argument.
1282   __ push(r0);
1283
1284   __ ldr(key, MemOperand(fp, indexOffset));
1285   __ add(key, key, Operand(1 << kSmiTagSize));
1286   __ str(key, MemOperand(fp, indexOffset));
1287
1288   // Test if the copy loop has finished copying all the elements from the
1289   // arguments object.
1290   __ bind(&entry);
1291   __ ldr(r1, MemOperand(fp, limitOffset));
1292   __ cmp(key, r1);
1293   __ b(ne, &loop);
1294
1295   // On exit, the pushed arguments count is in r0, untagged
1296   __ mov(r0, key);
1297   __ SmiUntag(r0);
1298 }
1299
1300
1301 // Used by FunctionApply and ReflectApply
1302 static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
1303   const int kFormalParameters = targetIsArgument ? 3 : 2;
1304   const int kStackSize = kFormalParameters + 1;
1305
1306   {
1307     FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL);
1308     const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
1309     const int kReceiverOffset = kArgumentsOffset + kPointerSize;
1310     const int kFunctionOffset = kReceiverOffset + kPointerSize;
1311     const int kVectorOffset =
1312         InternalFrameConstants::kCodeOffset - 1 * kPointerSize;
1313
1314     // Push the vector.
1315     __ ldr(r1, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1316     __ ldr(r1, FieldMemOperand(r1, SharedFunctionInfo::kFeedbackVectorOffset));
1317     __ Push(r1);
1318
1319     __ ldr(r0, MemOperand(fp, kFunctionOffset));  // get the function
1320     __ ldr(r1, MemOperand(fp, kArgumentsOffset));  // get the args array
1321     __ Push(r0, r1);
1322     if (targetIsArgument) {
1323       __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX,
1324                        CALL_FUNCTION);
1325     } else {
1326       __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION);
1327     }
1328
1329     Generate_CheckStackOverflow(masm, kFunctionOffset, r0, kArgcIsSmiTagged);
1330
1331     // Push current limit and index.
1332     const int kIndexOffset = kVectorOffset - (2 * kPointerSize);
1333     const int kLimitOffset = kVectorOffset - (1 * kPointerSize);
1334     __ mov(r1, Operand::Zero());
1335     __ ldr(r2, MemOperand(fp, kReceiverOffset));
1336     __ Push(r0, r1, r2);  // limit, initial index and receiver.
1337
1338     // Copy all arguments from the array to the stack.
1339     Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset,
1340                                   kIndexOffset, kLimitOffset);
1341
1342     // Call the callable.
1343     // TODO(bmeurer): This should be a tail call according to ES6.
1344     __ ldr(r1, MemOperand(fp, kFunctionOffset));
1345     __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1346
1347     // Tear down the internal frame and remove function, receiver and args.
1348   }
1349   __ add(sp, sp, Operand(kStackSize * kPointerSize));
1350   __ Jump(lr);
1351 }
1352
1353
1354 static void Generate_ConstructHelper(MacroAssembler* masm) {
1355   const int kFormalParameters = 3;
1356   const int kStackSize = kFormalParameters + 1;
1357
1358   {
1359     FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL);
1360     const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize;
1361     const int kArgumentsOffset = kNewTargetOffset + kPointerSize;
1362     const int kFunctionOffset = kArgumentsOffset + kPointerSize;
1363     static const int kVectorOffset =
1364         InternalFrameConstants::kCodeOffset - 1 * kPointerSize;
1365
1366     // Push the vector.
1367     __ ldr(r1, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1368     __ ldr(r1, FieldMemOperand(r1, SharedFunctionInfo::kFeedbackVectorOffset));
1369     __ Push(r1);
1370
1371     // If newTarget is not supplied, set it to constructor
1372     Label validate_arguments;
1373     __ ldr(r0, MemOperand(fp, kNewTargetOffset));
1374     __ CompareRoot(r0, Heap::kUndefinedValueRootIndex);
1375     __ b(ne, &validate_arguments);
1376     __ ldr(r0, MemOperand(fp, kFunctionOffset));
1377     __ str(r0, MemOperand(fp, kNewTargetOffset));
1378
1379     // Validate arguments
1380     __ bind(&validate_arguments);
1381     __ ldr(r0, MemOperand(fp, kFunctionOffset));  // get the function
1382     __ push(r0);
1383     __ ldr(r0, MemOperand(fp, kArgumentsOffset));  // get the args array
1384     __ push(r0);
1385     __ ldr(r0, MemOperand(fp, kNewTargetOffset));  // get the new.target
1386     __ push(r0);
1387     __ InvokeBuiltin(Context::REFLECT_CONSTRUCT_PREPARE_BUILTIN_INDEX,
1388                      CALL_FUNCTION);
1389
1390     Generate_CheckStackOverflow(masm, kFunctionOffset, r0, kArgcIsSmiTagged);
1391
1392     // Push current limit and index.
1393     const int kIndexOffset = kVectorOffset - (2 * kPointerSize);
1394     const int kLimitOffset = kVectorOffset - (1 * kPointerSize);
1395     __ push(r0);  // limit
1396     __ mov(r1, Operand::Zero());  // initial index
1397     __ push(r1);
1398     // Push the constructor function as callee.
1399     __ ldr(r0, MemOperand(fp, kFunctionOffset));
1400     __ push(r0);
1401
1402     // Copy all arguments from the array to the stack.
1403     Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset,
1404                                   kIndexOffset, kLimitOffset);
1405
1406     // Use undefined feedback vector
1407     __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
1408     __ ldr(r1, MemOperand(fp, kFunctionOffset));
1409     __ ldr(r4, MemOperand(fp, kNewTargetOffset));
1410
1411     // Call the function.
1412     CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL);
1413     __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
1414
1415     // Leave internal frame.
1416   }
1417   __ add(sp, sp, Operand(kStackSize * kPointerSize));
1418   __ Jump(lr);
1419 }
1420
1421
1422 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1423   Generate_ApplyHelper(masm, false);
1424 }
1425
1426
1427 void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
1428   Generate_ApplyHelper(masm, true);
1429 }
1430
1431
1432 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
1433   Generate_ConstructHelper(masm);
1434 }
1435
1436
1437 static void ArgumentAdaptorStackCheck(MacroAssembler* masm,
1438                                       Label* stack_overflow) {
1439   // ----------- S t a t e -------------
1440   //  -- r0 : actual number of arguments
1441   //  -- r1 : function (passed through to callee)
1442   //  -- r2 : expected number of arguments
1443   // -----------------------------------
1444   // Check the stack for overflow. We are not trying to catch
1445   // interruptions (e.g. debug break and preemption) here, so the "real stack
1446   // limit" is checked.
1447   __ LoadRoot(r5, Heap::kRealStackLimitRootIndex);
1448   // Make r5 the space we have left. The stack might already be overflowed
1449   // here which will cause r5 to become negative.
1450   __ sub(r5, sp, r5);
1451   // Check if the arguments will overflow the stack.
1452   __ cmp(r5, Operand(r2, LSL, kPointerSizeLog2));
1453   __ b(le, stack_overflow);  // Signed comparison.
1454 }
1455
1456
1457 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1458   __ SmiTag(r0);
1459   __ mov(r4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1460   __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() |
1461                        (FLAG_enable_embedded_constant_pool ? pp.bit() : 0) |
1462                        fp.bit() | lr.bit());
1463   __ add(fp, sp,
1464          Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize));
1465 }
1466
1467
1468 static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1469   // ----------- S t a t e -------------
1470   //  -- r0 : result being passed through
1471   // -----------------------------------
1472   // Get the number of arguments passed (as a smi), tear down the frame and
1473   // then tear down the parameters.
1474   __ ldr(r1, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp +
1475                               kPointerSize)));
1476
1477   __ LeaveFrame(StackFrame::ARGUMENTS_ADAPTOR);
1478   __ add(sp, sp, Operand::PointerOffsetFromSmiKey(r1));
1479   __ add(sp, sp, Operand(kPointerSize));  // adjust for receiver
1480 }
1481
1482
1483 // static
1484 void Builtins::Generate_CallFunction(MacroAssembler* masm) {
1485   // ----------- S t a t e -------------
1486   //  -- r0 : the number of arguments (not including the receiver)
1487   //  -- r1 : the function to call (checked to be a JSFunction)
1488   // -----------------------------------
1489
1490   Label convert, convert_global_proxy, convert_to_object, done_convert;
1491   __ AssertFunction(r1);
1492   // TODO(bmeurer): Throw a TypeError if function's [[FunctionKind]] internal
1493   // slot is "classConstructor".
1494   // Enter the context of the function; ToObject has to run in the function
1495   // context, and we also need to take the global proxy from the function
1496   // context in case of conversion.
1497   // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
1498   STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset ==
1499                 SharedFunctionInfo::kStrictModeByteOffset);
1500   __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1501   __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1502   // We need to convert the receiver for non-native sloppy mode functions.
1503   __ ldrb(r3, FieldMemOperand(r2, SharedFunctionInfo::kNativeByteOffset));
1504   __ tst(r3, Operand((1 << SharedFunctionInfo::kNativeBitWithinByte) |
1505                      (1 << SharedFunctionInfo::kStrictModeBitWithinByte)));
1506   __ b(ne, &done_convert);
1507   {
1508     __ ldr(r3, MemOperand(sp, r0, LSL, kPointerSizeLog2));
1509
1510     // ----------- S t a t e -------------
1511     //  -- r0 : the number of arguments (not including the receiver)
1512     //  -- r1 : the function to call (checked to be a JSFunction)
1513     //  -- r2 : the shared function info.
1514     //  -- r3 : the receiver
1515     //  -- cp : the function context.
1516     // -----------------------------------
1517
1518     Label convert_receiver;
1519     __ JumpIfSmi(r3, &convert_to_object);
1520     STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
1521     __ CompareObjectType(r3, r4, r4, FIRST_JS_RECEIVER_TYPE);
1522     __ b(hs, &done_convert);
1523     __ JumpIfRoot(r3, Heap::kUndefinedValueRootIndex, &convert_global_proxy);
1524     __ JumpIfNotRoot(r3, Heap::kNullValueRootIndex, &convert_to_object);
1525     __ bind(&convert_global_proxy);
1526     {
1527       // Patch receiver to global proxy.
1528       __ LoadGlobalProxy(r3);
1529     }
1530     __ b(&convert_receiver);
1531     __ bind(&convert_to_object);
1532     {
1533       // Convert receiver using ToObject.
1534       // TODO(bmeurer): Inline the allocation here to avoid building the frame
1535       // in the fast case? (fall back to AllocateInNewSpace?)
1536       FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
1537       __ SmiTag(r0);
1538       __ Push(r0, r1);
1539       __ mov(r0, r3);
1540       ToObjectStub stub(masm->isolate());
1541       __ CallStub(&stub);
1542       __ mov(r3, r0);
1543       __ Pop(r0, r1);
1544       __ SmiUntag(r0);
1545     }
1546     __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1547     __ bind(&convert_receiver);
1548     __ str(r3, MemOperand(sp, r0, LSL, kPointerSizeLog2));
1549   }
1550   __ bind(&done_convert);
1551
1552   // ----------- S t a t e -------------
1553   //  -- r0 : the number of arguments (not including the receiver)
1554   //  -- r1 : the function to call (checked to be a JSFunction)
1555   //  -- r2 : the shared function info.
1556   //  -- cp : the function context.
1557   // -----------------------------------
1558
1559   __ ldr(r2,
1560          FieldMemOperand(r2, SharedFunctionInfo::kFormalParameterCountOffset));
1561   __ SmiUntag(r2);
1562   __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
1563   ParameterCount actual(r0);
1564   ParameterCount expected(r2);
1565   __ InvokeCode(r3, expected, actual, JUMP_FUNCTION, NullCallWrapper());
1566 }
1567
1568
1569 // static
1570 void Builtins::Generate_Call(MacroAssembler* masm) {
1571   // ----------- S t a t e -------------
1572   //  -- r0 : the number of arguments (not including the receiver)
1573   //  -- r1 : the target to call (can be any Object).
1574   // -----------------------------------
1575
1576   Label non_smi, non_function;
1577   __ JumpIfSmi(r1, &non_function);
1578   __ bind(&non_smi);
1579   __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
1580   __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET,
1581           eq);
1582   __ cmp(r2, Operand(JS_FUNCTION_PROXY_TYPE));
1583   __ b(ne, &non_function);
1584
1585   // 1. Call to function proxy.
1586   // TODO(neis): This doesn't match the ES6 spec for [[Call]] on proxies.
1587   __ ldr(r1, FieldMemOperand(r1, JSFunctionProxy::kCallTrapOffset));
1588   __ AssertNotSmi(r1);
1589   __ b(&non_smi);
1590
1591   // 2. Call to something else, which might have a [[Call]] internal method (if
1592   // not we raise an exception).
1593   __ bind(&non_function);
1594   // TODO(bmeurer): I wonder why we prefer to have slow API calls? This could
1595   // be awesome instead; i.e. a trivial improvement would be to call into the
1596   // runtime and just deal with the API function there instead of returning a
1597   // delegate from a runtime call that just jumps back to the runtime once
1598   // called. Or, bonus points, call directly into the C API function here, as
1599   // we do in some Crankshaft fast cases.
1600   // Overwrite the original receiver with the (original) target.
1601   __ str(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
1602   {
1603     // Determine the delegate for the target (if any).
1604     FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
1605     __ SmiTag(r0);
1606     __ Push(r0, r1);
1607     __ CallRuntime(Runtime::kGetFunctionDelegate, 1);
1608     __ mov(r1, r0);
1609     __ Pop(r0);
1610     __ SmiUntag(r0);
1611   }
1612   // The delegate is always a regular function.
1613   __ AssertFunction(r1);
1614   __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
1615 }
1616
1617
1618 // static
1619 void Builtins::Generate_PushArgsAndCall(MacroAssembler* masm) {
1620   // ----------- S t a t e -------------
1621   //  -- r0 : the number of arguments (not including the receiver)
1622   //  -- r2 : the address of the first argument to be pushed. Subsequent
1623   //          arguments should be consecutive above this, in the same order as
1624   //          they are to be pushed onto the stack.
1625   //  -- r1 : the target to call (can be any Object).
1626
1627   // Find the address of the last argument.
1628   __ add(r3, r0, Operand(1));  // Add one for receiver.
1629   __ mov(r3, Operand(r3, LSL, kPointerSizeLog2));
1630   __ sub(r3, r2, r3);
1631
1632   // Push the arguments.
1633   Label loop_header, loop_check;
1634   __ b(al, &loop_check);
1635   __ bind(&loop_header);
1636   __ ldr(r4, MemOperand(r2, -kPointerSize, PostIndex));
1637   __ push(r4);
1638   __ bind(&loop_check);
1639   __ cmp(r2, r3);
1640   __ b(gt, &loop_header);
1641
1642   // Call the target.
1643   __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1644 }
1645
1646
1647 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1648   // ----------- S t a t e -------------
1649   //  -- r0 : actual number of arguments
1650   //  -- r1 : function (passed through to callee)
1651   //  -- r2 : expected number of arguments
1652   // -----------------------------------
1653
1654   Label stack_overflow;
1655   ArgumentAdaptorStackCheck(masm, &stack_overflow);
1656   Label invoke, dont_adapt_arguments;
1657
1658   Label enough, too_few;
1659   __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
1660   __ cmp(r0, r2);
1661   __ b(lt, &too_few);
1662   __ cmp(r2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
1663   __ b(eq, &dont_adapt_arguments);
1664
1665   {  // Enough parameters: actual >= expected
1666     __ bind(&enough);
1667     EnterArgumentsAdaptorFrame(masm);
1668
1669     // Calculate copy start address into r0 and copy end address into r4.
1670     // r0: actual number of arguments as a smi
1671     // r1: function
1672     // r2: expected number of arguments
1673     // r3: code entry to call
1674     __ add(r0, fp, Operand::PointerOffsetFromSmiKey(r0));
1675     // adjust for return address and receiver
1676     __ add(r0, r0, Operand(2 * kPointerSize));
1677     __ sub(r4, r0, Operand(r2, LSL, kPointerSizeLog2));
1678
1679     // Copy the arguments (including the receiver) to the new stack frame.
1680     // r0: copy start address
1681     // r1: function
1682     // r2: expected number of arguments
1683     // r3: code entry to call
1684     // r4: copy end address
1685
1686     Label copy;
1687     __ bind(&copy);
1688     __ ldr(ip, MemOperand(r0, 0));
1689     __ push(ip);
1690     __ cmp(r0, r4);  // Compare before moving to next argument.
1691     __ sub(r0, r0, Operand(kPointerSize));
1692     __ b(ne, &copy);
1693
1694     __ b(&invoke);
1695   }
1696
1697   {  // Too few parameters: Actual < expected
1698     __ bind(&too_few);
1699
1700     // If the function is strong we need to throw an error.
1701     Label no_strong_error;
1702     __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1703     __ ldr(r5, FieldMemOperand(r4, SharedFunctionInfo::kCompilerHintsOffset));
1704     __ tst(r5, Operand(1 << (SharedFunctionInfo::kStrongModeFunction +
1705                              kSmiTagSize)));
1706     __ b(eq, &no_strong_error);
1707
1708     // What we really care about is the required number of arguments.
1709     __ ldr(r4, FieldMemOperand(r4, SharedFunctionInfo::kLengthOffset));
1710     __ cmp(r0, Operand::SmiUntag(r4));
1711     __ b(ge, &no_strong_error);
1712
1713     {
1714       FrameScope frame(masm, StackFrame::MANUAL);
1715       EnterArgumentsAdaptorFrame(masm);
1716       __ CallRuntime(Runtime::kThrowStrongModeTooFewArguments, 0);
1717     }
1718
1719     __ bind(&no_strong_error);
1720     EnterArgumentsAdaptorFrame(masm);
1721
1722     // Calculate copy start address into r0 and copy end address is fp.
1723     // r0: actual number of arguments as a smi
1724     // r1: function
1725     // r2: expected number of arguments
1726     // r3: code entry to call
1727     __ add(r0, fp, Operand::PointerOffsetFromSmiKey(r0));
1728
1729     // Copy the arguments (including the receiver) to the new stack frame.
1730     // r0: copy start address
1731     // r1: function
1732     // r2: expected number of arguments
1733     // r3: code entry to call
1734     Label copy;
1735     __ bind(&copy);
1736     // Adjust load for return address and receiver.
1737     __ ldr(ip, MemOperand(r0, 2 * kPointerSize));
1738     __ push(ip);
1739     __ cmp(r0, fp);  // Compare before moving to next argument.
1740     __ sub(r0, r0, Operand(kPointerSize));
1741     __ b(ne, &copy);
1742
1743     // Fill the remaining expected arguments with undefined.
1744     // r1: function
1745     // r2: expected number of arguments
1746     // r3: code entry to call
1747     __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1748     __ sub(r4, fp, Operand(r2, LSL, kPointerSizeLog2));
1749     // Adjust for frame.
1750     __ sub(r4, r4, Operand(StandardFrameConstants::kFixedFrameSizeFromFp +
1751                            2 * kPointerSize));
1752
1753     Label fill;
1754     __ bind(&fill);
1755     __ push(ip);
1756     __ cmp(sp, r4);
1757     __ b(ne, &fill);
1758   }
1759
1760   // Call the entry point.
1761   __ bind(&invoke);
1762   __ mov(r0, r2);
1763   // r0 : expected number of arguments
1764   // r1 : function (passed through to callee)
1765   __ Call(r3);
1766
1767   // Store offset of return address for deoptimizer.
1768   masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
1769
1770   // Exit frame and return.
1771   LeaveArgumentsAdaptorFrame(masm);
1772   __ Jump(lr);
1773
1774
1775   // -------------------------------------------
1776   // Dont adapt arguments.
1777   // -------------------------------------------
1778   __ bind(&dont_adapt_arguments);
1779   __ Jump(r3);
1780
1781   __ bind(&stack_overflow);
1782   {
1783     FrameScope frame(masm, StackFrame::MANUAL);
1784     EnterArgumentsAdaptorFrame(masm);
1785     __ CallRuntime(Runtime::kThrowStackOverflow, 0);
1786     __ bkpt(0);
1787   }
1788 }
1789
1790
1791 #undef __
1792
1793 }  // namespace internal
1794 }  // namespace v8
1795
1796 #endif  // V8_TARGET_ARCH_ARM