Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / v8 / 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 #include "v8.h"
6
7 #if V8_TARGET_ARCH_ARM64
8
9 #include "codegen.h"
10 #include "debug.h"
11 #include "deoptimizer.h"
12 #include "full-codegen.h"
13 #include "runtime.h"
14 #include "stub-cache.h"
15
16 namespace v8 {
17 namespace internal {
18
19
20 #define __ ACCESS_MASM(masm)
21
22
23 // Load the built-in Array function from the current context.
24 static void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) {
25   // Load the native context.
26   __ Ldr(result, GlobalObjectMemOperand());
27   __ Ldr(result,
28          FieldMemOperand(result, GlobalObject::kNativeContextOffset));
29   // Load the InternalArray function from the native context.
30   __ Ldr(result,
31          MemOperand(result,
32                     Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
33 }
34
35
36 // Load the built-in InternalArray function from the current context.
37 static void GenerateLoadInternalArrayFunction(MacroAssembler* masm,
38                                               Register result) {
39   // Load the native context.
40   __ Ldr(result, GlobalObjectMemOperand());
41   __ Ldr(result,
42          FieldMemOperand(result, GlobalObject::kNativeContextOffset));
43   // Load the InternalArray function from the native context.
44   __ Ldr(result, ContextMemOperand(result,
45                                    Context::INTERNAL_ARRAY_FUNCTION_INDEX));
46 }
47
48
49 void Builtins::Generate_Adaptor(MacroAssembler* masm,
50                                 CFunctionId id,
51                                 BuiltinExtraArguments extra_args) {
52   // ----------- S t a t e -------------
53   //  -- x0                 : number of arguments excluding receiver
54   //  -- x1                 : called function (only guaranteed when
55   //                          extra_args requires it)
56   //  -- cp                 : context
57   //  -- sp[0]              : last argument
58   //  -- ...
59   //  -- sp[4 * (argc - 1)] : first argument (argc == x0)
60   //  -- sp[4 * argc]       : receiver
61   // -----------------------------------
62
63   // Insert extra arguments.
64   int num_extra_args = 0;
65   if (extra_args == NEEDS_CALLED_FUNCTION) {
66     num_extra_args = 1;
67     __ Push(x1);
68   } else {
69     ASSERT(extra_args == NO_EXTRA_ARGUMENTS);
70   }
71
72   // JumpToExternalReference expects x0 to contain the number of arguments
73   // including the receiver and the extra arguments.
74   __ Add(x0, x0, num_extra_args + 1);
75   __ JumpToExternalReference(ExternalReference(id, masm->isolate()));
76 }
77
78
79 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
80   // ----------- S t a t e -------------
81   //  -- x0     : number of arguments
82   //  -- lr     : return address
83   //  -- sp[...]: constructor arguments
84   // -----------------------------------
85   ASM_LOCATION("Builtins::Generate_InternalArrayCode");
86   Label generic_array_code;
87
88   // Get the InternalArray function.
89   GenerateLoadInternalArrayFunction(masm, x1);
90
91   if (FLAG_debug_code) {
92     // Initial map for the builtin InternalArray functions should be maps.
93     __ Ldr(x10, FieldMemOperand(x1, JSFunction::kPrototypeOrInitialMapOffset));
94     __ Tst(x10, kSmiTagMask);
95     __ Assert(ne, kUnexpectedInitialMapForInternalArrayFunction);
96     __ CompareObjectType(x10, x11, x12, MAP_TYPE);
97     __ Assert(eq, kUnexpectedInitialMapForInternalArrayFunction);
98   }
99
100   // Run the native code for the InternalArray function called as a normal
101   // function.
102   InternalArrayConstructorStub stub(masm->isolate());
103   __ TailCallStub(&stub);
104 }
105
106
107 void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
108   // ----------- S t a t e -------------
109   //  -- x0     : number of arguments
110   //  -- lr     : return address
111   //  -- sp[...]: constructor arguments
112   // -----------------------------------
113   ASM_LOCATION("Builtins::Generate_ArrayCode");
114   Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
115
116   // Get the Array function.
117   GenerateLoadArrayFunction(masm, x1);
118
119   if (FLAG_debug_code) {
120     // Initial map for the builtin Array functions should be maps.
121     __ Ldr(x10, FieldMemOperand(x1, JSFunction::kPrototypeOrInitialMapOffset));
122     __ Tst(x10, kSmiTagMask);
123     __ Assert(ne, kUnexpectedInitialMapForArrayFunction);
124     __ CompareObjectType(x10, x11, x12, MAP_TYPE);
125     __ Assert(eq, kUnexpectedInitialMapForArrayFunction);
126   }
127
128   // Run the native code for the Array function called as a normal function.
129   __ LoadRoot(x2, Heap::kUndefinedValueRootIndex);
130   ArrayConstructorStub stub(masm->isolate());
131   __ TailCallStub(&stub);
132 }
133
134
135 void Builtins::Generate_StringConstructCode(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_StringConstructCode");
144   Counters* counters = masm->isolate()->counters();
145   __ IncrementCounter(counters->string_ctor_calls(), 1, x10, x11);
146
147   Register argc = x0;
148   Register function = x1;
149   if (FLAG_debug_code) {
150     __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, x10);
151     __ Cmp(function, x10);
152     __ Assert(eq, kUnexpectedStringFunction);
153   }
154
155   // Load the first arguments in x0 and get rid of the rest.
156   Label no_arguments;
157   __ Cbz(argc, &no_arguments);
158   // First args = sp[(argc - 1) * 8].
159   __ Sub(argc, argc, 1);
160   __ Claim(argc, kXRegSize);
161   // jssp now point to args[0], load and drop args[0] + receiver.
162   Register arg = argc;
163   __ Ldr(arg, MemOperand(jssp, 2 * kPointerSize, PostIndex));
164   argc = NoReg;
165
166   Register argument = x2;
167   Label not_cached, argument_is_string;
168   __ LookupNumberStringCache(arg,        // Input.
169                              argument,   // Result.
170                              x10,        // Scratch.
171                              x11,        // Scratch.
172                              x12,        // Scratch.
173                              &not_cached);
174   __ IncrementCounter(counters->string_ctor_cached_number(), 1, x10, x11);
175   __ Bind(&argument_is_string);
176
177   // ----------- S t a t e -------------
178   //  -- x2     : argument converted to string
179   //  -- x1     : constructor function
180   //  -- lr     : return address
181   // -----------------------------------
182
183   Label gc_required;
184   Register new_obj = x0;
185   __ Allocate(JSValue::kSize, new_obj, x10, x11, &gc_required, TAG_OBJECT);
186
187   // Initialize the String object.
188   Register map = x3;
189   __ LoadGlobalFunctionInitialMap(function, map, x10);
190   if (FLAG_debug_code) {
191     __ Ldrb(x4, FieldMemOperand(map, Map::kInstanceSizeOffset));
192     __ Cmp(x4, JSValue::kSize >> kPointerSizeLog2);
193     __ Assert(eq, kUnexpectedStringWrapperInstanceSize);
194     __ Ldrb(x4, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset));
195     __ Cmp(x4, 0);
196     __ Assert(eq, kUnexpectedUnusedPropertiesOfStringWrapper);
197   }
198   __ Str(map, FieldMemOperand(new_obj, HeapObject::kMapOffset));
199
200   Register empty = x3;
201   __ LoadRoot(empty, Heap::kEmptyFixedArrayRootIndex);
202   __ Str(empty, FieldMemOperand(new_obj, JSObject::kPropertiesOffset));
203   __ Str(empty, FieldMemOperand(new_obj, JSObject::kElementsOffset));
204
205   __ Str(argument, FieldMemOperand(new_obj, JSValue::kValueOffset));
206
207   // Ensure the object is fully initialized.
208   STATIC_ASSERT(JSValue::kSize == (4 * kPointerSize));
209
210   __ Ret();
211
212   // The argument was not found in the number to string cache. Check
213   // if it's a string already before calling the conversion builtin.
214   Label convert_argument;
215   __ Bind(&not_cached);
216   __ JumpIfSmi(arg, &convert_argument);
217
218   // Is it a String?
219   __ Ldr(x10, FieldMemOperand(x0, HeapObject::kMapOffset));
220   __ Ldrb(x11, FieldMemOperand(x10, Map::kInstanceTypeOffset));
221   __ Tbnz(x11, MaskToBit(kIsNotStringMask), &convert_argument);
222   __ Mov(argument, arg);
223   __ IncrementCounter(counters->string_ctor_string_value(), 1, x10, x11);
224   __ B(&argument_is_string);
225
226   // Invoke the conversion builtin and put the result into x2.
227   __ Bind(&convert_argument);
228   __ Push(function);  // Preserve the function.
229   __ IncrementCounter(counters->string_ctor_conversions(), 1, x10, x11);
230   {
231     FrameScope scope(masm, StackFrame::INTERNAL);
232     __ Push(arg);
233     __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
234   }
235   __ Pop(function);
236   __ Mov(argument, x0);
237   __ B(&argument_is_string);
238
239   // Load the empty string into x2, remove the receiver from the
240   // stack, and jump back to the case where the argument is a string.
241   __ Bind(&no_arguments);
242   __ LoadRoot(argument, Heap::kempty_stringRootIndex);
243   __ Drop(1);
244   __ B(&argument_is_string);
245
246   // At this point the argument is already a string. Call runtime to create a
247   // string wrapper.
248   __ Bind(&gc_required);
249   __ IncrementCounter(counters->string_ctor_gc_required(), 1, x10, x11);
250   {
251     FrameScope scope(masm, StackFrame::INTERNAL);
252     __ Push(argument);
253     __ CallRuntime(Runtime::kNewStringWrapper, 1);
254   }
255   __ Ret();
256 }
257
258
259 static void CallRuntimePassFunction(MacroAssembler* masm,
260                                     Runtime::FunctionId function_id) {
261   FrameScope scope(masm, StackFrame::INTERNAL);
262   //   - Push a copy of the function onto the stack.
263   //   - Push another copy as a parameter to the runtime call.
264   __ Push(x1, x1);
265
266   __ CallRuntime(function_id, 1);
267
268   //   - Restore receiver.
269   __ Pop(x1);
270 }
271
272
273 static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
274   __ Ldr(x2, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
275   __ Ldr(x2, FieldMemOperand(x2, SharedFunctionInfo::kCodeOffset));
276   __ Add(x2, x2, Code::kHeaderSize - kHeapObjectTag);
277   __ Br(x2);
278 }
279
280
281 static void GenerateTailCallToReturnedCode(MacroAssembler* masm) {
282   __ Add(x0, x0, Code::kHeaderSize - kHeapObjectTag);
283   __ Br(x0);
284 }
285
286
287 void Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) {
288   // Checking whether the queued function is ready for install is optional,
289   // since we come across interrupts and stack checks elsewhere. However, not
290   // checking may delay installing ready functions, and always checking would be
291   // quite expensive. A good compromise is to first check against stack limit as
292   // a cue for an interrupt signal.
293   Label ok;
294   __ CompareRoot(masm->StackPointer(), Heap::kStackLimitRootIndex);
295   __ B(hs, &ok);
296
297   CallRuntimePassFunction(masm, Runtime::kHiddenTryInstallOptimizedCode);
298   GenerateTailCallToReturnedCode(masm);
299
300   __ Bind(&ok);
301   GenerateTailCallToSharedCode(masm);
302 }
303
304
305 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
306                                            bool is_api_function,
307                                            bool count_constructions,
308                                            bool create_memento) {
309   // ----------- S t a t e -------------
310   //  -- x0     : number of arguments
311   //  -- x1     : constructor function
312   //  -- x2     : allocation site or undefined
313   //  -- lr     : return address
314   //  -- sp[...]: constructor arguments
315   // -----------------------------------
316
317   ASM_LOCATION("Builtins::Generate_JSConstructStubHelper");
318   // Should never count constructions for api objects.
319   ASSERT(!is_api_function || !count_constructions);
320   // Should never create mementos for api functions.
321   ASSERT(!is_api_function || !create_memento);
322   // Should never create mementos before slack tracking is finished.
323   ASSERT(!count_constructions || !create_memento);
324
325   Isolate* isolate = masm->isolate();
326
327   // Enter a construct frame.
328   {
329     FrameScope scope(masm, StackFrame::CONSTRUCT);
330
331     // Preserve the three incoming parameters on the stack.
332     if (create_memento) {
333       __ AssertUndefinedOrAllocationSite(x2, x10);
334       __ Push(x2);
335     }
336
337     Register argc = x0;
338     Register constructor = x1;
339     // x1: constructor function
340     __ SmiTag(argc);
341     __ Push(argc, constructor);
342     // sp[0] : Constructor function.
343     // sp[1]: number of arguments (smi-tagged)
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       Label undo_allocation;
350       ExternalReference debug_step_in_fp =
351           ExternalReference::debug_step_in_fp_address(isolate);
352       __ Mov(x2, Operand(debug_step_in_fp));
353       __ Ldr(x2, MemOperand(x2));
354       __ Cbnz(x2, &rt_call);
355       // Load the initial map and verify that it is in fact a map.
356       Register init_map = x2;
357       __ Ldr(init_map,
358              FieldMemOperand(constructor,
359                              JSFunction::kPrototypeOrInitialMapOffset));
360       __ JumpIfSmi(init_map, &rt_call);
361       __ JumpIfNotObjectType(init_map, x10, x11, MAP_TYPE, &rt_call);
362
363       // Check that the constructor is not constructing a JSFunction (see
364       // comments in Runtime_NewObject in runtime.cc). In which case the initial
365       // map's instance type would be JS_FUNCTION_TYPE.
366       __ CompareInstanceType(init_map, x10, JS_FUNCTION_TYPE);
367       __ B(eq, &rt_call);
368
369       if (count_constructions) {
370         Label allocate;
371         // Decrease generous allocation count.
372         __ Ldr(x3, FieldMemOperand(constructor,
373                                    JSFunction::kSharedFunctionInfoOffset));
374         MemOperand constructor_count =
375             FieldMemOperand(x3, SharedFunctionInfo::kConstructionCountOffset);
376         __ Ldrb(x4, constructor_count);
377         __ Subs(x4, x4, 1);
378         __ Strb(x4, constructor_count);
379         __ B(ne, &allocate);
380
381         // Push the constructor and map to the stack, and the constructor again
382         // as argument to the runtime call.
383         __ Push(constructor, init_map, constructor);
384         // The call will replace the stub, so the countdown is only done once.
385         __ CallRuntime(Runtime::kHiddenFinalizeInstanceSize, 1);
386         __ Pop(init_map, constructor);
387         __ Bind(&allocate);
388       }
389
390       // Now allocate the JSObject on the heap.
391       Register obj_size = x3;
392       Register new_obj = x4;
393       __ Ldrb(obj_size, FieldMemOperand(init_map, Map::kInstanceSizeOffset));
394       if (create_memento) {
395         __ Add(x7, obj_size,
396                Operand(AllocationMemento::kSize / kPointerSize));
397         __ Allocate(x7, new_obj, x10, x11, &rt_call, SIZE_IN_WORDS);
398       } else {
399         __ Allocate(obj_size, new_obj, x10, x11, &rt_call, SIZE_IN_WORDS);
400       }
401
402       // Allocated the JSObject, now initialize the fields. Map is set to
403       // initial map and properties and elements are set to empty fixed array.
404       // NB. the object pointer is not tagged, so MemOperand is used.
405       Register empty = x5;
406       __ LoadRoot(empty, Heap::kEmptyFixedArrayRootIndex);
407       __ Str(init_map, MemOperand(new_obj, JSObject::kMapOffset));
408       STATIC_ASSERT(JSObject::kElementsOffset ==
409           (JSObject::kPropertiesOffset + kPointerSize));
410       __ Stp(empty, empty, MemOperand(new_obj, JSObject::kPropertiesOffset));
411
412       Register first_prop = x5;
413       __ Add(first_prop, new_obj, JSObject::kHeaderSize);
414
415       // Fill all of the in-object properties with the appropriate filler.
416       Register undef = x7;
417       __ LoadRoot(undef, Heap::kUndefinedValueRootIndex);
418
419       // Obtain number of pre-allocated property fields and in-object
420       // properties.
421       Register prealloc_fields = x10;
422       Register inobject_props = x11;
423       Register inst_sizes = x11;
424       __ Ldr(inst_sizes, FieldMemOperand(init_map, Map::kInstanceSizesOffset));
425       __ Ubfx(prealloc_fields, inst_sizes,
426               Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
427               kBitsPerByte);
428       __ Ubfx(inobject_props, inst_sizes,
429               Map::kInObjectPropertiesByte * kBitsPerByte, kBitsPerByte);
430
431       // Calculate number of property fields in the object.
432       Register prop_fields = x6;
433       __ Sub(prop_fields, obj_size, JSObject::kHeaderSize / kPointerSize);
434
435       if (count_constructions) {
436         // Fill the pre-allocated fields with undef.
437         __ FillFields(first_prop, prealloc_fields, undef);
438
439         // Register first_non_prealloc is the offset of the first field after
440         // pre-allocated fields.
441         Register first_non_prealloc = x12;
442         __ Add(first_non_prealloc, first_prop,
443                Operand(prealloc_fields, LSL, kPointerSizeLog2));
444
445         first_prop = NoReg;
446
447         if (FLAG_debug_code) {
448           Register obj_end = x5;
449           __ Add(obj_end, new_obj, Operand(obj_size, LSL, kPointerSizeLog2));
450           __ Cmp(first_non_prealloc, obj_end);
451           __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields);
452         }
453
454         // Fill the remaining fields with one pointer filler map.
455         Register one_pointer_filler = x5;
456         Register non_prealloc_fields = x6;
457         __ LoadRoot(one_pointer_filler, Heap::kOnePointerFillerMapRootIndex);
458         __ Sub(non_prealloc_fields, prop_fields, prealloc_fields);
459         __ FillFields(first_non_prealloc, non_prealloc_fields,
460                       one_pointer_filler);
461         prop_fields = NoReg;
462       } else if (create_memento) {
463         // Fill the pre-allocated fields with undef.
464         __ FillFields(first_prop, prop_fields, undef);
465         __ Add(first_prop, new_obj, Operand(obj_size, LSL, kPointerSizeLog2));
466         __ LoadRoot(x14, Heap::kAllocationMementoMapRootIndex);
467         ASSERT_EQ(0 * kPointerSize, AllocationMemento::kMapOffset);
468         __ Str(x14, MemOperand(first_prop, kPointerSize, PostIndex));
469         // Load the AllocationSite
470         __ Peek(x14, 2 * kXRegSize);
471         ASSERT_EQ(1 * kPointerSize, AllocationMemento::kAllocationSiteOffset);
472         __ Str(x14, MemOperand(first_prop, kPointerSize, PostIndex));
473         first_prop = NoReg;
474       } else {
475         // Fill all of the property fields with undef.
476         __ FillFields(first_prop, prop_fields, undef);
477         first_prop = NoReg;
478         prop_fields = NoReg;
479       }
480
481       // Add the object tag to make the JSObject real, so that we can continue
482       // and jump into the continuation code at any time from now on. Any
483       // failures need to undo the allocation, so that the heap is in a
484       // consistent state and verifiable.
485       __ Add(new_obj, new_obj, kHeapObjectTag);
486
487       // Check if a non-empty properties array is needed. Continue with
488       // allocated object if not, or fall through to runtime call if it is.
489       Register element_count = x3;
490       __ Ldrb(element_count,
491               FieldMemOperand(init_map, Map::kUnusedPropertyFieldsOffset));
492       // The field instance sizes contains both pre-allocated property fields
493       // and in-object properties.
494       __ Add(element_count, element_count, prealloc_fields);
495       __ Subs(element_count, element_count, inobject_props);
496
497       // Done if no extra properties are to be allocated.
498       __ B(eq, &allocated);
499       __ Assert(pl, kPropertyAllocationCountFailed);
500
501       // Scale the number of elements by pointer size and add the header for
502       // FixedArrays to the start of the next object calculation from above.
503       Register new_array = x5;
504       Register array_size = x6;
505       __ Add(array_size, element_count, FixedArray::kHeaderSize / kPointerSize);
506       __ Allocate(array_size, new_array, x11, x12, &undo_allocation,
507                   static_cast<AllocationFlags>(RESULT_CONTAINS_TOP |
508                                                SIZE_IN_WORDS));
509
510       Register array_map = x10;
511       __ LoadRoot(array_map, Heap::kFixedArrayMapRootIndex);
512       __ Str(array_map, MemOperand(new_array, FixedArray::kMapOffset));
513       __ SmiTag(x0, element_count);
514       __ Str(x0, MemOperand(new_array, FixedArray::kLengthOffset));
515
516       // Initialize the fields to undefined.
517       Register elements = x10;
518       __ Add(elements, new_array, FixedArray::kHeaderSize);
519       __ FillFields(elements, element_count, undef);
520
521       // Store the initialized FixedArray into the properties field of the
522       // JSObject.
523       __ Add(new_array, new_array, kHeapObjectTag);
524       __ Str(new_array, FieldMemOperand(new_obj, JSObject::kPropertiesOffset));
525
526       // Continue with JSObject being successfully allocated.
527       __ B(&allocated);
528
529       // Undo the setting of the new top so that the heap is verifiable. For
530       // example, the map's unused properties potentially do not match the
531       // allocated objects unused properties.
532       __ Bind(&undo_allocation);
533       __ UndoAllocationInNewSpace(new_obj, x14);
534     }
535
536     // Allocate the new receiver object using the runtime call.
537     __ Bind(&rt_call);
538     Label count_incremented;
539     if (create_memento) {
540       // Get the cell or allocation site.
541       __ Peek(x4, 2 * kXRegSize);
542       __ Push(x4);
543       __ Push(constructor);  // Argument for Runtime_NewObject.
544       __ CallRuntime(Runtime::kHiddenNewObjectWithAllocationSite, 2);
545       __ Mov(x4, x0);
546       // If we ended up using the runtime, and we want a memento, then the
547       // runtime call made it for us, and we shouldn't do create count
548       // increment.
549       __ jmp(&count_incremented);
550     } else {
551       __ Push(constructor);  // Argument for Runtime_NewObject.
552       __ CallRuntime(Runtime::kHiddenNewObject, 1);
553       __ Mov(x4, x0);
554     }
555
556     // Receiver for constructor call allocated.
557     // x4: JSObject
558     __ Bind(&allocated);
559
560     if (create_memento) {
561       __ Peek(x10, 2 * kXRegSize);
562       __ JumpIfRoot(x10, Heap::kUndefinedValueRootIndex, &count_incremented);
563       // r2 is an AllocationSite. We are creating a memento from it, so we
564       // need to increment the memento create count.
565       __ Ldr(x5, FieldMemOperand(x10,
566                                  AllocationSite::kPretenureCreateCountOffset));
567       __ Add(x5, x5, Operand(Smi::FromInt(1)));
568       __ Str(x5, FieldMemOperand(x10,
569                                  AllocationSite::kPretenureCreateCountOffset));
570       __ bind(&count_incremented);
571     }
572
573     __ Push(x4, x4);
574
575     // Reload the number of arguments from the stack.
576     // Set it up in x0 for the function call below.
577     // jssp[0]: receiver
578     // jssp[1]: receiver
579     // jssp[2]: constructor function
580     // jssp[3]: number of arguments (smi-tagged)
581     __ Peek(constructor, 2 * kXRegSize);  // Load constructor.
582     __ Peek(argc, 3 * kXRegSize);  // Load number of arguments.
583     __ SmiUntag(argc);
584
585     // Set up pointer to last argument.
586     __ Add(x2, fp, StandardFrameConstants::kCallerSPOffset);
587
588     // Copy arguments and receiver to the expression stack.
589     // Copy 2 values every loop to use ldp/stp.
590     // x0: number of arguments
591     // x1: constructor function
592     // x2: address of last argument (caller sp)
593     // jssp[0]: receiver
594     // jssp[1]: receiver
595     // jssp[2]: constructor function
596     // jssp[3]: number of arguments (smi-tagged)
597     // Compute the start address of the copy in x3.
598     __ Add(x3, x2, Operand(argc, LSL, kPointerSizeLog2));
599     Label loop, entry, done_copying_arguments;
600     __ B(&entry);
601     __ Bind(&loop);
602     __ Ldp(x10, x11, MemOperand(x3, -2 * kPointerSize, PreIndex));
603     __ Push(x11, x10);
604     __ Bind(&entry);
605     __ Cmp(x3, x2);
606     __ B(gt, &loop);
607     // Because we copied values 2 by 2 we may have copied one extra value.
608     // Drop it if that is the case.
609     __ B(eq, &done_copying_arguments);
610     __ Drop(1);
611     __ Bind(&done_copying_arguments);
612
613     // Call the function.
614     // x0: number of arguments
615     // x1: constructor function
616     if (is_api_function) {
617       __ Ldr(cp, FieldMemOperand(constructor, JSFunction::kContextOffset));
618       Handle<Code> code =
619           masm->isolate()->builtins()->HandleApiCallConstruct();
620       __ Call(code, RelocInfo::CODE_TARGET);
621     } else {
622       ParameterCount actual(argc);
623       __ InvokeFunction(constructor, actual, CALL_FUNCTION, NullCallWrapper());
624     }
625
626     // Store offset of return address for deoptimizer.
627     if (!is_api_function && !count_constructions) {
628       masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
629     }
630
631     // Restore the context from the frame.
632     // x0: result
633     // jssp[0]: receiver
634     // jssp[1]: constructor function
635     // jssp[2]: number of arguments (smi-tagged)
636     __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
637
638     // If the result is an object (in the ECMA sense), we should get rid
639     // of the receiver and use the result; see ECMA-262 section 13.2.2-7
640     // on page 74.
641     Label use_receiver, exit;
642
643     // If the result is a smi, it is *not* an object in the ECMA sense.
644     // x0: result
645     // jssp[0]: receiver (newly allocated object)
646     // jssp[1]: constructor function
647     // jssp[2]: number of arguments (smi-tagged)
648     __ JumpIfSmi(x0, &use_receiver);
649
650     // If the type of the result (stored in its map) is less than
651     // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
652     __ JumpIfObjectType(x0, x1, x3, FIRST_SPEC_OBJECT_TYPE, &exit, ge);
653
654     // Throw away the result of the constructor invocation and use the
655     // on-stack receiver as the result.
656     __ Bind(&use_receiver);
657     __ Peek(x0, 0);
658
659     // Remove the receiver from the stack, remove caller arguments, and
660     // return.
661     __ Bind(&exit);
662     // x0: result
663     // jssp[0]: receiver (newly allocated object)
664     // jssp[1]: constructor function
665     // jssp[2]: number of arguments (smi-tagged)
666     __ Peek(x1, 2 * kXRegSize);
667
668     // Leave construct frame.
669   }
670
671   __ DropBySMI(x1);
672   __ Drop(1);
673   __ IncrementCounter(isolate->counters()->constructed_objects(), 1, x1, x2);
674   __ Ret();
675 }
676
677
678 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
679   Generate_JSConstructStubHelper(masm, false, true, false);
680 }
681
682
683 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
684   Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new);
685 }
686
687
688 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
689   Generate_JSConstructStubHelper(masm, true, false, false);
690 }
691
692
693 // Input:
694 //   x0: code entry.
695 //   x1: function.
696 //   x2: receiver.
697 //   x3: argc.
698 //   x4: argv.
699 // Output:
700 //   x0: result.
701 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
702                                              bool is_construct) {
703   // Called from JSEntryStub::GenerateBody().
704   Register function = x1;
705   Register receiver = x2;
706   Register argc = x3;
707   Register argv = x4;
708
709   ProfileEntryHookStub::MaybeCallEntryHook(masm);
710
711   // Clear the context before we push it when entering the internal frame.
712   __ Mov(cp, 0);
713
714   {
715     // Enter an internal frame.
716     FrameScope scope(masm, StackFrame::INTERNAL);
717
718     // Set up the context from the function argument.
719     __ Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset));
720
721     __ InitializeRootRegister();
722
723     // Push the function and the receiver onto the stack.
724     __ Push(function, receiver);
725
726     // Copy arguments to the stack in a loop, in reverse order.
727     // x3: argc.
728     // x4: argv.
729     Label loop, entry;
730     // Compute the copy end address.
731     __ Add(x10, argv, Operand(argc, LSL, kPointerSizeLog2));
732
733     __ B(&entry);
734     __ Bind(&loop);
735     __ Ldr(x11, MemOperand(argv, kPointerSize, PostIndex));
736     __ Ldr(x12, MemOperand(x11));  // Dereference the handle.
737     __ Push(x12);  // Push the argument.
738     __ Bind(&entry);
739     __ Cmp(x10, argv);
740     __ B(ne, &loop);
741
742     // Initialize all JavaScript callee-saved registers, since they will be seen
743     // by the garbage collector as part of handlers.
744     // The original values have been saved in JSEntryStub::GenerateBody().
745     __ LoadRoot(x19, Heap::kUndefinedValueRootIndex);
746     __ Mov(x20, x19);
747     __ Mov(x21, x19);
748     __ Mov(x22, x19);
749     __ Mov(x23, x19);
750     __ Mov(x24, x19);
751     __ Mov(x25, x19);
752     // Don't initialize the reserved registers.
753     // x26 : root register (root).
754     // x27 : context pointer (cp).
755     // x28 : JS stack pointer (jssp).
756     // x29 : frame pointer (fp).
757
758     __ Mov(x0, argc);
759     if (is_construct) {
760       // No type feedback cell is available.
761       __ LoadRoot(x2, Heap::kUndefinedValueRootIndex);
762
763       CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
764       __ CallStub(&stub);
765     } else {
766       ParameterCount actual(x0);
767       __ InvokeFunction(function, actual, CALL_FUNCTION, NullCallWrapper());
768     }
769     // Exit the JS internal frame and remove the parameters (except function),
770     // and return.
771   }
772
773   // Result is in x0. Return.
774   __ Ret();
775 }
776
777
778 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
779   Generate_JSEntryTrampolineHelper(masm, false);
780 }
781
782
783 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
784   Generate_JSEntryTrampolineHelper(masm, true);
785 }
786
787
788 void Builtins::Generate_CompileUnoptimized(MacroAssembler* masm) {
789   CallRuntimePassFunction(masm, Runtime::kHiddenCompileUnoptimized);
790   GenerateTailCallToReturnedCode(masm);
791 }
792
793
794 static void CallCompileOptimized(MacroAssembler* masm, bool concurrent) {
795   FrameScope scope(masm, StackFrame::INTERNAL);
796   Register function = x1;
797
798   // Preserve function. At the same time, push arguments for
799   // kHiddenCompileOptimized.
800   __ LoadObject(x10, masm->isolate()->factory()->ToBoolean(concurrent));
801   __ Push(function, function, x10);
802
803   __ CallRuntime(Runtime::kHiddenCompileOptimized, 2);
804
805   // Restore receiver.
806   __ Pop(function);
807 }
808
809
810 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) {
811   CallCompileOptimized(masm, false);
812   GenerateTailCallToReturnedCode(masm);
813 }
814
815
816 void Builtins::Generate_CompileOptimizedConcurrent(MacroAssembler* masm) {
817   CallCompileOptimized(masm, true);
818   GenerateTailCallToReturnedCode(masm);
819 }
820
821
822 static void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) {
823   // For now, we are relying on the fact that make_code_young doesn't do any
824   // garbage collection which allows us to save/restore the registers without
825   // worrying about which of them contain pointers. We also don't build an
826   // internal frame to make the code fast, since we shouldn't have to do stack
827   // crawls in MakeCodeYoung. This seems a bit fragile.
828
829   // The following caller-saved registers must be saved and restored when
830   // calling through to the runtime:
831   //   x0 - The address from which to resume execution.
832   //   x1 - isolate
833   //   lr - The return address for the JSFunction itself. It has not yet been
834   //        preserved on the stack because the frame setup code was replaced
835   //        with a call to this stub, to handle code ageing.
836   {
837     FrameScope scope(masm, StackFrame::MANUAL);
838     __ Push(x0, x1, fp, lr);
839     __ Mov(x1, ExternalReference::isolate_address(masm->isolate()));
840     __ CallCFunction(
841         ExternalReference::get_make_code_young_function(masm->isolate()), 2);
842     __ Pop(lr, fp, x1, x0);
843   }
844
845   // The calling function has been made young again, so return to execute the
846   // real frame set-up code.
847   __ Br(x0);
848 }
849
850 #define DEFINE_CODE_AGE_BUILTIN_GENERATOR(C)                 \
851 void Builtins::Generate_Make##C##CodeYoungAgainEvenMarking(  \
852     MacroAssembler* masm) {                                  \
853   GenerateMakeCodeYoungAgainCommon(masm);                    \
854 }                                                            \
855 void Builtins::Generate_Make##C##CodeYoungAgainOddMarking(   \
856     MacroAssembler* masm) {                                  \
857   GenerateMakeCodeYoungAgainCommon(masm);                    \
858 }
859 CODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR)
860 #undef DEFINE_CODE_AGE_BUILTIN_GENERATOR
861
862
863 void Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) {
864   // For now, as in GenerateMakeCodeYoungAgainCommon, we are relying on the fact
865   // that make_code_young doesn't do any garbage collection which allows us to
866   // save/restore the registers without worrying about which of them contain
867   // pointers.
868
869   // The following caller-saved registers must be saved and restored when
870   // calling through to the runtime:
871   //   x0 - The address from which to resume execution.
872   //   x1 - isolate
873   //   lr - The return address for the JSFunction itself. It has not yet been
874   //        preserved on the stack because the frame setup code was replaced
875   //        with a call to this stub, to handle code ageing.
876   {
877     FrameScope scope(masm, StackFrame::MANUAL);
878     __ Push(x0, x1, fp, lr);
879     __ Mov(x1, ExternalReference::isolate_address(masm->isolate()));
880     __ CallCFunction(
881         ExternalReference::get_mark_code_as_executed_function(
882             masm->isolate()), 2);
883     __ Pop(lr, fp, x1, x0);
884
885     // Perform prologue operations usually performed by the young code stub.
886     __ EmitFrameSetupForCodeAgePatching(masm);
887   }
888
889   // Jump to point after the code-age stub.
890   __ Add(x0, x0, kCodeAgeSequenceSize);
891   __ Br(x0);
892 }
893
894
895 void Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) {
896   GenerateMakeCodeYoungAgainCommon(masm);
897 }
898
899
900 static void Generate_NotifyStubFailureHelper(MacroAssembler* masm,
901                                              SaveFPRegsMode save_doubles) {
902   {
903     FrameScope scope(masm, StackFrame::INTERNAL);
904
905     // Preserve registers across notification, this is important for compiled
906     // stubs that tail call the runtime on deopts passing their parameters in
907     // registers.
908     // TODO(jbramley): Is it correct (and appropriate) to use safepoint
909     // registers here? According to the comment above, we should only need to
910     // preserve the registers with parameters.
911     __ PushXRegList(kSafepointSavedRegisters);
912     // Pass the function and deoptimization type to the runtime system.
913     __ CallRuntime(Runtime::kHiddenNotifyStubFailure, 0, save_doubles);
914     __ PopXRegList(kSafepointSavedRegisters);
915   }
916
917   // Ignore state (pushed by Deoptimizer::EntryGenerator::Generate).
918   __ Drop(1);
919
920   // Jump to the miss handler. Deoptimizer::EntryGenerator::Generate loads this
921   // into lr before it jumps here.
922   __ Br(lr);
923 }
924
925
926 void Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) {
927   Generate_NotifyStubFailureHelper(masm, kDontSaveFPRegs);
928 }
929
930
931 void Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) {
932   Generate_NotifyStubFailureHelper(masm, kSaveFPRegs);
933 }
934
935
936 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
937                                              Deoptimizer::BailoutType type) {
938   {
939     FrameScope scope(masm, StackFrame::INTERNAL);
940     // Pass the deoptimization type to the runtime system.
941     __ Mov(x0, Smi::FromInt(static_cast<int>(type)));
942     __ Push(x0);
943     __ CallRuntime(Runtime::kHiddenNotifyDeoptimized, 1);
944   }
945
946   // Get the full codegen state from the stack and untag it.
947   Register state = x6;
948   __ Peek(state, 0);
949   __ SmiUntag(state);
950
951   // Switch on the state.
952   Label with_tos_register, unknown_state;
953   __ CompareAndBranch(
954       state, FullCodeGenerator::NO_REGISTERS, ne, &with_tos_register);
955   __ Drop(1);  // Remove state.
956   __ Ret();
957
958   __ Bind(&with_tos_register);
959   // Reload TOS register.
960   __ Peek(x0, kPointerSize);
961   __ CompareAndBranch(state, FullCodeGenerator::TOS_REG, ne, &unknown_state);
962   __ Drop(2);  // Remove state and TOS.
963   __ Ret();
964
965   __ Bind(&unknown_state);
966   __ Abort(kInvalidFullCodegenState);
967 }
968
969
970 void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
971   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
972 }
973
974
975 void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
976   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
977 }
978
979
980 void Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) {
981   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
982 }
983
984
985 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
986   // Lookup the function in the JavaScript frame.
987   __ Ldr(x0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
988   {
989     FrameScope scope(masm, StackFrame::INTERNAL);
990     // Pass function as argument.
991     __ Push(x0);
992     __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
993   }
994
995   // If the code object is null, just return to the unoptimized code.
996   Label skip;
997   __ CompareAndBranch(x0, Smi::FromInt(0), ne, &skip);
998   __ Ret();
999
1000   __ Bind(&skip);
1001
1002   // Load deoptimization data from the code object.
1003   // <deopt_data> = <code>[#deoptimization_data_offset]
1004   __ Ldr(x1, MemOperand(x0, Code::kDeoptimizationDataOffset - kHeapObjectTag));
1005
1006   // Load the OSR entrypoint offset from the deoptimization data.
1007   // <osr_offset> = <deopt_data>[#header_size + #osr_pc_offset]
1008   __ Ldrsw(w1, UntagSmiFieldMemOperand(x1, FixedArray::OffsetOfElementAt(
1009       DeoptimizationInputData::kOsrPcOffsetIndex)));
1010
1011   // Compute the target address = code_obj + header_size + osr_offset
1012   // <entry_addr> = <code_obj> + #header_size + <osr_offset>
1013   __ Add(x0, x0, x1);
1014   __ Add(lr, x0, Code::kHeaderSize - kHeapObjectTag);
1015
1016   // And "return" to the OSR entry point of the function.
1017   __ Ret();
1018 }
1019
1020
1021 void Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) {
1022   // We check the stack limit as indicator that recompilation might be done.
1023   Label ok;
1024   __ CompareRoot(jssp, Heap::kStackLimitRootIndex);
1025   __ B(hs, &ok);
1026   {
1027     FrameScope scope(masm, StackFrame::INTERNAL);
1028     __ CallRuntime(Runtime::kHiddenStackGuard, 0);
1029   }
1030   __ Jump(masm->isolate()->builtins()->OnStackReplacement(),
1031           RelocInfo::CODE_TARGET);
1032
1033   __ Bind(&ok);
1034   __ Ret();
1035 }
1036
1037
1038 void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
1039   enum {
1040     call_type_JS_func = 0,
1041     call_type_func_proxy = 1,
1042     call_type_non_func = 2
1043   };
1044   Register argc = x0;
1045   Register function = x1;
1046   Register call_type = x4;
1047   Register scratch1 = x10;
1048   Register scratch2 = x11;
1049   Register receiver_type = x13;
1050
1051   ASM_LOCATION("Builtins::Generate_FunctionCall");
1052   // 1. Make sure we have at least one argument.
1053   { Label done;
1054     __ Cbnz(argc, &done);
1055     __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex);
1056     __ Push(scratch1);
1057     __ Mov(argc, 1);
1058     __ Bind(&done);
1059   }
1060
1061   // 2. Get the function to call (passed as receiver) from the stack, check
1062   //    if it is a function.
1063   Label slow, non_function;
1064   __ Peek(function, Operand(argc, LSL, kXRegSizeLog2));
1065   __ JumpIfSmi(function, &non_function);
1066   __ JumpIfNotObjectType(function, scratch1, receiver_type,
1067                          JS_FUNCTION_TYPE, &slow);
1068
1069   // 3a. Patch the first argument if necessary when calling a function.
1070   Label shift_arguments;
1071   __ Mov(call_type, static_cast<int>(call_type_JS_func));
1072   { Label convert_to_object, use_global_receiver, patch_receiver;
1073     // Change context eagerly in case we need the global receiver.
1074     __ Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset));
1075
1076     // Do not transform the receiver for strict mode functions.
1077     // Also do not transform the receiver for native (Compilerhints already in
1078     // x3).
1079     __ Ldr(scratch1,
1080            FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
1081     __ Ldr(scratch2.W(),
1082            FieldMemOperand(scratch1, SharedFunctionInfo::kCompilerHintsOffset));
1083     __ TestAndBranchIfAnySet(
1084         scratch2.W(),
1085         (1 << SharedFunctionInfo::kStrictModeFunction) |
1086         (1 << SharedFunctionInfo::kNative),
1087         &shift_arguments);
1088
1089     // Compute the receiver in sloppy mode.
1090     Register receiver = x2;
1091     __ Sub(scratch1, argc, 1);
1092     __ Peek(receiver, Operand(scratch1, LSL, kXRegSizeLog2));
1093     __ JumpIfSmi(receiver, &convert_to_object);
1094
1095     __ JumpIfRoot(receiver, Heap::kUndefinedValueRootIndex,
1096                   &use_global_receiver);
1097     __ JumpIfRoot(receiver, Heap::kNullValueRootIndex, &use_global_receiver);
1098
1099     STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1100     __ JumpIfObjectType(receiver, scratch1, scratch2,
1101                         FIRST_SPEC_OBJECT_TYPE, &shift_arguments, ge);
1102
1103     __ Bind(&convert_to_object);
1104
1105     {
1106       // Enter an internal frame in order to preserve argument count.
1107       FrameScope scope(masm, StackFrame::INTERNAL);
1108       __ SmiTag(argc);
1109
1110       __ Push(argc, receiver);
1111       __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1112       __ Mov(receiver, x0);
1113
1114       __ Pop(argc);
1115       __ SmiUntag(argc);
1116
1117       // Exit the internal frame.
1118     }
1119
1120     // Restore the function and flag in the registers.
1121     __ Peek(function, Operand(argc, LSL, kXRegSizeLog2));
1122     __ Mov(call_type, static_cast<int>(call_type_JS_func));
1123     __ B(&patch_receiver);
1124
1125     __ Bind(&use_global_receiver);
1126     __ Ldr(receiver, GlobalObjectMemOperand());
1127     __ Ldr(receiver,
1128            FieldMemOperand(receiver, GlobalObject::kGlobalReceiverOffset));
1129
1130
1131     __ Bind(&patch_receiver);
1132     __ Sub(scratch1, argc, 1);
1133     __ Poke(receiver, Operand(scratch1, LSL, kXRegSizeLog2));
1134
1135     __ B(&shift_arguments);
1136   }
1137
1138   // 3b. Check for function proxy.
1139   __ Bind(&slow);
1140   __ Mov(call_type, static_cast<int>(call_type_func_proxy));
1141   __ Cmp(receiver_type, JS_FUNCTION_PROXY_TYPE);
1142   __ B(eq, &shift_arguments);
1143   __ Bind(&non_function);
1144   __ Mov(call_type, static_cast<int>(call_type_non_func));
1145
1146   // 3c. Patch the first argument when calling a non-function.  The
1147   //     CALL_NON_FUNCTION builtin expects the non-function callee as
1148   //     receiver, so overwrite the first argument which will ultimately
1149   //     become the receiver.
1150   // call type (0: JS function, 1: function proxy, 2: non-function)
1151   __ Sub(scratch1, argc, 1);
1152   __ Poke(function, Operand(scratch1, LSL, kXRegSizeLog2));
1153
1154   // 4. Shift arguments and return address one slot down on the stack
1155   //    (overwriting the original receiver).  Adjust argument count to make
1156   //    the original first argument the new receiver.
1157   // call type (0: JS function, 1: function proxy, 2: non-function)
1158   __ Bind(&shift_arguments);
1159   { Label loop;
1160     // Calculate the copy start address (destination). Copy end address is jssp.
1161     __ Add(scratch2, jssp, Operand(argc, LSL, kPointerSizeLog2));
1162     __ Sub(scratch1, scratch2, kPointerSize);
1163
1164     __ Bind(&loop);
1165     __ Ldr(x12, MemOperand(scratch1, -kPointerSize, PostIndex));
1166     __ Str(x12, MemOperand(scratch2, -kPointerSize, PostIndex));
1167     __ Cmp(scratch1, jssp);
1168     __ B(ge, &loop);
1169     // Adjust the actual number of arguments and remove the top element
1170     // (which is a copy of the last argument).
1171     __ Sub(argc, argc, 1);
1172     __ Drop(1);
1173   }
1174
1175   // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin,
1176   //     or a function proxy via CALL_FUNCTION_PROXY.
1177   // call type (0: JS function, 1: function proxy, 2: non-function)
1178   { Label js_function, non_proxy;
1179     __ Cbz(call_type, &js_function);
1180     // Expected number of arguments is 0 for CALL_NON_FUNCTION.
1181     __ Mov(x2, 0);
1182     __ Cmp(call_type, static_cast<int>(call_type_func_proxy));
1183     __ B(ne, &non_proxy);
1184
1185     __ Push(function);  // Re-add proxy object as additional argument.
1186     __ Add(argc, argc, 1);
1187     __ GetBuiltinFunction(function, Builtins::CALL_FUNCTION_PROXY);
1188     __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1189             RelocInfo::CODE_TARGET);
1190
1191     __ Bind(&non_proxy);
1192     __ GetBuiltinFunction(function, Builtins::CALL_NON_FUNCTION);
1193     __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1194             RelocInfo::CODE_TARGET);
1195     __ Bind(&js_function);
1196   }
1197
1198   // 5b. Get the code to call from the function and check that the number of
1199   //     expected arguments matches what we're providing.  If so, jump
1200   //     (tail-call) to the code in register edx without checking arguments.
1201   __ Ldr(x3, FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
1202   __ Ldrsw(x2,
1203            FieldMemOperand(x3,
1204              SharedFunctionInfo::kFormalParameterCountOffset));
1205   Label dont_adapt_args;
1206   __ Cmp(x2, argc);  // Check formal and actual parameter counts.
1207   __ B(eq, &dont_adapt_args);
1208   __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1209           RelocInfo::CODE_TARGET);
1210   __ Bind(&dont_adapt_args);
1211
1212   __ Ldr(x3, FieldMemOperand(function, JSFunction::kCodeEntryOffset));
1213   ParameterCount expected(0);
1214   __ InvokeCode(x3, expected, expected, JUMP_FUNCTION, NullCallWrapper());
1215 }
1216
1217
1218 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1219   ASM_LOCATION("Builtins::Generate_FunctionApply");
1220   const int kIndexOffset    =
1221       StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize);
1222   const int kLimitOffset    =
1223       StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize);
1224   const int kArgsOffset     =  2 * kPointerSize;
1225   const int kReceiverOffset =  3 * kPointerSize;
1226   const int kFunctionOffset =  4 * kPointerSize;
1227
1228   {
1229     FrameScope frame_scope(masm, StackFrame::INTERNAL);
1230
1231     Register args = x12;
1232     Register receiver = x14;
1233     Register function = x15;
1234
1235     // Get the length of the arguments via a builtin call.
1236     __ Ldr(function, MemOperand(fp, kFunctionOffset));
1237     __ Ldr(args, MemOperand(fp, kArgsOffset));
1238     __ Push(function, args);
1239     __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
1240     Register argc = x0;
1241
1242     // Check the stack for overflow.
1243     // We are not trying to catch interruptions (e.g. debug break and
1244     // preemption) here, so the "real stack limit" is checked.
1245     Label enough_stack_space;
1246     __ LoadRoot(x10, Heap::kRealStackLimitRootIndex);
1247     __ Ldr(function, MemOperand(fp, kFunctionOffset));
1248     // Make x10 the space we have left. The stack might already be overflowed
1249     // here which will cause x10 to become negative.
1250     // TODO(jbramley): Check that the stack usage here is safe.
1251     __ Sub(x10, jssp, x10);
1252     // Check if the arguments will overflow the stack.
1253     __ Cmp(x10, Operand(argc, LSR, kSmiShift - kPointerSizeLog2));
1254     __ B(gt, &enough_stack_space);
1255     // There is not enough stack space, so use a builtin to throw an appropriate
1256     // error.
1257     __ Push(function, argc);
1258     __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1259     // We should never return from the APPLY_OVERFLOW builtin.
1260     if (__ emit_debug_code()) {
1261       __ Unreachable();
1262     }
1263
1264     __ Bind(&enough_stack_space);
1265     // Push current limit and index.
1266     __ Mov(x1, 0);  // Initial index.
1267     __ Push(argc, x1);
1268
1269     Label push_receiver;
1270     __ Ldr(receiver, MemOperand(fp, kReceiverOffset));
1271
1272     // Check that the function is a JS function. Otherwise it must be a proxy.
1273     // When it is not the function proxy will be invoked later.
1274     __ JumpIfNotObjectType(function, x10, x11, JS_FUNCTION_TYPE,
1275                            &push_receiver);
1276
1277     // Change context eagerly to get the right global object if necessary.
1278     __ Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset));
1279     // Load the shared function info.
1280     __ Ldr(x2, FieldMemOperand(function,
1281                                JSFunction::kSharedFunctionInfoOffset));
1282
1283     // Compute and push the receiver.
1284     // Do not transform the receiver for strict mode functions.
1285     Label convert_receiver_to_object, use_global_receiver;
1286     __ Ldr(w10, FieldMemOperand(x2, SharedFunctionInfo::kCompilerHintsOffset));
1287     __ Tbnz(x10, SharedFunctionInfo::kStrictModeFunction, &push_receiver);
1288     // Do not transform the receiver for native functions.
1289     __ Tbnz(x10, SharedFunctionInfo::kNative, &push_receiver);
1290
1291     // Compute the receiver in sloppy mode.
1292     __ JumpIfSmi(receiver, &convert_receiver_to_object);
1293     __ JumpIfRoot(receiver, Heap::kNullValueRootIndex, &use_global_receiver);
1294     __ JumpIfRoot(receiver, Heap::kUndefinedValueRootIndex,
1295                   &use_global_receiver);
1296
1297     // Check if the receiver is already a JavaScript object.
1298     STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1299     __ JumpIfObjectType(receiver, x10, x11, FIRST_SPEC_OBJECT_TYPE,
1300                         &push_receiver, ge);
1301
1302     // Call a builtin to convert the receiver to a regular object.
1303     __ Bind(&convert_receiver_to_object);
1304     __ Push(receiver);
1305     __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1306     __ Mov(receiver, x0);
1307     __ B(&push_receiver);
1308
1309     __ Bind(&use_global_receiver);
1310     __ Ldr(x10, GlobalObjectMemOperand());
1311     __ Ldr(receiver, FieldMemOperand(x10, GlobalObject::kGlobalReceiverOffset));
1312
1313     // Push the receiver
1314     __ Bind(&push_receiver);
1315     __ Push(receiver);
1316
1317     // Copy all arguments from the array to the stack.
1318     Label entry, loop;
1319     Register current = x0;
1320     __ Ldr(current, MemOperand(fp, kIndexOffset));
1321     __ B(&entry);
1322
1323     __ Bind(&loop);
1324     // Load the current argument from the arguments array and push it.
1325     // TODO(all): Couldn't we optimize this for JS arrays?
1326
1327     __ Ldr(x1, MemOperand(fp, kArgsOffset));
1328     __ Push(x1, current);
1329
1330     // Call the runtime to access the property in the arguments array.
1331     __ CallRuntime(Runtime::kGetProperty, 2);
1332     __ Push(x0);
1333
1334     // Use inline caching to access the arguments.
1335     __ Ldr(current, MemOperand(fp, kIndexOffset));
1336     __ Add(current, current, Smi::FromInt(1));
1337     __ Str(current, MemOperand(fp, kIndexOffset));
1338
1339     // Test if the copy loop has finished copying all the elements from the
1340     // arguments object.
1341     __ Bind(&entry);
1342     __ Ldr(x1, MemOperand(fp, kLimitOffset));
1343     __ Cmp(current, x1);
1344     __ B(ne, &loop);
1345
1346     // At the end of the loop, the number of arguments is stored in 'current',
1347     // represented as a smi.
1348
1349     function = x1;  // From now on we want the function to be kept in x1;
1350     __ Ldr(function, MemOperand(fp, kFunctionOffset));
1351
1352     // Call the function.
1353     Label call_proxy;
1354     ParameterCount actual(current);
1355     __ SmiUntag(current);
1356     __ JumpIfNotObjectType(function, x10, x11, JS_FUNCTION_TYPE, &call_proxy);
1357     __ InvokeFunction(function, actual, CALL_FUNCTION, NullCallWrapper());
1358     frame_scope.GenerateLeaveFrame();
1359     __ Drop(3);
1360     __ Ret();
1361
1362     // Call the function proxy.
1363     __ Bind(&call_proxy);
1364     // x0 : argc
1365     // x1 : function
1366     __ Push(function);  // Add function proxy as last argument.
1367     __ Add(x0, x0, 1);
1368     __ Mov(x2, 0);
1369     __ GetBuiltinFunction(x1, Builtins::CALL_FUNCTION_PROXY);
1370     __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1371             RelocInfo::CODE_TARGET);
1372   }
1373   __ Drop(3);
1374   __ Ret();
1375 }
1376
1377
1378 static void ArgumentAdaptorStackCheck(MacroAssembler* masm,
1379                                       Label* stack_overflow) {
1380   // ----------- S t a t e -------------
1381   //  -- x0 : actual number of arguments
1382   //  -- x1 : function (passed through to callee)
1383   //  -- x2 : expected number of arguments
1384   // -----------------------------------
1385   // Check the stack for overflow.
1386   // We are not trying to catch interruptions (e.g. debug break and
1387   // preemption) here, so the "real stack limit" is checked.
1388   Label enough_stack_space;
1389   __ LoadRoot(x10, Heap::kRealStackLimitRootIndex);
1390   // Make x10 the space we have left. The stack might already be overflowed
1391   // here which will cause x10 to become negative.
1392   __ Sub(x10, jssp, x10);
1393   // Check if the arguments will overflow the stack.
1394   __ Cmp(x10, Operand(x2, LSL, kPointerSizeLog2));
1395   __ B(le, stack_overflow);
1396 }
1397
1398
1399 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1400   __ SmiTag(x10, x0);
1401   __ Mov(x11, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
1402   __ Push(lr, fp);
1403   __ Push(x11, x1, x10);
1404   __ Add(fp, jssp,
1405          StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize);
1406 }
1407
1408
1409 static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1410   // ----------- S t a t e -------------
1411   //  -- x0 : result being passed through
1412   // -----------------------------------
1413   // Get the number of arguments passed (as a smi), tear down the frame and
1414   // then drop the parameters and the receiver.
1415   __ Ldr(x10, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp +
1416                                kPointerSize)));
1417   __ Mov(jssp, fp);
1418   __ Pop(fp, lr);
1419   __ DropBySMI(x10, kXRegSize);
1420   __ Drop(1);
1421 }
1422
1423
1424 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1425   ASM_LOCATION("Builtins::Generate_ArgumentsAdaptorTrampoline");
1426   // ----------- S t a t e -------------
1427   //  -- x0 : actual number of arguments
1428   //  -- x1 : function (passed through to callee)
1429   //  -- x2 : expected number of arguments
1430   // -----------------------------------
1431
1432   Label stack_overflow;
1433   ArgumentAdaptorStackCheck(masm, &stack_overflow);
1434
1435   Register argc_actual = x0;  // Excluding the receiver.
1436   Register argc_expected = x2;  // Excluding the receiver.
1437   Register function = x1;
1438   Register code_entry = x3;
1439
1440   Label invoke, dont_adapt_arguments;
1441
1442   Label enough, too_few;
1443   __ Ldr(code_entry, FieldMemOperand(function, JSFunction::kCodeEntryOffset));
1444   __ Cmp(argc_actual, argc_expected);
1445   __ B(lt, &too_few);
1446   __ Cmp(argc_expected, SharedFunctionInfo::kDontAdaptArgumentsSentinel);
1447   __ B(eq, &dont_adapt_arguments);
1448
1449   {  // Enough parameters: actual >= expected
1450     EnterArgumentsAdaptorFrame(masm);
1451
1452     Register copy_start = x10;
1453     Register copy_end = x11;
1454     Register copy_to = x12;
1455     Register scratch1 = x13, scratch2 = x14;
1456
1457     __ Lsl(argc_expected, argc_expected, kPointerSizeLog2);
1458
1459     // Adjust for fp, lr, and the receiver.
1460     __ Add(copy_start, fp, 3 * kPointerSize);
1461     __ Add(copy_start, copy_start, Operand(argc_actual, LSL, kPointerSizeLog2));
1462     __ Sub(copy_end, copy_start, argc_expected);
1463     __ Sub(copy_end, copy_end, kPointerSize);
1464     __ Mov(copy_to, jssp);
1465
1466     // Claim space for the arguments, the receiver, and one extra slot.
1467     // The extra slot ensures we do not write under jssp. It will be popped
1468     // later.
1469     __ Add(scratch1, argc_expected, 2 * kPointerSize);
1470     __ Claim(scratch1, 1);
1471
1472     // Copy the arguments (including the receiver) to the new stack frame.
1473     Label copy_2_by_2;
1474     __ Bind(&copy_2_by_2);
1475     __ Ldp(scratch1, scratch2,
1476            MemOperand(copy_start, - 2 * kPointerSize, PreIndex));
1477     __ Stp(scratch1, scratch2,
1478            MemOperand(copy_to, - 2 * kPointerSize, PreIndex));
1479     __ Cmp(copy_start, copy_end);
1480     __ B(hi, &copy_2_by_2);
1481
1482     // Correct the space allocated for the extra slot.
1483     __ Drop(1);
1484
1485     __ B(&invoke);
1486   }
1487
1488   {  // Too few parameters: Actual < expected
1489     __ Bind(&too_few);
1490     EnterArgumentsAdaptorFrame(masm);
1491
1492     Register copy_from = x10;
1493     Register copy_end = x11;
1494     Register copy_to = x12;
1495     Register scratch1 = x13, scratch2 = x14;
1496
1497     __ Lsl(argc_expected, argc_expected, kPointerSizeLog2);
1498     __ Lsl(argc_actual, argc_actual, kPointerSizeLog2);
1499
1500     // Adjust for fp, lr, and the receiver.
1501     __ Add(copy_from, fp, 3 * kPointerSize);
1502     __ Add(copy_from, copy_from, argc_actual);
1503     __ Mov(copy_to, jssp);
1504     __ Sub(copy_end, copy_to, 1 * kPointerSize);   // Adjust for the receiver.
1505     __ Sub(copy_end, copy_end, argc_actual);
1506
1507     // Claim space for the arguments, the receiver, and one extra slot.
1508     // The extra slot ensures we do not write under jssp. It will be popped
1509     // later.
1510     __ Add(scratch1, argc_expected, 2 * kPointerSize);
1511     __ Claim(scratch1, 1);
1512
1513     // Copy the arguments (including the receiver) to the new stack frame.
1514     Label copy_2_by_2;
1515     __ Bind(&copy_2_by_2);
1516     __ Ldp(scratch1, scratch2,
1517            MemOperand(copy_from, - 2 * kPointerSize, PreIndex));
1518     __ Stp(scratch1, scratch2,
1519            MemOperand(copy_to, - 2 * kPointerSize, PreIndex));
1520     __ Cmp(copy_to, copy_end);
1521     __ B(hi, &copy_2_by_2);
1522
1523     __ Mov(copy_to, copy_end);
1524
1525     // Fill the remaining expected arguments with undefined.
1526     __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex);
1527     __ Add(copy_end, jssp, kPointerSize);
1528
1529     Label fill;
1530     __ Bind(&fill);
1531     __ Stp(scratch1, scratch1,
1532            MemOperand(copy_to, - 2 * kPointerSize, PreIndex));
1533     __ Cmp(copy_to, copy_end);
1534     __ B(hi, &fill);
1535
1536     // Correct the space allocated for the extra slot.
1537     __ Drop(1);
1538   }
1539
1540   // Arguments have been adapted. Now call the entry point.
1541   __ Bind(&invoke);
1542   __ Call(code_entry);
1543
1544   // Store offset of return address for deoptimizer.
1545   masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
1546
1547   // Exit frame and return.
1548   LeaveArgumentsAdaptorFrame(masm);
1549   __ Ret();
1550
1551   // Call the entry point without adapting the arguments.
1552   __ Bind(&dont_adapt_arguments);
1553   __ Jump(code_entry);
1554
1555   __ Bind(&stack_overflow);
1556   {
1557     FrameScope frame(masm, StackFrame::MANUAL);
1558     EnterArgumentsAdaptorFrame(masm);
1559     __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1560     __ Unreachable();
1561   }
1562 }
1563
1564
1565 #undef __
1566
1567 } }  // namespace v8::internal
1568
1569 #endif  // V8_TARGET_ARCH_ARM