deps: update v8 to 4.3.61.21
[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 static void Generate_CheckStackOverflow(MacroAssembler* masm,
1055                                         const int calleeOffset) {
1056   // rax   : the number of items to be pushed to the stack
1057   //
1058   // Check the stack for overflow. We are not trying to catch
1059   // interruptions (e.g. debug break and preemption) here, so the "real stack
1060   // limit" is checked.
1061   Label okay;
1062   __ LoadRoot(kScratchRegister, Heap::kRealStackLimitRootIndex);
1063   __ movp(rcx, rsp);
1064   // Make rcx the space we have left. The stack might already be overflowed
1065   // here which will cause rcx to become negative.
1066   __ subp(rcx, kScratchRegister);
1067   // Make rdx the space we need for the array when it is unrolled onto the
1068   // stack.
1069   __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rax, kPointerSizeLog2);
1070   // Check if the arguments will overflow the stack.
1071   __ cmpp(rcx, rdx);
1072   __ j(greater, &okay);  // Signed comparison.
1073
1074   // Out of stack space.
1075   __ Push(Operand(rbp, calleeOffset));
1076   __ Push(rax);
1077   __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1078
1079   __ bind(&okay);
1080 }
1081
1082
1083 static void Generate_PushAppliedArguments(MacroAssembler* masm,
1084                                           const int argumentsOffset,
1085                                           const int indexOffset,
1086                                           const int limitOffset) {
1087   Register receiver = LoadDescriptor::ReceiverRegister();
1088   Register key = LoadDescriptor::NameRegister();
1089
1090   // Copy all arguments from the array to the stack.
1091   Label entry, loop;
1092   __ movp(key, Operand(rbp, indexOffset));
1093   __ jmp(&entry);
1094   __ bind(&loop);
1095   __ movp(receiver, Operand(rbp, argumentsOffset));  // load arguments
1096
1097   // Use inline caching to speed up access to arguments.
1098   if (FLAG_vector_ics) {
1099     // TODO(mvstanton): Vector-based ics need additional infrastructure to
1100     // be embedded here. For now, just call the runtime.
1101     __ Push(receiver);
1102     __ Push(key);
1103     __ CallRuntime(Runtime::kGetProperty, 2);
1104   } else {
1105     Handle<Code> ic = CodeFactory::KeyedLoadIC(masm->isolate()).code();
1106     __ Call(ic, RelocInfo::CODE_TARGET);
1107     // It is important that we do not have a test instruction after the
1108     // call.  A test instruction after the call is used to indicate that
1109     // we have generated an inline version of the keyed load.  In this
1110     // case, we know that we are not generating a test instruction next.
1111   }
1112
1113   // Push the nth argument.
1114   __ Push(rax);
1115
1116   // Update the index on the stack and in register key.
1117   __ movp(key, Operand(rbp, indexOffset));
1118   __ SmiAddConstant(key, key, Smi::FromInt(1));
1119   __ movp(Operand(rbp, indexOffset), key);
1120
1121   __ bind(&entry);
1122   __ cmpp(key, Operand(rbp, limitOffset));
1123   __ j(not_equal, &loop);
1124
1125   // On exit, the pushed arguments count is in rax, untagged
1126   __ SmiToInteger64(rax, key);
1127 }
1128
1129
1130 // Used by FunctionApply and ReflectApply
1131 static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
1132   const int kFormalParameters = targetIsArgument ? 3 : 2;
1133   const int kStackSize = kFormalParameters + 1;
1134
1135   // Stack at entry:
1136   // rsp     : return address
1137   // rsp[8]  : arguments
1138   // rsp[16] : receiver ("this")
1139   // rsp[24] : function
1140   {
1141     FrameScope frame_scope(masm, StackFrame::INTERNAL);
1142     // Stack frame:
1143     // rbp     : Old base pointer
1144     // rbp[8]  : return address
1145     // rbp[16] : function arguments
1146     // rbp[24] : receiver
1147     // rbp[32] : function
1148     static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
1149     static const int kReceiverOffset = kArgumentsOffset + kPointerSize;
1150     static const int kFunctionOffset = kReceiverOffset + kPointerSize;
1151
1152     __ Push(Operand(rbp, kFunctionOffset));
1153     __ Push(Operand(rbp, kArgumentsOffset));
1154     if (targetIsArgument) {
1155       __ InvokeBuiltin(Builtins::REFLECT_APPLY_PREPARE, CALL_FUNCTION);
1156     } else {
1157       __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
1158     }
1159
1160     Generate_CheckStackOverflow(masm, kFunctionOffset);
1161
1162     // Push current index and limit.
1163     const int kLimitOffset =
1164         StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
1165     const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
1166     __ Push(rax);  // limit
1167     __ Push(Immediate(0));  // index
1168
1169     // Get the receiver.
1170     __ movp(rbx, Operand(rbp, kReceiverOffset));
1171
1172     // Check that the function is a JS function (otherwise it must be a proxy).
1173     Label push_receiver;
1174     __ movp(rdi, Operand(rbp, kFunctionOffset));
1175     __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
1176     __ j(not_equal, &push_receiver);
1177
1178     // Change context eagerly to get the right global object if necessary.
1179     __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
1180
1181     // Do not transform the receiver for strict mode functions.
1182     Label call_to_object, use_global_proxy;
1183     __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
1184     __ testb(FieldOperand(rdx, SharedFunctionInfo::kStrictModeByteOffset),
1185              Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
1186     __ j(not_equal, &push_receiver);
1187
1188     // Do not transform the receiver for natives.
1189     __ testb(FieldOperand(rdx, SharedFunctionInfo::kNativeByteOffset),
1190              Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
1191     __ j(not_equal, &push_receiver);
1192
1193     // Compute the receiver in sloppy mode.
1194     __ JumpIfSmi(rbx, &call_to_object, Label::kNear);
1195     __ CompareRoot(rbx, Heap::kNullValueRootIndex);
1196     __ j(equal, &use_global_proxy);
1197     __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
1198     __ j(equal, &use_global_proxy);
1199
1200     // If given receiver is already a JavaScript object then there's no
1201     // reason for converting it.
1202     STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1203     __ CmpObjectType(rbx, FIRST_SPEC_OBJECT_TYPE, rcx);
1204     __ j(above_equal, &push_receiver);
1205
1206     // Convert the receiver to an object.
1207     __ bind(&call_to_object);
1208     __ Push(rbx);
1209     __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1210     __ movp(rbx, rax);
1211     __ jmp(&push_receiver, Label::kNear);
1212
1213     __ bind(&use_global_proxy);
1214     __ movp(rbx,
1215             Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
1216     __ movp(rbx, FieldOperand(rbx, GlobalObject::kGlobalProxyOffset));
1217
1218     // Push the receiver.
1219     __ bind(&push_receiver);
1220     __ Push(rbx);
1221
1222     // Loop over the arguments array, pushing each value to the stack
1223     Generate_PushAppliedArguments(
1224         masm, kArgumentsOffset, kIndexOffset, kLimitOffset);
1225
1226     // Call the function.
1227     Label call_proxy;
1228     ParameterCount actual(rax);
1229     __ movp(rdi, Operand(rbp, kFunctionOffset));
1230     __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
1231     __ j(not_equal, &call_proxy);
1232     __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper());
1233
1234     frame_scope.GenerateLeaveFrame();
1235     __ ret(kStackSize * kPointerSize);  // remove this, receiver, and arguments
1236
1237     // Call the function proxy.
1238     __ bind(&call_proxy);
1239     __ Push(rdi);  // add function proxy as last argument
1240     __ incp(rax);
1241     __ Set(rbx, 0);
1242     __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY);
1243     __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1244             RelocInfo::CODE_TARGET);
1245
1246     // Leave internal frame.
1247   }
1248   __ ret(kStackSize * kPointerSize);  // remove this, receiver, and arguments
1249 }
1250
1251
1252 // Used by ReflectConstruct
1253 static void Generate_ConstructHelper(MacroAssembler* masm) {
1254   const int kFormalParameters = 3;
1255   const int kStackSize = kFormalParameters + 1;
1256
1257   // Stack at entry:
1258   // rsp     : return address
1259   // rsp[8]  : original constructor (new.target)
1260   // rsp[16] : arguments
1261   // rsp[24] : constructor
1262   {
1263     FrameScope frame_scope(masm, StackFrame::INTERNAL);
1264     // Stack frame:
1265     // rbp     : Old base pointer
1266     // rbp[8]  : return address
1267     // rbp[16] : original constructor (new.target)
1268     // rbp[24] : arguments
1269     // rbp[32] : constructor
1270     static const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize;
1271     static const int kArgumentsOffset = kNewTargetOffset + kPointerSize;
1272     static const int kFunctionOffset = kArgumentsOffset + kPointerSize;
1273
1274     // If newTarget is not supplied, set it to constructor
1275     Label validate_arguments;
1276     __ movp(rax, Operand(rbp, kNewTargetOffset));
1277     __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
1278     __ j(not_equal, &validate_arguments, Label::kNear);
1279     __ movp(rax, Operand(rbp, kFunctionOffset));
1280     __ movp(Operand(rbp, kNewTargetOffset), rax);
1281
1282     // Validate arguments
1283     __ bind(&validate_arguments);
1284     __ Push(Operand(rbp, kFunctionOffset));
1285     __ Push(Operand(rbp, kArgumentsOffset));
1286     __ Push(Operand(rbp, kNewTargetOffset));
1287     __ InvokeBuiltin(Builtins::REFLECT_CONSTRUCT_PREPARE, CALL_FUNCTION);
1288
1289     Generate_CheckStackOverflow(masm, kFunctionOffset);
1290
1291     // Push current index and limit.
1292     const int kLimitOffset =
1293         StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
1294     const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
1295     __ Push(rax);  // limit
1296     __ Push(Immediate(0));  // index
1297     // Push newTarget and callee functions
1298     __ Push(Operand(rbp, kNewTargetOffset));
1299     __ Push(Operand(rbp, kFunctionOffset));
1300
1301     // Loop over the arguments array, pushing each value to the stack
1302     Generate_PushAppliedArguments(
1303         masm, kArgumentsOffset, kIndexOffset, kLimitOffset);
1304
1305     // Use undefined feedback vector
1306     __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
1307     __ movp(rdi, Operand(rbp, kFunctionOffset));
1308
1309     // Call the function.
1310     CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL);
1311     __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
1312
1313     __ Drop(1);
1314
1315     // Leave internal frame.
1316   }
1317   // remove this, target, arguments and newTarget
1318   __ ret(kStackSize * kPointerSize);
1319 }
1320
1321
1322 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1323   Generate_ApplyHelper(masm, false);
1324 }
1325
1326
1327 void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
1328   Generate_ApplyHelper(masm, true);
1329 }
1330
1331
1332 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
1333   Generate_ConstructHelper(masm);
1334 }
1335
1336
1337 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
1338   // ----------- S t a t e -------------
1339   //  -- rax    : argc
1340   //  -- rsp[0] : return address
1341   //  -- rsp[8] : last argument
1342   // -----------------------------------
1343   Label generic_array_code;
1344
1345   // Get the InternalArray function.
1346   __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, rdi);
1347
1348   if (FLAG_debug_code) {
1349     // Initial map for the builtin InternalArray functions should be maps.
1350     __ movp(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
1351     // Will both indicate a NULL and a Smi.
1352     STATIC_ASSERT(kSmiTag == 0);
1353     Condition not_smi = NegateCondition(masm->CheckSmi(rbx));
1354     __ Check(not_smi, kUnexpectedInitialMapForInternalArrayFunction);
1355     __ CmpObjectType(rbx, MAP_TYPE, rcx);
1356     __ Check(equal, kUnexpectedInitialMapForInternalArrayFunction);
1357   }
1358
1359   // Run the native code for the InternalArray function called as a normal
1360   // function.
1361   // tail call a stub
1362   InternalArrayConstructorStub stub(masm->isolate());
1363   __ TailCallStub(&stub);
1364 }
1365
1366
1367 void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
1368   // ----------- S t a t e -------------
1369   //  -- rax    : argc
1370   //  -- rsp[0] : return address
1371   //  -- rsp[8] : last argument
1372   // -----------------------------------
1373   Label generic_array_code;
1374
1375   // Get the Array function.
1376   __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rdi);
1377
1378   if (FLAG_debug_code) {
1379     // Initial map for the builtin Array functions should be maps.
1380     __ movp(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
1381     // Will both indicate a NULL and a Smi.
1382     STATIC_ASSERT(kSmiTag == 0);
1383     Condition not_smi = NegateCondition(masm->CheckSmi(rbx));
1384     __ Check(not_smi, kUnexpectedInitialMapForArrayFunction);
1385     __ CmpObjectType(rbx, MAP_TYPE, rcx);
1386     __ Check(equal, kUnexpectedInitialMapForArrayFunction);
1387   }
1388
1389   __ movp(rdx, rdi);
1390   // Run the native code for the Array function called as a normal function.
1391   // tail call a stub
1392   __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
1393   ArrayConstructorStub stub(masm->isolate());
1394   __ TailCallStub(&stub);
1395 }
1396
1397
1398 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
1399   // ----------- S t a t e -------------
1400   //  -- rax                 : number of arguments
1401   //  -- rdi                 : constructor function
1402   //  -- rsp[0]              : return address
1403   //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
1404   //  -- rsp[(argc + 1) * 8] : receiver
1405   // -----------------------------------
1406   Counters* counters = masm->isolate()->counters();
1407   __ IncrementCounter(counters->string_ctor_calls(), 1);
1408
1409   if (FLAG_debug_code) {
1410     __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, rcx);
1411     __ cmpp(rdi, rcx);
1412     __ Assert(equal, kUnexpectedStringFunction);
1413   }
1414
1415   // Load the first argument into rax and get rid of the rest
1416   // (including the receiver).
1417   StackArgumentsAccessor args(rsp, rax);
1418   Label no_arguments;
1419   __ testp(rax, rax);
1420   __ j(zero, &no_arguments);
1421   __ movp(rbx, args.GetArgumentOperand(1));
1422   __ PopReturnAddressTo(rcx);
1423   __ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize));
1424   __ PushReturnAddressFrom(rcx);
1425   __ movp(rax, rbx);
1426
1427   // Lookup the argument in the number to string cache.
1428   Label not_cached, argument_is_string;
1429   __ LookupNumberStringCache(rax,  // Input.
1430                              rbx,  // Result.
1431                              rcx,  // Scratch 1.
1432                              rdx,  // Scratch 2.
1433                              &not_cached);
1434   __ IncrementCounter(counters->string_ctor_cached_number(), 1);
1435   __ bind(&argument_is_string);
1436
1437   // ----------- S t a t e -------------
1438   //  -- rbx    : argument converted to string
1439   //  -- rdi    : constructor function
1440   //  -- rsp[0] : return address
1441   // -----------------------------------
1442
1443   // Allocate a JSValue and put the tagged pointer into rax.
1444   Label gc_required;
1445   __ Allocate(JSValue::kSize,
1446               rax,  // Result.
1447               rcx,  // New allocation top (we ignore it).
1448               no_reg,
1449               &gc_required,
1450               TAG_OBJECT);
1451
1452   // Set the map.
1453   __ LoadGlobalFunctionInitialMap(rdi, rcx);
1454   if (FLAG_debug_code) {
1455     __ cmpb(FieldOperand(rcx, Map::kInstanceSizeOffset),
1456             Immediate(JSValue::kSize >> kPointerSizeLog2));
1457     __ Assert(equal, kUnexpectedStringWrapperInstanceSize);
1458     __ cmpb(FieldOperand(rcx, Map::kUnusedPropertyFieldsOffset), Immediate(0));
1459     __ Assert(equal, kUnexpectedUnusedPropertiesOfStringWrapper);
1460   }
1461   __ movp(FieldOperand(rax, HeapObject::kMapOffset), rcx);
1462
1463   // Set properties and elements.
1464   __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex);
1465   __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rcx);
1466   __ movp(FieldOperand(rax, JSObject::kElementsOffset), rcx);
1467
1468   // Set the value.
1469   __ movp(FieldOperand(rax, JSValue::kValueOffset), rbx);
1470
1471   // Ensure the object is fully initialized.
1472   STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
1473
1474   // We're done. Return.
1475   __ ret(0);
1476
1477   // The argument was not found in the number to string cache. Check
1478   // if it's a string already before calling the conversion builtin.
1479   Label convert_argument;
1480   __ bind(&not_cached);
1481   STATIC_ASSERT(kSmiTag == 0);
1482   __ JumpIfSmi(rax, &convert_argument);
1483   Condition is_string = masm->IsObjectStringType(rax, rbx, rcx);
1484   __ j(NegateCondition(is_string), &convert_argument);
1485   __ movp(rbx, rax);
1486   __ IncrementCounter(counters->string_ctor_string_value(), 1);
1487   __ jmp(&argument_is_string);
1488
1489   // Invoke the conversion builtin and put the result into rbx.
1490   __ bind(&convert_argument);
1491   __ IncrementCounter(counters->string_ctor_conversions(), 1);
1492   {
1493     FrameScope scope(masm, StackFrame::INTERNAL);
1494     __ Push(rdi);  // Preserve the function.
1495     __ Push(rax);
1496     __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
1497     __ Pop(rdi);
1498   }
1499   __ movp(rbx, rax);
1500   __ jmp(&argument_is_string);
1501
1502   // Load the empty string into rbx, remove the receiver from the
1503   // stack, and jump back to the case where the argument is a string.
1504   __ bind(&no_arguments);
1505   __ LoadRoot(rbx, Heap::kempty_stringRootIndex);
1506   __ PopReturnAddressTo(rcx);
1507   __ leap(rsp, Operand(rsp, kPointerSize));
1508   __ PushReturnAddressFrom(rcx);
1509   __ jmp(&argument_is_string);
1510
1511   // At this point the argument is already a string. Call runtime to
1512   // create a string wrapper.
1513   __ bind(&gc_required);
1514   __ IncrementCounter(counters->string_ctor_gc_required(), 1);
1515   {
1516     FrameScope scope(masm, StackFrame::INTERNAL);
1517     __ Push(rbx);
1518     __ CallRuntime(Runtime::kNewStringWrapper, 1);
1519   }
1520   __ ret(0);
1521 }
1522
1523
1524 static void ArgumentsAdaptorStackCheck(MacroAssembler* masm,
1525                                        Label* stack_overflow) {
1526   // ----------- S t a t e -------------
1527   //  -- rax : actual number of arguments
1528   //  -- rbx : expected number of arguments
1529   //  -- rdi: function (passed through to callee)
1530   // -----------------------------------
1531   // Check the stack for overflow. We are not trying to catch
1532   // interruptions (e.g. debug break and preemption) here, so the "real stack
1533   // limit" is checked.
1534   Label okay;
1535   __ LoadRoot(rdx, Heap::kRealStackLimitRootIndex);
1536   __ movp(rcx, rsp);
1537   // Make rcx the space we have left. The stack might already be overflowed
1538   // here which will cause rcx to become negative.
1539   __ subp(rcx, rdx);
1540   // Make rdx the space we need for the array when it is unrolled onto the
1541   // stack.
1542   __ movp(rdx, rbx);
1543   __ shlp(rdx, Immediate(kPointerSizeLog2));
1544   // Check if the arguments will overflow the stack.
1545   __ cmpp(rcx, rdx);
1546   __ j(less_equal, stack_overflow);  // Signed comparison.
1547 }
1548
1549
1550 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1551   __ pushq(rbp);
1552   __ movp(rbp, rsp);
1553
1554   // Store the arguments adaptor context sentinel.
1555   __ Push(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
1556
1557   // Push the function on the stack.
1558   __ Push(rdi);
1559
1560   // Preserve the number of arguments on the stack. Must preserve rax,
1561   // rbx and rcx because these registers are used when copying the
1562   // arguments and the receiver.
1563   __ Integer32ToSmi(r8, rax);
1564   __ Push(r8);
1565 }
1566
1567
1568 static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1569   // Retrieve the number of arguments from the stack. Number is a Smi.
1570   __ movp(rbx, Operand(rbp, ArgumentsAdaptorFrameConstants::kLengthOffset));
1571
1572   // Leave the frame.
1573   __ movp(rsp, rbp);
1574   __ popq(rbp);
1575
1576   // Remove caller arguments from the stack.
1577   __ PopReturnAddressTo(rcx);
1578   SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2);
1579   __ leap(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize));
1580   __ PushReturnAddressFrom(rcx);
1581 }
1582
1583
1584 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1585   // ----------- S t a t e -------------
1586   //  -- rax : actual number of arguments
1587   //  -- rbx : expected number of arguments
1588   //  -- rdi: function (passed through to callee)
1589   // -----------------------------------
1590
1591   Label invoke, dont_adapt_arguments;
1592   Counters* counters = masm->isolate()->counters();
1593   __ IncrementCounter(counters->arguments_adaptors(), 1);
1594
1595   Label stack_overflow;
1596   ArgumentsAdaptorStackCheck(masm, &stack_overflow);
1597
1598   Label enough, too_few;
1599   __ movp(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
1600   __ cmpp(rax, rbx);
1601   __ j(less, &too_few);
1602   __ cmpp(rbx, Immediate(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
1603   __ j(equal, &dont_adapt_arguments);
1604
1605   {  // Enough parameters: Actual >= expected.
1606     __ bind(&enough);
1607     EnterArgumentsAdaptorFrame(masm);
1608
1609     // Copy receiver and all expected arguments.
1610     const int offset = StandardFrameConstants::kCallerSPOffset;
1611     __ leap(rax, Operand(rbp, rax, times_pointer_size, offset));
1612     __ Set(r8, -1);  // account for receiver
1613
1614     Label copy;
1615     __ bind(&copy);
1616     __ incp(r8);
1617     __ Push(Operand(rax, 0));
1618     __ subp(rax, Immediate(kPointerSize));
1619     __ cmpp(r8, rbx);
1620     __ j(less, &copy);
1621     __ jmp(&invoke);
1622   }
1623
1624   {  // Too few parameters: Actual < expected.
1625     __ bind(&too_few);
1626     EnterArgumentsAdaptorFrame(masm);
1627
1628     // Copy receiver and all actual arguments.
1629     const int offset = StandardFrameConstants::kCallerSPOffset;
1630     __ leap(rdi, Operand(rbp, rax, times_pointer_size, offset));
1631     __ Set(r8, -1);  // account for receiver
1632
1633     Label copy;
1634     __ bind(&copy);
1635     __ incp(r8);
1636     __ Push(Operand(rdi, 0));
1637     __ subp(rdi, Immediate(kPointerSize));
1638     __ cmpp(r8, rax);
1639     __ j(less, &copy);
1640
1641     // Fill remaining expected arguments with undefined values.
1642     Label fill;
1643     __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
1644     __ bind(&fill);
1645     __ incp(r8);
1646     __ Push(kScratchRegister);
1647     __ cmpp(r8, rbx);
1648     __ j(less, &fill);
1649
1650     // Restore function pointer.
1651     __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1652   }
1653
1654   // Call the entry point.
1655   __ bind(&invoke);
1656   __ call(rdx);
1657
1658   // Store offset of return address for deoptimizer.
1659   masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
1660
1661   // Leave frame and return.
1662   LeaveArgumentsAdaptorFrame(masm);
1663   __ ret(0);
1664
1665   // -------------------------------------------
1666   // Dont adapt arguments.
1667   // -------------------------------------------
1668   __ bind(&dont_adapt_arguments);
1669   __ jmp(rdx);
1670
1671   __ bind(&stack_overflow);
1672   {
1673     FrameScope frame(masm, StackFrame::MANUAL);
1674     EnterArgumentsAdaptorFrame(masm);
1675     __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1676     __ int3();
1677   }
1678 }
1679
1680
1681 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1682   // Lookup the function in the JavaScript frame.
1683   __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1684   {
1685     FrameScope scope(masm, StackFrame::INTERNAL);
1686     // Pass function as argument.
1687     __ Push(rax);
1688     __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
1689   }
1690
1691   Label skip;
1692   // If the code object is null, just return to the unoptimized code.
1693   __ cmpp(rax, Immediate(0));
1694   __ j(not_equal, &skip, Label::kNear);
1695   __ ret(0);
1696
1697   __ bind(&skip);
1698
1699   // Load deoptimization data from the code object.
1700   __ movp(rbx, Operand(rax, Code::kDeoptimizationDataOffset - kHeapObjectTag));
1701
1702   // Load the OSR entrypoint offset from the deoptimization data.
1703   __ SmiToInteger32(rbx, Operand(rbx, FixedArray::OffsetOfElementAt(
1704       DeoptimizationInputData::kOsrPcOffsetIndex) - kHeapObjectTag));
1705
1706   // Compute the target address = code_obj + header_size + osr_offset
1707   __ leap(rax, Operand(rax, rbx, times_1, Code::kHeaderSize - kHeapObjectTag));
1708
1709   // Overwrite the return address on the stack.
1710   __ movq(StackOperandForReturnAddress(0), rax);
1711
1712   // And "return" to the OSR entry point of the function.
1713   __ ret(0);
1714 }
1715
1716
1717 void Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) {
1718   // We check the stack limit as indicator that recompilation might be done.
1719   Label ok;
1720   __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
1721   __ j(above_equal, &ok);
1722   {
1723     FrameScope scope(masm, StackFrame::INTERNAL);
1724     __ CallRuntime(Runtime::kStackGuard, 0);
1725   }
1726   __ jmp(masm->isolate()->builtins()->OnStackReplacement(),
1727          RelocInfo::CODE_TARGET);
1728
1729   __ bind(&ok);
1730   __ ret(0);
1731 }
1732
1733
1734 #undef __
1735
1736 } }  // namespace v8::internal
1737
1738 #endif  // V8_TARGET_ARCH_X64