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