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