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