Home | History | Annotate | Download | only in mips64
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #if V8_TARGET_ARCH_MIPS64
      6 
      7 #include "src/codegen.h"
      8 #include "src/debug/debug.h"
      9 #include "src/deoptimizer.h"
     10 #include "src/full-codegen/full-codegen.h"
     11 #include "src/runtime/runtime.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 
     16 
     17 #define __ ACCESS_MASM(masm)
     18 
     19 void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
     20   // ----------- S t a t e -------------
     21   //  -- a0                 : number of arguments excluding receiver
     22   //  -- a1                 : target
     23   //  -- a3                 : new.target
     24   //  -- sp[0]              : last argument
     25   //  -- ...
     26   //  -- sp[8 * (argc - 1)] : first argument
     27   //  -- sp[8 * agrc]       : receiver
     28   // -----------------------------------
     29   __ AssertFunction(a1);
     30 
     31   // Make sure we operate in the context of the called function (for example
     32   // ConstructStubs implemented in C++ will be run in the context of the caller
     33   // instead of the callee, due to the way that [[Construct]] is defined for
     34   // ordinary functions).
     35   __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
     36 
     37   // Insert extra arguments.
     38   const int num_extra_args = 2;
     39   __ Push(a1, a3);
     40 
     41   // JumpToExternalReference expects a0 to contain the number of arguments
     42   // including the receiver and the extra arguments.
     43   __ Daddu(a0, a0, num_extra_args + 1);
     44 
     45   __ JumpToExternalReference(ExternalReference(id, masm->isolate()));
     46 }
     47 
     48 
     49 // Load the built-in InternalArray function from the current context.
     50 static void GenerateLoadInternalArrayFunction(MacroAssembler* masm,
     51                                               Register result) {
     52   // Load the InternalArray function from the native context.
     53   __ LoadNativeContextSlot(Context::INTERNAL_ARRAY_FUNCTION_INDEX, result);
     54 }
     55 
     56 
     57 // Load the built-in Array function from the current context.
     58 static void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) {
     59   // Load the Array function from the native context.
     60   __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, result);
     61 }
     62 
     63 
     64 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
     65   // ----------- S t a t e -------------
     66   //  -- a0     : number of arguments
     67   //  -- ra     : return address
     68   //  -- sp[...]: constructor arguments
     69   // -----------------------------------
     70   Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
     71 
     72   // Get the InternalArray function.
     73   GenerateLoadInternalArrayFunction(masm, a1);
     74 
     75   if (FLAG_debug_code) {
     76     // Initial map for the builtin InternalArray functions should be maps.
     77     __ ld(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
     78     __ SmiTst(a2, a4);
     79     __ Assert(ne, kUnexpectedInitialMapForInternalArrayFunction,
     80               a4, Operand(zero_reg));
     81     __ GetObjectType(a2, a3, a4);
     82     __ Assert(eq, kUnexpectedInitialMapForInternalArrayFunction,
     83               a4, Operand(MAP_TYPE));
     84   }
     85 
     86   // Run the native code for the InternalArray function called as a normal
     87   // function.
     88   // Tail call a stub.
     89   InternalArrayConstructorStub stub(masm->isolate());
     90   __ TailCallStub(&stub);
     91 }
     92 
     93 
     94 void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
     95   // ----------- S t a t e -------------
     96   //  -- a0     : number of arguments
     97   //  -- ra     : return address
     98   //  -- sp[...]: constructor arguments
     99   // -----------------------------------
    100   Label generic_array_code;
    101 
    102   // Get the Array function.
    103   GenerateLoadArrayFunction(masm, a1);
    104 
    105   if (FLAG_debug_code) {
    106     // Initial map for the builtin Array functions should be maps.
    107     __ ld(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
    108     __ SmiTst(a2, a4);
    109     __ Assert(ne, kUnexpectedInitialMapForArrayFunction1,
    110               a4, Operand(zero_reg));
    111     __ GetObjectType(a2, a3, a4);
    112     __ Assert(eq, kUnexpectedInitialMapForArrayFunction2,
    113               a4, Operand(MAP_TYPE));
    114   }
    115 
    116   // Run the native code for the Array function called as a normal function.
    117   // Tail call a stub.
    118   __ mov(a3, a1);
    119   __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
    120   ArrayConstructorStub stub(masm->isolate());
    121   __ TailCallStub(&stub);
    122 }
    123 
    124 
    125 // static
    126 void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
    127   // ----------- S t a t e -------------
    128   //  -- a0                 : number of arguments
    129   //  -- a1                 : function
    130   //  -- cp                 : context
    131   //  -- ra                 : return address
    132   //  -- sp[(argc - n) * 8] : arg[n] (zero-based)
    133   //  -- sp[(argc + 1) * 8] : receiver
    134   // -----------------------------------
    135   Heap::RootListIndex const root_index =
    136       (kind == MathMaxMinKind::kMin) ? Heap::kInfinityValueRootIndex
    137                                      : Heap::kMinusInfinityValueRootIndex;
    138 
    139   // Load the accumulator with the default return value (either -Infinity or
    140   // +Infinity), with the tagged value in t1 and the double value in f0.
    141   __ LoadRoot(t1, root_index);
    142   __ ldc1(f0, FieldMemOperand(t1, HeapNumber::kValueOffset));
    143   __ Addu(a3, a0, 1);
    144 
    145   Label done_loop, loop;
    146   __ bind(&loop);
    147   {
    148     // Check if all parameters done.
    149     __ Dsubu(a0, a0, Operand(1));
    150     __ Branch(&done_loop, lt, a0, Operand(zero_reg));
    151 
    152     // Load the next parameter tagged value into a2.
    153     __ Dlsa(at, sp, a0, kPointerSizeLog2);
    154     __ ld(a2, MemOperand(at));
    155 
    156     // Load the double value of the parameter into f2, maybe converting the
    157     // parameter to a number first using the ToNumber builtin if necessary.
    158     Label convert, convert_smi, convert_number, done_convert;
    159     __ bind(&convert);
    160     __ JumpIfSmi(a2, &convert_smi);
    161     __ ld(a4, FieldMemOperand(a2, HeapObject::kMapOffset));
    162     __ JumpIfRoot(a4, Heap::kHeapNumberMapRootIndex, &convert_number);
    163     {
    164       // Parameter is not a Number, use the ToNumber builtin to convert it.
    165       FrameScope scope(masm, StackFrame::MANUAL);
    166       __ Push(ra, fp);
    167       __ Move(fp, sp);
    168       __ Push(cp, a1);
    169       __ SmiTag(a0);
    170       __ SmiTag(a3);
    171       __ Push(a0, t1, a3);
    172       __ mov(a0, a2);
    173       __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
    174       __ mov(a2, v0);
    175       __ Pop(a0, t1, a3);
    176       {
    177         // Restore the double accumulator value (f0).
    178         Label restore_smi, done_restore;
    179         __ JumpIfSmi(t1, &restore_smi);
    180         __ ldc1(f0, FieldMemOperand(t1, HeapNumber::kValueOffset));
    181         __ jmp(&done_restore);
    182         __ bind(&restore_smi);
    183         __ SmiToDoubleFPURegister(t1, f0, a4);
    184         __ bind(&done_restore);
    185       }
    186       __ SmiUntag(a3);
    187       __ SmiUntag(a0);
    188       __ Pop(cp, a1);
    189       __ Pop(ra, fp);
    190     }
    191     __ jmp(&convert);
    192     __ bind(&convert_number);
    193     __ ldc1(f2, FieldMemOperand(a2, HeapNumber::kValueOffset));
    194     __ jmp(&done_convert);
    195     __ bind(&convert_smi);
    196     __ SmiToDoubleFPURegister(a2, f2, a4);
    197     __ bind(&done_convert);
    198 
    199     // Perform the actual comparison with using Min/Max macro instructions the
    200     // accumulator value on the left hand side (f0) and the next parameter value
    201     // on the right hand side (f2).
    202     // We need to work out which HeapNumber (or smi) the result came from.
    203     Label compare_nan;
    204     __ BranchF(nullptr, &compare_nan, eq, f0, f2);
    205     __ Move(a4, f0);
    206     if (kind == MathMaxMinKind::kMin) {
    207       __ MinNaNCheck_d(f0, f0, f2);
    208     } else {
    209       DCHECK(kind == MathMaxMinKind::kMax);
    210       __ MaxNaNCheck_d(f0, f0, f2);
    211     }
    212     __ Move(at, f0);
    213     __ Branch(&loop, eq, a4, Operand(at));
    214     __ mov(t1, a2);
    215     __ jmp(&loop);
    216 
    217     // At least one side is NaN, which means that the result will be NaN too.
    218     __ bind(&compare_nan);
    219     __ LoadRoot(t1, Heap::kNanValueRootIndex);
    220     __ ldc1(f0, FieldMemOperand(t1, HeapNumber::kValueOffset));
    221     __ jmp(&loop);
    222   }
    223 
    224   __ bind(&done_loop);
    225   __ Dlsa(sp, sp, a3, kPointerSizeLog2);
    226   __ Ret(USE_DELAY_SLOT);
    227   __ mov(v0, t1);  // In delay slot.
    228 }
    229 
    230 // static
    231 void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
    232   // ----------- S t a t e -------------
    233   //  -- a0                     : number of arguments
    234   //  -- a1                     : constructor function
    235   //  -- ra                     : return address
    236   //  -- sp[(argc - n - 1) * 8] : arg[n] (zero based)
    237   //  -- sp[argc * 8]           : receiver
    238   // -----------------------------------
    239 
    240   // 1. Load the first argument into a0 and get rid of the rest (including the
    241   // receiver).
    242   Label no_arguments;
    243   {
    244     __ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg));
    245     __ Dsubu(a0, a0, Operand(1));
    246     __ Dlsa(sp, sp, a0, kPointerSizeLog2);
    247     __ ld(a0, MemOperand(sp));
    248     __ Drop(2);
    249   }
    250 
    251   // 2a. Convert first argument to number.
    252   __ Jump(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
    253 
    254   // 2b. No arguments, return +0.
    255   __ bind(&no_arguments);
    256   __ Move(v0, Smi::FromInt(0));
    257   __ DropAndRet(1);
    258 }
    259 
    260 
    261 void Builtins::Generate_NumberConstructor_ConstructStub(MacroAssembler* masm) {
    262   // ----------- S t a t e -------------
    263   //  -- a0                     : number of arguments
    264   //  -- a1                     : constructor function
    265   //  -- a3                     : new target
    266   //  -- ra                     : return address
    267   //  -- sp[(argc - n - 1) * 8] : arg[n] (zero based)
    268   //  -- sp[argc * 8]           : receiver
    269   // -----------------------------------
    270 
    271   // 1. Make sure we operate in the context of the called function.
    272   __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
    273 
    274   // 2. Load the first argument into a0 and get rid of the rest (including the
    275   // receiver).
    276   {
    277     Label no_arguments, done;
    278     __ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg));
    279     __ Dsubu(a0, a0, Operand(1));
    280     __ Dlsa(sp, sp, a0, kPointerSizeLog2);
    281     __ ld(a0, MemOperand(sp));
    282     __ Drop(2);
    283     __ jmp(&done);
    284     __ bind(&no_arguments);
    285     __ Move(a0, Smi::FromInt(0));
    286     __ Drop(1);
    287     __ bind(&done);
    288   }
    289 
    290   // 3. Make sure a0 is a number.
    291   {
    292     Label done_convert;
    293     __ JumpIfSmi(a0, &done_convert);
    294     __ GetObjectType(a0, a2, a2);
    295     __ Branch(&done_convert, eq, t0, Operand(HEAP_NUMBER_TYPE));
    296     {
    297       FrameScope scope(masm, StackFrame::INTERNAL);
    298       __ Push(a1, a3);
    299       __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
    300       __ Move(a0, v0);
    301       __ Pop(a1, a3);
    302     }
    303     __ bind(&done_convert);
    304   }
    305 
    306   // 4. Check if new target and constructor differ.
    307   Label new_object;
    308   __ Branch(&new_object, ne, a1, Operand(a3));
    309 
    310   // 5. Allocate a JSValue wrapper for the number.
    311   __ AllocateJSValue(v0, a1, a0, a2, t0, &new_object);
    312   __ Ret();
    313 
    314   // 6. Fallback to the runtime to create new object.
    315   __ bind(&new_object);
    316   {
    317     FrameScope scope(masm, StackFrame::INTERNAL);
    318     __ Push(a0);
    319     FastNewObjectStub stub(masm->isolate());
    320     __ CallStub(&stub);
    321     __ Pop(a0);
    322   }
    323   __ Ret(USE_DELAY_SLOT);
    324   __ sd(a0, FieldMemOperand(v0, JSValue::kValueOffset));  // In delay slot.
    325 }
    326 
    327 
    328 // static
    329 void Builtins::Generate_StringConstructor(MacroAssembler* masm) {
    330   // ----------- S t a t e -------------
    331   //  -- a0                     : number of arguments
    332   //  -- a1                     : constructor function
    333   //  -- ra                     : return address
    334   //  -- sp[(argc - n - 1) * 8] : arg[n] (zero based)
    335   //  -- sp[argc * 8]           : receiver
    336   // -----------------------------------
    337 
    338   // 1. Load the first argument into a0 and get rid of the rest (including the
    339   // receiver).
    340   Label no_arguments;
    341   {
    342     __ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg));
    343     __ Dsubu(a0, a0, Operand(1));
    344     __ Dlsa(sp, sp, a0, kPointerSizeLog2);
    345     __ ld(a0, MemOperand(sp));
    346     __ Drop(2);
    347   }
    348 
    349   // 2a. At least one argument, return a0 if it's a string, otherwise
    350   // dispatch to appropriate conversion.
    351   Label to_string, symbol_descriptive_string;
    352   {
    353     __ JumpIfSmi(a0, &to_string);
    354     __ GetObjectType(a0, a1, a1);
    355     STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE);
    356     __ Subu(a1, a1, Operand(FIRST_NONSTRING_TYPE));
    357     __ Branch(&symbol_descriptive_string, eq, a1, Operand(zero_reg));
    358     __ Branch(&to_string, gt, a1, Operand(zero_reg));
    359     __ Ret(USE_DELAY_SLOT);
    360     __ mov(v0, a0);
    361   }
    362 
    363   // 2b. No arguments, return the empty string (and pop the receiver).
    364   __ bind(&no_arguments);
    365   {
    366     __ LoadRoot(v0, Heap::kempty_stringRootIndex);
    367     __ DropAndRet(1);
    368   }
    369 
    370   // 3a. Convert a0 to a string.
    371   __ bind(&to_string);
    372   {
    373     ToStringStub stub(masm->isolate());
    374     __ TailCallStub(&stub);
    375   }
    376 
    377   // 3b. Convert symbol in a0 to a string.
    378   __ bind(&symbol_descriptive_string);
    379   {
    380     __ Push(a0);
    381     __ TailCallRuntime(Runtime::kSymbolDescriptiveString);
    382   }
    383 }
    384 
    385 
    386 void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
    387   // ----------- S t a t e -------------
    388   //  -- a0                     : number of arguments
    389   //  -- a1                     : constructor function
    390   //  -- a3                     : new target
    391   //  -- ra                     : return address
    392   //  -- sp[(argc - n - 1) * 8] : arg[n] (zero based)
    393   //  -- sp[argc * 8]           : receiver
    394   // -----------------------------------
    395 
    396   // 1. Make sure we operate in the context of the called function.
    397   __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
    398 
    399   // 2. Load the first argument into a0 and get rid of the rest (including the
    400   // receiver).
    401   {
    402     Label no_arguments, done;
    403     __ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg));
    404     __ Dsubu(a0, a0, Operand(1));
    405     __ Dlsa(sp, sp, a0, kPointerSizeLog2);
    406     __ ld(a0, MemOperand(sp));
    407     __ Drop(2);
    408     __ jmp(&done);
    409     __ bind(&no_arguments);
    410     __ LoadRoot(a0, Heap::kempty_stringRootIndex);
    411     __ Drop(1);
    412     __ bind(&done);
    413   }
    414 
    415   // 3. Make sure a0 is a string.
    416   {
    417     Label convert, done_convert;
    418     __ JumpIfSmi(a0, &convert);
    419     __ GetObjectType(a0, a2, a2);
    420     __ And(t0, a2, Operand(kIsNotStringMask));
    421     __ Branch(&done_convert, eq, t0, Operand(zero_reg));
    422     __ bind(&convert);
    423     {
    424       FrameScope scope(masm, StackFrame::INTERNAL);
    425       ToStringStub stub(masm->isolate());
    426       __ Push(a1, a3);
    427       __ CallStub(&stub);
    428       __ Move(a0, v0);
    429       __ Pop(a1, a3);
    430     }
    431     __ bind(&done_convert);
    432   }
    433 
    434   // 4. Check if new target and constructor differ.
    435   Label new_object;
    436   __ Branch(&new_object, ne, a1, Operand(a3));
    437 
    438   // 5. Allocate a JSValue wrapper for the string.
    439   __ AllocateJSValue(v0, a1, a0, a2, t0, &new_object);
    440   __ Ret();
    441 
    442   // 6. Fallback to the runtime to create new object.
    443   __ bind(&new_object);
    444   {
    445     FrameScope scope(masm, StackFrame::INTERNAL);
    446     __ Push(a0);
    447     FastNewObjectStub stub(masm->isolate());
    448     __ CallStub(&stub);
    449     __ Pop(a0);
    450   }
    451   __ Ret(USE_DELAY_SLOT);
    452   __ sd(a0, FieldMemOperand(v0, JSValue::kValueOffset));  // In delay slot.
    453 }
    454 
    455 static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
    456   __ ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
    457   __ ld(a2, FieldMemOperand(a2, SharedFunctionInfo::kCodeOffset));
    458   __ Daddu(at, a2, Operand(Code::kHeaderSize - kHeapObjectTag));
    459   __ Jump(at);
    460 }
    461 
    462 static void GenerateTailCallToReturnedCode(MacroAssembler* masm,
    463                                            Runtime::FunctionId function_id) {
    464   // ----------- S t a t e -------------
    465   //  -- a0 : argument count (preserved for callee)
    466   //  -- a1 : target function (preserved for callee)
    467   //  -- a3 : new target (preserved for callee)
    468   // -----------------------------------
    469   {
    470     FrameScope scope(masm, StackFrame::INTERNAL);
    471     // Push a copy of the function onto the stack.
    472     // Push a copy of the target function and the new target.
    473     __ SmiTag(a0);
    474     __ Push(a0, a1, a3, a1);
    475 
    476     __ CallRuntime(function_id, 1);
    477     // Restore target function and new target.
    478     __ Pop(a0, a1, a3);
    479     __ SmiUntag(a0);
    480   }
    481 
    482   __ Daddu(at, v0, Operand(Code::kHeaderSize - kHeapObjectTag));
    483   __ Jump(at);
    484 }
    485 
    486 
    487 void Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) {
    488   // Checking whether the queued function is ready for install is optional,
    489   // since we come across interrupts and stack checks elsewhere.  However,
    490   // not checking may delay installing ready functions, and always checking
    491   // would be quite expensive.  A good compromise is to first check against
    492   // stack limit as a cue for an interrupt signal.
    493   Label ok;
    494   __ LoadRoot(a4, Heap::kStackLimitRootIndex);
    495   __ Branch(&ok, hs, sp, Operand(a4));
    496 
    497   GenerateTailCallToReturnedCode(masm, Runtime::kTryInstallOptimizedCode);
    498 
    499   __ bind(&ok);
    500   GenerateTailCallToSharedCode(masm);
    501 }
    502 
    503 
    504 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
    505                                            bool is_api_function,
    506                                            bool create_implicit_receiver,
    507                                            bool check_derived_construct) {
    508   // ----------- S t a t e -------------
    509   //  -- a0     : number of arguments
    510   //  -- a1     : constructor function
    511   //  -- a2     : allocation site or undefined
    512   //  -- a3     : new target
    513   //  -- cp     : context
    514   //  -- ra     : return address
    515   //  -- sp[...]: constructor arguments
    516   // -----------------------------------
    517 
    518   Isolate* isolate = masm->isolate();
    519 
    520   // Enter a construct frame.
    521   {
    522     FrameScope scope(masm, StackFrame::CONSTRUCT);
    523 
    524     // Preserve the incoming parameters on the stack.
    525     __ AssertUndefinedOrAllocationSite(a2, t0);
    526     __ SmiTag(a0);
    527     __ Push(cp, a2, a0);
    528 
    529     if (create_implicit_receiver) {
    530       __ Push(a1, a3);
    531       FastNewObjectStub stub(masm->isolate());
    532       __ CallStub(&stub);
    533       __ mov(t0, v0);
    534       __ Pop(a1, a3);
    535 
    536       // ----------- S t a t e -------------
    537       // -- a1: constructor function
    538       // -- a3: new target
    539       // -- t0: newly allocated object
    540       // -----------------------------------
    541       __ ld(a0, MemOperand(sp));
    542     }
    543     __ SmiUntag(a0);
    544 
    545     if (create_implicit_receiver) {
    546       // Push the allocated receiver to the stack. We need two copies
    547       // because we may have to return the original one and the calling
    548       // conventions dictate that the called function pops the receiver.
    549       __ Push(t0, t0);
    550     } else {
    551       __ PushRoot(Heap::kTheHoleValueRootIndex);
    552     }
    553 
    554     // Set up pointer to last argument.
    555     __ Daddu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
    556 
    557     // Copy arguments and receiver to the expression stack.
    558     // a0: number of arguments
    559     // a1: constructor function
    560     // a2: address of last argument (caller sp)
    561     // a3: new target
    562     // t0: number of arguments (smi-tagged)
    563     // sp[0]: receiver
    564     // sp[1]: receiver
    565     // sp[2]: number of arguments (smi-tagged)
    566     Label loop, entry;
    567     __ mov(t0, a0);
    568     __ jmp(&entry);
    569     __ bind(&loop);
    570     __ Dlsa(a4, a2, t0, kPointerSizeLog2);
    571     __ ld(a5, MemOperand(a4));
    572     __ push(a5);
    573     __ bind(&entry);
    574     __ Daddu(t0, t0, Operand(-1));
    575     __ Branch(&loop, greater_equal, t0, Operand(zero_reg));
    576 
    577     // Call the function.
    578     // a0: number of arguments
    579     // a1: constructor function
    580     // a3: new target
    581     ParameterCount actual(a0);
    582     __ InvokeFunction(a1, a3, actual, CALL_FUNCTION,
    583                       CheckDebugStepCallWrapper());
    584 
    585     // Store offset of return address for deoptimizer.
    586     if (create_implicit_receiver && !is_api_function) {
    587       masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
    588     }
    589 
    590     // Restore context from the frame.
    591     __ ld(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
    592 
    593     if (create_implicit_receiver) {
    594       // If the result is an object (in the ECMA sense), we should get rid
    595       // of the receiver and use the result; see ECMA-262 section 13.2.2-7
    596       // on page 74.
    597       Label use_receiver, exit;
    598 
    599       // If the result is a smi, it is *not* an object in the ECMA sense.
    600       // v0: result
    601       // sp[0]: receiver (newly allocated object)
    602       // sp[1]: number of arguments (smi-tagged)
    603       __ JumpIfSmi(v0, &use_receiver);
    604 
    605       // If the type of the result (stored in its map) is less than
    606       // FIRST_JS_RECEIVER_TYPE, it is not an object in the ECMA sense.
    607       __ GetObjectType(v0, a1, a3);
    608       __ Branch(&exit, greater_equal, a3, Operand(FIRST_JS_RECEIVER_TYPE));
    609 
    610       // Throw away the result of the constructor invocation and use the
    611       // on-stack receiver as the result.
    612       __ bind(&use_receiver);
    613       __ ld(v0, MemOperand(sp));
    614 
    615       // Remove receiver from the stack, remove caller arguments, and
    616       // return.
    617       __ bind(&exit);
    618       // v0: result
    619       // sp[0]: receiver (newly allocated object)
    620       // sp[1]: number of arguments (smi-tagged)
    621       __ ld(a1, MemOperand(sp, 1 * kPointerSize));
    622     } else {
    623       __ ld(a1, MemOperand(sp));
    624     }
    625 
    626     // Leave construct frame.
    627   }
    628 
    629   // ES6 9.2.2. Step 13+
    630   // Check that the result is not a Smi, indicating that the constructor result
    631   // from a derived class is neither undefined nor an Object.
    632   if (check_derived_construct) {
    633     Label dont_throw;
    634     __ JumpIfNotSmi(v0, &dont_throw);
    635     {
    636       FrameScope scope(masm, StackFrame::INTERNAL);
    637       __ CallRuntime(Runtime::kThrowDerivedConstructorReturnedNonObject);
    638     }
    639     __ bind(&dont_throw);
    640   }
    641 
    642   __ SmiScale(a4, a1, kPointerSizeLog2);
    643   __ Daddu(sp, sp, a4);
    644   __ Daddu(sp, sp, kPointerSize);
    645   if (create_implicit_receiver) {
    646     __ IncrementCounter(isolate->counters()->constructed_objects(), 1, a1, a2);
    647   }
    648   __ Ret();
    649 }
    650 
    651 
    652 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
    653   Generate_JSConstructStubHelper(masm, false, true, false);
    654 }
    655 
    656 
    657 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
    658   Generate_JSConstructStubHelper(masm, true, false, false);
    659 }
    660 
    661 
    662 void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
    663   Generate_JSConstructStubHelper(masm, false, false, false);
    664 }
    665 
    666 
    667 void Builtins::Generate_JSBuiltinsConstructStubForDerived(
    668     MacroAssembler* masm) {
    669   Generate_JSConstructStubHelper(masm, false, false, true);
    670 }
    671 
    672 // static
    673 void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
    674   // ----------- S t a t e -------------
    675   //  -- v0 : the value to pass to the generator
    676   //  -- a1 : the JSGeneratorObject to resume
    677   //  -- a2 : the resume mode (tagged)
    678   //  -- ra : return address
    679   // -----------------------------------
    680   __ AssertGeneratorObject(a1);
    681 
    682   // Store input value into generator object.
    683   __ sd(v0, FieldMemOperand(a1, JSGeneratorObject::kInputOrDebugPosOffset));
    684   __ RecordWriteField(a1, JSGeneratorObject::kInputOrDebugPosOffset, v0, a3,
    685                       kRAHasNotBeenSaved, kDontSaveFPRegs);
    686 
    687   // Store resume mode into generator object.
    688   __ sd(a2, FieldMemOperand(a1, JSGeneratorObject::kResumeModeOffset));
    689 
    690   // Load suspended function and context.
    691   __ ld(cp, FieldMemOperand(a1, JSGeneratorObject::kContextOffset));
    692   __ ld(a4, FieldMemOperand(a1, JSGeneratorObject::kFunctionOffset));
    693 
    694   // Flood function if we are stepping.
    695   Label prepare_step_in_if_stepping, prepare_step_in_suspended_generator;
    696   Label stepping_prepared;
    697   ExternalReference last_step_action =
    698       ExternalReference::debug_last_step_action_address(masm->isolate());
    699   STATIC_ASSERT(StepFrame > StepIn);
    700   __ li(a5, Operand(last_step_action));
    701   __ lb(a5, MemOperand(a5));
    702   __ Branch(&prepare_step_in_if_stepping, ge, a5, Operand(StepIn));
    703 
    704   // Flood function if we need to continue stepping in the suspended generator.
    705   ExternalReference debug_suspended_generator =
    706       ExternalReference::debug_suspended_generator_address(masm->isolate());
    707   __ li(a5, Operand(debug_suspended_generator));
    708   __ ld(a5, MemOperand(a5));
    709   __ Branch(&prepare_step_in_suspended_generator, eq, a1, Operand(a5));
    710   __ bind(&stepping_prepared);
    711 
    712   // Push receiver.
    713   __ ld(a5, FieldMemOperand(a1, JSGeneratorObject::kReceiverOffset));
    714   __ Push(a5);
    715 
    716   // ----------- S t a t e -------------
    717   //  -- a1    : the JSGeneratorObject to resume
    718   //  -- a2    : the resume mode (tagged)
    719   //  -- a4    : generator function
    720   //  -- cp    : generator context
    721   //  -- ra    : return address
    722   //  -- sp[0] : generator receiver
    723   // -----------------------------------
    724 
    725   // Push holes for arguments to generator function. Since the parser forced
    726   // context allocation for any variables in generators, the actual argument
    727   // values have already been copied into the context and these dummy values
    728   // will never be used.
    729   __ ld(a3, FieldMemOperand(a4, JSFunction::kSharedFunctionInfoOffset));
    730   __ lw(a3,
    731         FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset));
    732   {
    733     Label done_loop, loop;
    734     __ bind(&loop);
    735     __ Dsubu(a3, a3, Operand(1));
    736     __ Branch(&done_loop, lt, a3, Operand(zero_reg));
    737     __ PushRoot(Heap::kTheHoleValueRootIndex);
    738     __ Branch(&loop);
    739     __ bind(&done_loop);
    740   }
    741 
    742   // Dispatch on the kind of generator object.
    743   Label old_generator;
    744   __ ld(a3, FieldMemOperand(a4, JSFunction::kSharedFunctionInfoOffset));
    745   __ ld(a3, FieldMemOperand(a3, SharedFunctionInfo::kFunctionDataOffset));
    746   __ GetObjectType(a3, a3, a3);
    747   __ Branch(&old_generator, ne, a3, Operand(BYTECODE_ARRAY_TYPE));
    748 
    749   // New-style (ignition/turbofan) generator object.
    750   {
    751     __ ld(a0, FieldMemOperand(a4, JSFunction::kSharedFunctionInfoOffset));
    752     __ lw(a0,
    753          FieldMemOperand(a0, SharedFunctionInfo::kFormalParameterCountOffset));
    754     // We abuse new.target both to indicate that this is a resume call and to
    755     // pass in the generator object.  In ordinary calls, new.target is always
    756     // undefined because generator functions are non-constructable.
    757     __ Move(a3, a1);
    758     __ Move(a1, a4);
    759     __ ld(a2, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
    760     __ Jump(a2);
    761   }
    762 
    763   // Old-style (full-codegen) generator object
    764   __ bind(&old_generator);
    765   {
    766     // Enter a new JavaScript frame, and initialize its slots as they were when
    767     // the generator was suspended.
    768     FrameScope scope(masm, StackFrame::MANUAL);
    769     __ Push(ra, fp);
    770     __ Move(fp, sp);
    771     __ Push(cp, a4);
    772 
    773     // Restore the operand stack.
    774     __ ld(a0, FieldMemOperand(a1, JSGeneratorObject::kOperandStackOffset));
    775     __ ld(a3, FieldMemOperand(a0, FixedArray::kLengthOffset));
    776     __ SmiUntag(a3);
    777     __ Daddu(a0, a0, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
    778     __ Dlsa(a3, a0, a3, kPointerSizeLog2);
    779     {
    780       Label done_loop, loop;
    781       __ bind(&loop);
    782       __ Branch(&done_loop, eq, a0, Operand(a3));
    783       __ ld(a5, MemOperand(a0));
    784       __ Push(a5);
    785       __ Branch(USE_DELAY_SLOT, &loop);
    786       __ daddiu(a0, a0, kPointerSize);  // In delay slot.
    787       __ bind(&done_loop);
    788     }
    789 
    790     // Reset operand stack so we don't leak.
    791     __ LoadRoot(a5, Heap::kEmptyFixedArrayRootIndex);
    792     __ sd(a5, FieldMemOperand(a1, JSGeneratorObject::kOperandStackOffset));
    793 
    794     // Resume the generator function at the continuation.
    795     __ ld(a3, FieldMemOperand(a4, JSFunction::kSharedFunctionInfoOffset));
    796     __ ld(a3, FieldMemOperand(a3, SharedFunctionInfo::kCodeOffset));
    797     __ Daddu(a3, a3, Operand(Code::kHeaderSize - kHeapObjectTag));
    798     __ ld(a2, FieldMemOperand(a1, JSGeneratorObject::kContinuationOffset));
    799     __ SmiUntag(a2);
    800     __ Daddu(a3, a3, Operand(a2));
    801     __ li(a2, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)));
    802     __ sd(a2, FieldMemOperand(a1, JSGeneratorObject::kContinuationOffset));
    803     __ Move(v0, a1);  // Continuation expects generator object in v0.
    804     __ Jump(a3);
    805   }
    806 
    807   __ bind(&prepare_step_in_if_stepping);
    808   {
    809     FrameScope scope(masm, StackFrame::INTERNAL);
    810     __ Push(a1, a2, a4);
    811     __ CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
    812     __ Pop(a1, a2);
    813   }
    814   __ Branch(USE_DELAY_SLOT, &stepping_prepared);
    815   __ ld(a4, FieldMemOperand(a1, JSGeneratorObject::kFunctionOffset));
    816 
    817   __ bind(&prepare_step_in_suspended_generator);
    818   {
    819     FrameScope scope(masm, StackFrame::INTERNAL);
    820     __ Push(a1, a2);
    821     __ CallRuntime(Runtime::kDebugPrepareStepInSuspendedGenerator);
    822     __ Pop(a1, a2);
    823   }
    824   __ Branch(USE_DELAY_SLOT, &stepping_prepared);
    825   __ ld(a4, FieldMemOperand(a1, JSGeneratorObject::kFunctionOffset));
    826 }
    827 
    828 void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
    829   FrameScope scope(masm, StackFrame::INTERNAL);
    830   __ Push(a1);
    831   __ CallRuntime(Runtime::kThrowConstructedNonConstructable);
    832 }
    833 
    834 
    835 enum IsTagged { kArgcIsSmiTagged, kArgcIsUntaggedInt };
    836 
    837 
    838 // Clobbers a2; preserves all other registers.
    839 static void Generate_CheckStackOverflow(MacroAssembler* masm, Register argc,
    840                                         IsTagged argc_is_tagged) {
    841   // Check the stack for overflow. We are not trying to catch
    842   // interruptions (e.g. debug break and preemption) here, so the "real stack
    843   // limit" is checked.
    844   Label okay;
    845   __ LoadRoot(a2, Heap::kRealStackLimitRootIndex);
    846   // Make a2 the space we have left. The stack might already be overflowed
    847   // here which will cause r2 to become negative.
    848   __ dsubu(a2, sp, a2);
    849   // Check if the arguments will overflow the stack.
    850   if (argc_is_tagged == kArgcIsSmiTagged) {
    851     __ SmiScale(a7, v0, kPointerSizeLog2);
    852   } else {
    853     DCHECK(argc_is_tagged == kArgcIsUntaggedInt);
    854     __ dsll(a7, argc, kPointerSizeLog2);
    855   }
    856   __ Branch(&okay, gt, a2, Operand(a7));  // Signed comparison.
    857 
    858   // Out of stack space.
    859   __ CallRuntime(Runtime::kThrowStackOverflow);
    860 
    861   __ bind(&okay);
    862 }
    863 
    864 
    865 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
    866                                              bool is_construct) {
    867   // Called from JSEntryStub::GenerateBody
    868 
    869   // ----------- S t a t e -------------
    870   //  -- a0: new.target
    871   //  -- a1: function
    872   //  -- a2: receiver_pointer
    873   //  -- a3: argc
    874   //  -- s0: argv
    875   // -----------------------------------
    876   ProfileEntryHookStub::MaybeCallEntryHook(masm);
    877 
    878   // Enter an internal frame.
    879   {
    880     FrameScope scope(masm, StackFrame::INTERNAL);
    881 
    882     // Setup the context (we need to use the caller context from the isolate).
    883     ExternalReference context_address(Isolate::kContextAddress,
    884                                       masm->isolate());
    885     __ li(cp, Operand(context_address));
    886     __ ld(cp, MemOperand(cp));
    887 
    888     // Push the function and the receiver onto the stack.
    889     __ Push(a1, a2);
    890 
    891     // Check if we have enough stack space to push all arguments.
    892     // Clobbers a2.
    893     Generate_CheckStackOverflow(masm, a3, kArgcIsUntaggedInt);
    894 
    895     // Remember new.target.
    896     __ mov(a5, a0);
    897 
    898     // Copy arguments to the stack in a loop.
    899     // a3: argc
    900     // s0: argv, i.e. points to first arg
    901     Label loop, entry;
    902     __ Dlsa(a6, s0, a3, kPointerSizeLog2);
    903     __ b(&entry);
    904     __ nop();   // Branch delay slot nop.
    905     // a6 points past last arg.
    906     __ bind(&loop);
    907     __ ld(a4, MemOperand(s0));  // Read next parameter.
    908     __ daddiu(s0, s0, kPointerSize);
    909     __ ld(a4, MemOperand(a4));  // Dereference handle.
    910     __ push(a4);  // Push parameter.
    911     __ bind(&entry);
    912     __ Branch(&loop, ne, s0, Operand(a6));
    913 
    914     // Setup new.target and argc.
    915     __ mov(a0, a3);
    916     __ mov(a3, a5);
    917 
    918     // Initialize all JavaScript callee-saved registers, since they will be seen
    919     // by the garbage collector as part of handlers.
    920     __ LoadRoot(a4, Heap::kUndefinedValueRootIndex);
    921     __ mov(s1, a4);
    922     __ mov(s2, a4);
    923     __ mov(s3, a4);
    924     __ mov(s4, a4);
    925     __ mov(s5, a4);
    926     // s6 holds the root address. Do not clobber.
    927     // s7 is cp. Do not init.
    928 
    929     // Invoke the code.
    930     Handle<Code> builtin = is_construct
    931                                ? masm->isolate()->builtins()->Construct()
    932                                : masm->isolate()->builtins()->Call();
    933     __ Call(builtin, RelocInfo::CODE_TARGET);
    934 
    935     // Leave internal frame.
    936   }
    937   __ Jump(ra);
    938 }
    939 
    940 
    941 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
    942   Generate_JSEntryTrampolineHelper(masm, false);
    943 }
    944 
    945 
    946 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
    947   Generate_JSEntryTrampolineHelper(masm, true);
    948 }
    949 
    950 static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch) {
    951   Register args_count = scratch;
    952 
    953   // Get the arguments + receiver count.
    954   __ ld(args_count,
    955         MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
    956   __ lw(t0, FieldMemOperand(args_count, BytecodeArray::kParameterSizeOffset));
    957 
    958   // Leave the frame (also dropping the register file).
    959   __ LeaveFrame(StackFrame::JAVA_SCRIPT);
    960 
    961   // Drop receiver + arguments.
    962   __ Daddu(sp, sp, args_count);
    963 }
    964 
    965 // Generate code for entering a JS function with the interpreter.
    966 // On entry to the function the receiver and arguments have been pushed on the
    967 // stack left to right.  The actual argument count matches the formal parameter
    968 // count expected by the function.
    969 //
    970 // The live registers are:
    971 //   o a1: the JS function object being called.
    972 //   o a3: the new target
    973 //   o cp: our context
    974 //   o fp: the caller's frame pointer
    975 //   o sp: stack pointer
    976 //   o ra: return address
    977 //
    978 // The function builds an interpreter frame.  See InterpreterFrameConstants in
    979 // frames.h for its layout.
    980 void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
    981   ProfileEntryHookStub::MaybeCallEntryHook(masm);
    982 
    983   // Open a frame scope to indicate that there is a frame on the stack.  The
    984   // MANUAL indicates that the scope shouldn't actually generate code to set up
    985   // the frame (that is done below).
    986   FrameScope frame_scope(masm, StackFrame::MANUAL);
    987   __ PushStandardFrame(a1);
    988 
    989   // Get the bytecode array from the function object (or from the DebugInfo if
    990   // it is present) and load it into kInterpreterBytecodeArrayRegister.
    991   __ ld(a0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
    992   Label load_debug_bytecode_array, bytecode_array_loaded;
    993   Register debug_info = kInterpreterBytecodeArrayRegister;
    994   DCHECK(!debug_info.is(a0));
    995   __ ld(debug_info, FieldMemOperand(a0, SharedFunctionInfo::kDebugInfoOffset));
    996   __ Branch(&load_debug_bytecode_array, ne, debug_info,
    997             Operand(DebugInfo::uninitialized()));
    998   __ ld(kInterpreterBytecodeArrayRegister,
    999         FieldMemOperand(a0, SharedFunctionInfo::kFunctionDataOffset));
   1000   __ bind(&bytecode_array_loaded);
   1001 
   1002   // Check function data field is actually a BytecodeArray object.
   1003   Label bytecode_array_not_present;
   1004   __ JumpIfRoot(kInterpreterBytecodeArrayRegister,
   1005                 Heap::kUndefinedValueRootIndex, &bytecode_array_not_present);
   1006   if (FLAG_debug_code) {
   1007     __ SmiTst(kInterpreterBytecodeArrayRegister, a4);
   1008     __ Assert(ne, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry, a4,
   1009               Operand(zero_reg));
   1010     __ GetObjectType(kInterpreterBytecodeArrayRegister, a4, a4);
   1011     __ Assert(eq, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry, a4,
   1012               Operand(BYTECODE_ARRAY_TYPE));
   1013   }
   1014 
   1015   // Load initial bytecode offset.
   1016   __ li(kInterpreterBytecodeOffsetRegister,
   1017         Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
   1018 
   1019   // Push new.target, bytecode array and Smi tagged bytecode array offset.
   1020   __ SmiTag(a4, kInterpreterBytecodeOffsetRegister);
   1021   __ Push(a3, kInterpreterBytecodeArrayRegister, a4);
   1022 
   1023   // Allocate the local and temporary register file on the stack.
   1024   {
   1025     // Load frame size (word) from the BytecodeArray object.
   1026     __ lw(a4, FieldMemOperand(kInterpreterBytecodeArrayRegister,
   1027                               BytecodeArray::kFrameSizeOffset));
   1028 
   1029     // Do a stack check to ensure we don't go over the limit.
   1030     Label ok;
   1031     __ Dsubu(a5, sp, Operand(a4));
   1032     __ LoadRoot(a2, Heap::kRealStackLimitRootIndex);
   1033     __ Branch(&ok, hs, a5, Operand(a2));
   1034     __ CallRuntime(Runtime::kThrowStackOverflow);
   1035     __ bind(&ok);
   1036 
   1037     // If ok, push undefined as the initial value for all register file entries.
   1038     Label loop_header;
   1039     Label loop_check;
   1040     __ LoadRoot(a5, Heap::kUndefinedValueRootIndex);
   1041     __ Branch(&loop_check);
   1042     __ bind(&loop_header);
   1043     // TODO(rmcilroy): Consider doing more than one push per loop iteration.
   1044     __ push(a5);
   1045     // Continue loop if not done.
   1046     __ bind(&loop_check);
   1047     __ Dsubu(a4, a4, Operand(kPointerSize));
   1048     __ Branch(&loop_header, ge, a4, Operand(zero_reg));
   1049   }
   1050 
   1051   // Load accumulator and dispatch table into registers.
   1052   __ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
   1053   __ li(kInterpreterDispatchTableRegister,
   1054         Operand(ExternalReference::interpreter_dispatch_table_address(
   1055             masm->isolate())));
   1056 
   1057   // Dispatch to the first bytecode handler for the function.
   1058   __ Daddu(a0, kInterpreterBytecodeArrayRegister,
   1059            kInterpreterBytecodeOffsetRegister);
   1060   __ lbu(a0, MemOperand(a0));
   1061   __ Dlsa(at, kInterpreterDispatchTableRegister, a0, kPointerSizeLog2);
   1062   __ ld(at, MemOperand(at));
   1063   __ Call(at);
   1064   masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
   1065 
   1066   // The return value is in v0.
   1067   LeaveInterpreterFrame(masm, t0);
   1068   __ Jump(ra);
   1069 
   1070   // Load debug copy of the bytecode array.
   1071   __ bind(&load_debug_bytecode_array);
   1072   __ ld(kInterpreterBytecodeArrayRegister,
   1073         FieldMemOperand(debug_info, DebugInfo::kAbstractCodeIndex));
   1074   __ Branch(&bytecode_array_loaded);
   1075 
   1076   // If the bytecode array is no longer present, then the underlying function
   1077   // has been switched to a different kind of code and we heal the closure by
   1078   // switching the code entry field over to the new code object as well.
   1079   __ bind(&bytecode_array_not_present);
   1080   __ LeaveFrame(StackFrame::JAVA_SCRIPT);
   1081   __ ld(a4, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
   1082   __ ld(a4, FieldMemOperand(a4, SharedFunctionInfo::kCodeOffset));
   1083   __ Daddu(a4, a4, Operand(Code::kHeaderSize - kHeapObjectTag));
   1084   __ sd(a4, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
   1085   __ RecordWriteCodeEntryField(a1, a4, a5);
   1086   __ Jump(a4);
   1087 }
   1088 
   1089 void Builtins::Generate_InterpreterMarkBaselineOnReturn(MacroAssembler* masm) {
   1090   // Save the function and context for call to CompileBaseline.
   1091   __ ld(a1, MemOperand(fp, StandardFrameConstants::kFunctionOffset));
   1092   __ ld(kContextRegister,
   1093         MemOperand(fp, StandardFrameConstants::kContextOffset));
   1094 
   1095   // Leave the frame before recompiling for baseline so that we don't count as
   1096   // an activation on the stack.
   1097   LeaveInterpreterFrame(masm, t0);
   1098 
   1099   {
   1100     FrameScope frame_scope(masm, StackFrame::INTERNAL);
   1101     // Push return value.
   1102     __ push(v0);
   1103 
   1104     // Push function as argument and compile for baseline.
   1105     __ push(a1);
   1106     __ CallRuntime(Runtime::kCompileBaseline);
   1107 
   1108     // Restore return value.
   1109     __ pop(v0);
   1110   }
   1111   __ Jump(ra);
   1112 }
   1113 
   1114 // static
   1115 void Builtins::Generate_InterpreterPushArgsAndCallImpl(
   1116     MacroAssembler* masm, TailCallMode tail_call_mode) {
   1117   // ----------- S t a t e -------------
   1118   //  -- a0 : the number of arguments (not including the receiver)
   1119   //  -- a2 : the address of the first argument to be pushed. Subsequent
   1120   //          arguments should be consecutive above this, in the same order as
   1121   //          they are to be pushed onto the stack.
   1122   //  -- a1 : the target to call (can be any Object).
   1123   // -----------------------------------
   1124 
   1125   // Find the address of the last argument.
   1126   __ Daddu(a3, a0, Operand(1));  // Add one for receiver.
   1127   __ dsll(a3, a3, kPointerSizeLog2);
   1128   __ Dsubu(a3, a2, Operand(a3));
   1129 
   1130   // Push the arguments.
   1131   Label loop_header, loop_check;
   1132   __ Branch(&loop_check);
   1133   __ bind(&loop_header);
   1134   __ ld(t0, MemOperand(a2));
   1135   __ Daddu(a2, a2, Operand(-kPointerSize));
   1136   __ push(t0);
   1137   __ bind(&loop_check);
   1138   __ Branch(&loop_header, gt, a2, Operand(a3));
   1139 
   1140   // Call the target.
   1141   __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny,
   1142                                             tail_call_mode),
   1143           RelocInfo::CODE_TARGET);
   1144 }
   1145 
   1146 // static
   1147 void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
   1148   // ----------- S t a t e -------------
   1149   // -- a0 : argument count (not including receiver)
   1150   // -- a3 : new target
   1151   // -- a1 : constructor to call
   1152   // -- a2 : address of the first argument
   1153   // -----------------------------------
   1154 
   1155   // Find the address of the last argument.
   1156   __ dsll(t0, a0, kPointerSizeLog2);
   1157   __ Dsubu(t0, a2, Operand(t0));
   1158 
   1159   // Push a slot for the receiver.
   1160   __ push(zero_reg);
   1161 
   1162   // Push the arguments.
   1163   Label loop_header, loop_check;
   1164   __ Branch(&loop_check);
   1165   __ bind(&loop_header);
   1166   __ ld(t1, MemOperand(a2));
   1167   __ Daddu(a2, a2, Operand(-kPointerSize));
   1168   __ push(t1);
   1169   __ bind(&loop_check);
   1170   __ Branch(&loop_header, gt, a2, Operand(t0));
   1171 
   1172   // Call the constructor with a0, a1, and a3 unmodified.
   1173   __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
   1174 }
   1175 
   1176 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
   1177   // Set the return address to the correct point in the interpreter entry
   1178   // trampoline.
   1179   Smi* interpreter_entry_return_pc_offset(
   1180       masm->isolate()->heap()->interpreter_entry_return_pc_offset());
   1181   DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
   1182   __ li(t0, Operand(masm->isolate()->builtins()->InterpreterEntryTrampoline()));
   1183   __ Daddu(ra, t0, Operand(interpreter_entry_return_pc_offset->value() +
   1184                            Code::kHeaderSize - kHeapObjectTag));
   1185 
   1186   // Initialize the dispatch table register.
   1187   __ li(kInterpreterDispatchTableRegister,
   1188         Operand(ExternalReference::interpreter_dispatch_table_address(
   1189             masm->isolate())));
   1190 
   1191   // Get the bytecode array pointer from the frame.
   1192   __ ld(kInterpreterBytecodeArrayRegister,
   1193         MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
   1194 
   1195   if (FLAG_debug_code) {
   1196     // Check function data field is actually a BytecodeArray object.
   1197     __ SmiTst(kInterpreterBytecodeArrayRegister, at);
   1198     __ Assert(ne, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry, at,
   1199               Operand(zero_reg));
   1200     __ GetObjectType(kInterpreterBytecodeArrayRegister, a1, a1);
   1201     __ Assert(eq, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry, a1,
   1202               Operand(BYTECODE_ARRAY_TYPE));
   1203   }
   1204 
   1205   // Get the target bytecode offset from the frame.
   1206   __ ld(kInterpreterBytecodeOffsetRegister,
   1207         MemOperand(fp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
   1208   __ SmiUntag(kInterpreterBytecodeOffsetRegister);
   1209 
   1210   // Dispatch to the target bytecode.
   1211   __ Daddu(a1, kInterpreterBytecodeArrayRegister,
   1212            kInterpreterBytecodeOffsetRegister);
   1213   __ lbu(a1, MemOperand(a1));
   1214   __ Dlsa(a1, kInterpreterDispatchTableRegister, a1, kPointerSizeLog2);
   1215   __ ld(a1, MemOperand(a1));
   1216   __ Jump(a1);
   1217 }
   1218 
   1219 void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
   1220   // ----------- S t a t e -------------
   1221   //  -- a0 : argument count (preserved for callee)
   1222   //  -- a3 : new target (preserved for callee)
   1223   //  -- a1 : target function (preserved for callee)
   1224   // -----------------------------------
   1225   // First lookup code, maybe we don't need to compile!
   1226   Label gotta_call_runtime, gotta_call_runtime_no_stack;
   1227   Label maybe_call_runtime;
   1228   Label try_shared;
   1229   Label loop_top, loop_bottom;
   1230 
   1231   Register argument_count = a0;
   1232   Register closure = a1;
   1233   Register new_target = a3;
   1234   __ push(argument_count);
   1235   __ push(new_target);
   1236   __ push(closure);
   1237 
   1238   Register map = a0;
   1239   Register index = a2;
   1240   __ ld(map, FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
   1241   __ ld(map, FieldMemOperand(map, SharedFunctionInfo::kOptimizedCodeMapOffset));
   1242   __ ld(index, FieldMemOperand(map, FixedArray::kLengthOffset));
   1243   __ Branch(&gotta_call_runtime, lt, index, Operand(Smi::FromInt(2)));
   1244 
   1245   // Find literals.
   1246   // a3  : native context
   1247   // a2  : length / index
   1248   // a0  : optimized code map
   1249   // stack[0] : new target
   1250   // stack[4] : closure
   1251   Register native_context = a3;
   1252   __ ld(native_context, NativeContextMemOperand());
   1253 
   1254   __ bind(&loop_top);
   1255   Register temp = a1;
   1256   Register array_pointer = a5;
   1257 
   1258   // Does the native context match?
   1259   __ SmiScale(at, index, kPointerSizeLog2);
   1260   __ Daddu(array_pointer, map, Operand(at));
   1261   __ ld(temp, FieldMemOperand(array_pointer,
   1262                               SharedFunctionInfo::kOffsetToPreviousContext));
   1263   __ ld(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
   1264   __ Branch(&loop_bottom, ne, temp, Operand(native_context));
   1265   // OSR id set to none?
   1266   __ ld(temp, FieldMemOperand(array_pointer,
   1267                               SharedFunctionInfo::kOffsetToPreviousOsrAstId));
   1268   const int bailout_id = BailoutId::None().ToInt();
   1269   __ Branch(&loop_bottom, ne, temp, Operand(Smi::FromInt(bailout_id)));
   1270 
   1271   // Literals available?
   1272   Label got_literals, maybe_cleared_weakcell;
   1273   __ ld(temp, FieldMemOperand(array_pointer,
   1274                               SharedFunctionInfo::kOffsetToPreviousLiterals));
   1275   // temp contains either a WeakCell pointing to the literals array or the
   1276   // literals array directly.
   1277   __ ld(a4, FieldMemOperand(temp, WeakCell::kValueOffset));
   1278   __ JumpIfSmi(a4, &maybe_cleared_weakcell);
   1279   // a4 is a pointer, therefore temp is a WeakCell pointing to a literals array.
   1280   __ ld(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
   1281   __ jmp(&got_literals);
   1282 
   1283   // a4 is a smi. If it's 0, then we are looking at a cleared WeakCell
   1284   // around the literals array, and we should visit the runtime. If it's > 0,
   1285   // then temp already contains the literals array.
   1286   __ bind(&maybe_cleared_weakcell);
   1287   __ Branch(&gotta_call_runtime, eq, a4, Operand(Smi::FromInt(0)));
   1288 
   1289   // Save the literals in the closure.
   1290   __ bind(&got_literals);
   1291   __ ld(a4, MemOperand(sp, 0));
   1292   __ sd(temp, FieldMemOperand(a4, JSFunction::kLiteralsOffset));
   1293   __ push(index);
   1294   __ RecordWriteField(a4, JSFunction::kLiteralsOffset, temp, index,
   1295                       kRAHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
   1296                       OMIT_SMI_CHECK);
   1297   __ pop(index);
   1298 
   1299   // Code available?
   1300   Register entry = a4;
   1301   __ ld(entry,
   1302         FieldMemOperand(array_pointer,
   1303                         SharedFunctionInfo::kOffsetToPreviousCachedCode));
   1304   __ ld(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
   1305   __ JumpIfSmi(entry, &maybe_call_runtime);
   1306 
   1307   // Found literals and code. Get them into the closure and return.
   1308   __ pop(closure);
   1309   // Store code entry in the closure.
   1310   __ Daddu(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
   1311 
   1312   Label install_optimized_code_and_tailcall;
   1313   __ bind(&install_optimized_code_and_tailcall);
   1314   __ sd(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset));
   1315   __ RecordWriteCodeEntryField(closure, entry, a5);
   1316 
   1317   // Link the closure into the optimized function list.
   1318   // a4 : code entry
   1319   // a3 : native context
   1320   // a1 : closure
   1321   __ ld(a5,
   1322         ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
   1323   __ sd(a5, FieldMemOperand(closure, JSFunction::kNextFunctionLinkOffset));
   1324   __ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, a5, a0,
   1325                       kRAHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
   1326                       OMIT_SMI_CHECK);
   1327   const int function_list_offset =
   1328       Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
   1329   __ sd(closure,
   1330         ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
   1331   // Save closure before the write barrier.
   1332   __ mov(a5, closure);
   1333   __ RecordWriteContextSlot(native_context, function_list_offset, closure, a0,
   1334                             kRAHasNotBeenSaved, kDontSaveFPRegs);
   1335   __ mov(closure, a5);
   1336   __ pop(new_target);
   1337   __ pop(argument_count);
   1338   __ Jump(entry);
   1339 
   1340   __ bind(&loop_bottom);
   1341   __ Dsubu(index, index,
   1342            Operand(Smi::FromInt(SharedFunctionInfo::kEntryLength)));
   1343   __ Branch(&loop_top, gt, index, Operand(Smi::FromInt(1)));
   1344 
   1345   // We found neither literals nor code.
   1346   __ jmp(&gotta_call_runtime);
   1347 
   1348   __ bind(&maybe_call_runtime);
   1349   __ pop(closure);
   1350 
   1351   // Last possibility. Check the context free optimized code map entry.
   1352   __ ld(entry, FieldMemOperand(map, FixedArray::kHeaderSize +
   1353                                         SharedFunctionInfo::kSharedCodeIndex));
   1354   __ ld(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
   1355   __ JumpIfSmi(entry, &try_shared);
   1356 
   1357   // Store code entry in the closure.
   1358   __ Daddu(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
   1359   __ jmp(&install_optimized_code_and_tailcall);
   1360 
   1361   __ bind(&try_shared);
   1362   __ pop(new_target);
   1363   __ pop(argument_count);
   1364   // Is the full code valid?
   1365   __ ld(entry, FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
   1366   __ ld(entry, FieldMemOperand(entry, SharedFunctionInfo::kCodeOffset));
   1367   __ lw(a5, FieldMemOperand(entry, Code::kFlagsOffset));
   1368   __ And(a5, a5, Operand(Code::KindField::kMask));
   1369   __ dsrl(a5, a5, Code::KindField::kShift);
   1370   __ Branch(&gotta_call_runtime_no_stack, eq, a5, Operand(Code::BUILTIN));
   1371   // Yes, install the full code.
   1372   __ Daddu(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
   1373   __ sd(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset));
   1374   __ RecordWriteCodeEntryField(closure, entry, a5);
   1375   __ Jump(entry);
   1376 
   1377   __ bind(&gotta_call_runtime);
   1378   __ pop(closure);
   1379   __ pop(new_target);
   1380   __ pop(argument_count);
   1381   __ bind(&gotta_call_runtime_no_stack);
   1382   GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy);
   1383 }
   1384 
   1385 void Builtins::Generate_CompileBaseline(MacroAssembler* masm) {
   1386   GenerateTailCallToReturnedCode(masm, Runtime::kCompileBaseline);
   1387 }
   1388 
   1389 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) {
   1390   GenerateTailCallToReturnedCode(masm,
   1391                                  Runtime::kCompileOptimized_NotConcurrent);
   1392 }
   1393 
   1394 void Builtins::Generate_CompileOptimizedConcurrent(MacroAssembler* masm) {
   1395   GenerateTailCallToReturnedCode(masm, Runtime::kCompileOptimized_Concurrent);
   1396 }
   1397 
   1398 
   1399 static void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) {
   1400   // For now, we are relying on the fact that make_code_young doesn't do any
   1401   // garbage collection which allows us to save/restore the registers without
   1402   // worrying about which of them contain pointers. We also don't build an
   1403   // internal frame to make the code faster, since we shouldn't have to do stack
   1404   // crawls in MakeCodeYoung. This seems a bit fragile.
   1405 
   1406   // Set a0 to point to the head of the PlatformCodeAge sequence.
   1407   __ Dsubu(a0, a0,
   1408       Operand(kNoCodeAgeSequenceLength - Assembler::kInstrSize));
   1409 
   1410   // The following registers must be saved and restored when calling through to
   1411   // the runtime:
   1412   //   a0 - contains return address (beginning of patch sequence)
   1413   //   a1 - isolate
   1414   //   a3 - new target
   1415   RegList saved_regs =
   1416       (a0.bit() | a1.bit() | a3.bit() | ra.bit() | fp.bit()) & ~sp.bit();
   1417   FrameScope scope(masm, StackFrame::MANUAL);
   1418   __ MultiPush(saved_regs);
   1419   __ PrepareCallCFunction(2, 0, a2);
   1420   __ li(a1, Operand(ExternalReference::isolate_address(masm->isolate())));
   1421   __ CallCFunction(
   1422       ExternalReference::get_make_code_young_function(masm->isolate()), 2);
   1423   __ MultiPop(saved_regs);
   1424   __ Jump(a0);
   1425 }
   1426 
   1427 #define DEFINE_CODE_AGE_BUILTIN_GENERATOR(C)                 \
   1428 void Builtins::Generate_Make##C##CodeYoungAgainEvenMarking(  \
   1429     MacroAssembler* masm) {                                  \
   1430   GenerateMakeCodeYoungAgainCommon(masm);                    \
   1431 }                                                            \
   1432 void Builtins::Generate_Make##C##CodeYoungAgainOddMarking(   \
   1433     MacroAssembler* masm) {                                  \
   1434   GenerateMakeCodeYoungAgainCommon(masm);                    \
   1435 }
   1436 CODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR)
   1437 #undef DEFINE_CODE_AGE_BUILTIN_GENERATOR
   1438 
   1439 
   1440 void Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) {
   1441   // For now, as in GenerateMakeCodeYoungAgainCommon, we are relying on the fact
   1442   // that make_code_young doesn't do any garbage collection which allows us to
   1443   // save/restore the registers without worrying about which of them contain
   1444   // pointers.
   1445 
   1446   // Set a0 to point to the head of the PlatformCodeAge sequence.
   1447   __ Dsubu(a0, a0,
   1448       Operand(kNoCodeAgeSequenceLength - Assembler::kInstrSize));
   1449 
   1450   // The following registers must be saved and restored when calling through to
   1451   // the runtime:
   1452   //   a0 - contains return address (beginning of patch sequence)
   1453   //   a1 - isolate
   1454   //   a3 - new target
   1455   RegList saved_regs =
   1456       (a0.bit() | a1.bit() | a3.bit() | ra.bit() | fp.bit()) & ~sp.bit();
   1457   FrameScope scope(masm, StackFrame::MANUAL);
   1458   __ MultiPush(saved_regs);
   1459   __ PrepareCallCFunction(2, 0, a2);
   1460   __ li(a1, Operand(ExternalReference::isolate_address(masm->isolate())));
   1461   __ CallCFunction(
   1462       ExternalReference::get_mark_code_as_executed_function(masm->isolate()),
   1463       2);
   1464   __ MultiPop(saved_regs);
   1465 
   1466   // Perform prologue operations usually performed by the young code stub.
   1467   __ PushStandardFrame(a1);
   1468 
   1469   // Jump to point after the code-age stub.
   1470   __ Daddu(a0, a0, Operand((kNoCodeAgeSequenceLength)));
   1471   __ Jump(a0);
   1472 }
   1473 
   1474 
   1475 void Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) {
   1476   GenerateMakeCodeYoungAgainCommon(masm);
   1477 }
   1478 
   1479 
   1480 void Builtins::Generate_MarkCodeAsToBeExecutedOnce(MacroAssembler* masm) {
   1481   Generate_MarkCodeAsExecutedOnce(masm);
   1482 }
   1483 
   1484 
   1485 static void Generate_NotifyStubFailureHelper(MacroAssembler* masm,
   1486                                              SaveFPRegsMode save_doubles) {
   1487   {
   1488     FrameScope scope(masm, StackFrame::INTERNAL);
   1489 
   1490     // Preserve registers across notification, this is important for compiled
   1491     // stubs that tail call the runtime on deopts passing their parameters in
   1492     // registers.
   1493     __ MultiPush(kJSCallerSaved | kCalleeSaved);
   1494     // Pass the function and deoptimization type to the runtime system.
   1495     __ CallRuntime(Runtime::kNotifyStubFailure, save_doubles);
   1496     __ MultiPop(kJSCallerSaved | kCalleeSaved);
   1497   }
   1498 
   1499   __ Daddu(sp, sp, Operand(kPointerSize));  // Ignore state
   1500   __ Jump(ra);  // Jump to miss handler
   1501 }
   1502 
   1503 
   1504 void Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) {
   1505   Generate_NotifyStubFailureHelper(masm, kDontSaveFPRegs);
   1506 }
   1507 
   1508 
   1509 void Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) {
   1510   Generate_NotifyStubFailureHelper(masm, kSaveFPRegs);
   1511 }
   1512 
   1513 
   1514 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
   1515                                              Deoptimizer::BailoutType type) {
   1516   {
   1517     FrameScope scope(masm, StackFrame::INTERNAL);
   1518     // Pass the function and deoptimization type to the runtime system.
   1519     __ li(a0, Operand(Smi::FromInt(static_cast<int>(type))));
   1520     __ push(a0);
   1521     __ CallRuntime(Runtime::kNotifyDeoptimized);
   1522   }
   1523 
   1524   // Get the full codegen state from the stack and untag it -> a6.
   1525   __ ld(a6, MemOperand(sp, 0 * kPointerSize));
   1526   __ SmiUntag(a6);
   1527   // Switch on the state.
   1528   Label with_tos_register, unknown_state;
   1529   __ Branch(
   1530       &with_tos_register, ne, a6,
   1531       Operand(static_cast<int64_t>(Deoptimizer::BailoutState::NO_REGISTERS)));
   1532   __ Ret(USE_DELAY_SLOT);
   1533   // Safe to fill delay slot Addu will emit one instruction.
   1534   __ Daddu(sp, sp, Operand(1 * kPointerSize));  // Remove state.
   1535 
   1536   __ bind(&with_tos_register);
   1537   DCHECK_EQ(kInterpreterAccumulatorRegister.code(), v0.code());
   1538   __ ld(v0, MemOperand(sp, 1 * kPointerSize));
   1539   __ Branch(
   1540       &unknown_state, ne, a6,
   1541       Operand(static_cast<int64_t>(Deoptimizer::BailoutState::TOS_REGISTER)));
   1542 
   1543   __ Ret(USE_DELAY_SLOT);
   1544   // Safe to fill delay slot Addu will emit one instruction.
   1545   __ Daddu(sp, sp, Operand(2 * kPointerSize));  // Remove state.
   1546 
   1547   __ bind(&unknown_state);
   1548   __ stop("no cases left");
   1549 }
   1550 
   1551 
   1552 void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
   1553   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
   1554 }
   1555 
   1556 
   1557 void Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) {
   1558   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
   1559 }
   1560 
   1561 
   1562 void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
   1563   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
   1564 }
   1565 
   1566 
   1567 // Clobbers {t2, t3, a4, a5}.
   1568 static void CompatibleReceiverCheck(MacroAssembler* masm, Register receiver,
   1569                                     Register function_template_info,
   1570                                     Label* receiver_check_failed) {
   1571   Register signature = t2;
   1572   Register map = t3;
   1573   Register constructor = a4;
   1574   Register scratch = a5;
   1575 
   1576   // If there is no signature, return the holder.
   1577   __ ld(signature, FieldMemOperand(function_template_info,
   1578                                    FunctionTemplateInfo::kSignatureOffset));
   1579   Label receiver_check_passed;
   1580   __ JumpIfRoot(signature, Heap::kUndefinedValueRootIndex,
   1581                 &receiver_check_passed);
   1582 
   1583   // Walk the prototype chain.
   1584   __ ld(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
   1585   Label prototype_loop_start;
   1586   __ bind(&prototype_loop_start);
   1587 
   1588   // Get the constructor, if any.
   1589   __ GetMapConstructor(constructor, map, scratch, scratch);
   1590   Label next_prototype;
   1591   __ Branch(&next_prototype, ne, scratch, Operand(JS_FUNCTION_TYPE));
   1592   Register type = constructor;
   1593   __ ld(type,
   1594         FieldMemOperand(constructor, JSFunction::kSharedFunctionInfoOffset));
   1595   __ ld(type, FieldMemOperand(type, SharedFunctionInfo::kFunctionDataOffset));
   1596 
   1597   // Loop through the chain of inheriting function templates.
   1598   Label function_template_loop;
   1599   __ bind(&function_template_loop);
   1600 
   1601   // If the signatures match, we have a compatible receiver.
   1602   __ Branch(&receiver_check_passed, eq, signature, Operand(type),
   1603             USE_DELAY_SLOT);
   1604 
   1605   // If the current type is not a FunctionTemplateInfo, load the next prototype
   1606   // in the chain.
   1607   __ JumpIfSmi(type, &next_prototype);
   1608   __ GetObjectType(type, scratch, scratch);
   1609   __ Branch(&next_prototype, ne, scratch, Operand(FUNCTION_TEMPLATE_INFO_TYPE));
   1610 
   1611   // Otherwise load the parent function template and iterate.
   1612   __ ld(type,
   1613         FieldMemOperand(type, FunctionTemplateInfo::kParentTemplateOffset));
   1614   __ Branch(&function_template_loop);
   1615 
   1616   // Load the next prototype.
   1617   __ bind(&next_prototype);
   1618   __ lwu(scratch, FieldMemOperand(map, Map::kBitField3Offset));
   1619   __ DecodeField<Map::HasHiddenPrototype>(scratch);
   1620   __ Branch(receiver_check_failed, eq, scratch, Operand(zero_reg));
   1621 
   1622   __ ld(receiver, FieldMemOperand(map, Map::kPrototypeOffset));
   1623   __ ld(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
   1624   // Iterate.
   1625   __ Branch(&prototype_loop_start);
   1626 
   1627   __ bind(&receiver_check_passed);
   1628 }
   1629 
   1630 
   1631 void Builtins::Generate_HandleFastApiCall(MacroAssembler* masm) {
   1632   // ----------- S t a t e -------------
   1633   //  -- a0                 : number of arguments excluding receiver
   1634   //  -- a1                 : callee
   1635   //  -- ra                 : return address
   1636   //  -- sp[0]              : last argument
   1637   //  -- ...
   1638   //  -- sp[8 * (argc - 1)] : first argument
   1639   //  -- sp[8 * argc]       : receiver
   1640   // -----------------------------------
   1641 
   1642   // Load the FunctionTemplateInfo.
   1643   __ ld(t1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
   1644   __ ld(t1, FieldMemOperand(t1, SharedFunctionInfo::kFunctionDataOffset));
   1645 
   1646   // Do the compatible receiver check
   1647   Label receiver_check_failed;
   1648   __ Dlsa(t8, sp, a0, kPointerSizeLog2);
   1649   __ ld(t0, MemOperand(t8));
   1650   CompatibleReceiverCheck(masm, t0, t1, &receiver_check_failed);
   1651 
   1652   // Get the callback offset from the FunctionTemplateInfo, and jump to the
   1653   // beginning of the code.
   1654   __ ld(t2, FieldMemOperand(t1, FunctionTemplateInfo::kCallCodeOffset));
   1655   __ ld(t2, FieldMemOperand(t2, CallHandlerInfo::kFastHandlerOffset));
   1656   __ Daddu(t2, t2, Operand(Code::kHeaderSize - kHeapObjectTag));
   1657   __ Jump(t2);
   1658 
   1659   // Compatible receiver check failed: throw an Illegal Invocation exception.
   1660   __ bind(&receiver_check_failed);
   1661   // Drop the arguments (including the receiver);
   1662   __ Daddu(t8, t8, Operand(kPointerSize));
   1663   __ daddu(sp, t8, zero_reg);
   1664   __ TailCallRuntime(Runtime::kThrowIllegalInvocation);
   1665 }
   1666 
   1667 
   1668 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
   1669   // Lookup the function in the JavaScript frame.
   1670   __ ld(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
   1671   {
   1672     FrameScope scope(masm, StackFrame::INTERNAL);
   1673     // Pass function as argument.
   1674     __ push(a0);
   1675     __ CallRuntime(Runtime::kCompileForOnStackReplacement);
   1676   }
   1677 
   1678   // If the code object is null, just return to the unoptimized code.
   1679   __ Ret(eq, v0, Operand(Smi::FromInt(0)));
   1680 
   1681   // Load deoptimization data from the code object.
   1682   // <deopt_data> = <code>[#deoptimization_data_offset]
   1683   __ ld(a1, MemOperand(v0, Code::kDeoptimizationDataOffset - kHeapObjectTag));
   1684 
   1685   // Load the OSR entrypoint offset from the deoptimization data.
   1686   // <osr_offset> = <deopt_data>[#header_size + #osr_pc_offset]
   1687   __ ld(a1, MemOperand(a1, FixedArray::OffsetOfElementAt(
   1688       DeoptimizationInputData::kOsrPcOffsetIndex) - kHeapObjectTag));
   1689   __ SmiUntag(a1);
   1690 
   1691   // Compute the target address = code_obj + header_size + osr_offset
   1692   // <entry_addr> = <code_obj> + #header_size + <osr_offset>
   1693   __ daddu(v0, v0, a1);
   1694   __ daddiu(ra, v0, Code::kHeaderSize - kHeapObjectTag);
   1695 
   1696   // And "return" to the OSR entry point of the function.
   1697   __ Ret();
   1698 }
   1699 
   1700 
   1701 // static
   1702 void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
   1703                                                int field_index) {
   1704   // ----------- S t a t e -------------
   1705   //  -- a0                 : number of arguments
   1706   //  -- a1                 : function
   1707   //  -- cp                 : context
   1708   //  -- sp[0] : receiver
   1709   // -----------------------------------
   1710 
   1711   // 1. Pop receiver into a0 and check that it's actually a JSDate object.
   1712   Label receiver_not_date;
   1713   {
   1714     __ Pop(a0);
   1715     __ JumpIfSmi(a0, &receiver_not_date);
   1716     __ GetObjectType(a0, t0, t0);
   1717     __ Branch(&receiver_not_date, ne, t0, Operand(JS_DATE_TYPE));
   1718   }
   1719 
   1720   // 2. Load the specified date field, falling back to the runtime as necessary.
   1721   if (field_index == JSDate::kDateValue) {
   1722     __ Ret(USE_DELAY_SLOT);
   1723     __ ld(v0, FieldMemOperand(a0, JSDate::kValueOffset));  // In delay slot.
   1724   } else {
   1725     if (field_index < JSDate::kFirstUncachedField) {
   1726       Label stamp_mismatch;
   1727       __ li(a1, Operand(ExternalReference::date_cache_stamp(masm->isolate())));
   1728       __ ld(a1, MemOperand(a1));
   1729       __ ld(t0, FieldMemOperand(a0, JSDate::kCacheStampOffset));
   1730       __ Branch(&stamp_mismatch, ne, t0, Operand(a1));
   1731       __ Ret(USE_DELAY_SLOT);
   1732       __ ld(v0, FieldMemOperand(
   1733                     a0, JSDate::kValueOffset +
   1734                             field_index * kPointerSize));  // In delay slot.
   1735       __ bind(&stamp_mismatch);
   1736     }
   1737     FrameScope scope(masm, StackFrame::INTERNAL);
   1738     __ PrepareCallCFunction(2, t0);
   1739     __ li(a1, Operand(Smi::FromInt(field_index)));
   1740     __ CallCFunction(
   1741         ExternalReference::get_date_field_function(masm->isolate()), 2);
   1742   }
   1743   __ Ret();
   1744 
   1745   // 3. Raise a TypeError if the receiver is not a date.
   1746   __ bind(&receiver_not_date);
   1747   {
   1748     FrameScope scope(masm, StackFrame::MANUAL);
   1749     __ Push(a0, ra, fp);
   1750     __ Move(fp, sp);
   1751     __ Push(cp, a1);
   1752     __ Push(Smi::FromInt(0));
   1753     __ CallRuntime(Runtime::kThrowNotDateError);
   1754   }
   1755 }
   1756 
   1757 // static
   1758 void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
   1759   // ----------- S t a t e -------------
   1760   //  -- a0    : argc
   1761   //  -- sp[0] : argArray
   1762   //  -- sp[4] : thisArg
   1763   //  -- sp[8] : receiver
   1764   // -----------------------------------
   1765 
   1766   // 1. Load receiver into a1, argArray into a0 (if present), remove all
   1767   // arguments from the stack (including the receiver), and push thisArg (if
   1768   // present) instead.
   1769   {
   1770     Label no_arg;
   1771     Register scratch = a4;
   1772     __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
   1773     __ mov(a3, a2);
   1774     // Dlsa() cannot be used hare as scratch value used later.
   1775     __ dsll(scratch, a0, kPointerSizeLog2);
   1776     __ Daddu(a0, sp, Operand(scratch));
   1777     __ ld(a1, MemOperand(a0));  // receiver
   1778     __ Dsubu(a0, a0, Operand(kPointerSize));
   1779     __ Branch(&no_arg, lt, a0, Operand(sp));
   1780     __ ld(a2, MemOperand(a0));  // thisArg
   1781     __ Dsubu(a0, a0, Operand(kPointerSize));
   1782     __ Branch(&no_arg, lt, a0, Operand(sp));
   1783     __ ld(a3, MemOperand(a0));  // argArray
   1784     __ bind(&no_arg);
   1785     __ Daddu(sp, sp, Operand(scratch));
   1786     __ sd(a2, MemOperand(sp));
   1787     __ mov(a0, a3);
   1788   }
   1789 
   1790   // ----------- S t a t e -------------
   1791   //  -- a0    : argArray
   1792   //  -- a1    : receiver
   1793   //  -- sp[0] : thisArg
   1794   // -----------------------------------
   1795 
   1796   // 2. Make sure the receiver is actually callable.
   1797   Label receiver_not_callable;
   1798   __ JumpIfSmi(a1, &receiver_not_callable);
   1799   __ ld(a4, FieldMemOperand(a1, HeapObject::kMapOffset));
   1800   __ lbu(a4, FieldMemOperand(a4, Map::kBitFieldOffset));
   1801   __ And(a4, a4, Operand(1 << Map::kIsCallable));
   1802   __ Branch(&receiver_not_callable, eq, a4, Operand(zero_reg));
   1803 
   1804   // 3. Tail call with no arguments if argArray is null or undefined.
   1805   Label no_arguments;
   1806   __ JumpIfRoot(a0, Heap::kNullValueRootIndex, &no_arguments);
   1807   __ JumpIfRoot(a0, Heap::kUndefinedValueRootIndex, &no_arguments);
   1808 
   1809   // 4a. Apply the receiver to the given argArray (passing undefined for
   1810   // new.target).
   1811   __ LoadRoot(a3, Heap::kUndefinedValueRootIndex);
   1812   __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
   1813 
   1814   // 4b. The argArray is either null or undefined, so we tail call without any
   1815   // arguments to the receiver.
   1816   __ bind(&no_arguments);
   1817   {
   1818     __ mov(a0, zero_reg);
   1819     __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
   1820   }
   1821 
   1822   // 4c. The receiver is not callable, throw an appropriate TypeError.
   1823   __ bind(&receiver_not_callable);
   1824   {
   1825     __ sd(a1, MemOperand(sp));
   1826     __ TailCallRuntime(Runtime::kThrowApplyNonFunction);
   1827   }
   1828 }
   1829 
   1830 
   1831 // static
   1832 void Builtins::Generate_FunctionPrototypeCall(MacroAssembler* masm) {
   1833   // 1. Make sure we have at least one argument.
   1834   // a0: actual number of arguments
   1835   {
   1836     Label done;
   1837     __ Branch(&done, ne, a0, Operand(zero_reg));
   1838     __ PushRoot(Heap::kUndefinedValueRootIndex);
   1839     __ Daddu(a0, a0, Operand(1));
   1840     __ bind(&done);
   1841   }
   1842 
   1843   // 2. Get the function to call (passed as receiver) from the stack.
   1844   // a0: actual number of arguments
   1845   __ Dlsa(at, sp, a0, kPointerSizeLog2);
   1846   __ ld(a1, MemOperand(at));
   1847 
   1848   // 3. Shift arguments and return address one slot down on the stack
   1849   //    (overwriting the original receiver).  Adjust argument count to make
   1850   //    the original first argument the new receiver.
   1851   // a0: actual number of arguments
   1852   // a1: function
   1853   {
   1854     Label loop;
   1855     // Calculate the copy start address (destination). Copy end address is sp.
   1856     __ Dlsa(a2, sp, a0, kPointerSizeLog2);
   1857 
   1858     __ bind(&loop);
   1859     __ ld(at, MemOperand(a2, -kPointerSize));
   1860     __ sd(at, MemOperand(a2));
   1861     __ Dsubu(a2, a2, Operand(kPointerSize));
   1862     __ Branch(&loop, ne, a2, Operand(sp));
   1863     // Adjust the actual number of arguments and remove the top element
   1864     // (which is a copy of the last argument).
   1865     __ Dsubu(a0, a0, Operand(1));
   1866     __ Pop();
   1867   }
   1868 
   1869   // 4. Call the callable.
   1870   __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
   1871 }
   1872 
   1873 
   1874 void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
   1875   // ----------- S t a t e -------------
   1876   //  -- a0     : argc
   1877   //  -- sp[0]  : argumentsList
   1878   //  -- sp[4]  : thisArgument
   1879   //  -- sp[8]  : target
   1880   //  -- sp[12] : receiver
   1881   // -----------------------------------
   1882 
   1883   // 1. Load target into a1 (if present), argumentsList into a0 (if present),
   1884   // remove all arguments from the stack (including the receiver), and push
   1885   // thisArgument (if present) instead.
   1886   {
   1887     Label no_arg;
   1888     Register scratch = a4;
   1889     __ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
   1890     __ mov(a2, a1);
   1891     __ mov(a3, a1);
   1892     __ dsll(scratch, a0, kPointerSizeLog2);
   1893     __ mov(a0, scratch);
   1894     __ Dsubu(a0, a0, Operand(kPointerSize));
   1895     __ Branch(&no_arg, lt, a0, Operand(zero_reg));
   1896     __ Daddu(a0, sp, Operand(a0));
   1897     __ ld(a1, MemOperand(a0));  // target
   1898     __ Dsubu(a0, a0, Operand(kPointerSize));
   1899     __ Branch(&no_arg, lt, a0, Operand(sp));
   1900     __ ld(a2, MemOperand(a0));  // thisArgument
   1901     __ Dsubu(a0, a0, Operand(kPointerSize));
   1902     __ Branch(&no_arg, lt, a0, Operand(sp));
   1903     __ ld(a3, MemOperand(a0));  // argumentsList
   1904     __ bind(&no_arg);
   1905     __ Daddu(sp, sp, Operand(scratch));
   1906     __ sd(a2, MemOperand(sp));
   1907     __ mov(a0, a3);
   1908   }
   1909 
   1910   // ----------- S t a t e -------------
   1911   //  -- a0    : argumentsList
   1912   //  -- a1    : target
   1913   //  -- sp[0] : thisArgument
   1914   // -----------------------------------
   1915 
   1916   // 2. Make sure the target is actually callable.
   1917   Label target_not_callable;
   1918   __ JumpIfSmi(a1, &target_not_callable);
   1919   __ ld(a4, FieldMemOperand(a1, HeapObject::kMapOffset));
   1920   __ lbu(a4, FieldMemOperand(a4, Map::kBitFieldOffset));
   1921   __ And(a4, a4, Operand(1 << Map::kIsCallable));
   1922   __ Branch(&target_not_callable, eq, a4, Operand(zero_reg));
   1923 
   1924   // 3a. Apply the target to the given argumentsList (passing undefined for
   1925   // new.target).
   1926   __ LoadRoot(a3, Heap::kUndefinedValueRootIndex);
   1927   __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
   1928 
   1929   // 3b. The target is not callable, throw an appropriate TypeError.
   1930   __ bind(&target_not_callable);
   1931   {
   1932     __ sd(a1, MemOperand(sp));
   1933     __ TailCallRuntime(Runtime::kThrowApplyNonFunction);
   1934   }
   1935 }
   1936 
   1937 
   1938 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
   1939   // ----------- S t a t e -------------
   1940   //  -- a0     : argc
   1941   //  -- sp[0]  : new.target (optional)
   1942   //  -- sp[4]  : argumentsList
   1943   //  -- sp[8]  : target
   1944   //  -- sp[12] : receiver
   1945   // -----------------------------------
   1946 
   1947   // 1. Load target into a1 (if present), argumentsList into a0 (if present),
   1948   // new.target into a3 (if present, otherwise use target), remove all
   1949   // arguments from the stack (including the receiver), and push thisArgument
   1950   // (if present) instead.
   1951   {
   1952     Label no_arg;
   1953     Register scratch = a4;
   1954     __ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
   1955     __ mov(a2, a1);
   1956     // Dlsa() cannot be used hare as scratch value used later.
   1957     __ dsll(scratch, a0, kPointerSizeLog2);
   1958     __ Daddu(a0, sp, Operand(scratch));
   1959     __ sd(a2, MemOperand(a0));  // receiver
   1960     __ Dsubu(a0, a0, Operand(kPointerSize));
   1961     __ Branch(&no_arg, lt, a0, Operand(sp));
   1962     __ ld(a1, MemOperand(a0));  // target
   1963     __ mov(a3, a1);             // new.target defaults to target
   1964     __ Dsubu(a0, a0, Operand(kPointerSize));
   1965     __ Branch(&no_arg, lt, a0, Operand(sp));
   1966     __ ld(a2, MemOperand(a0));  // argumentsList
   1967     __ Dsubu(a0, a0, Operand(kPointerSize));
   1968     __ Branch(&no_arg, lt, a0, Operand(sp));
   1969     __ ld(a3, MemOperand(a0));  // new.target
   1970     __ bind(&no_arg);
   1971     __ Daddu(sp, sp, Operand(scratch));
   1972     __ mov(a0, a2);
   1973   }
   1974 
   1975   // ----------- S t a t e -------------
   1976   //  -- a0    : argumentsList
   1977   //  -- a3    : new.target
   1978   //  -- a1    : target
   1979   //  -- sp[0] : receiver (undefined)
   1980   // -----------------------------------
   1981 
   1982   // 2. Make sure the target is actually a constructor.
   1983   Label target_not_constructor;
   1984   __ JumpIfSmi(a1, &target_not_constructor);
   1985   __ ld(a4, FieldMemOperand(a1, HeapObject::kMapOffset));
   1986   __ lbu(a4, FieldMemOperand(a4, Map::kBitFieldOffset));
   1987   __ And(a4, a4, Operand(1 << Map::kIsConstructor));
   1988   __ Branch(&target_not_constructor, eq, a4, Operand(zero_reg));
   1989 
   1990   // 3. Make sure the target is actually a constructor.
   1991   Label new_target_not_constructor;
   1992   __ JumpIfSmi(a3, &new_target_not_constructor);
   1993   __ ld(a4, FieldMemOperand(a3, HeapObject::kMapOffset));
   1994   __ lbu(a4, FieldMemOperand(a4, Map::kBitFieldOffset));
   1995   __ And(a4, a4, Operand(1 << Map::kIsConstructor));
   1996   __ Branch(&new_target_not_constructor, eq, a4, Operand(zero_reg));
   1997 
   1998   // 4a. Construct the target with the given new.target and argumentsList.
   1999   __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
   2000 
   2001   // 4b. The target is not a constructor, throw an appropriate TypeError.
   2002   __ bind(&target_not_constructor);
   2003   {
   2004     __ sd(a1, MemOperand(sp));
   2005     __ TailCallRuntime(Runtime::kThrowCalledNonCallable);
   2006   }
   2007 
   2008   // 4c. The new.target is not a constructor, throw an appropriate TypeError.
   2009   __ bind(&new_target_not_constructor);
   2010   {
   2011     __ sd(a3, MemOperand(sp));
   2012     __ TailCallRuntime(Runtime::kThrowCalledNonCallable);
   2013   }
   2014 }
   2015 
   2016 
   2017 static void ArgumentAdaptorStackCheck(MacroAssembler* masm,
   2018                                       Label* stack_overflow) {
   2019   // ----------- S t a t e -------------
   2020   //  -- a0 : actual number of arguments
   2021   //  -- a1 : function (passed through to callee)
   2022   //  -- a2 : expected number of arguments
   2023   //  -- a3 : new target (passed through to callee)
   2024   // -----------------------------------
   2025   // Check the stack for overflow. We are not trying to catch
   2026   // interruptions (e.g. debug break and preemption) here, so the "real stack
   2027   // limit" is checked.
   2028   __ LoadRoot(a5, Heap::kRealStackLimitRootIndex);
   2029   // Make a5 the space we have left. The stack might already be overflowed
   2030   // here which will cause a5 to become negative.
   2031   __ dsubu(a5, sp, a5);
   2032   // Check if the arguments will overflow the stack.
   2033   __ dsll(at, a2, kPointerSizeLog2);
   2034   // Signed comparison.
   2035   __ Branch(stack_overflow, le, a5, Operand(at));
   2036 }
   2037 
   2038 
   2039 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
   2040   // __ sll(a0, a0, kSmiTagSize);
   2041   __ dsll32(a0, a0, 0);
   2042   __ li(a4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
   2043   __ MultiPush(a0.bit() | a1.bit() | a4.bit() | fp.bit() | ra.bit());
   2044   __ Daddu(fp, sp,
   2045       Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize));
   2046 }
   2047 
   2048 
   2049 static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
   2050   // ----------- S t a t e -------------
   2051   //  -- v0 : result being passed through
   2052   // -----------------------------------
   2053   // Get the number of arguments passed (as a smi), tear down the frame and
   2054   // then tear down the parameters.
   2055   __ ld(a1, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp +
   2056                              kPointerSize)));
   2057   __ mov(sp, fp);
   2058   __ MultiPop(fp.bit() | ra.bit());
   2059   __ SmiScale(a4, a1, kPointerSizeLog2);
   2060   __ Daddu(sp, sp, a4);
   2061   // Adjust for the receiver.
   2062   __ Daddu(sp, sp, Operand(kPointerSize));
   2063 }
   2064 
   2065 
   2066 // static
   2067 void Builtins::Generate_Apply(MacroAssembler* masm) {
   2068   // ----------- S t a t e -------------
   2069   //  -- a0    : argumentsList
   2070   //  -- a1    : target
   2071   //  -- a3    : new.target (checked to be constructor or undefined)
   2072   //  -- sp[0] : thisArgument
   2073   // -----------------------------------
   2074 
   2075   // Create the list of arguments from the array-like argumentsList.
   2076   {
   2077     Label create_arguments, create_array, create_runtime, done_create;
   2078     __ JumpIfSmi(a0, &create_runtime);
   2079 
   2080     // Load the map of argumentsList into a2.
   2081     __ ld(a2, FieldMemOperand(a0, HeapObject::kMapOffset));
   2082 
   2083     // Load native context into a4.
   2084     __ ld(a4, NativeContextMemOperand());
   2085 
   2086     // Check if argumentsList is an (unmodified) arguments object.
   2087     __ ld(at, ContextMemOperand(a4, Context::SLOPPY_ARGUMENTS_MAP_INDEX));
   2088     __ Branch(&create_arguments, eq, a2, Operand(at));
   2089     __ ld(at, ContextMemOperand(a4, Context::STRICT_ARGUMENTS_MAP_INDEX));
   2090     __ Branch(&create_arguments, eq, a2, Operand(at));
   2091 
   2092     // Check if argumentsList is a fast JSArray.
   2093     __ ld(v0, FieldMemOperand(a2, HeapObject::kMapOffset));
   2094     __ lbu(v0, FieldMemOperand(v0, Map::kInstanceTypeOffset));
   2095     __ Branch(&create_array, eq, v0, Operand(JS_ARRAY_TYPE));
   2096 
   2097     // Ask the runtime to create the list (actually a FixedArray).
   2098     __ bind(&create_runtime);
   2099     {
   2100       FrameScope scope(masm, StackFrame::INTERNAL);
   2101       __ Push(a1, a3, a0);
   2102       __ CallRuntime(Runtime::kCreateListFromArrayLike);
   2103       __ mov(a0, v0);
   2104       __ Pop(a1, a3);
   2105       __ ld(a2, FieldMemOperand(v0, FixedArray::kLengthOffset));
   2106       __ SmiUntag(a2);
   2107     }
   2108     __ Branch(&done_create);
   2109 
   2110     // Try to create the list from an arguments object.
   2111     __ bind(&create_arguments);
   2112     __ ld(a2, FieldMemOperand(a0, JSArgumentsObject::kLengthOffset));
   2113     __ ld(a4, FieldMemOperand(a0, JSObject::kElementsOffset));
   2114     __ ld(at, FieldMemOperand(a4, FixedArray::kLengthOffset));
   2115     __ Branch(&create_runtime, ne, a2, Operand(at));
   2116     __ SmiUntag(a2);
   2117     __ mov(a0, a4);
   2118     __ Branch(&done_create);
   2119 
   2120     // Try to create the list from a JSArray object.
   2121     __ bind(&create_array);
   2122     __ ld(a2, FieldMemOperand(a2, Map::kBitField2Offset));
   2123     __ DecodeField<Map::ElementsKindBits>(a2);
   2124     STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
   2125     STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
   2126     STATIC_ASSERT(FAST_ELEMENTS == 2);
   2127     __ Branch(&create_runtime, hi, a2, Operand(FAST_ELEMENTS));
   2128     __ Branch(&create_runtime, eq, a2, Operand(FAST_HOLEY_SMI_ELEMENTS));
   2129     __ ld(a2, FieldMemOperand(a0, JSArray::kLengthOffset));
   2130     __ ld(a0, FieldMemOperand(a0, JSArray::kElementsOffset));
   2131     __ SmiUntag(a2);
   2132 
   2133     __ bind(&done_create);
   2134   }
   2135 
   2136   // Check for stack overflow.
   2137   {
   2138     // Check the stack for overflow. We are not trying to catch interruptions
   2139     // (i.e. debug break and preemption) here, so check the "real stack limit".
   2140     Label done;
   2141     __ LoadRoot(a4, Heap::kRealStackLimitRootIndex);
   2142     // Make ip the space we have left. The stack might already be overflowed
   2143     // here which will cause ip to become negative.
   2144     __ Dsubu(a4, sp, a4);
   2145     // Check if the arguments will overflow the stack.
   2146     __ dsll(at, a2, kPointerSizeLog2);
   2147     __ Branch(&done, gt, a4, Operand(at));  // Signed comparison.
   2148     __ TailCallRuntime(Runtime::kThrowStackOverflow);
   2149     __ bind(&done);
   2150   }
   2151 
   2152   // ----------- S t a t e -------------
   2153   //  -- a1    : target
   2154   //  -- a0    : args (a FixedArray built from argumentsList)
   2155   //  -- a2    : len (number of elements to push from args)
   2156   //  -- a3    : new.target (checked to be constructor or undefined)
   2157   //  -- sp[0] : thisArgument
   2158   // -----------------------------------
   2159 
   2160   // Push arguments onto the stack (thisArgument is already on the stack).
   2161   {
   2162     __ mov(a4, zero_reg);
   2163     Label done, loop;
   2164     __ bind(&loop);
   2165     __ Branch(&done, eq, a4, Operand(a2));
   2166     __ Dlsa(at, a0, a4, kPointerSizeLog2);
   2167     __ ld(at, FieldMemOperand(at, FixedArray::kHeaderSize));
   2168     __ Push(at);
   2169     __ Daddu(a4, a4, Operand(1));
   2170     __ Branch(&loop);
   2171     __ bind(&done);
   2172     __ Move(a0, a4);
   2173   }
   2174 
   2175   // Dispatch to Call or Construct depending on whether new.target is undefined.
   2176   {
   2177     Label construct;
   2178     __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
   2179     __ Branch(&construct, ne, a3, Operand(at));
   2180     __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
   2181     __ bind(&construct);
   2182     __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
   2183   }
   2184 }
   2185 
   2186 namespace {
   2187 
   2188 // Drops top JavaScript frame and an arguments adaptor frame below it (if
   2189 // present) preserving all the arguments prepared for current call.
   2190 // Does nothing if debugger is currently active.
   2191 // ES6 14.6.3. PrepareForTailCall
   2192 //
   2193 // Stack structure for the function g() tail calling f():
   2194 //
   2195 // ------- Caller frame: -------
   2196 // |  ...
   2197 // |  g()'s arg M
   2198 // |  ...
   2199 // |  g()'s arg 1
   2200 // |  g()'s receiver arg
   2201 // |  g()'s caller pc
   2202 // ------- g()'s frame: -------
   2203 // |  g()'s caller fp      <- fp
   2204 // |  g()'s context
   2205 // |  function pointer: g
   2206 // |  -------------------------
   2207 // |  ...
   2208 // |  ...
   2209 // |  f()'s arg N
   2210 // |  ...
   2211 // |  f()'s arg 1
   2212 // |  f()'s receiver arg   <- sp (f()'s caller pc is not on the stack yet!)
   2213 // ----------------------
   2214 //
   2215 void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
   2216                         Register scratch1, Register scratch2,
   2217                         Register scratch3) {
   2218   DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
   2219   Comment cmnt(masm, "[ PrepareForTailCall");
   2220 
   2221   // Prepare for tail call only if ES2015 tail call elimination is enabled.
   2222   Label done;
   2223   ExternalReference is_tail_call_elimination_enabled =
   2224       ExternalReference::is_tail_call_elimination_enabled_address(
   2225           masm->isolate());
   2226   __ li(at, Operand(is_tail_call_elimination_enabled));
   2227   __ lb(scratch1, MemOperand(at));
   2228   __ Branch(&done, eq, scratch1, Operand(zero_reg));
   2229 
   2230   // Drop possible interpreter handler/stub frame.
   2231   {
   2232     Label no_interpreter_frame;
   2233     __ ld(scratch3,
   2234           MemOperand(fp, CommonFrameConstants::kContextOrFrameTypeOffset));
   2235     __ Branch(&no_interpreter_frame, ne, scratch3,
   2236               Operand(Smi::FromInt(StackFrame::STUB)));
   2237     __ ld(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
   2238     __ bind(&no_interpreter_frame);
   2239   }
   2240 
   2241   // Check if next frame is an arguments adaptor frame.
   2242   Register caller_args_count_reg = scratch1;
   2243   Label no_arguments_adaptor, formal_parameter_count_loaded;
   2244   __ ld(scratch2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
   2245   __ ld(scratch3,
   2246         MemOperand(scratch2, CommonFrameConstants::kContextOrFrameTypeOffset));
   2247   __ Branch(&no_arguments_adaptor, ne, scratch3,
   2248             Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
   2249 
   2250   // Drop current frame and load arguments count from arguments adaptor frame.
   2251   __ mov(fp, scratch2);
   2252   __ ld(caller_args_count_reg,
   2253         MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset));
   2254   __ SmiUntag(caller_args_count_reg);
   2255   __ Branch(&formal_parameter_count_loaded);
   2256 
   2257   __ bind(&no_arguments_adaptor);
   2258   // Load caller's formal parameter count
   2259   __ ld(scratch1,
   2260         MemOperand(fp, ArgumentsAdaptorFrameConstants::kFunctionOffset));
   2261   __ ld(scratch1,
   2262         FieldMemOperand(scratch1, JSFunction::kSharedFunctionInfoOffset));
   2263   __ lw(caller_args_count_reg,
   2264         FieldMemOperand(scratch1,
   2265                         SharedFunctionInfo::kFormalParameterCountOffset));
   2266 
   2267   __ bind(&formal_parameter_count_loaded);
   2268 
   2269   ParameterCount callee_args_count(args_reg);
   2270   __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
   2271                         scratch3);
   2272   __ bind(&done);
   2273 }
   2274 }  // namespace
   2275 
   2276 // static
   2277 void Builtins::Generate_CallFunction(MacroAssembler* masm,
   2278                                      ConvertReceiverMode mode,
   2279                                      TailCallMode tail_call_mode) {
   2280   // ----------- S t a t e -------------
   2281   //  -- a0 : the number of arguments (not including the receiver)
   2282   //  -- a1 : the function to call (checked to be a JSFunction)
   2283   // -----------------------------------
   2284   __ AssertFunction(a1);
   2285 
   2286   // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
   2287   // Check that function is not a "classConstructor".
   2288   Label class_constructor;
   2289   __ ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
   2290   __ lbu(a3, FieldMemOperand(a2, SharedFunctionInfo::kFunctionKindByteOffset));
   2291   __ And(at, a3, Operand(SharedFunctionInfo::kClassConstructorBitsWithinByte));
   2292   __ Branch(&class_constructor, ne, at, Operand(zero_reg));
   2293 
   2294   // Enter the context of the function; ToObject has to run in the function
   2295   // context, and we also need to take the global proxy from the function
   2296   // context in case of conversion.
   2297   STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset ==
   2298                 SharedFunctionInfo::kStrictModeByteOffset);
   2299   __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
   2300   // We need to convert the receiver for non-native sloppy mode functions.
   2301   Label done_convert;
   2302   __ lbu(a3, FieldMemOperand(a2, SharedFunctionInfo::kNativeByteOffset));
   2303   __ And(at, a3, Operand((1 << SharedFunctionInfo::kNativeBitWithinByte) |
   2304                          (1 << SharedFunctionInfo::kStrictModeBitWithinByte)));
   2305   __ Branch(&done_convert, ne, at, Operand(zero_reg));
   2306   {
   2307     // ----------- S t a t e -------------
   2308     //  -- a0 : the number of arguments (not including the receiver)
   2309     //  -- a1 : the function to call (checked to be a JSFunction)
   2310     //  -- a2 : the shared function info.
   2311     //  -- cp : the function context.
   2312     // -----------------------------------
   2313 
   2314     if (mode == ConvertReceiverMode::kNullOrUndefined) {
   2315       // Patch receiver to global proxy.
   2316       __ LoadGlobalProxy(a3);
   2317     } else {
   2318       Label convert_to_object, convert_receiver;
   2319       __ Dlsa(at, sp, a0, kPointerSizeLog2);
   2320       __ ld(a3, MemOperand(at));
   2321       __ JumpIfSmi(a3, &convert_to_object);
   2322       STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
   2323       __ GetObjectType(a3, a4, a4);
   2324       __ Branch(&done_convert, hs, a4, Operand(FIRST_JS_RECEIVER_TYPE));
   2325       if (mode != ConvertReceiverMode::kNotNullOrUndefined) {
   2326         Label convert_global_proxy;
   2327         __ JumpIfRoot(a3, Heap::kUndefinedValueRootIndex,
   2328                       &convert_global_proxy);
   2329         __ JumpIfNotRoot(a3, Heap::kNullValueRootIndex, &convert_to_object);
   2330         __ bind(&convert_global_proxy);
   2331         {
   2332           // Patch receiver to global proxy.
   2333           __ LoadGlobalProxy(a3);
   2334         }
   2335         __ Branch(&convert_receiver);
   2336       }
   2337       __ bind(&convert_to_object);
   2338       {
   2339         // Convert receiver using ToObject.
   2340         // TODO(bmeurer): Inline the allocation here to avoid building the frame
   2341         // in the fast case? (fall back to AllocateInNewSpace?)
   2342         FrameScope scope(masm, StackFrame::INTERNAL);
   2343         __ SmiTag(a0);
   2344         __ Push(a0, a1);
   2345         __ mov(a0, a3);
   2346         ToObjectStub stub(masm->isolate());
   2347         __ CallStub(&stub);
   2348         __ mov(a3, v0);
   2349         __ Pop(a0, a1);
   2350         __ SmiUntag(a0);
   2351       }
   2352       __ ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
   2353       __ bind(&convert_receiver);
   2354     }
   2355     __ Dlsa(at, sp, a0, kPointerSizeLog2);
   2356     __ sd(a3, MemOperand(at));
   2357   }
   2358   __ bind(&done_convert);
   2359 
   2360   // ----------- S t a t e -------------
   2361   //  -- a0 : the number of arguments (not including the receiver)
   2362   //  -- a1 : the function to call (checked to be a JSFunction)
   2363   //  -- a2 : the shared function info.
   2364   //  -- cp : the function context.
   2365   // -----------------------------------
   2366 
   2367   if (tail_call_mode == TailCallMode::kAllow) {
   2368     PrepareForTailCall(masm, a0, t0, t1, t2);
   2369   }
   2370 
   2371   __ lw(a2,
   2372         FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset));
   2373   ParameterCount actual(a0);
   2374   ParameterCount expected(a2);
   2375   __ InvokeFunctionCode(a1, no_reg, expected, actual, JUMP_FUNCTION,
   2376                         CheckDebugStepCallWrapper());
   2377 
   2378   // The function is a "classConstructor", need to raise an exception.
   2379   __ bind(&class_constructor);
   2380   {
   2381     FrameScope frame(masm, StackFrame::INTERNAL);
   2382     __ Push(a1);
   2383     __ CallRuntime(Runtime::kThrowConstructorNonCallableError);
   2384   }
   2385 }
   2386 
   2387 
   2388 // static
   2389 void Builtins::Generate_CallBoundFunctionImpl(MacroAssembler* masm,
   2390                                               TailCallMode tail_call_mode) {
   2391   // ----------- S t a t e -------------
   2392   //  -- a0 : the number of arguments (not including the receiver)
   2393   //  -- a1 : the function to call (checked to be a JSBoundFunction)
   2394   // -----------------------------------
   2395   __ AssertBoundFunction(a1);
   2396 
   2397   if (tail_call_mode == TailCallMode::kAllow) {
   2398     PrepareForTailCall(masm, a0, t0, t1, t2);
   2399   }
   2400 
   2401   // Patch the receiver to [[BoundThis]].
   2402   {
   2403     __ ld(at, FieldMemOperand(a1, JSBoundFunction::kBoundThisOffset));
   2404     __ Dlsa(a4, sp, a0, kPointerSizeLog2);
   2405     __ sd(at, MemOperand(a4));
   2406   }
   2407 
   2408   // Load [[BoundArguments]] into a2 and length of that into a4.
   2409   __ ld(a2, FieldMemOperand(a1, JSBoundFunction::kBoundArgumentsOffset));
   2410   __ ld(a4, FieldMemOperand(a2, FixedArray::kLengthOffset));
   2411   __ SmiUntag(a4);
   2412 
   2413   // ----------- S t a t e -------------
   2414   //  -- a0 : the number of arguments (not including the receiver)
   2415   //  -- a1 : the function to call (checked to be a JSBoundFunction)
   2416   //  -- a2 : the [[BoundArguments]] (implemented as FixedArray)
   2417   //  -- a4 : the number of [[BoundArguments]]
   2418   // -----------------------------------
   2419 
   2420   // Reserve stack space for the [[BoundArguments]].
   2421   {
   2422     Label done;
   2423     __ dsll(a5, a4, kPointerSizeLog2);
   2424     __ Dsubu(sp, sp, Operand(a5));
   2425     // Check the stack for overflow. We are not trying to catch interruptions
   2426     // (i.e. debug break and preemption) here, so check the "real stack limit".
   2427     __ LoadRoot(at, Heap::kRealStackLimitRootIndex);
   2428     __ Branch(&done, gt, sp, Operand(at));  // Signed comparison.
   2429     // Restore the stack pointer.
   2430     __ Daddu(sp, sp, Operand(a5));
   2431     {
   2432       FrameScope scope(masm, StackFrame::MANUAL);
   2433       __ EnterFrame(StackFrame::INTERNAL);
   2434       __ CallRuntime(Runtime::kThrowStackOverflow);
   2435     }
   2436     __ bind(&done);
   2437   }
   2438 
   2439   // Relocate arguments down the stack.
   2440   {
   2441     Label loop, done_loop;
   2442     __ mov(a5, zero_reg);
   2443     __ bind(&loop);
   2444     __ Branch(&done_loop, gt, a5, Operand(a0));
   2445     __ Dlsa(a6, sp, a4, kPointerSizeLog2);
   2446     __ ld(at, MemOperand(a6));
   2447     __ Dlsa(a6, sp, a5, kPointerSizeLog2);
   2448     __ sd(at, MemOperand(a6));
   2449     __ Daddu(a4, a4, Operand(1));
   2450     __ Daddu(a5, a5, Operand(1));
   2451     __ Branch(&loop);
   2452     __ bind(&done_loop);
   2453   }
   2454 
   2455   // Copy [[BoundArguments]] to the stack (below the arguments).
   2456   {
   2457     Label loop, done_loop;
   2458     __ ld(a4, FieldMemOperand(a2, FixedArray::kLengthOffset));
   2459     __ SmiUntag(a4);
   2460     __ Daddu(a2, a2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
   2461     __ bind(&loop);
   2462     __ Dsubu(a4, a4, Operand(1));
   2463     __ Branch(&done_loop, lt, a4, Operand(zero_reg));
   2464     __ Dlsa(a5, a2, a4, kPointerSizeLog2);
   2465     __ ld(at, MemOperand(a5));
   2466     __ Dlsa(a5, sp, a0, kPointerSizeLog2);
   2467     __ sd(at, MemOperand(a5));
   2468     __ Daddu(a0, a0, Operand(1));
   2469     __ Branch(&loop);
   2470     __ bind(&done_loop);
   2471   }
   2472 
   2473   // Call the [[BoundTargetFunction]] via the Call builtin.
   2474   __ ld(a1, FieldMemOperand(a1, JSBoundFunction::kBoundTargetFunctionOffset));
   2475   __ li(at, Operand(ExternalReference(Builtins::kCall_ReceiverIsAny,
   2476                                       masm->isolate())));
   2477   __ ld(at, MemOperand(at));
   2478   __ Daddu(at, at, Operand(Code::kHeaderSize - kHeapObjectTag));
   2479   __ Jump(at);
   2480 }
   2481 
   2482 
   2483 // static
   2484 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode,
   2485                              TailCallMode tail_call_mode) {
   2486   // ----------- S t a t e -------------
   2487   //  -- a0 : the number of arguments (not including the receiver)
   2488   //  -- a1 : the target to call (can be any Object).
   2489   // -----------------------------------
   2490 
   2491   Label non_callable, non_function, non_smi;
   2492   __ JumpIfSmi(a1, &non_callable);
   2493   __ bind(&non_smi);
   2494   __ GetObjectType(a1, t1, t2);
   2495   __ Jump(masm->isolate()->builtins()->CallFunction(mode, tail_call_mode),
   2496           RelocInfo::CODE_TARGET, eq, t2, Operand(JS_FUNCTION_TYPE));
   2497   __ Jump(masm->isolate()->builtins()->CallBoundFunction(tail_call_mode),
   2498           RelocInfo::CODE_TARGET, eq, t2, Operand(JS_BOUND_FUNCTION_TYPE));
   2499 
   2500   // Check if target has a [[Call]] internal method.
   2501   __ lbu(t1, FieldMemOperand(t1, Map::kBitFieldOffset));
   2502   __ And(t1, t1, Operand(1 << Map::kIsCallable));
   2503   __ Branch(&non_callable, eq, t1, Operand(zero_reg));
   2504 
   2505   __ Branch(&non_function, ne, t2, Operand(JS_PROXY_TYPE));
   2506 
   2507   // 0. Prepare for tail call if necessary.
   2508   if (tail_call_mode == TailCallMode::kAllow) {
   2509     PrepareForTailCall(masm, a0, t0, t1, t2);
   2510   }
   2511 
   2512   // 1. Runtime fallback for Proxy [[Call]].
   2513   __ Push(a1);
   2514   // Increase the arguments size to include the pushed function and the
   2515   // existing receiver on the stack.
   2516   __ Daddu(a0, a0, 2);
   2517   // Tail-call to the runtime.
   2518   __ JumpToExternalReference(
   2519       ExternalReference(Runtime::kJSProxyCall, masm->isolate()));
   2520 
   2521   // 2. Call to something else, which might have a [[Call]] internal method (if
   2522   // not we raise an exception).
   2523   __ bind(&non_function);
   2524   // Overwrite the original receiver with the (original) target.
   2525   __ Dlsa(at, sp, a0, kPointerSizeLog2);
   2526   __ sd(a1, MemOperand(at));
   2527   // Let the "call_as_function_delegate" take care of the rest.
   2528   __ LoadNativeContextSlot(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, a1);
   2529   __ Jump(masm->isolate()->builtins()->CallFunction(
   2530               ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode),
   2531           RelocInfo::CODE_TARGET);
   2532 
   2533   // 3. Call to something that is not callable.
   2534   __ bind(&non_callable);
   2535   {
   2536     FrameScope scope(masm, StackFrame::INTERNAL);
   2537     __ Push(a1);
   2538     __ CallRuntime(Runtime::kThrowCalledNonCallable);
   2539   }
   2540 }
   2541 
   2542 
   2543 void Builtins::Generate_ConstructFunction(MacroAssembler* masm) {
   2544   // ----------- S t a t e -------------
   2545   //  -- a0 : the number of arguments (not including the receiver)
   2546   //  -- a1 : the constructor to call (checked to be a JSFunction)
   2547   //  -- a3 : the new target (checked to be a constructor)
   2548   // -----------------------------------
   2549   __ AssertFunction(a1);
   2550 
   2551   // Calling convention for function specific ConstructStubs require
   2552   // a2 to contain either an AllocationSite or undefined.
   2553   __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
   2554 
   2555   // Tail call to the function-specific construct stub (still in the caller
   2556   // context at this point).
   2557   __ ld(a4, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
   2558   __ ld(a4, FieldMemOperand(a4, SharedFunctionInfo::kConstructStubOffset));
   2559   __ Daddu(at, a4, Operand(Code::kHeaderSize - kHeapObjectTag));
   2560   __ Jump(at);
   2561 }
   2562 
   2563 
   2564 // static
   2565 void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) {
   2566   // ----------- S t a t e -------------
   2567   //  -- a0 : the number of arguments (not including the receiver)
   2568   //  -- a1 : the function to call (checked to be a JSBoundFunction)
   2569   //  -- a3 : the new target (checked to be a constructor)
   2570   // -----------------------------------
   2571   __ AssertBoundFunction(a1);
   2572 
   2573   // Load [[BoundArguments]] into a2 and length of that into a4.
   2574   __ ld(a2, FieldMemOperand(a1, JSBoundFunction::kBoundArgumentsOffset));
   2575   __ ld(a4, FieldMemOperand(a2, FixedArray::kLengthOffset));
   2576   __ SmiUntag(a4);
   2577 
   2578   // ----------- S t a t e -------------
   2579   //  -- a0 : the number of arguments (not including the receiver)
   2580   //  -- a1 : the function to call (checked to be a JSBoundFunction)
   2581   //  -- a2 : the [[BoundArguments]] (implemented as FixedArray)
   2582   //  -- a3 : the new target (checked to be a constructor)
   2583   //  -- a4 : the number of [[BoundArguments]]
   2584   // -----------------------------------
   2585 
   2586   // Reserve stack space for the [[BoundArguments]].
   2587   {
   2588     Label done;
   2589     __ dsll(a5, a4, kPointerSizeLog2);
   2590     __ Dsubu(sp, sp, Operand(a5));
   2591     // Check the stack for overflow. We are not trying to catch interruptions
   2592     // (i.e. debug break and preemption) here, so check the "real stack limit".
   2593     __ LoadRoot(at, Heap::kRealStackLimitRootIndex);
   2594     __ Branch(&done, gt, sp, Operand(at));  // Signed comparison.
   2595     // Restore the stack pointer.
   2596     __ Daddu(sp, sp, Operand(a5));
   2597     {
   2598       FrameScope scope(masm, StackFrame::MANUAL);
   2599       __ EnterFrame(StackFrame::INTERNAL);
   2600       __ CallRuntime(Runtime::kThrowStackOverflow);
   2601     }
   2602     __ bind(&done);
   2603   }
   2604 
   2605   // Relocate arguments down the stack.
   2606   {
   2607     Label loop, done_loop;
   2608     __ mov(a5, zero_reg);
   2609     __ bind(&loop);
   2610     __ Branch(&done_loop, ge, a5, Operand(a0));
   2611     __ Dlsa(a6, sp, a4, kPointerSizeLog2);
   2612     __ ld(at, MemOperand(a6));
   2613     __ Dlsa(a6, sp, a5, kPointerSizeLog2);
   2614     __ sd(at, MemOperand(a6));
   2615     __ Daddu(a4, a4, Operand(1));
   2616     __ Daddu(a5, a5, Operand(1));
   2617     __ Branch(&loop);
   2618     __ bind(&done_loop);
   2619   }
   2620 
   2621   // Copy [[BoundArguments]] to the stack (below the arguments).
   2622   {
   2623     Label loop, done_loop;
   2624     __ ld(a4, FieldMemOperand(a2, FixedArray::kLengthOffset));
   2625     __ SmiUntag(a4);
   2626     __ Daddu(a2, a2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
   2627     __ bind(&loop);
   2628     __ Dsubu(a4, a4, Operand(1));
   2629     __ Branch(&done_loop, lt, a4, Operand(zero_reg));
   2630     __ Dlsa(a5, a2, a4, kPointerSizeLog2);
   2631     __ ld(at, MemOperand(a5));
   2632     __ Dlsa(a5, sp, a0, kPointerSizeLog2);
   2633     __ sd(at, MemOperand(a5));
   2634     __ Daddu(a0, a0, Operand(1));
   2635     __ Branch(&loop);
   2636     __ bind(&done_loop);
   2637   }
   2638 
   2639   // Patch new.target to [[BoundTargetFunction]] if new.target equals target.
   2640   {
   2641     Label skip_load;
   2642     __ Branch(&skip_load, ne, a1, Operand(a3));
   2643     __ ld(a3, FieldMemOperand(a1, JSBoundFunction::kBoundTargetFunctionOffset));
   2644     __ bind(&skip_load);
   2645   }
   2646 
   2647   // Construct the [[BoundTargetFunction]] via the Construct builtin.
   2648   __ ld(a1, FieldMemOperand(a1, JSBoundFunction::kBoundTargetFunctionOffset));
   2649   __ li(at, Operand(ExternalReference(Builtins::kConstruct, masm->isolate())));
   2650   __ ld(at, MemOperand(at));
   2651   __ Daddu(at, at, Operand(Code::kHeaderSize - kHeapObjectTag));
   2652   __ Jump(at);
   2653 }
   2654 
   2655 
   2656 // static
   2657 void Builtins::Generate_ConstructProxy(MacroAssembler* masm) {
   2658   // ----------- S t a t e -------------
   2659   //  -- a0 : the number of arguments (not including the receiver)
   2660   //  -- a1 : the constructor to call (checked to be a JSProxy)
   2661   //  -- a3 : the new target (either the same as the constructor or
   2662   //          the JSFunction on which new was invoked initially)
   2663   // -----------------------------------
   2664 
   2665   // Call into the Runtime for Proxy [[Construct]].
   2666   __ Push(a1, a3);
   2667   // Include the pushed new_target, constructor and the receiver.
   2668   __ Daddu(a0, a0, Operand(3));
   2669   // Tail-call to the runtime.
   2670   __ JumpToExternalReference(
   2671       ExternalReference(Runtime::kJSProxyConstruct, masm->isolate()));
   2672 }
   2673 
   2674 
   2675 // static
   2676 void Builtins::Generate_Construct(MacroAssembler* masm) {
   2677   // ----------- S t a t e -------------
   2678   //  -- a0 : the number of arguments (not including the receiver)
   2679   //  -- a1 : the constructor to call (can be any Object)
   2680   //  -- a3 : the new target (either the same as the constructor or
   2681   //          the JSFunction on which new was invoked initially)
   2682   // -----------------------------------
   2683 
   2684   // Check if target is a Smi.
   2685   Label non_constructor;
   2686   __ JumpIfSmi(a1, &non_constructor);
   2687 
   2688   // Dispatch based on instance type.
   2689   __ ld(t1, FieldMemOperand(a1, HeapObject::kMapOffset));
   2690   __ lbu(t2, FieldMemOperand(t1, Map::kInstanceTypeOffset));
   2691   __ Jump(masm->isolate()->builtins()->ConstructFunction(),
   2692           RelocInfo::CODE_TARGET, eq, t2, Operand(JS_FUNCTION_TYPE));
   2693 
   2694   // Check if target has a [[Construct]] internal method.
   2695   __ lbu(t3, FieldMemOperand(t1, Map::kBitFieldOffset));
   2696   __ And(t3, t3, Operand(1 << Map::kIsConstructor));
   2697   __ Branch(&non_constructor, eq, t3, Operand(zero_reg));
   2698 
   2699   // Only dispatch to bound functions after checking whether they are
   2700   // constructors.
   2701   __ Jump(masm->isolate()->builtins()->ConstructBoundFunction(),
   2702           RelocInfo::CODE_TARGET, eq, t2, Operand(JS_BOUND_FUNCTION_TYPE));
   2703 
   2704   // Only dispatch to proxies after checking whether they are constructors.
   2705   __ Jump(masm->isolate()->builtins()->ConstructProxy(), RelocInfo::CODE_TARGET,
   2706           eq, t2, Operand(JS_PROXY_TYPE));
   2707 
   2708   // Called Construct on an exotic Object with a [[Construct]] internal method.
   2709   {
   2710     // Overwrite the original receiver with the (original) target.
   2711     __ Dlsa(at, sp, a0, kPointerSizeLog2);
   2712     __ sd(a1, MemOperand(at));
   2713     // Let the "call_as_constructor_delegate" take care of the rest.
   2714     __ LoadNativeContextSlot(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, a1);
   2715     __ Jump(masm->isolate()->builtins()->CallFunction(),
   2716             RelocInfo::CODE_TARGET);
   2717   }
   2718 
   2719   // Called Construct on an Object that doesn't have a [[Construct]] internal
   2720   // method.
   2721   __ bind(&non_constructor);
   2722   __ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(),
   2723           RelocInfo::CODE_TARGET);
   2724 }
   2725 
   2726 // static
   2727 void Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) {
   2728   // ----------- S t a t e -------------
   2729   //  -- a0 : requested object size (untagged)
   2730   //  -- ra : return address
   2731   // -----------------------------------
   2732   __ SmiTag(a0);
   2733   __ Push(a0);
   2734   __ Move(cp, Smi::FromInt(0));
   2735   __ TailCallRuntime(Runtime::kAllocateInNewSpace);
   2736 }
   2737 
   2738 // static
   2739 void Builtins::Generate_AllocateInOldSpace(MacroAssembler* masm) {
   2740   // ----------- S t a t e -------------
   2741   //  -- a0 : requested object size (untagged)
   2742   //  -- ra : return address
   2743   // -----------------------------------
   2744   __ SmiTag(a0);
   2745   __ Move(a1, Smi::FromInt(AllocateTargetSpace::encode(OLD_SPACE)));
   2746   __ Push(a0, a1);
   2747   __ Move(cp, Smi::FromInt(0));
   2748   __ TailCallRuntime(Runtime::kAllocateInTargetSpace);
   2749 }
   2750 
   2751 // static
   2752 void Builtins::Generate_StringToNumber(MacroAssembler* masm) {
   2753   // The StringToNumber stub takes on argument in a0.
   2754   __ AssertString(a0);
   2755 
   2756   // Check if string has a cached array index.
   2757   Label runtime;
   2758   __ lwu(a2, FieldMemOperand(a0, String::kHashFieldOffset));
   2759   __ And(at, a2, Operand(String::kContainsCachedArrayIndexMask));
   2760   __ Branch(&runtime, ne, at, Operand(zero_reg));
   2761   __ IndexFromHash(a2, v0);
   2762   __ Ret();
   2763 
   2764   __ bind(&runtime);
   2765   {
   2766     FrameScope frame(masm, StackFrame::INTERNAL);
   2767     // Push argument.
   2768     __ Push(a0);
   2769     // We cannot use a tail call here because this builtin can also be called
   2770     // from wasm.
   2771     __ CallRuntime(Runtime::kStringToNumber);
   2772   }
   2773   __ Ret();
   2774 }
   2775 
   2776 // static
   2777 void Builtins::Generate_ToNumber(MacroAssembler* masm) {
   2778   // The ToNumber stub takes one argument in a0.
   2779   Label not_smi;
   2780   __ JumpIfNotSmi(a0, &not_smi);
   2781   __ Ret(USE_DELAY_SLOT);
   2782   __ mov(v0, a0);
   2783   __ bind(&not_smi);
   2784 
   2785   Label not_heap_number;
   2786   __ GetObjectType(a0, a1, a1);
   2787   // a0: receiver
   2788   // a1: receiver instance type
   2789   __ Branch(&not_heap_number, ne, a1, Operand(HEAP_NUMBER_TYPE));
   2790   __ Ret(USE_DELAY_SLOT);
   2791   __ mov(v0, a0);
   2792   __ bind(&not_heap_number);
   2793 
   2794   __ Jump(masm->isolate()->builtins()->NonNumberToNumber(),
   2795           RelocInfo::CODE_TARGET);
   2796 }
   2797 
   2798 // static
   2799 void Builtins::Generate_NonNumberToNumber(MacroAssembler* masm) {
   2800   // The NonNumberToNumber stub takes on argument in a0.
   2801   __ AssertNotNumber(a0);
   2802 
   2803   Label not_string;
   2804   __ GetObjectType(a0, a1, a1);
   2805   // a0: receiver
   2806   // a1: receiver instance type
   2807   __ Branch(&not_string, hs, a1, Operand(FIRST_NONSTRING_TYPE));
   2808   __ Jump(masm->isolate()->builtins()->StringToNumber(),
   2809           RelocInfo::CODE_TARGET);
   2810   __ bind(&not_string);
   2811 
   2812   Label not_oddball;
   2813   __ Branch(&not_oddball, ne, a1, Operand(ODDBALL_TYPE));
   2814   __ Ret(USE_DELAY_SLOT);
   2815   __ ld(v0, FieldMemOperand(a0, Oddball::kToNumberOffset));  // In delay slot.
   2816   __ bind(&not_oddball);
   2817   {
   2818     FrameScope frame(masm, StackFrame::INTERNAL);
   2819     // Push argument.
   2820     __ Push(a0);
   2821     // We cannot use a tail call here because this builtin can also be called
   2822     // from wasm.
   2823     __ CallRuntime(Runtime::kToNumber);
   2824   }
   2825   __ Ret();
   2826 }
   2827 
   2828 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
   2829   // State setup as expected by MacroAssembler::InvokePrologue.
   2830   // ----------- S t a t e -------------
   2831   //  -- a0: actual arguments count
   2832   //  -- a1: function (passed through to callee)
   2833   //  -- a2: expected arguments count
   2834   //  -- a3: new target (passed through to callee)
   2835   // -----------------------------------
   2836 
   2837   Label invoke, dont_adapt_arguments, stack_overflow;
   2838 
   2839   Label enough, too_few;
   2840   __ Branch(&dont_adapt_arguments, eq,
   2841       a2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
   2842   // We use Uless as the number of argument should always be greater than 0.
   2843   __ Branch(&too_few, Uless, a0, Operand(a2));
   2844 
   2845   {  // Enough parameters: actual >= expected.
   2846     // a0: actual number of arguments as a smi
   2847     // a1: function
   2848     // a2: expected number of arguments
   2849     // a3: new target (passed through to callee)
   2850     __ bind(&enough);
   2851     EnterArgumentsAdaptorFrame(masm);
   2852     ArgumentAdaptorStackCheck(masm, &stack_overflow);
   2853 
   2854     // Calculate copy start address into a0 and copy end address into a4.
   2855     __ SmiScale(a0, a0, kPointerSizeLog2);
   2856     __ Daddu(a0, fp, a0);
   2857     // Adjust for return address and receiver.
   2858     __ Daddu(a0, a0, Operand(2 * kPointerSize));
   2859     // Compute copy end address.
   2860     __ dsll(a4, a2, kPointerSizeLog2);
   2861     __ dsubu(a4, a0, a4);
   2862 
   2863     // Copy the arguments (including the receiver) to the new stack frame.
   2864     // a0: copy start address
   2865     // a1: function
   2866     // a2: expected number of arguments
   2867     // a3: new target (passed through to callee)
   2868     // a4: copy end address
   2869 
   2870     Label copy;
   2871     __ bind(&copy);
   2872     __ ld(a5, MemOperand(a0));
   2873     __ push(a5);
   2874     __ Branch(USE_DELAY_SLOT, &copy, ne, a0, Operand(a4));
   2875     __ daddiu(a0, a0, -kPointerSize);  // In delay slot.
   2876 
   2877     __ jmp(&invoke);
   2878   }
   2879 
   2880   {  // Too few parameters: Actual < expected.
   2881     __ bind(&too_few);
   2882     EnterArgumentsAdaptorFrame(masm);
   2883     ArgumentAdaptorStackCheck(masm, &stack_overflow);
   2884 
   2885     // Calculate copy start address into a0 and copy end address into a7.
   2886     // a0: actual number of arguments as a smi
   2887     // a1: function
   2888     // a2: expected number of arguments
   2889     // a3: new target (passed through to callee)
   2890     __ SmiScale(a0, a0, kPointerSizeLog2);
   2891     __ Daddu(a0, fp, a0);
   2892     // Adjust for return address and receiver.
   2893     __ Daddu(a0, a0, Operand(2 * kPointerSize));
   2894     // Compute copy end address. Also adjust for return address.
   2895     __ Daddu(a7, fp, kPointerSize);
   2896 
   2897     // Copy the arguments (including the receiver) to the new stack frame.
   2898     // a0: copy start address
   2899     // a1: function
   2900     // a2: expected number of arguments
   2901     // a3: new target (passed through to callee)
   2902     // a7: copy end address
   2903     Label copy;
   2904     __ bind(&copy);
   2905     __ ld(a4, MemOperand(a0));  // Adjusted above for return addr and receiver.
   2906     __ Dsubu(sp, sp, kPointerSize);
   2907     __ Dsubu(a0, a0, kPointerSize);
   2908     __ Branch(USE_DELAY_SLOT, &copy, ne, a0, Operand(a7));
   2909     __ sd(a4, MemOperand(sp));  // In the delay slot.
   2910 
   2911     // Fill the remaining expected arguments with undefined.
   2912     // a1: function
   2913     // a2: expected number of arguments
   2914     // a3: new target (passed through to callee)
   2915     __ LoadRoot(a5, Heap::kUndefinedValueRootIndex);
   2916     __ dsll(a6, a2, kPointerSizeLog2);
   2917     __ Dsubu(a4, fp, Operand(a6));
   2918     // Adjust for frame.
   2919     __ Dsubu(a4, a4, Operand(StandardFrameConstants::kFixedFrameSizeFromFp +
   2920                              2 * kPointerSize));
   2921 
   2922     Label fill;
   2923     __ bind(&fill);
   2924     __ Dsubu(sp, sp, kPointerSize);
   2925     __ Branch(USE_DELAY_SLOT, &fill, ne, sp, Operand(a4));
   2926     __ sd(a5, MemOperand(sp));
   2927   }
   2928 
   2929   // Call the entry point.
   2930   __ bind(&invoke);
   2931   __ mov(a0, a2);
   2932   // a0 : expected number of arguments
   2933   // a1 : function (passed through to callee)
   2934   // a3: new target (passed through to callee)
   2935   __ ld(a4, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
   2936   __ Call(a4);
   2937 
   2938   // Store offset of return address for deoptimizer.
   2939   masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
   2940 
   2941   // Exit frame and return.
   2942   LeaveArgumentsAdaptorFrame(masm);
   2943   __ Ret();
   2944 
   2945 
   2946   // -------------------------------------------
   2947   // Don't adapt arguments.
   2948   // -------------------------------------------
   2949   __ bind(&dont_adapt_arguments);
   2950   __ ld(a4, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
   2951   __ Jump(a4);
   2952 
   2953   __ bind(&stack_overflow);
   2954   {
   2955     FrameScope frame(masm, StackFrame::MANUAL);
   2956     __ CallRuntime(Runtime::kThrowStackOverflow);
   2957     __ break_(0xCC);
   2958   }
   2959 }
   2960 
   2961 
   2962 #undef __
   2963 
   2964 }  // namespace internal
   2965 }  // namespace v8
   2966 
   2967 #endif  // V8_TARGET_ARCH_MIPS64
   2968