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