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