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