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