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