f43084b13f6bd6011a3d81a6970c1a8206ce35f9
[platform/upstream/nodejs.git] / deps / v8 / 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 #include "src/v8.h"
6
7 #if V8_TARGET_ARCH_X64
8
9 #include "src/code-factory.h"
10 #include "src/codegen.h"
11 #include "src/deoptimizer.h"
12 #include "src/full-codegen.h"
13
14 namespace v8 {
15 namespace internal {
16
17
18 #define __ ACCESS_MASM(masm)
19
20
21 void Builtins::Generate_Adaptor(MacroAssembler* masm,
22                                 CFunctionId id,
23                                 BuiltinExtraArguments extra_args) {
24   // ----------- S t a t e -------------
25   //  -- rax                 : number of arguments excluding receiver
26   //  -- rdi                 : called function (only guaranteed when
27   //                           extra_args requires it)
28   //  -- rsi                 : context
29   //  -- rsp[0]              : return address
30   //  -- rsp[8]              : last argument
31   //  -- ...
32   //  -- rsp[8 * argc]       : first argument (argc == rax)
33   //  -- rsp[8 * (argc + 1)] : receiver
34   // -----------------------------------
35
36   // Insert extra arguments.
37   int num_extra_args = 0;
38   if (extra_args == NEEDS_CALLED_FUNCTION) {
39     num_extra_args = 1;
40     __ PopReturnAddressTo(kScratchRegister);
41     __ Push(rdi);
42     __ PushReturnAddressFrom(kScratchRegister);
43   } else {
44     DCHECK(extra_args == NO_EXTRA_ARGUMENTS);
45   }
46
47   // JumpToExternalReference expects rax to contain the number of arguments
48   // including the receiver and the extra arguments.
49   __ addp(rax, Immediate(num_extra_args + 1));
50   __ JumpToExternalReference(ExternalReference(id, masm->isolate()), 1);
51 }
52
53
54 static void CallRuntimePassFunction(
55     MacroAssembler* masm, Runtime::FunctionId function_id) {
56   FrameScope scope(masm, StackFrame::INTERNAL);
57   // Push a copy of the function onto the stack.
58   __ Push(rdi);
59   // Function is also the parameter to the runtime call.
60   __ Push(rdi);
61
62   __ CallRuntime(function_id, 1);
63   // Restore receiver.
64   __ Pop(rdi);
65 }
66
67
68 static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
69   __ movp(kScratchRegister,
70           FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
71   __ movp(kScratchRegister,
72           FieldOperand(kScratchRegister, SharedFunctionInfo::kCodeOffset));
73   __ leap(kScratchRegister, FieldOperand(kScratchRegister, Code::kHeaderSize));
74   __ jmp(kScratchRegister);
75 }
76
77
78 static void GenerateTailCallToReturnedCode(MacroAssembler* masm) {
79   __ leap(rax, FieldOperand(rax, Code::kHeaderSize));
80   __ jmp(rax);
81 }
82
83
84 void Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) {
85   // Checking whether the queued function is ready for install is optional,
86   // since we come across interrupts and stack checks elsewhere.  However,
87   // not checking may delay installing ready functions, and always checking
88   // would be quite expensive.  A good compromise is to first check against
89   // stack limit as a cue for an interrupt signal.
90   Label ok;
91   __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
92   __ j(above_equal, &ok);
93
94   CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode);
95   GenerateTailCallToReturnedCode(masm);
96
97   __ bind(&ok);
98   GenerateTailCallToSharedCode(masm);
99 }
100
101
102 static void Generate_Runtime_NewObject(MacroAssembler* masm,
103                                        bool create_memento,
104                                        Register original_constructor,
105                                        Label* count_incremented,
106                                        Label* allocated) {
107   int offset = 0;
108   if (create_memento) {
109     // Get the cell or allocation site.
110     __ movp(rdi, Operand(rsp, kPointerSize * 2));
111     __ Push(rdi);
112     offset = kPointerSize;
113   }
114
115   // Must restore rsi (context) and rdi (constructor) before calling runtime.
116   __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
117   __ movp(rdi, Operand(rsp, offset));
118   __ Push(rdi);
119   __ Push(original_constructor);
120   if (create_memento) {
121     __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3);
122   } else {
123     __ CallRuntime(Runtime::kNewObject, 2);
124   }
125   __ movp(rbx, rax);  // store result in rbx
126
127   // Runtime_NewObjectWithAllocationSite increments allocation count.
128   // Skip the increment.
129   if (create_memento) {
130     __ jmp(count_incremented);
131   } else {
132     __ jmp(allocated);
133   }
134 }
135
136
137 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
138                                            bool is_api_function,
139                                            bool create_memento) {
140   // ----------- S t a t e -------------
141   //  -- rax: number of arguments
142   //  -- rdi: constructor function
143   //  -- rbx: allocation site or undefined
144   //  -- rdx: original constructor
145   // -----------------------------------
146
147   // Should never create mementos for api functions.
148   DCHECK(!is_api_function || !create_memento);
149
150   // Enter a construct frame.
151   {
152     FrameScope scope(masm, StackFrame::CONSTRUCT);
153
154     if (create_memento) {
155       __ AssertUndefinedOrAllocationSite(rbx);
156       __ Push(rbx);
157     }
158
159     // Store a smi-tagged arguments count on the stack.
160     __ Integer32ToSmi(rax, rax);
161     __ Push(rax);
162
163     // Push the function to invoke on the stack.
164     __ Push(rdi);
165
166     Label rt_call, normal_new, allocated, count_incremented;
167     __ cmpp(rdx, rdi);
168     __ j(equal, &normal_new);
169
170     Generate_Runtime_NewObject(masm, create_memento, rdx, &count_incremented,
171                                &allocated);
172
173     __ bind(&normal_new);
174     // Try to allocate the object without transitioning into C code. If any of
175     // the preconditions is not met, the code bails out to the runtime call.
176     if (FLAG_inline_new) {
177       Label undo_allocation;
178
179       ExternalReference debug_step_in_fp =
180           ExternalReference::debug_step_in_fp_address(masm->isolate());
181       __ Move(kScratchRegister, debug_step_in_fp);
182       __ cmpp(Operand(kScratchRegister, 0), Immediate(0));
183       __ j(not_equal, &rt_call);
184
185       // Verified that the constructor is a JSFunction.
186       // Load the initial map and verify that it is in fact a map.
187       // rdi: constructor
188       __ movp(rax, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
189       // Will both indicate a NULL and a Smi
190       DCHECK(kSmiTag == 0);
191       __ JumpIfSmi(rax, &rt_call);
192       // rdi: constructor
193       // rax: initial map (if proven valid below)
194       __ CmpObjectType(rax, MAP_TYPE, rbx);
195       __ j(not_equal, &rt_call);
196
197       // Check that the constructor is not constructing a JSFunction (see
198       // comments in Runtime_NewObject in runtime.cc). In which case the
199       // initial map's instance type would be JS_FUNCTION_TYPE.
200       // rdi: constructor
201       // rax: initial map
202       __ CmpInstanceType(rax, JS_FUNCTION_TYPE);
203       __ j(equal, &rt_call);
204       if (!is_api_function) {
205         Label allocate;
206         // The code below relies on these assumptions.
207         STATIC_ASSERT(Map::Counter::kShift + Map::Counter::kSize == 32);
208         // Check if slack tracking is enabled.
209         __ movl(rsi, FieldOperand(rax, Map::kBitField3Offset));
210         __ shrl(rsi, Immediate(Map::Counter::kShift));
211         __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd));
212         __ j(less, &allocate);
213         // Decrease generous allocation count.
214         __ subl(FieldOperand(rax, Map::kBitField3Offset),
215                 Immediate(1 << Map::Counter::kShift));
216
217         __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd));
218         __ j(not_equal, &allocate);
219
220         __ Push(rax);
221         __ Push(rdi);
222
223         __ Push(rdi);  // constructor
224         __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
225
226         __ Pop(rdi);
227         __ Pop(rax);
228         __ movl(rsi, Immediate(Map::kSlackTrackingCounterEnd - 1));
229
230         __ bind(&allocate);
231       }
232
233       // Now allocate the JSObject on the heap.
234       __ movzxbp(rdi, FieldOperand(rax, Map::kInstanceSizeOffset));
235       __ shlp(rdi, Immediate(kPointerSizeLog2));
236       if (create_memento) {
237         __ addp(rdi, Immediate(AllocationMemento::kSize));
238       }
239       // rdi: size of new object
240       __ Allocate(rdi,
241                   rbx,
242                   rdi,
243                   no_reg,
244                   &rt_call,
245                   NO_ALLOCATION_FLAGS);
246       Factory* factory = masm->isolate()->factory();
247       // Allocated the JSObject, now initialize the fields.
248       // rax: initial map
249       // rbx: JSObject (not HeapObject tagged - the actual address).
250       // rdi: start of next object (including memento if create_memento)
251       __ movp(Operand(rbx, JSObject::kMapOffset), rax);
252       __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex);
253       __ movp(Operand(rbx, JSObject::kPropertiesOffset), rcx);
254       __ movp(Operand(rbx, JSObject::kElementsOffset), rcx);
255       // Set extra fields in the newly allocated object.
256       // rax: initial map
257       // rbx: JSObject
258       // rdi: start of next object (including memento if create_memento)
259       // rsi: slack tracking counter (non-API function case)
260       __ leap(rcx, Operand(rbx, JSObject::kHeaderSize));
261       __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
262       if (!is_api_function) {
263         Label no_inobject_slack_tracking;
264
265         // Check if slack tracking is enabled.
266         __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd));
267         __ j(less, &no_inobject_slack_tracking);
268
269         // Allocate object with a slack.
270         __ movzxbp(rsi,
271                    FieldOperand(rax, Map::kPreAllocatedPropertyFieldsOffset));
272         __ leap(rsi,
273                Operand(rbx, rsi, times_pointer_size, JSObject::kHeaderSize));
274         // rsi: offset of first field after pre-allocated fields
275         if (FLAG_debug_code) {
276           __ cmpp(rsi, rdi);
277           __ Assert(less_equal,
278                     kUnexpectedNumberOfPreAllocatedPropertyFields);
279         }
280         __ InitializeFieldsWithFiller(rcx, rsi, rdx);
281         __ LoadRoot(rdx, Heap::kOnePointerFillerMapRootIndex);
282         // Fill the remaining fields with one pointer filler map.
283
284         __ bind(&no_inobject_slack_tracking);
285       }
286       if (create_memento) {
287         __ leap(rsi, Operand(rdi, -AllocationMemento::kSize));
288         __ InitializeFieldsWithFiller(rcx, rsi, rdx);
289
290         // Fill in memento fields if necessary.
291         // rsi: points to the allocated but uninitialized memento.
292         __ Move(Operand(rsi, AllocationMemento::kMapOffset),
293                 factory->allocation_memento_map());
294         // Get the cell or undefined.
295         __ movp(rdx, Operand(rsp, kPointerSize*2));
296         __ movp(Operand(rsi, AllocationMemento::kAllocationSiteOffset), rdx);
297       } else {
298         __ InitializeFieldsWithFiller(rcx, rdi, rdx);
299       }
300
301       // Add the object tag to make the JSObject real, so that we can continue
302       // and jump into the continuation code at any time from now on. Any
303       // failures need to undo the allocation, so that the heap is in a
304       // consistent state and verifiable.
305       // rax: initial map
306       // rbx: JSObject
307       // rdi: start of next object
308       __ orp(rbx, Immediate(kHeapObjectTag));
309
310       // Check if a non-empty properties array is needed.
311       // Allocate and initialize a FixedArray if it is.
312       // rax: initial map
313       // rbx: JSObject
314       // rdi: start of next object
315       // Calculate total properties described map.
316       __ movzxbp(rdx, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset));
317       __ movzxbp(rcx,
318                  FieldOperand(rax, Map::kPreAllocatedPropertyFieldsOffset));
319       __ addp(rdx, rcx);
320       // Calculate unused properties past the end of the in-object properties.
321       __ movzxbp(rcx, FieldOperand(rax, Map::kInObjectPropertiesOffset));
322       __ subp(rdx, rcx);
323       // Done if no extra properties are to be allocated.
324       __ j(zero, &allocated);
325       __ Assert(positive, kPropertyAllocationCountFailed);
326
327       // Scale the number of elements by pointer size and add the header for
328       // FixedArrays to the start of the next object calculation from above.
329       // rbx: JSObject
330       // rdi: start of next object (will be start of FixedArray)
331       // rdx: number of elements in properties array
332       __ Allocate(FixedArray::kHeaderSize,
333                   times_pointer_size,
334                   rdx,
335                   rdi,
336                   rax,
337                   no_reg,
338                   &undo_allocation,
339                   RESULT_CONTAINS_TOP);
340
341       // Initialize the FixedArray.
342       // rbx: JSObject
343       // rdi: FixedArray
344       // rdx: number of elements
345       // rax: start of next object
346       __ LoadRoot(rcx, Heap::kFixedArrayMapRootIndex);
347       __ movp(Operand(rdi, HeapObject::kMapOffset), rcx);  // setup the map
348       __ Integer32ToSmi(rdx, rdx);
349       __ movp(Operand(rdi, FixedArray::kLengthOffset), rdx);  // and length
350
351       // Initialize the fields to undefined.
352       // rbx: JSObject
353       // rdi: FixedArray
354       // rax: start of next object
355       // rdx: number of elements
356       { Label loop, entry;
357         __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
358         __ leap(rcx, Operand(rdi, FixedArray::kHeaderSize));
359         __ jmp(&entry);
360         __ bind(&loop);
361         __ movp(Operand(rcx, 0), rdx);
362         __ addp(rcx, Immediate(kPointerSize));
363         __ bind(&entry);
364         __ cmpp(rcx, rax);
365         __ j(below, &loop);
366       }
367
368       // Store the initialized FixedArray into the properties field of
369       // the JSObject
370       // rbx: JSObject
371       // rdi: FixedArray
372       __ orp(rdi, Immediate(kHeapObjectTag));  // add the heap tag
373       __ movp(FieldOperand(rbx, JSObject::kPropertiesOffset), rdi);
374
375
376       // Continue with JSObject being successfully allocated
377       // rbx: JSObject
378       __ jmp(&allocated);
379
380       // Undo the setting of the new top so that the heap is verifiable. For
381       // example, the map's unused properties potentially do not match the
382       // allocated objects unused properties.
383       // rbx: JSObject (previous new top)
384       __ bind(&undo_allocation);
385       __ UndoAllocationInNewSpace(rbx);
386     }
387
388     // Allocate the new receiver object using the runtime call.
389     // rdi: function (constructor)
390     __ bind(&rt_call);
391     Generate_Runtime_NewObject(masm, create_memento, rdi, &count_incremented,
392                                &allocated);
393
394     // New object allocated.
395     // rbx: newly allocated object
396     __ bind(&allocated);
397
398     if (create_memento) {
399       __ movp(rcx, Operand(rsp, kPointerSize*2));
400       __ Cmp(rcx, masm->isolate()->factory()->undefined_value());
401       __ j(equal, &count_incremented);
402       // rcx is an AllocationSite. We are creating a memento from it, so we
403       // need to increment the memento create count.
404       __ SmiAddConstant(
405           FieldOperand(rcx, AllocationSite::kPretenureCreateCountOffset),
406           Smi::FromInt(1));
407       __ bind(&count_incremented);
408     }
409
410     // Retrieve the function from the stack.
411     __ Pop(rdi);
412
413     // Retrieve smi-tagged arguments count from the stack.
414     __ movp(rax, Operand(rsp, 0));
415     __ SmiToInteger32(rax, rax);
416
417     // Push the allocated receiver to the stack. We need two copies
418     // because we may have to return the original one and the calling
419     // conventions dictate that the called function pops the receiver.
420     __ Push(rbx);
421     __ Push(rbx);
422
423     // Set up pointer to last argument.
424     __ leap(rbx, Operand(rbp, StandardFrameConstants::kCallerSPOffset));
425
426     // Copy arguments and receiver to the expression stack.
427     Label loop, entry;
428     __ movp(rcx, rax);
429     __ jmp(&entry);
430     __ bind(&loop);
431     __ Push(Operand(rbx, rcx, times_pointer_size, 0));
432     __ bind(&entry);
433     __ decp(rcx);
434     __ j(greater_equal, &loop);
435
436     // Call the function.
437     if (is_api_function) {
438       __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
439       Handle<Code> code =
440           masm->isolate()->builtins()->HandleApiCallConstruct();
441       __ Call(code, RelocInfo::CODE_TARGET);
442     } else {
443       ParameterCount actual(rax);
444       __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper());
445     }
446
447     // Store offset of return address for deoptimizer.
448     if (!is_api_function) {
449       masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
450     }
451
452     // Restore context from the frame.
453     __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
454
455     // If the result is an object (in the ECMA sense), we should get rid
456     // of the receiver and use the result; see ECMA-262 section 13.2.2-7
457     // on page 74.
458     Label use_receiver, exit;
459     // If the result is a smi, it is *not* an object in the ECMA sense.
460     __ JumpIfSmi(rax, &use_receiver);
461
462     // If the type of the result (stored in its map) is less than
463     // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
464     STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
465     __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
466     __ j(above_equal, &exit);
467
468     // Throw away the result of the constructor invocation and use the
469     // on-stack receiver as the result.
470     __ bind(&use_receiver);
471     __ movp(rax, Operand(rsp, 0));
472
473     // Restore the arguments count and leave the construct frame.
474     __ bind(&exit);
475     __ movp(rbx, Operand(rsp, kPointerSize));  // Get arguments count.
476
477     // Leave construct frame.
478   }
479
480   // Remove caller arguments from the stack and return.
481   __ PopReturnAddressTo(rcx);
482   SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2);
483   __ leap(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize));
484   __ PushReturnAddressFrom(rcx);
485   Counters* counters = masm->isolate()->counters();
486   __ IncrementCounter(counters->constructed_objects(), 1);
487   __ ret(0);
488 }
489
490
491 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
492   Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new);
493 }
494
495
496 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
497   Generate_JSConstructStubHelper(masm, true, false);
498 }
499
500
501 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
502   // ----------- S t a t e -------------
503   //  -- rax: number of arguments
504   //  -- rdi: constructor function
505   //  -- rbx: allocation site or undefined
506   //  -- rdx: original constructor
507   // -----------------------------------
508   // TODO(dslomov): support pretenuring
509   CHECK(!FLAG_pretenuring_call_new);
510
511   {
512     FrameScope frame_scope(masm, StackFrame::CONSTRUCT);
513
514     // Store a smi-tagged arguments count on the stack.
515     __ Integer32ToSmi(rax, rax);
516     __ Push(rax);
517     __ SmiToInteger32(rax, rax);
518
519     // Push new.target
520     __ Push(rdx);
521
522     // receiver is the hole.
523     __ Push(masm->isolate()->factory()->the_hole_value());
524
525     // Set up pointer to last argument.
526     __ leap(rbx, Operand(rbp, StandardFrameConstants::kCallerSPOffset));
527
528     // Copy arguments and receiver to the expression stack.
529     Label loop, entry;
530     __ movp(rcx, rax);
531     __ jmp(&entry);
532     __ bind(&loop);
533     __ Push(Operand(rbx, rcx, times_pointer_size, 0));
534     __ bind(&entry);
535     __ decp(rcx);
536     __ j(greater_equal, &loop);
537
538     __ incp(rax);  // Pushed new.target.
539
540     // Handle step in.
541     Label skip_step_in;
542     ExternalReference debug_step_in_fp =
543         ExternalReference::debug_step_in_fp_address(masm->isolate());
544     __ Move(kScratchRegister, debug_step_in_fp);
545     __ cmpp(Operand(kScratchRegister, 0), Immediate(0));
546     __ j(equal, &skip_step_in);
547
548     __ Push(rax);
549     __ Push(rdi);
550     __ Push(rdi);
551     __ CallRuntime(Runtime::kHandleStepInForDerivedConstructors, 1);
552     __ Pop(rdi);
553     __ Pop(rax);
554
555     __ bind(&skip_step_in);
556
557     // Call the function.
558     ParameterCount actual(rax);
559     __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper());
560
561     // Restore context from the frame.
562     __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
563
564     __ movp(rbx, Operand(rsp, 0));  // Get arguments count.
565   }                                 // Leave construct frame.
566
567   // Remove caller arguments from the stack and return.
568   __ PopReturnAddressTo(rcx);
569   SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2);
570   __ leap(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize));
571   __ PushReturnAddressFrom(rcx);
572   __ ret(0);
573 }
574
575
576 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
577                                              bool is_construct) {
578   ProfileEntryHookStub::MaybeCallEntryHook(masm);
579
580   // Expects five C++ function parameters.
581   // - Address entry (ignored)
582   // - JSFunction* function (
583   // - Object* receiver
584   // - int argc
585   // - Object*** argv
586   // (see Handle::Invoke in execution.cc).
587
588   // Open a C++ scope for the FrameScope.
589   {
590     // Platform specific argument handling. After this, the stack contains
591     // an internal frame and the pushed function and receiver, and
592     // register rax and rbx holds the argument count and argument array,
593     // while rdi holds the function pointer and rsi the context.
594
595 #ifdef _WIN64
596     // MSVC parameters in:
597     // rcx        : entry (ignored)
598     // rdx        : function
599     // r8         : receiver
600     // r9         : argc
601     // [rsp+0x20] : argv
602
603     // Clear the context before we push it when entering the internal frame.
604     __ Set(rsi, 0);
605     // Enter an internal frame.
606     FrameScope scope(masm, StackFrame::INTERNAL);
607
608     // Load the function context into rsi.
609     __ movp(rsi, FieldOperand(rdx, JSFunction::kContextOffset));
610
611     // Push the function and the receiver onto the stack.
612     __ Push(rdx);
613     __ Push(r8);
614
615     // Load the number of arguments and setup pointer to the arguments.
616     __ movp(rax, r9);
617     // Load the previous frame pointer to access C argument on stack
618     __ movp(kScratchRegister, Operand(rbp, 0));
619     __ movp(rbx, Operand(kScratchRegister, EntryFrameConstants::kArgvOffset));
620     // Load the function pointer into rdi.
621     __ movp(rdi, rdx);
622 #else  // _WIN64
623     // GCC parameters in:
624     // rdi : entry (ignored)
625     // rsi : function
626     // rdx : receiver
627     // rcx : argc
628     // r8  : argv
629
630     __ movp(rdi, rsi);
631     // rdi : function
632
633     // Clear the context before we push it when entering the internal frame.
634     __ Set(rsi, 0);
635     // Enter an internal frame.
636     FrameScope scope(masm, StackFrame::INTERNAL);
637
638     // Push the function and receiver and setup the context.
639     __ Push(rdi);
640     __ Push(rdx);
641     __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
642
643     // Load the number of arguments and setup pointer to the arguments.
644     __ movp(rax, rcx);
645     __ movp(rbx, r8);
646 #endif  // _WIN64
647
648     // Current stack contents:
649     // [rsp + 2 * kPointerSize ... ] : Internal frame
650     // [rsp + kPointerSize]          : function
651     // [rsp]                         : receiver
652     // Current register contents:
653     // rax : argc
654     // rbx : argv
655     // rsi : context
656     // rdi : function
657
658     // Copy arguments to the stack in a loop.
659     // Register rbx points to array of pointers to handle locations.
660     // Push the values of these handles.
661     Label loop, entry;
662     __ Set(rcx, 0);  // Set loop variable to 0.
663     __ jmp(&entry);
664     __ bind(&loop);
665     __ movp(kScratchRegister, Operand(rbx, rcx, times_pointer_size, 0));
666     __ Push(Operand(kScratchRegister, 0));  // dereference handle
667     __ addp(rcx, Immediate(1));
668     __ bind(&entry);
669     __ cmpp(rcx, rax);
670     __ j(not_equal, &loop);
671
672     // Invoke the code.
673     if (is_construct) {
674       // No type feedback cell is available
675       __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
676       // Expects rdi to hold function pointer.
677       CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
678       __ CallStub(&stub);
679     } else {
680       ParameterCount actual(rax);
681       // Function must be in rdi.
682       __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper());
683     }
684     // Exit the internal frame. Notice that this also removes the empty
685     // context and the function left on the stack by the code
686     // invocation.
687   }
688
689   // TODO(X64): Is argument correct? Is there a receiver to remove?
690   __ ret(1 * kPointerSize);  // Remove receiver.
691 }
692
693
694 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
695   Generate_JSEntryTrampolineHelper(masm, false);
696 }
697
698
699 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
700   Generate_JSEntryTrampolineHelper(masm, true);
701 }
702
703
704 void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
705   CallRuntimePassFunction(masm, Runtime::kCompileLazy);
706   GenerateTailCallToReturnedCode(masm);
707 }
708
709
710 static void CallCompileOptimized(MacroAssembler* masm,
711                                             bool concurrent) {
712   FrameScope scope(masm, StackFrame::INTERNAL);
713   // Push a copy of the function onto the stack.
714   __ Push(rdi);
715   // Function is also the parameter to the runtime call.
716   __ Push(rdi);
717   // Whether to compile in a background thread.
718   __ Push(masm->isolate()->factory()->ToBoolean(concurrent));
719
720   __ CallRuntime(Runtime::kCompileOptimized, 2);
721   // Restore receiver.
722   __ Pop(rdi);
723 }
724
725
726 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) {
727   CallCompileOptimized(masm, false);
728   GenerateTailCallToReturnedCode(masm);
729 }
730
731
732 void Builtins::Generate_CompileOptimizedConcurrent(MacroAssembler* masm) {
733   CallCompileOptimized(masm, true);
734   GenerateTailCallToReturnedCode(masm);
735 }
736
737
738 static void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) {
739   // For now, we are relying on the fact that make_code_young doesn't do any
740   // garbage collection which allows us to save/restore the registers without
741   // worrying about which of them contain pointers. We also don't build an
742   // internal frame to make the code faster, since we shouldn't have to do stack
743   // crawls in MakeCodeYoung. This seems a bit fragile.
744
745   // Re-execute the code that was patched back to the young age when
746   // the stub returns.
747   __ subp(Operand(rsp, 0), Immediate(5));
748   __ Pushad();
749   __ Move(arg_reg_2, ExternalReference::isolate_address(masm->isolate()));
750   __ movp(arg_reg_1, Operand(rsp, kNumSafepointRegisters * kPointerSize));
751   {  // NOLINT
752     FrameScope scope(masm, StackFrame::MANUAL);
753     __ PrepareCallCFunction(2);
754     __ CallCFunction(
755         ExternalReference::get_make_code_young_function(masm->isolate()), 2);
756   }
757   __ Popad();
758   __ ret(0);
759 }
760
761
762 #define DEFINE_CODE_AGE_BUILTIN_GENERATOR(C)                 \
763 void Builtins::Generate_Make##C##CodeYoungAgainEvenMarking(  \
764     MacroAssembler* masm) {                                  \
765   GenerateMakeCodeYoungAgainCommon(masm);                    \
766 }                                                            \
767 void Builtins::Generate_Make##C##CodeYoungAgainOddMarking(   \
768     MacroAssembler* masm) {                                  \
769   GenerateMakeCodeYoungAgainCommon(masm);                    \
770 }
771 CODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR)
772 #undef DEFINE_CODE_AGE_BUILTIN_GENERATOR
773
774
775 void Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) {
776   // For now, as in GenerateMakeCodeYoungAgainCommon, we are relying on the fact
777   // that make_code_young doesn't do any garbage collection which allows us to
778   // save/restore the registers without worrying about which of them contain
779   // pointers.
780   __ Pushad();
781   __ Move(arg_reg_2, ExternalReference::isolate_address(masm->isolate()));
782   __ movp(arg_reg_1, Operand(rsp, kNumSafepointRegisters * kPointerSize));
783   __ subp(arg_reg_1, Immediate(Assembler::kShortCallInstructionLength));
784   {  // NOLINT
785     FrameScope scope(masm, StackFrame::MANUAL);
786     __ PrepareCallCFunction(2);
787     __ CallCFunction(
788         ExternalReference::get_mark_code_as_executed_function(masm->isolate()),
789         2);
790   }
791   __ Popad();
792
793   // Perform prologue operations usually performed by the young code stub.
794   __ PopReturnAddressTo(kScratchRegister);
795   __ pushq(rbp);  // Caller's frame pointer.
796   __ movp(rbp, rsp);
797   __ Push(rsi);  // Callee's context.
798   __ Push(rdi);  // Callee's JS Function.
799   __ PushReturnAddressFrom(kScratchRegister);
800
801   // Jump to point after the code-age stub.
802   __ ret(0);
803 }
804
805
806 void Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) {
807   GenerateMakeCodeYoungAgainCommon(masm);
808 }
809
810
811 static void Generate_NotifyStubFailureHelper(MacroAssembler* masm,
812                                              SaveFPRegsMode save_doubles) {
813   // Enter an internal frame.
814   {
815     FrameScope scope(masm, StackFrame::INTERNAL);
816
817     // Preserve registers across notification, this is important for compiled
818     // stubs that tail call the runtime on deopts passing their parameters in
819     // registers.
820     __ Pushad();
821     __ CallRuntime(Runtime::kNotifyStubFailure, 0, save_doubles);
822     __ Popad();
823     // Tear down internal frame.
824   }
825
826   __ DropUnderReturnAddress(1);  // Ignore state offset
827   __ ret(0);  // Return to IC Miss stub, continuation still on stack.
828 }
829
830
831 void Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) {
832   Generate_NotifyStubFailureHelper(masm, kDontSaveFPRegs);
833 }
834
835
836 void Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) {
837   Generate_NotifyStubFailureHelper(masm, kSaveFPRegs);
838 }
839
840
841 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
842                                              Deoptimizer::BailoutType type) {
843   // Enter an internal frame.
844   {
845     FrameScope scope(masm, StackFrame::INTERNAL);
846
847     // Pass the deoptimization type to the runtime system.
848     __ Push(Smi::FromInt(static_cast<int>(type)));
849
850     __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
851     // Tear down internal frame.
852   }
853
854   // Get the full codegen state from the stack and untag it.
855   __ SmiToInteger32(kScratchRegister, Operand(rsp, kPCOnStackSize));
856
857   // Switch on the state.
858   Label not_no_registers, not_tos_rax;
859   __ cmpp(kScratchRegister, Immediate(FullCodeGenerator::NO_REGISTERS));
860   __ j(not_equal, &not_no_registers, Label::kNear);
861   __ ret(1 * kPointerSize);  // Remove state.
862
863   __ bind(&not_no_registers);
864   __ movp(rax, Operand(rsp, kPCOnStackSize + kPointerSize));
865   __ cmpp(kScratchRegister, Immediate(FullCodeGenerator::TOS_REG));
866   __ j(not_equal, &not_tos_rax, Label::kNear);
867   __ ret(2 * kPointerSize);  // Remove state, rax.
868
869   __ bind(&not_tos_rax);
870   __ Abort(kNoCasesLeft);
871 }
872
873
874 void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
875   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
876 }
877
878
879 void Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) {
880   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
881 }
882
883
884 void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
885   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
886 }
887
888
889 void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
890   // Stack Layout:
891   // rsp[0]           : Return address
892   // rsp[8]           : Argument n
893   // rsp[16]          : Argument n-1
894   //  ...
895   // rsp[8 * n]       : Argument 1
896   // rsp[8 * (n + 1)] : Receiver (function to call)
897   //
898   // rax contains the number of arguments, n, not counting the receiver.
899   //
900   // 1. Make sure we have at least one argument.
901   { Label done;
902     __ testp(rax, rax);
903     __ j(not_zero, &done);
904     __ PopReturnAddressTo(rbx);
905     __ Push(masm->isolate()->factory()->undefined_value());
906     __ PushReturnAddressFrom(rbx);
907     __ incp(rax);
908     __ bind(&done);
909   }
910
911   // 2. Get the function to call (passed as receiver) from the stack, check
912   //    if it is a function.
913   Label slow, non_function;
914   StackArgumentsAccessor args(rsp, rax);
915   __ movp(rdi, args.GetReceiverOperand());
916   __ JumpIfSmi(rdi, &non_function);
917   __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
918   __ j(not_equal, &slow);
919
920   // 3a. Patch the first argument if necessary when calling a function.
921   Label shift_arguments;
922   __ Set(rdx, 0);  // indicate regular JS_FUNCTION
923   { Label convert_to_object, use_global_proxy, patch_receiver;
924     // Change context eagerly in case we need the global receiver.
925     __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
926
927     // Do not transform the receiver for strict mode functions.
928     __ movp(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
929     __ testb(FieldOperand(rbx, SharedFunctionInfo::kStrictModeByteOffset),
930              Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
931     __ j(not_equal, &shift_arguments);
932
933     // Do not transform the receiver for natives.
934     // SharedFunctionInfo is already loaded into rbx.
935     __ testb(FieldOperand(rbx, SharedFunctionInfo::kNativeByteOffset),
936              Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
937     __ j(not_zero, &shift_arguments);
938
939     // Compute the receiver in sloppy mode.
940     __ movp(rbx, args.GetArgumentOperand(1));
941     __ JumpIfSmi(rbx, &convert_to_object, Label::kNear);
942
943     __ CompareRoot(rbx, Heap::kNullValueRootIndex);
944     __ j(equal, &use_global_proxy);
945     __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
946     __ j(equal, &use_global_proxy);
947
948     STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
949     __ CmpObjectType(rbx, FIRST_SPEC_OBJECT_TYPE, rcx);
950     __ j(above_equal, &shift_arguments);
951
952     __ bind(&convert_to_object);
953     {
954       // Enter an internal frame in order to preserve argument count.
955       FrameScope scope(masm, StackFrame::INTERNAL);
956       __ Integer32ToSmi(rax, rax);
957       __ Push(rax);
958
959       __ Push(rbx);
960       __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
961       __ movp(rbx, rax);
962       __ Set(rdx, 0);  // indicate regular JS_FUNCTION
963
964       __ Pop(rax);
965       __ SmiToInteger32(rax, rax);
966     }
967
968     // Restore the function to rdi.
969     __ movp(rdi, args.GetReceiverOperand());
970     __ jmp(&patch_receiver, Label::kNear);
971
972     __ bind(&use_global_proxy);
973     __ movp(rbx,
974             Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
975     __ movp(rbx, FieldOperand(rbx, GlobalObject::kGlobalProxyOffset));
976
977     __ bind(&patch_receiver);
978     __ movp(args.GetArgumentOperand(1), rbx);
979
980     __ jmp(&shift_arguments);
981   }
982
983   // 3b. Check for function proxy.
984   __ bind(&slow);
985   __ Set(rdx, 1);  // indicate function proxy
986   __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE);
987   __ j(equal, &shift_arguments);
988   __ bind(&non_function);
989   __ Set(rdx, 2);  // indicate non-function
990
991   // 3c. Patch the first argument when calling a non-function.  The
992   //     CALL_NON_FUNCTION builtin expects the non-function callee as
993   //     receiver, so overwrite the first argument which will ultimately
994   //     become the receiver.
995   __ movp(args.GetArgumentOperand(1), rdi);
996
997   // 4. Shift arguments and return address one slot down on the stack
998   //    (overwriting the original receiver).  Adjust argument count to make
999   //    the original first argument the new receiver.
1000   __ bind(&shift_arguments);
1001   { Label loop;
1002     __ movp(rcx, rax);
1003     StackArgumentsAccessor args(rsp, rcx);
1004     __ bind(&loop);
1005     __ movp(rbx, args.GetArgumentOperand(1));
1006     __ movp(args.GetArgumentOperand(0), rbx);
1007     __ decp(rcx);
1008     __ j(not_zero, &loop);  // While non-zero.
1009     __ DropUnderReturnAddress(1, rbx);  // Drop one slot under return address.
1010     __ decp(rax);  // One fewer argument (first argument is new receiver).
1011   }
1012
1013   // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin,
1014   //     or a function proxy via CALL_FUNCTION_PROXY.
1015   { Label function, non_proxy;
1016     __ testp(rdx, rdx);
1017     __ j(zero, &function);
1018     __ Set(rbx, 0);
1019     __ cmpp(rdx, Immediate(1));
1020     __ j(not_equal, &non_proxy);
1021
1022     __ PopReturnAddressTo(rdx);
1023     __ Push(rdi);  // re-add proxy object as additional argument
1024     __ PushReturnAddressFrom(rdx);
1025     __ incp(rax);
1026     __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY);
1027     __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1028            RelocInfo::CODE_TARGET);
1029
1030     __ bind(&non_proxy);
1031     __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
1032     __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1033             RelocInfo::CODE_TARGET);
1034     __ bind(&function);
1035   }
1036
1037   // 5b. Get the code to call from the function and check that the number of
1038   //     expected arguments matches what we're providing.  If so, jump
1039   //     (tail-call) to the code in register edx without checking arguments.
1040   __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
1041   __ LoadSharedFunctionInfoSpecialField(rbx, rdx,
1042       SharedFunctionInfo::kFormalParameterCountOffset);
1043   __ movp(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
1044   __ cmpp(rax, rbx);
1045   __ j(not_equal,
1046        masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1047        RelocInfo::CODE_TARGET);
1048
1049   ParameterCount expected(0);
1050   __ InvokeCode(rdx, expected, expected, JUMP_FUNCTION, NullCallWrapper());
1051 }
1052
1053
1054 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1055   // Stack at entry:
1056   // rsp     : return address
1057   // rsp[8]  : arguments
1058   // rsp[16] : receiver ("this")
1059   // rsp[24] : function
1060   {
1061     FrameScope frame_scope(masm, StackFrame::INTERNAL);
1062     // Stack frame:
1063     // rbp     : Old base pointer
1064     // rbp[8]  : return address
1065     // rbp[16] : function arguments
1066     // rbp[24] : receiver
1067     // rbp[32] : function
1068     static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
1069     static const int kReceiverOffset = kArgumentsOffset + kPointerSize;
1070     static const int kFunctionOffset = kReceiverOffset + kPointerSize;
1071
1072     __ Push(Operand(rbp, kFunctionOffset));
1073     __ Push(Operand(rbp, kArgumentsOffset));
1074     __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
1075
1076     // Check the stack for overflow. We are not trying to catch
1077     // interruptions (e.g. debug break and preemption) here, so the "real stack
1078     // limit" is checked.
1079     Label okay;
1080     __ LoadRoot(kScratchRegister, Heap::kRealStackLimitRootIndex);
1081     __ movp(rcx, rsp);
1082     // Make rcx the space we have left. The stack might already be overflowed
1083     // here which will cause rcx to become negative.
1084     __ subp(rcx, kScratchRegister);
1085     // Make rdx the space we need for the array when it is unrolled onto the
1086     // stack.
1087     __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rax, kPointerSizeLog2);
1088     // Check if the arguments will overflow the stack.
1089     __ cmpp(rcx, rdx);
1090     __ j(greater, &okay);  // Signed comparison.
1091
1092     // Out of stack space.
1093     __ Push(Operand(rbp, kFunctionOffset));
1094     __ Push(rax);
1095     __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1096     __ bind(&okay);
1097     // End of stack check.
1098
1099     // Push current index and limit.
1100     const int kLimitOffset =
1101         StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
1102     const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
1103     __ Push(rax);  // limit
1104     __ Push(Immediate(0));  // index
1105
1106     // Get the receiver.
1107     __ movp(rbx, Operand(rbp, kReceiverOffset));
1108
1109     // Check that the function is a JS function (otherwise it must be a proxy).
1110     Label push_receiver;
1111     __ movp(rdi, Operand(rbp, kFunctionOffset));
1112     __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
1113     __ j(not_equal, &push_receiver);
1114
1115     // Change context eagerly to get the right global object if necessary.
1116     __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
1117
1118     // Do not transform the receiver for strict mode functions.
1119     Label call_to_object, use_global_proxy;
1120     __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
1121     __ testb(FieldOperand(rdx, SharedFunctionInfo::kStrictModeByteOffset),
1122              Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
1123     __ j(not_equal, &push_receiver);
1124
1125     // Do not transform the receiver for natives.
1126     __ testb(FieldOperand(rdx, SharedFunctionInfo::kNativeByteOffset),
1127              Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
1128     __ j(not_equal, &push_receiver);
1129
1130     // Compute the receiver in sloppy mode.
1131     __ JumpIfSmi(rbx, &call_to_object, Label::kNear);
1132     __ CompareRoot(rbx, Heap::kNullValueRootIndex);
1133     __ j(equal, &use_global_proxy);
1134     __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
1135     __ j(equal, &use_global_proxy);
1136
1137     // If given receiver is already a JavaScript object then there's no
1138     // reason for converting it.
1139     STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1140     __ CmpObjectType(rbx, FIRST_SPEC_OBJECT_TYPE, rcx);
1141     __ j(above_equal, &push_receiver);
1142
1143     // Convert the receiver to an object.
1144     __ bind(&call_to_object);
1145     __ Push(rbx);
1146     __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1147     __ movp(rbx, rax);
1148     __ jmp(&push_receiver, Label::kNear);
1149
1150     __ bind(&use_global_proxy);
1151     __ movp(rbx,
1152             Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
1153     __ movp(rbx, FieldOperand(rbx, GlobalObject::kGlobalProxyOffset));
1154
1155     // Push the receiver.
1156     __ bind(&push_receiver);
1157     __ Push(rbx);
1158
1159     // Copy all arguments from the array to the stack.
1160     Label entry, loop;
1161     Register receiver = LoadDescriptor::ReceiverRegister();
1162     Register key = LoadDescriptor::NameRegister();
1163     __ movp(key, Operand(rbp, kIndexOffset));
1164     __ jmp(&entry);
1165     __ bind(&loop);
1166     __ movp(receiver, Operand(rbp, kArgumentsOffset));  // load arguments
1167
1168     // Use inline caching to speed up access to arguments.
1169     if (FLAG_vector_ics) {
1170       // TODO(mvstanton): Vector-based ics need additional infrastructure to
1171       // be embedded here. For now, just call the runtime.
1172       __ Push(receiver);
1173       __ Push(key);
1174       __ CallRuntime(Runtime::kGetProperty, 2);
1175     } else {
1176       Handle<Code> ic = CodeFactory::KeyedLoadIC(masm->isolate()).code();
1177       __ Call(ic, RelocInfo::CODE_TARGET);
1178       // It is important that we do not have a test instruction after the
1179       // call.  A test instruction after the call is used to indicate that
1180       // we have generated an inline version of the keyed load.  In this
1181       // case, we know that we are not generating a test instruction next.
1182     }
1183
1184     // Push the nth argument.
1185     __ Push(rax);
1186
1187     // Update the index on the stack and in register key.
1188     __ movp(key, Operand(rbp, kIndexOffset));
1189     __ SmiAddConstant(key, key, Smi::FromInt(1));
1190     __ movp(Operand(rbp, kIndexOffset), key);
1191
1192     __ bind(&entry);
1193     __ cmpp(key, Operand(rbp, kLimitOffset));
1194     __ j(not_equal, &loop);
1195
1196     // Call the function.
1197     Label call_proxy;
1198     ParameterCount actual(rax);
1199     __ SmiToInteger32(rax, key);
1200     __ movp(rdi, Operand(rbp, kFunctionOffset));
1201     __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
1202     __ j(not_equal, &call_proxy);
1203     __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper());
1204
1205     frame_scope.GenerateLeaveFrame();
1206     __ ret(3 * kPointerSize);  // remove this, receiver, and arguments
1207
1208     // Call the function proxy.
1209     __ bind(&call_proxy);
1210     __ Push(rdi);  // add function proxy as last argument
1211     __ incp(rax);
1212     __ Set(rbx, 0);
1213     __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY);
1214     __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1215             RelocInfo::CODE_TARGET);
1216
1217     // Leave internal frame.
1218   }
1219   __ ret(3 * kPointerSize);  // remove this, receiver, and arguments
1220 }
1221
1222
1223 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
1224   // ----------- S t a t e -------------
1225   //  -- rax    : argc
1226   //  -- rsp[0] : return address
1227   //  -- rsp[8] : last argument
1228   // -----------------------------------
1229   Label generic_array_code;
1230
1231   // Get the InternalArray function.
1232   __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, rdi);
1233
1234   if (FLAG_debug_code) {
1235     // Initial map for the builtin InternalArray functions should be maps.
1236     __ movp(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
1237     // Will both indicate a NULL and a Smi.
1238     STATIC_ASSERT(kSmiTag == 0);
1239     Condition not_smi = NegateCondition(masm->CheckSmi(rbx));
1240     __ Check(not_smi, kUnexpectedInitialMapForInternalArrayFunction);
1241     __ CmpObjectType(rbx, MAP_TYPE, rcx);
1242     __ Check(equal, kUnexpectedInitialMapForInternalArrayFunction);
1243   }
1244
1245   // Run the native code for the InternalArray function called as a normal
1246   // function.
1247   // tail call a stub
1248   InternalArrayConstructorStub stub(masm->isolate());
1249   __ TailCallStub(&stub);
1250 }
1251
1252
1253 void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
1254   // ----------- S t a t e -------------
1255   //  -- rax    : argc
1256   //  -- rsp[0] : return address
1257   //  -- rsp[8] : last argument
1258   // -----------------------------------
1259   Label generic_array_code;
1260
1261   // Get the Array function.
1262   __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rdi);
1263
1264   if (FLAG_debug_code) {
1265     // Initial map for the builtin Array functions should be maps.
1266     __ movp(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
1267     // Will both indicate a NULL and a Smi.
1268     STATIC_ASSERT(kSmiTag == 0);
1269     Condition not_smi = NegateCondition(masm->CheckSmi(rbx));
1270     __ Check(not_smi, kUnexpectedInitialMapForArrayFunction);
1271     __ CmpObjectType(rbx, MAP_TYPE, rcx);
1272     __ Check(equal, kUnexpectedInitialMapForArrayFunction);
1273   }
1274
1275   __ movp(rdx, rdi);
1276   // Run the native code for the Array function called as a normal function.
1277   // tail call a stub
1278   __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
1279   ArrayConstructorStub stub(masm->isolate());
1280   __ TailCallStub(&stub);
1281 }
1282
1283
1284 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
1285   // ----------- S t a t e -------------
1286   //  -- rax                 : number of arguments
1287   //  -- rdi                 : constructor function
1288   //  -- rsp[0]              : return address
1289   //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
1290   //  -- rsp[(argc + 1) * 8] : receiver
1291   // -----------------------------------
1292   Counters* counters = masm->isolate()->counters();
1293   __ IncrementCounter(counters->string_ctor_calls(), 1);
1294
1295   if (FLAG_debug_code) {
1296     __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, rcx);
1297     __ cmpp(rdi, rcx);
1298     __ Assert(equal, kUnexpectedStringFunction);
1299   }
1300
1301   // Load the first argument into rax and get rid of the rest
1302   // (including the receiver).
1303   StackArgumentsAccessor args(rsp, rax);
1304   Label no_arguments;
1305   __ testp(rax, rax);
1306   __ j(zero, &no_arguments);
1307   __ movp(rbx, args.GetArgumentOperand(1));
1308   __ PopReturnAddressTo(rcx);
1309   __ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize));
1310   __ PushReturnAddressFrom(rcx);
1311   __ movp(rax, rbx);
1312
1313   // Lookup the argument in the number to string cache.
1314   Label not_cached, argument_is_string;
1315   __ LookupNumberStringCache(rax,  // Input.
1316                              rbx,  // Result.
1317                              rcx,  // Scratch 1.
1318                              rdx,  // Scratch 2.
1319                              &not_cached);
1320   __ IncrementCounter(counters->string_ctor_cached_number(), 1);
1321   __ bind(&argument_is_string);
1322
1323   // ----------- S t a t e -------------
1324   //  -- rbx    : argument converted to string
1325   //  -- rdi    : constructor function
1326   //  -- rsp[0] : return address
1327   // -----------------------------------
1328
1329   // Allocate a JSValue and put the tagged pointer into rax.
1330   Label gc_required;
1331   __ Allocate(JSValue::kSize,
1332               rax,  // Result.
1333               rcx,  // New allocation top (we ignore it).
1334               no_reg,
1335               &gc_required,
1336               TAG_OBJECT);
1337
1338   // Set the map.
1339   __ LoadGlobalFunctionInitialMap(rdi, rcx);
1340   if (FLAG_debug_code) {
1341     __ cmpb(FieldOperand(rcx, Map::kInstanceSizeOffset),
1342             Immediate(JSValue::kSize >> kPointerSizeLog2));
1343     __ Assert(equal, kUnexpectedStringWrapperInstanceSize);
1344     __ cmpb(FieldOperand(rcx, Map::kUnusedPropertyFieldsOffset), Immediate(0));
1345     __ Assert(equal, kUnexpectedUnusedPropertiesOfStringWrapper);
1346   }
1347   __ movp(FieldOperand(rax, HeapObject::kMapOffset), rcx);
1348
1349   // Set properties and elements.
1350   __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex);
1351   __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rcx);
1352   __ movp(FieldOperand(rax, JSObject::kElementsOffset), rcx);
1353
1354   // Set the value.
1355   __ movp(FieldOperand(rax, JSValue::kValueOffset), rbx);
1356
1357   // Ensure the object is fully initialized.
1358   STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
1359
1360   // We're done. Return.
1361   __ ret(0);
1362
1363   // The argument was not found in the number to string cache. Check
1364   // if it's a string already before calling the conversion builtin.
1365   Label convert_argument;
1366   __ bind(&not_cached);
1367   STATIC_ASSERT(kSmiTag == 0);
1368   __ JumpIfSmi(rax, &convert_argument);
1369   Condition is_string = masm->IsObjectStringType(rax, rbx, rcx);
1370   __ j(NegateCondition(is_string), &convert_argument);
1371   __ movp(rbx, rax);
1372   __ IncrementCounter(counters->string_ctor_string_value(), 1);
1373   __ jmp(&argument_is_string);
1374
1375   // Invoke the conversion builtin and put the result into rbx.
1376   __ bind(&convert_argument);
1377   __ IncrementCounter(counters->string_ctor_conversions(), 1);
1378   {
1379     FrameScope scope(masm, StackFrame::INTERNAL);
1380     __ Push(rdi);  // Preserve the function.
1381     __ Push(rax);
1382     __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
1383     __ Pop(rdi);
1384   }
1385   __ movp(rbx, rax);
1386   __ jmp(&argument_is_string);
1387
1388   // Load the empty string into rbx, remove the receiver from the
1389   // stack, and jump back to the case where the argument is a string.
1390   __ bind(&no_arguments);
1391   __ LoadRoot(rbx, Heap::kempty_stringRootIndex);
1392   __ PopReturnAddressTo(rcx);
1393   __ leap(rsp, Operand(rsp, kPointerSize));
1394   __ PushReturnAddressFrom(rcx);
1395   __ jmp(&argument_is_string);
1396
1397   // At this point the argument is already a string. Call runtime to
1398   // create a string wrapper.
1399   __ bind(&gc_required);
1400   __ IncrementCounter(counters->string_ctor_gc_required(), 1);
1401   {
1402     FrameScope scope(masm, StackFrame::INTERNAL);
1403     __ Push(rbx);
1404     __ CallRuntime(Runtime::kNewStringWrapper, 1);
1405   }
1406   __ ret(0);
1407 }
1408
1409
1410 static void ArgumentsAdaptorStackCheck(MacroAssembler* masm,
1411                                        Label* stack_overflow) {
1412   // ----------- S t a t e -------------
1413   //  -- rax : actual number of arguments
1414   //  -- rbx : expected number of arguments
1415   //  -- rdi: function (passed through to callee)
1416   // -----------------------------------
1417   // Check the stack for overflow. We are not trying to catch
1418   // interruptions (e.g. debug break and preemption) here, so the "real stack
1419   // limit" is checked.
1420   Label okay;
1421   __ LoadRoot(rdx, Heap::kRealStackLimitRootIndex);
1422   __ movp(rcx, rsp);
1423   // Make rcx the space we have left. The stack might already be overflowed
1424   // here which will cause rcx to become negative.
1425   __ subp(rcx, rdx);
1426   // Make rdx the space we need for the array when it is unrolled onto the
1427   // stack.
1428   __ movp(rdx, rbx);
1429   __ shlp(rdx, Immediate(kPointerSizeLog2));
1430   // Check if the arguments will overflow the stack.
1431   __ cmpp(rcx, rdx);
1432   __ j(less_equal, stack_overflow);  // Signed comparison.
1433 }
1434
1435
1436 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1437   __ pushq(rbp);
1438   __ movp(rbp, rsp);
1439
1440   // Store the arguments adaptor context sentinel.
1441   __ Push(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
1442
1443   // Push the function on the stack.
1444   __ Push(rdi);
1445
1446   // Preserve the number of arguments on the stack. Must preserve rax,
1447   // rbx and rcx because these registers are used when copying the
1448   // arguments and the receiver.
1449   __ Integer32ToSmi(r8, rax);
1450   __ Push(r8);
1451 }
1452
1453
1454 static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1455   // Retrieve the number of arguments from the stack. Number is a Smi.
1456   __ movp(rbx, Operand(rbp, ArgumentsAdaptorFrameConstants::kLengthOffset));
1457
1458   // Leave the frame.
1459   __ movp(rsp, rbp);
1460   __ popq(rbp);
1461
1462   // Remove caller arguments from the stack.
1463   __ PopReturnAddressTo(rcx);
1464   SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2);
1465   __ leap(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize));
1466   __ PushReturnAddressFrom(rcx);
1467 }
1468
1469
1470 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1471   // ----------- S t a t e -------------
1472   //  -- rax : actual number of arguments
1473   //  -- rbx : expected number of arguments
1474   //  -- rdi: function (passed through to callee)
1475   // -----------------------------------
1476
1477   Label invoke, dont_adapt_arguments;
1478   Counters* counters = masm->isolate()->counters();
1479   __ IncrementCounter(counters->arguments_adaptors(), 1);
1480
1481   Label stack_overflow;
1482   ArgumentsAdaptorStackCheck(masm, &stack_overflow);
1483
1484   Label enough, too_few;
1485   __ movp(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
1486   __ cmpp(rax, rbx);
1487   __ j(less, &too_few);
1488   __ cmpp(rbx, Immediate(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
1489   __ j(equal, &dont_adapt_arguments);
1490
1491   {  // Enough parameters: Actual >= expected.
1492     __ bind(&enough);
1493     EnterArgumentsAdaptorFrame(masm);
1494
1495     // Copy receiver and all expected arguments.
1496     const int offset = StandardFrameConstants::kCallerSPOffset;
1497     __ leap(rax, Operand(rbp, rax, times_pointer_size, offset));
1498     __ Set(r8, -1);  // account for receiver
1499
1500     Label copy;
1501     __ bind(&copy);
1502     __ incp(r8);
1503     __ Push(Operand(rax, 0));
1504     __ subp(rax, Immediate(kPointerSize));
1505     __ cmpp(r8, rbx);
1506     __ j(less, &copy);
1507     __ jmp(&invoke);
1508   }
1509
1510   {  // Too few parameters: Actual < expected.
1511     __ bind(&too_few);
1512     EnterArgumentsAdaptorFrame(masm);
1513
1514     // Copy receiver and all actual arguments.
1515     const int offset = StandardFrameConstants::kCallerSPOffset;
1516     __ leap(rdi, Operand(rbp, rax, times_pointer_size, offset));
1517     __ Set(r8, -1);  // account for receiver
1518
1519     Label copy;
1520     __ bind(&copy);
1521     __ incp(r8);
1522     __ Push(Operand(rdi, 0));
1523     __ subp(rdi, Immediate(kPointerSize));
1524     __ cmpp(r8, rax);
1525     __ j(less, &copy);
1526
1527     // Fill remaining expected arguments with undefined values.
1528     Label fill;
1529     __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
1530     __ bind(&fill);
1531     __ incp(r8);
1532     __ Push(kScratchRegister);
1533     __ cmpp(r8, rbx);
1534     __ j(less, &fill);
1535
1536     // Restore function pointer.
1537     __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1538   }
1539
1540   // Call the entry point.
1541   __ bind(&invoke);
1542   __ call(rdx);
1543
1544   // Store offset of return address for deoptimizer.
1545   masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
1546
1547   // Leave frame and return.
1548   LeaveArgumentsAdaptorFrame(masm);
1549   __ ret(0);
1550
1551   // -------------------------------------------
1552   // Dont adapt arguments.
1553   // -------------------------------------------
1554   __ bind(&dont_adapt_arguments);
1555   __ jmp(rdx);
1556
1557   __ bind(&stack_overflow);
1558   {
1559     FrameScope frame(masm, StackFrame::MANUAL);
1560     EnterArgumentsAdaptorFrame(masm);
1561     __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1562     __ int3();
1563   }
1564 }
1565
1566
1567 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1568   // Lookup the function in the JavaScript frame.
1569   __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1570   {
1571     FrameScope scope(masm, StackFrame::INTERNAL);
1572     // Pass function as argument.
1573     __ Push(rax);
1574     __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
1575   }
1576
1577   Label skip;
1578   // If the code object is null, just return to the unoptimized code.
1579   __ cmpp(rax, Immediate(0));
1580   __ j(not_equal, &skip, Label::kNear);
1581   __ ret(0);
1582
1583   __ bind(&skip);
1584
1585   // Load deoptimization data from the code object.
1586   __ movp(rbx, Operand(rax, Code::kDeoptimizationDataOffset - kHeapObjectTag));
1587
1588   // Load the OSR entrypoint offset from the deoptimization data.
1589   __ SmiToInteger32(rbx, Operand(rbx, FixedArray::OffsetOfElementAt(
1590       DeoptimizationInputData::kOsrPcOffsetIndex) - kHeapObjectTag));
1591
1592   // Compute the target address = code_obj + header_size + osr_offset
1593   __ leap(rax, Operand(rax, rbx, times_1, Code::kHeaderSize - kHeapObjectTag));
1594
1595   // Overwrite the return address on the stack.
1596   __ movq(StackOperandForReturnAddress(0), rax);
1597
1598   // And "return" to the OSR entry point of the function.
1599   __ ret(0);
1600 }
1601
1602
1603 void Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) {
1604   // We check the stack limit as indicator that recompilation might be done.
1605   Label ok;
1606   __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
1607   __ j(above_equal, &ok);
1608   {
1609     FrameScope scope(masm, StackFrame::INTERNAL);
1610     __ CallRuntime(Runtime::kStackGuard, 0);
1611   }
1612   __ jmp(masm->isolate()->builtins()->OnStackReplacement(),
1613          RelocInfo::CODE_TARGET);
1614
1615   __ bind(&ok);
1616   __ ret(0);
1617 }
1618
1619
1620 #undef __
1621
1622 } }  // namespace v8::internal
1623
1624 #endif  // V8_TARGET_ARCH_X64