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