1fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
45c838251403b0be9a882540f1922577abba4c872ager@chromium.org
55c838251403b0be9a882540f1922577abba4c872ager@chromium.org
65c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
85c838251403b0be9a882540f1922577abba4c872ager@chromium.org
993a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_MIPS
109dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
11196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/codegen.h"
12196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/debug.h"
13196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/deoptimizer.h"
14196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/full-codegen.h"
15196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/runtime.h"
166474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
175c838251403b0be9a882540f1922577abba4c872ager@chromium.org
185c838251403b0be9a882540f1922577abba4c872ager@chromium.orgnamespace v8 {
195c838251403b0be9a882540f1922577abba4c872ager@chromium.orgnamespace internal {
205c838251403b0be9a882540f1922577abba4c872ager@chromium.org
215c838251403b0be9a882540f1922577abba4c872ager@chromium.org
225c838251403b0be9a882540f1922577abba4c872ager@chromium.org#define __ ACCESS_MASM(masm)
235c838251403b0be9a882540f1922577abba4c872ager@chromium.org
245c838251403b0be9a882540f1922577abba4c872ager@chromium.org
255c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Builtins::Generate_Adaptor(MacroAssembler* masm,
265c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                CFunctionId id,
275c838251403b0be9a882540f1922577abba4c872ager@chromium.org                                BuiltinExtraArguments extra_args) {
287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // ----------- S t a t e -------------
297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- a0                 : number of arguments excluding receiver
307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- a1                 : called function (only guaranteed when
317304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  --                      extra_args requires it)
327304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- cp                 : context
337304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- sp[0]              : last argument
347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- ...
357304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- sp[4 * (argc - 1)] : first argument
367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- sp[4 * agrc]       : receiver
377304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // -----------------------------------
387304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
397304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Insert extra arguments.
407304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  int num_extra_args = 0;
417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  if (extra_args == NEEDS_CALLED_FUNCTION) {
427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    num_extra_args = 1;
437304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ push(a1);
447304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  } else {
45e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(extra_args == NO_EXTRA_ARGUMENTS);
467304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
477304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
486ff651481ed0a881f176f6d55e26679ca359792bulan@chromium.org  // JumpToExternalReference expects s0 to contain the number of arguments
497304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // including the receiver and the extra arguments.
506ff651481ed0a881f176f6d55e26679ca359792bulan@chromium.org  __ Addu(s0, a0, num_extra_args + 1);
516ff651481ed0a881f176f6d55e26679ca359792bulan@chromium.org  __ sll(s1, s0, kPointerSizeLog2);
526ff651481ed0a881f176f6d55e26679ca359792bulan@chromium.org  __ Subu(s1, s1, kPointerSize);
537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ JumpToExternalReference(ExternalReference(id, masm->isolate()));
547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org}
557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
57fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org// Load the built-in InternalArray function from the current context.
58fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.orgstatic void GenerateLoadInternalArrayFunction(MacroAssembler* masm,
59fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org                                              Register result) {
6046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Load the native context.
61fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org
62fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  __ lw(result,
6346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org        MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
6446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ lw(result,
6546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org        FieldMemOperand(result, GlobalObject::kNativeContextOffset));
6646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Load the InternalArray function from the native context.
67fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  __ lw(result,
68fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org         MemOperand(result,
69fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org                    Context::SlotOffset(
70fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org                        Context::INTERNAL_ARRAY_FUNCTION_INDEX)));
71fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org}
72fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org
73fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org
747304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org// Load the built-in Array function from the current context.
757304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgstatic void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) {
7646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Load the native context.
777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ lw(result,
7946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org        MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
8046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ lw(result,
8146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org        FieldMemOperand(result, GlobalObject::kNativeContextOffset));
8246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Load the Array function from the native context.
837304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ lw(result,
84fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org        MemOperand(result,
85fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org                   Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
867304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org}
877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
887304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
89fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.orgvoid Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
90fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  // ----------- S t a t e -------------
91fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  //  -- a0     : number of arguments
92fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  //  -- ra     : return address
93fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  //  -- sp[...]: constructor arguments
94fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  // -----------------------------------
95fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
96fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org
97fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  // Get the InternalArray function.
98fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  GenerateLoadInternalArrayFunction(masm, a1);
99fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org
100fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  if (FLAG_debug_code) {
101fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org    // Initial map for the builtin InternalArray functions should be maps.
102fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org    __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
1037ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org    __ SmiTst(a2, t0);
104594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(ne, kUnexpectedInitialMapForInternalArrayFunction,
105fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org              t0, Operand(zero_reg));
106fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org    __ GetObjectType(a2, a3, t0);
107594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(eq, kUnexpectedInitialMapForInternalArrayFunction,
108fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org              t0, Operand(MAP_TYPE));
109fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  }
110fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org
111fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  // Run the native code for the InternalArray function called as a normal
112fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  // function.
1131510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // Tail call a stub.
1141510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  InternalArrayConstructorStub stub(masm->isolate());
1151510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ TailCallStub(&stub);
1165c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
1175c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1185c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1195c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Builtins::Generate_ArrayCode(MacroAssembler* masm) {
1207304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // ----------- S t a t e -------------
1217304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- a0     : number of arguments
1227304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- ra     : return address
1237304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- sp[...]: constructor arguments
1247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // -----------------------------------
1257304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Label generic_array_code;
1267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Get the Array function.
1287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  GenerateLoadArrayFunction(masm, a1);
1297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  if (FLAG_debug_code) {
1317304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // Initial map for the builtin Array functions should be maps.
1327304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
1337ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org    __ SmiTst(a2, t0);
134594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(ne, kUnexpectedInitialMapForArrayFunction1,
1357304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org              t0, Operand(zero_reg));
1367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ GetObjectType(a2, a3, t0);
137594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(eq, kUnexpectedInitialMapForArrayFunction2,
1387304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org              t0, Operand(MAP_TYPE));
1397304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
1407304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Run the native code for the Array function called as a normal function.
1421510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // Tail call a stub.
14369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
1441510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  ArrayConstructorStub stub(masm->isolate());
1451510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ TailCallStub(&stub);
1465c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
1475c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1485c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
1507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // ----------- S t a t e -------------
1517304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- a0                     : number of arguments
1527304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- a1                     : constructor function
1537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- ra                     : return address
1547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
1557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- sp[argc * 4]           : receiver
1567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // -----------------------------------
1577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Counters* counters = masm->isolate()->counters();
1587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ IncrementCounter(counters->string_ctor_calls(), 1, a2, a3);
1597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1607304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Register function = a1;
1617304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  if (FLAG_debug_code) {
1627304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, a2);
163594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(eq, kUnexpectedStringFunction, function, Operand(a2));
1647304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
1657304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1667304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Load the first arguments in a0 and get rid of the rest.
1677304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Label no_arguments;
1687304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Branch(&no_arguments, eq, a0, Operand(zero_reg));
1697304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // First args = sp[(argc - 1) * 4].
1707304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Subu(a0, a0, Operand(1));
1717304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ sll(a0, a0, kPointerSizeLog2);
1727304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Addu(sp, a0, sp);
1737304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ lw(a0, MemOperand(sp));
1747304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // sp now point to args[0], drop args[0] + receiver.
1757304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Drop(2);
1767304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Register argument = a2;
1787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Label not_cached, argument_is_string;
179528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ LookupNumberStringCache(a0,        // Input.
180528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                             argument,  // Result.
181528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                             a3,        // Scratch.
182528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                             t0,        // Scratch.
183528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                             t1,        // Scratch.
184528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                             &not_cached);
1857304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ IncrementCounter(counters->string_ctor_cached_number(), 1, a3, t0);
1867304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ bind(&argument_is_string);
1877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1887304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // ----------- S t a t e -------------
1897304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- a2     : argument converted to string
1907304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- a1     : constructor function
1917304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- ra     : return address
1927304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // -----------------------------------
1937304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1947304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Label gc_required;
1954c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org  __ Allocate(JSValue::kSize,
1964c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org              v0,  // Result.
1974c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org              a3,  // Scratch.
1984c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org              t0,  // Scratch.
1994c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org              &gc_required,
2004c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org              TAG_OBJECT);
2017304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
2027304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Initialising the String Object.
2037304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Register map = a3;
2047304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ LoadGlobalFunctionInitialMap(function, map, t0);
2057304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  if (FLAG_debug_code) {
2067304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ lbu(t0, FieldMemOperand(map, Map::kInstanceSizeOffset));
207594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(eq, kUnexpectedStringWrapperInstanceSize,
2087304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        t0, Operand(JSValue::kSize >> kPointerSizeLog2));
2097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ lbu(t0, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset));
210594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(eq, kUnexpectedUnusedPropertiesOfStringWrapper,
2117304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        t0, Operand(zero_reg));
2127304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
2137304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ sw(map, FieldMemOperand(v0, HeapObject::kMapOffset));
2147304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
2157304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex);
2167304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ sw(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset));
2177304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ sw(a3, FieldMemOperand(v0, JSObject::kElementsOffset));
2187304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
2197304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ sw(argument, FieldMemOperand(v0, JSValue::kValueOffset));
2207304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
2217304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Ensure the object is fully initialized.
2227304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
2237304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
2247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Ret();
2257304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
2267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // The argument was not found in the number to string cache. Check
2277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // if it's a string already before calling the conversion builtin.
2287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Label convert_argument;
2297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ bind(&not_cached);
2307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ JumpIfSmi(a0, &convert_argument);
2317304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
2327304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Is it a String?
2337304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ lw(a2, FieldMemOperand(a0, HeapObject::kMapOffset));
2347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset));
2351805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  STATIC_ASSERT(kNotStringTag != 0);
2367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ And(t0, a3, Operand(kIsNotStringMask));
2377304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Branch(&convert_argument, ne, t0, Operand(zero_reg));
2387304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ mov(argument, a0);
2397304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ IncrementCounter(counters->string_ctor_conversions(), 1, a3, t0);
2407304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Branch(&argument_is_string);
2417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
2427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Invoke the conversion builtin and put the result into a2.
2437304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ bind(&convert_argument);
2447304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ push(function);  // Preserve the function.
2457304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ IncrementCounter(counters->string_ctor_conversions(), 1, a3, t0);
246c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {
247c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    FrameScope scope(masm, StackFrame::INTERNAL);
248c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org    __ push(a0);
249c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
250c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
2517304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ pop(function);
2527304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ mov(argument, v0);
2537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Branch(&argument_is_string);
2547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
2557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Load the empty string into a2, remove the receiver from the
2567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // stack, and jump back to the case where the argument is a string.
2577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ bind(&no_arguments);
258750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  __ LoadRoot(argument, Heap::kempty_stringRootIndex);
2597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Drop(1);
2607304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Branch(&argument_is_string);
2617304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
2627304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // At this point the argument is already a string. Call runtime to
2637304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // create a string wrapper.
2647304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ bind(&gc_required);
2657304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ IncrementCounter(counters->string_ctor_gc_required(), 1, a3, t0);
266c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {
267c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    FrameScope scope(masm, StackFrame::INTERNAL);
268c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(argument);
269c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CallRuntime(Runtime::kNewStringWrapper, 1);
270c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
2717304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Ret();
2727516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
2737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2754954674151afa960af66efb4831df06bde727333yangguo@chromium.orgstatic void CallRuntimePassFunction(
2764954674151afa960af66efb4831df06bde727333yangguo@chromium.org    MacroAssembler* masm, Runtime::FunctionId function_id) {
2774a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  FrameScope scope(masm, StackFrame::INTERNAL);
2784a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  // Push a copy of the function onto the stack.
279057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  // Push call kind information and function as parameter to the runtime call.
280e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  __ Push(a1, a1);
2814a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org
2824a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ CallRuntime(function_id, 1);
283057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  // Restore call kind information and receiver.
284e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  __ Pop(a1);
2854a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org}
2864a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org
2874a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org
288129d398d682e6ca3910808c913212ce532f1e155danno@chromium.orgstatic void GenerateTailCallToSharedCode(MacroAssembler* masm) {
289129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org  __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
290129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org  __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kCodeOffset));
291129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org  __ Addu(at, a2, Operand(Code::kHeaderSize - kHeapObjectTag));
292129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org  __ Jump(at);
293129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org}
294129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org
295129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org
2964954674151afa960af66efb4831df06bde727333yangguo@chromium.orgstatic void GenerateTailCallToReturnedCode(MacroAssembler* masm) {
2974954674151afa960af66efb4831df06bde727333yangguo@chromium.org  __ Addu(at, v0, Operand(Code::kHeaderSize - kHeapObjectTag));
2984954674151afa960af66efb4831df06bde727333yangguo@chromium.org  __ Jump(at);
2994954674151afa960af66efb4831df06bde727333yangguo@chromium.org}
3004954674151afa960af66efb4831df06bde727333yangguo@chromium.org
3014954674151afa960af66efb4831df06bde727333yangguo@chromium.org
3024954674151afa960af66efb4831df06bde727333yangguo@chromium.orgvoid Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) {
3034a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  // Checking whether the queued function is ready for install is optional,
3044a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  // since we come across interrupts and stack checks elsewhere.  However,
3054a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  // not checking may delay installing ready functions, and always checking
3064a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  // would be quite expensive.  A good compromise is to first check against
3074a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  // stack limit as a cue for an interrupt signal.
3084a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  Label ok;
3094a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ LoadRoot(t0, Heap::kStackLimitRootIndex);
3104a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ Branch(&ok, hs, sp, Operand(t0));
3114a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org
31247390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org  CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode);
3134954674151afa960af66efb4831df06bde727333yangguo@chromium.org  GenerateTailCallToReturnedCode(masm);
3146e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org
3154a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ bind(&ok);
3164a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  GenerateTailCallToSharedCode(masm);
3176e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org}
3186e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org
3196e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org
320fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.orgstatic void Generate_JSConstructStubHelper(MacroAssembler* masm,
321fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org                                           bool is_api_function,
32269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org                                           bool create_memento) {
3237304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // ----------- S t a t e -------------
3247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- a0     : number of arguments
3257304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- a1     : constructor function
32669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  //  -- a2     : allocation site or undefined
3277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- ra     : return address
3287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- sp[...]: constructor arguments
3297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // -----------------------------------
3307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
33169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  // Should never create mementos for api functions.
332e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!is_api_function || !create_memento);
33369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org
3347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Isolate* isolate = masm->isolate();
3357304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
3367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // ----------- S t a t e -------------
3377304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- a0     : number of arguments
3387304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- a1     : constructor function
3397304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- ra     : return address
3407304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- sp[...]: constructor arguments
3417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // -----------------------------------
3427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
3437304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Enter a construct frame.
344c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {
345c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    FrameScope scope(masm, StackFrame::CONSTRUCT);
3467304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
34769f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    if (create_memento) {
34869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      __ AssertUndefinedOrAllocationSite(a2, a3);
34969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      __ push(a2);
35069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    }
35169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org
352c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Preserve the two incoming parameters on the stack.
353c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ sll(a0, a0, kSmiTagSize);  // Tag arguments count.
354c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ MultiPushReversed(a0.bit() | a1.bit());
3557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
356c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label rt_call, allocated;
357c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Try to allocate the object without transitioning into C code. If any of
358c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // the preconditions is not met, the code bails out to the runtime call.
359c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (FLAG_inline_new) {
360c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Label undo_allocation;
361c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ExternalReference debug_step_in_fp =
362c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          ExternalReference::debug_step_in_fp_address(isolate);
363c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ li(a2, Operand(debug_step_in_fp));
364c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ lw(a2, MemOperand(a2));
365c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ Branch(&rt_call, ne, a2, Operand(zero_reg));
3667304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
367c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Load the initial map and verify that it is in fact a map.
368c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // a1: constructor function
369c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
370c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      __ JumpIfSmi(a2, &rt_call);
371c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ GetObjectType(a2, a3, t4);
372c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ Branch(&rt_call, ne, t4, Operand(MAP_TYPE));
373c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
374c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Check that the constructor is not constructing a JSFunction (see
375c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // comments in Runtime_NewObject in runtime.cc). In which case the
376c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // initial map's instance type would be JS_FUNCTION_TYPE.
377c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // a1: constructor function
378c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // a2: initial map
379c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset));
380c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ Branch(&rt_call, eq, a3, Operand(JS_FUNCTION_TYPE));
3817304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (!is_api_function) {
383c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        Label allocate;
384864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        MemOperand bit_field3 = FieldMemOperand(a2, Map::kBitField3Offset);
385864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Check if slack tracking is enabled.
386864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ lw(t0, bit_field3);
387864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ DecodeField<Map::ConstructionCount>(t2, t0);
388864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ Branch(&allocate, eq, t2, Operand(JSFunction::kNoSlackTracking));
389c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        // Decrease generous allocation count.
390864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ Subu(t0, t0, Operand(1 << Map::ConstructionCount::kShift));
391864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ Branch(USE_DELAY_SLOT,
392864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            &allocate, ne, t2, Operand(JSFunction::kFinishSlackTracking));
393864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ sw(t0, bit_field3);  // In delay slot.
394c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
395057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org        __ Push(a1, a2, a1);  // a1 = Constructor.
39647390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org        __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
397c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
398057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org        __ Pop(a1, a2);
399864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Slack tracking counter is kNoSlackTracking after runtime call.
400e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK(JSFunction::kNoSlackTracking == 0);
401864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(t2, zero_reg);
402c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
403c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ bind(&allocate);
4047304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      }
4057304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
406c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Now allocate the JSObject on the heap.
407c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // a1: constructor function
408c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // a2: initial map
409c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset));
41069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      if (create_memento) {
41169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        __ Addu(a3, a3, Operand(AllocationMemento::kSize / kPointerSize));
41269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      }
41369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org
414f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      __ Allocate(a3, t4, t5, t6, &rt_call, SIZE_IN_WORDS);
415c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
416c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Allocated the JSObject, now initialize the fields. Map is set to
417c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // initial map and properties and elements are set to empty fixed array.
418c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // a1: constructor function
419c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // a2: initial map
42069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      // a3: object size (not including memento if create_memento)
421c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // t4: JSObject (not tagged)
422c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ LoadRoot(t6, Heap::kEmptyFixedArrayRootIndex);
423c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ mov(t5, t4);
424c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ sw(a2, MemOperand(t5, JSObject::kMapOffset));
425c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ sw(t6, MemOperand(t5, JSObject::kPropertiesOffset));
426c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ sw(t6, MemOperand(t5, JSObject::kElementsOffset));
427c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ Addu(t5, t5, Operand(3*kPointerSize));
428e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK_EQ(0 * kPointerSize, JSObject::kMapOffset);
429e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
430e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK_EQ(2 * kPointerSize, JSObject::kElementsOffset);
431c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
432c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Fill all the in-object properties with appropriate filler.
433c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // a1: constructor function
434c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // a2: initial map
43569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      // a3: object size (in words, including memento if create_memento)
436c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // t4: JSObject (not tagged)
437c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // t5: First in-object property of JSObject (not tagged)
438864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // t2: slack tracking counter (non-API function case)
439e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK_EQ(3 * kPointerSize, JSObject::kHeaderSize);
44069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org
441864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Use t7 to hold undefined, which is used in several places below.
442864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
443864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
444864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (!is_api_function) {
445864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Label no_inobject_slack_tracking;
446864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
447864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Check if slack tracking is enabled.
448864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ Branch(&no_inobject_slack_tracking,
449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            eq, t2, Operand(JSFunction::kNoSlackTracking));
450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Allocate object with a slack.
452731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org        __ lbu(a0, FieldMemOperand(a2, Map::kPreAllocatedPropertyFieldsOffset));
453fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org        __ sll(at, a0, kPointerSizeLog2);
454fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org        __ addu(a0, t5, at);
455b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org        // a0: offset of first field after pre-allocated fields
456b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org        if (FLAG_debug_code) {
457864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ sll(at, a3, kPointerSizeLog2);
458864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ Addu(t6, t4, Operand(at));   // End of object.
459594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org          __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields,
460b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org              a0, Operand(t6));
461c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        }
462b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org        __ InitializeFieldsWithFiller(t5, a0, t7);
463b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org        // To allow for truncation.
464b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org        __ LoadRoot(t7, Heap::kOnePointerFillerMapRootIndex);
465864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Fill the remaining fields with one pointer filler map.
466864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
467864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ bind(&no_inobject_slack_tracking);
468864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
469864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
470864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (create_memento) {
471864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ Subu(a0, a3, Operand(AllocationMemento::kSize / kPointerSize));
472864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ sll(a0, a0, kPointerSizeLog2);
473864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ Addu(a0, t4, Operand(a0));  // End of object.
47469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        __ InitializeFieldsWithFiller(t5, a0, t7);
47569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org
47669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        // Fill in memento fields.
47769f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        // t5: points to the allocated but uninitialized memento.
47869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        __ LoadRoot(t7, Heap::kAllocationMementoMapRootIndex);
479e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK_EQ(0 * kPointerSize, AllocationMemento::kMapOffset);
48069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        __ sw(t7, MemOperand(t5));
48169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        __ Addu(t5, t5, kPointerSize);
48269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        // Load the AllocationSite.
48369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        __ lw(t7, MemOperand(sp, 2 * kPointerSize));
484e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK_EQ(1 * kPointerSize, AllocationMemento::kAllocationSiteOffset);
48569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        __ sw(t7, MemOperand(t5));
48669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        __ Addu(t5, t5, kPointerSize);
48769f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      } else {
48869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        __ sll(at, a3, kPointerSizeLog2);
48969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        __ Addu(a0, t4, Operand(at));  // End of object.
49069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        __ InitializeFieldsWithFiller(t5, a0, t7);
491c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
4927304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
493c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Add the object tag to make the JSObject real, so that we can continue
494c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // and jump into the continuation code at any time from now on. Any
495c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // failures need to undo the allocation, so that the heap is in a
496c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // consistent state and verifiable.
497c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ Addu(t4, t4, Operand(kHeapObjectTag));
498c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
499c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Check if a non-empty properties array is needed. Continue with
500c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // allocated object if not fall through to runtime call if it is.
501c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // a1: constructor function
502c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // t4: JSObject
503c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // t5: start of next object (not tagged)
504c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ lbu(a3, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset));
505c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // The field instance sizes contains both pre-allocated property fields
506c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // and in-object properties.
507731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org      __ lbu(t6, FieldMemOperand(a2, Map::kPreAllocatedPropertyFieldsOffset));
508b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      __ Addu(a3, a3, Operand(t6));
509731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org      __ lbu(t6, FieldMemOperand(a2, Map::kInObjectPropertiesOffset));
510b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org      __ subu(a3, a3, t6);
511c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
512c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Done if no extra properties are to be allocated.
513c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ Branch(&allocated, eq, a3, Operand(zero_reg));
514594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      __ Assert(greater_equal, kPropertyAllocationCountFailed,
515c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          a3, Operand(zero_reg));
516c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
517c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Scale the number of elements by pointer size and add the header for
518c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // FixedArrays to the start of the next object calculation from above.
519c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // a1: constructor
520c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // a3: number of elements in properties array
521c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // t4: JSObject
522c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // t5: start of next object
523c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ Addu(a0, a3, Operand(FixedArray::kHeaderSize / kPointerSize));
524f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      __ Allocate(
525c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          a0,
526c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          t5,
527c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          t6,
528c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          a2,
529c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          &undo_allocation,
530c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS));
531c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
532c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Initialize the FixedArray.
533c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // a1: constructor
5342efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org      // a3: number of elements in properties array (untagged)
535c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // t4: JSObject
536c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // t5: start of next object
537c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ LoadRoot(t6, Heap::kFixedArrayMapRootIndex);
538c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ mov(a2, t5);
539c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ sw(t6, MemOperand(a2, JSObject::kMapOffset));
540c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ sll(a0, a3, kSmiTagSize);
541c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ sw(a0, MemOperand(a2, FixedArray::kLengthOffset));
542c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ Addu(a2, a2, Operand(2 * kPointerSize));
543c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
544e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK_EQ(0 * kPointerSize, JSObject::kMapOffset);
545e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
546c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
547c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Initialize the fields to undefined.
548c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // a1: constructor
549c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // a2: First element of FixedArray (not tagged)
550c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // a3: number of elements in properties array
551c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // t4: JSObject
552c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // t5: FixedArray (not tagged)
553c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ sll(t3, a3, kPointerSizeLog2);
554c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ addu(t6, a2, t3);  // End of object.
555e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
556c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      { Label loop, entry;
557864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (!is_api_function || create_memento) {
558c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          __ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
559c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        } else if (FLAG_debug_code) {
560864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ LoadRoot(t2, Heap::kUndefinedValueRootIndex);
561864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ Assert(eq, kUndefinedValueNotLoaded, t7, Operand(t2));
562c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        }
563c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ jmp(&entry);
564c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ bind(&loop);
565c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ sw(t7, MemOperand(a2));
566c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ addiu(a2, a2, kPointerSize);
567c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ bind(&entry);
568c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ Branch(&loop, less, a2, Operand(t6));
5697304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      }
570c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
571c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Store the initialized FixedArray into the properties field of
572c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // the JSObject.
573c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // a1: constructor function
574c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // t4: JSObject
575c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // t5: FixedArray (not tagged)
576c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ Addu(t5, t5, Operand(kHeapObjectTag));  // Add the heap tag.
577c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ sw(t5, FieldMemOperand(t4, JSObject::kPropertiesOffset));
578c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
579c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Continue with JSObject being successfully allocated.
580c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // a1: constructor function
581c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // a4: JSObject
582c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ jmp(&allocated);
583c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
584c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Undo the setting of the new top so that the heap is verifiable. For
585c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // example, the map's unused properties potentially do not match the
586c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // allocated objects unused properties.
587c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // t4: JSObject (previous new top)
588c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ bind(&undo_allocation);
589c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ UndoAllocationInNewSpace(t4, t5);
5907304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
5917304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
592c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Allocate the new receiver object using the runtime call.
5937304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a1: constructor function
59469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    __ bind(&rt_call);
59569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    if (create_memento) {
59669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      // Get the cell or allocation site.
59769f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      __ lw(a2, MemOperand(sp, 2 * kPointerSize));
59869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      __ push(a2);
59969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    }
60069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org
601c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(a1);  // Argument for Runtime_NewObject.
60269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    if (create_memento) {
60347390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org      __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 2);
60469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    } else {
60547390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org      __ CallRuntime(Runtime::kNewObject, 1);
60669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    }
607c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ mov(t4, v0);
6087304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
60969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    // If we ended up using the runtime, and we want a memento, then the
61069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    // runtime call made it for us, and we shouldn't do create count
61169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    // increment.
61269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    Label count_incremented;
61369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    if (create_memento) {
61469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      __ jmp(&count_incremented);
61569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    }
61669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org
617c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Receiver for constructor call allocated.
618c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // t4: JSObject
61938de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org    __ bind(&allocated);
62069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org
62169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    if (create_memento) {
62269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      __ lw(a2, MemOperand(sp, kPointerSize * 2));
62369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      __ LoadRoot(t5, Heap::kUndefinedValueRootIndex);
62469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      __ Branch(&count_incremented, eq, a2, Operand(t5));
62569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      // a2 is an AllocationSite. We are creating a memento from it, so we
62669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      // need to increment the memento create count.
62769f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      __ lw(a3, FieldMemOperand(a2,
62869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org                                AllocationSite::kPretenureCreateCountOffset));
62969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      __ Addu(a3, a3, Operand(Smi::FromInt(1)));
63069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      __ sw(a3, FieldMemOperand(a2,
63169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org                                AllocationSite::kPretenureCreateCountOffset));
63269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      __ bind(&count_incremented);
63369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    }
63469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org
6356f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org    __ Push(t4, t4);
6367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
637c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Reload the number of arguments from the stack.
638c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // sp[0]: receiver
63978d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    // sp[1]: receiver
64078d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    // sp[2]: constructor function
64178d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    // sp[3]: number of arguments (smi-tagged)
64278d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    __ lw(a1, MemOperand(sp, 2 * kPointerSize));
64378d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    __ lw(a3, MemOperand(sp, 3 * kPointerSize));
6447304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
645f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com    // Set up pointer to last argument.
646c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Addu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
6477304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
648f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com    // Set up number of arguments for function call below.
649c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ srl(a0, a3, kSmiTagSize);
6507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
651c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Copy arguments and receiver to the expression stack.
652c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // a0: number of arguments
653c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // a1: constructor function
654c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // a2: address of last argument (caller sp)
655c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // a3: number of arguments (smi-tagged)
656c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // sp[0]: receiver
65778d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    // sp[1]: receiver
65878d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    // sp[2]: constructor function
65978d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    // sp[3]: number of arguments (smi-tagged)
660c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label loop, entry;
661c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ jmp(&entry);
662c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&loop);
663c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ sll(t0, a3, kPointerSizeLog2 - kSmiTagSize);
664c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Addu(t0, a2, Operand(t0));
665c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ lw(t1, MemOperand(t0));
666c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(t1);
667c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&entry);
668c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Addu(a3, a3, Operand(-2));
669c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Branch(&loop, greater_equal, a3, Operand(zero_reg));
6707304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
671c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Call the function.
672c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // a0: number of arguments
673c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // a1: constructor function
674c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (is_api_function) {
675c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
676c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Handle<Code> code =
677c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          masm->isolate()->builtins()->HandleApiCallConstruct();
67826ca35cc4ec47151d9c6d3890b0f052fc79cb8afmachenbach@chromium.org      __ Call(code, RelocInfo::CODE_TARGET);
679c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    } else {
680c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ParameterCount actual(a0);
681e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org      __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
682c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
6837304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
684812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    // Store offset of return address for deoptimizer.
685864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (!is_api_function) {
686812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
687812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    }
688812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
689c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Restore context from the frame.
690c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
691c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
692c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // If the result is an object (in the ECMA sense), we should get rid
693c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // of the receiver and use the result; see ECMA-262 section 13.2.2-7
694c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // on page 74.
695c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label use_receiver, exit;
696c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
697c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // If the result is a smi, it is *not* an object in the ECMA sense.
698c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // v0: result
699c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // sp[0]: receiver (newly allocated object)
700c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // sp[1]: constructor function
701c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // sp[2]: number of arguments (smi-tagged)
702c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    __ JumpIfSmi(v0, &use_receiver);
703c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
704c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // If the type of the result (stored in its map) is less than
705c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
7069faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    __ GetObjectType(v0, a1, a3);
707c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Branch(&exit, greater_equal, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
708c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
709c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Throw away the result of the constructor invocation and use the
710c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // on-stack receiver as the result.
711c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&use_receiver);
712c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ lw(v0, MemOperand(sp));
713c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
714c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Remove receiver from the stack, remove caller arguments, and
715c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // return.
716c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&exit);
717c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // v0: result
718c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // sp[0]: receiver (newly allocated object)
719c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // sp[1]: constructor function
720c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // sp[2]: number of arguments (smi-tagged)
721c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ lw(a1, MemOperand(sp, 2 * kPointerSize));
722c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
723c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Leave construct frame.
7247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
7257304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ sll(t0, a1, kPointerSizeLog2 - 1);
7277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Addu(sp, sp, t0);
7287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Addu(sp, sp, kPointerSize);
7297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ IncrementCounter(isolate->counters()->constructed_objects(), 1, a1, a2);
7307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Ret();
7315c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
7325c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7335c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
735864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new);
7365c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
7375c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7385c838251403b0be9a882540f1922577abba4c872ager@chromium.org
7397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
740864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Generate_JSConstructStubHelper(masm, true, false);
7417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org}
7427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7437304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7447304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgstatic void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
7457304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                                             bool is_construct) {
7467304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Called from JSEntryStub::GenerateBody
7477304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7487304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // ----------- S t a t e -------------
7497304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- a0: code entry
7507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- a1: function
7512efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  //  -- a2: receiver_pointer
7527304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- a3: argc
7537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- s0: argv
7547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // -----------------------------------
75507237aaaed914a17c1afd64234883bff619581d5palfia@homejinni.com  ProfileEntryHookStub::MaybeCallEntryHook(masm);
7567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Clear the context before we push it when entering the JS frame.
7587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ mov(cp, zero_reg);
7597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7607304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Enter an internal frame.
761c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {
762c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    FrameScope scope(masm, StackFrame::INTERNAL);
7637304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
764c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Set up the context from the function argument.
765c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
7667304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
767c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Push the function and the receiver onto the stack.
768c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Push(a1, a2);
7697304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
770c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Copy arguments to the stack in a loop.
771c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // a3: argc
7722efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    // s0: argv, i.e. points to first arg
773c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label loop, entry;
774c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ sll(t0, a3, kPointerSizeLog2);
775c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ addu(t2, s0, t0);
776c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ b(&entry);
777c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ nop();   // Branch delay slot nop.
778c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // t2 points past last arg.
779c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&loop);
780c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ lw(t0, MemOperand(s0));  // Read next parameter.
781c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ addiu(s0, s0, kPointerSize);
782c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ lw(t0, MemOperand(t0));  // Dereference handle.
783c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(t0);  // Push parameter.
784c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&entry);
785c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Branch(&loop, ne, s0, Operand(t2));
786c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
787c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Initialize all JavaScript callee-saved registers, since they will be seen
788c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // by the garbage collector as part of handlers.
789c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ LoadRoot(t0, Heap::kUndefinedValueRootIndex);
790c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ mov(s1, t0);
791c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ mov(s2, t0);
792c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ mov(s3, t0);
793c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ mov(s4, t0);
794c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ mov(s5, t0);
795c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // s6 holds the root address. Do not clobber.
796c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // s7 is cp. Do not init.
797c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
798c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Invoke the code and pass argc as a0.
799c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ mov(a0, a3);
800c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (is_construct) {
801750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org      // No type feedback cell is available
80269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
80326ff407a06ed21bb3a1d7d147a6c0c092a2dff6dpalfia@homejinni.com      CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
804fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org      __ CallStub(&stub);
805c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    } else {
806c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ParameterCount actual(a0);
807e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org      __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
808c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
8097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
810c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Leave internal frame.
811c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
8127304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
8137304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Jump(ra);
8145c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
8155c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8165c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8175c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
8187304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Generate_JSEntryTrampolineHelper(masm, false);
8195c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
8205c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8215c838251403b0be9a882540f1922577abba4c872ager@chromium.org
8225c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
8237304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Generate_JSEntryTrampolineHelper(masm, true);
8247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
8257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
827a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.orgvoid Builtins::Generate_CompileLazy(MacroAssembler* masm) {
828a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  CallRuntimePassFunction(masm, Runtime::kCompileLazy);
8294954674151afa960af66efb4831df06bde727333yangguo@chromium.org  GenerateTailCallToReturnedCode(masm);
8307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
8317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
833e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.orgstatic void CallCompileOptimized(MacroAssembler* masm, bool concurrent) {
8344954674151afa960af66efb4831df06bde727333yangguo@chromium.org  FrameScope scope(masm, StackFrame::INTERNAL);
8354954674151afa960af66efb4831df06bde727333yangguo@chromium.org  // Push a copy of the function onto the stack.
836e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  // Push function as parameter to the runtime call.
837e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  __ Push(a1, a1);
8384954674151afa960af66efb4831df06bde727333yangguo@chromium.org  // Whether to compile in a background thread.
8394954674151afa960af66efb4831df06bde727333yangguo@chromium.org  __ Push(masm->isolate()->factory()->ToBoolean(concurrent));
8404954674151afa960af66efb4831df06bde727333yangguo@chromium.org
84147390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org  __ CallRuntime(Runtime::kCompileOptimized, 2);
842e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  // Restore receiver.
843e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  __ Pop(a1);
8444954674151afa960af66efb4831df06bde727333yangguo@chromium.org}
8454954674151afa960af66efb4831df06bde727333yangguo@chromium.org
8464954674151afa960af66efb4831df06bde727333yangguo@chromium.org
8474954674151afa960af66efb4831df06bde727333yangguo@chromium.orgvoid Builtins::Generate_CompileOptimized(MacroAssembler* masm) {
8484954674151afa960af66efb4831df06bde727333yangguo@chromium.org  CallCompileOptimized(masm, false);
8494954674151afa960af66efb4831df06bde727333yangguo@chromium.org  GenerateTailCallToReturnedCode(masm);
8504954674151afa960af66efb4831df06bde727333yangguo@chromium.org}
8514954674151afa960af66efb4831df06bde727333yangguo@chromium.org
8524954674151afa960af66efb4831df06bde727333yangguo@chromium.org
8534954674151afa960af66efb4831df06bde727333yangguo@chromium.orgvoid Builtins::Generate_CompileOptimizedConcurrent(MacroAssembler* masm) {
8544954674151afa960af66efb4831df06bde727333yangguo@chromium.org  CallCompileOptimized(masm, true);
8554954674151afa960af66efb4831df06bde727333yangguo@chromium.org  GenerateTailCallToReturnedCode(masm);
8567516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
8577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8594954674151afa960af66efb4831df06bde727333yangguo@chromium.org
860fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgstatic void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) {
861fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // For now, we are relying on the fact that make_code_young doesn't do any
862fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // garbage collection which allows us to save/restore the registers without
863fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // worrying about which of them contain pointers. We also don't build an
864fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // internal frame to make the code faster, since we shouldn't have to do stack
865fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // crawls in MakeCodeYoung. This seems a bit fragile.
866fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
867f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  // Set a0 to point to the head of the PlatformCodeAge sequence.
868fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ Subu(a0, a0,
8695924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org      Operand(kNoCodeAgeSequenceLength - Assembler::kInstrSize));
870fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
871fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // The following registers must be saved and restored when calling through to
872fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // the runtime:
873fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  //   a0 - contains return address (beginning of patch sequence)
874528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  //   a1 - isolate
875fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  RegList saved_regs =
876fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      (a0.bit() | a1.bit() | ra.bit() | fp.bit()) & ~sp.bit();
877fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  FrameScope scope(masm, StackFrame::MANUAL);
878fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ MultiPush(saved_regs);
879ea9b8ba58955b7efcc3e1550dd33a44fb4530136hpayer@chromium.org  __ PrepareCallCFunction(2, 0, a2);
880528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ li(a1, Operand(ExternalReference::isolate_address(masm->isolate())));
881fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ CallCFunction(
882528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org      ExternalReference::get_make_code_young_function(masm->isolate()), 2);
883fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ MultiPop(saved_regs);
884fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ Jump(a0);
885fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org}
886fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
887fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org#define DEFINE_CODE_AGE_BUILTIN_GENERATOR(C)                 \
888fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgvoid Builtins::Generate_Make##C##CodeYoungAgainEvenMarking(  \
889fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    MacroAssembler* masm) {                                  \
890fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  GenerateMakeCodeYoungAgainCommon(masm);                    \
891fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org}                                                            \
892fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgvoid Builtins::Generate_Make##C##CodeYoungAgainOddMarking(   \
893fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    MacroAssembler* masm) {                                  \
894fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  GenerateMakeCodeYoungAgainCommon(masm);                    \
895fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org}
896fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgCODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR)
897fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org#undef DEFINE_CODE_AGE_BUILTIN_GENERATOR
898fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
899fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
900c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.orgvoid Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) {
901c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // For now, as in GenerateMakeCodeYoungAgainCommon, we are relying on the fact
902c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // that make_code_young doesn't do any garbage collection which allows us to
903c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // save/restore the registers without worrying about which of them contain
904c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // pointers.
905c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
906f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  // Set a0 to point to the head of the PlatformCodeAge sequence.
907c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ Subu(a0, a0,
9085924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org      Operand(kNoCodeAgeSequenceLength - Assembler::kInstrSize));
909c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
910c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // The following registers must be saved and restored when calling through to
911c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // the runtime:
912c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  //   a0 - contains return address (beginning of patch sequence)
913c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  //   a1 - isolate
914c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  RegList saved_regs =
915c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org      (a0.bit() | a1.bit() | ra.bit() | fp.bit()) & ~sp.bit();
916c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  FrameScope scope(masm, StackFrame::MANUAL);
917c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ MultiPush(saved_regs);
918ea9b8ba58955b7efcc3e1550dd33a44fb4530136hpayer@chromium.org  __ PrepareCallCFunction(2, 0, a2);
919c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ li(a1, Operand(ExternalReference::isolate_address(masm->isolate())));
920c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ CallCFunction(
921c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org      ExternalReference::get_mark_code_as_executed_function(masm->isolate()),
922c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org      2);
923c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ MultiPop(saved_regs);
924c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
925c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // Perform prologue operations usually performed by the young code stub.
926c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ Push(ra, fp, cp, a1);
9277ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ Addu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
928c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
929c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // Jump to point after the code-age stub.
9305924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org  __ Addu(a0, a0, Operand(kNoCodeAgeSequenceLength));
931c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ Jump(a0);
932c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org}
933c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
934c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
935c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.orgvoid Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) {
936c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  GenerateMakeCodeYoungAgainCommon(masm);
937c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org}
938c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
939c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
940f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgstatic void Generate_NotifyStubFailureHelper(MacroAssembler* masm,
941f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                             SaveFPRegsMode save_doubles) {
94259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  {
94359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
94459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
94559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    // Preserve registers across notification, this is important for compiled
94659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    // stubs that tail call the runtime on deopts passing their parameters in
94759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    // registers.
94859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ MultiPush(kJSCallerSaved | kCalleeSaved);
94959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    // Pass the function and deoptimization type to the runtime system.
95047390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org    __ CallRuntime(Runtime::kNotifyStubFailure, 0, save_doubles);
95159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ MultiPop(kJSCallerSaved | kCalleeSaved);
95259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  }
95359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
95459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ Addu(sp, sp, Operand(kPointerSize));  // Ignore state
955e3b8d0fe80e858c990832db1233c069f8b8cd5c9mstarzinger@chromium.org  __ Jump(ra);  // Jump to miss handler
95659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org}
95759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
95859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
959f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgvoid Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) {
960f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Generate_NotifyStubFailureHelper(masm, kDontSaveFPRegs);
961f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org}
962f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org
963f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org
964f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgvoid Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) {
965f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Generate_NotifyStubFailureHelper(masm, kSaveFPRegs);
966f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org}
967f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org
968f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org
969c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgstatic void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
970c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                             Deoptimizer::BailoutType type) {
971c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  {
972c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
973c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    // Pass the function and deoptimization type to the runtime system.
974c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    __ li(a0, Operand(Smi::FromInt(static_cast<int>(type))));
975c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    __ push(a0);
97647390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org    __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
977c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  }
978c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
979c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // Get the full codegen state from the stack and untag it -> t2.
980c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ lw(t2, MemOperand(sp, 0 * kPointerSize));
981c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ SmiUntag(t2);
982c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // Switch on the state.
983c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Label with_tos_register, unknown_state;
984c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ Branch(&with_tos_register,
985c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org            ne, t2, Operand(FullCodeGenerator::NO_REGISTERS));
9868a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ Ret(USE_DELAY_SLOT);
9878a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  // Safe to fill delay slot Addu will emit one instruction.
988c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ Addu(sp, sp, Operand(1 * kPointerSize));  // Remove state.
989c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
990c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ bind(&with_tos_register);
991c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ lw(v0, MemOperand(sp, 1 * kPointerSize));
992c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ Branch(&unknown_state, ne, t2, Operand(FullCodeGenerator::TOS_REG));
993c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
9948a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  __ Ret(USE_DELAY_SLOT);
9958a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  // Safe to fill delay slot Addu will emit one instruction.
996c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ Addu(sp, sp, Operand(2 * kPointerSize));  // Remove state.
997c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
998c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ bind(&unknown_state);
999c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ stop("no cases left");
1000c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org}
1001c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
1002c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
10037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
1004c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
10057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
10067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10080410973aac1fa3a7aa16285ba799f531983bc916palfia@homejinni.comvoid Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) {
10090410973aac1fa3a7aa16285ba799f531983bc916palfia@homejinni.com  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
10100410973aac1fa3a7aa16285ba799f531983bc916palfia@homejinni.com}
10110410973aac1fa3a7aa16285ba799f531983bc916palfia@homejinni.com
10120410973aac1fa3a7aa16285ba799f531983bc916palfia@homejinni.com
10137516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
1014c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
10157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
10167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1019e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org  // Lookup the function in the JavaScript frame.
1020c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ lw(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1021c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  {
1022c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
1023afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org    // Pass function as argument.
1024c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    __ push(a0);
1025afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org    __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
1026c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  }
1027c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
1028c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // If the code object is null, just return to the unoptimized code.
1029c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ Ret(eq, v0, Operand(Smi::FromInt(0)));
1030c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
1031c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // Load deoptimization data from the code object.
1032c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // <deopt_data> = <code>[#deoptimization_data_offset]
1033c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ lw(a1, MemOperand(v0, Code::kDeoptimizationDataOffset - kHeapObjectTag));
1034c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
1035c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // Load the OSR entrypoint offset from the deoptimization data.
1036c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // <osr_offset> = <deopt_data>[#header_size + #osr_pc_offset]
1037c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ lw(a1, MemOperand(a1, FixedArray::OffsetOfElementAt(
1038c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org      DeoptimizationInputData::kOsrPcOffsetIndex) - kHeapObjectTag));
1039c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ SmiUntag(a1);
1040c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
1041c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // Compute the target address = code_obj + header_size + osr_offset
1042c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // <entry_addr> = <code_obj> + #header_size + <osr_offset>
1043c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ addu(v0, v0, a1);
1044c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ addiu(ra, v0, Code::kHeaderSize - kHeapObjectTag);
1045c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
1046c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // And "return" to the OSR entry point of the function.
1047c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ Ret();
10485c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
10495c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10505c838251403b0be9a882540f1922577abba4c872ager@chromium.org
10518e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.orgvoid Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) {
10528e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  // We check the stack limit as indicator that recompilation might be done.
10538e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  Label ok;
10548e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  __ LoadRoot(at, Heap::kStackLimitRootIndex);
10558e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  __ Branch(&ok, hs, sp, Operand(at));
10568e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  {
10578e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
105847390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org    __ CallRuntime(Runtime::kStackGuard, 0);
10598e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  }
10608e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  __ Jump(masm->isolate()->builtins()->OnStackReplacement(),
10618e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org          RelocInfo::CODE_TARGET);
10628e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org
10638e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  __ bind(&ok);
10648e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  __ Ret();
10658e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org}
10668e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org
10678e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org
10685c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Builtins::Generate_FunctionCall(MacroAssembler* masm) {
10697304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // 1. Make sure we have at least one argument.
10707304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // a0: actual number of arguments
10717304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  { Label done;
10727304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ Branch(&done, ne, a0, Operand(zero_reg));
10737304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ LoadRoot(t2, Heap::kUndefinedValueRootIndex);
10747304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ push(t2);
10757304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ Addu(a0, a0, Operand(1));
10767304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ bind(&done);
10777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
10787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
10797304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // 2. Get the function to call (passed as receiver) from the stack, check
10807304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //    if it is a function.
10817304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // a0: actual number of arguments
1082c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label slow, non_function;
10837304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ sll(at, a0, kPointerSizeLog2);
10847304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ addu(at, sp, at);
10857304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ lw(a1, MemOperand(at));
1086c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ JumpIfSmi(a1, &non_function);
10877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ GetObjectType(a1, a2, a2);
1088c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ Branch(&slow, ne, a2, Operand(JS_FUNCTION_TYPE));
10897304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
10907304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // 3a. Patch the first argument if necessary when calling a function.
10917304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // a0: actual number of arguments
10927304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // a1: function
10937304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Label shift_arguments;
109459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ li(t0, Operand(0, RelocInfo::NONE32));  // Indicate regular JS_FUNCTION.
1095f6e8ed2294f2eccae83564eead8b79ea050b9f21yangguo@chromium.org  { Label convert_to_object, use_global_proxy, patch_receiver;
10967304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // Change context eagerly in case we need the global receiver.
10977304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
10987304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
10997304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // Do not transform the receiver for strict mode functions.
11007304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
11017304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ lw(a3, FieldMemOperand(a2, SharedFunctionInfo::kCompilerHintsOffset));
1102c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ And(t3, a3, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
11037304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                                 kSmiTagSize)));
1104c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Branch(&shift_arguments, ne, t3, Operand(zero_reg));
11057304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
110640cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    // Do not transform the receiver for native (Compilerhints already in a3).
1107c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ And(t3, a3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
1108c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Branch(&shift_arguments, ne, t3, Operand(zero_reg));
11097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1110486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    // Compute the receiver in sloppy mode.
11117304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // Load first argument in a2. a2 = -kPointerSize(sp + n_args << 2).
11127304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ sll(at, a0, kPointerSizeLog2);
11137304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ addu(a2, sp, at);
11147304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ lw(a2, MemOperand(a2, -kPointerSize));
11157304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a0: actual number of arguments
11167304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a1: function
11177304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a2: first argument
11187304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ JumpIfSmi(a2, &convert_to_object, t2);
11197304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
112040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    __ LoadRoot(a3, Heap::kUndefinedValueRootIndex);
1121f6e8ed2294f2eccae83564eead8b79ea050b9f21yangguo@chromium.org    __ Branch(&use_global_proxy, eq, a2, Operand(a3));
11227304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ LoadRoot(a3, Heap::kNullValueRootIndex);
1123f6e8ed2294f2eccae83564eead8b79ea050b9f21yangguo@chromium.org    __ Branch(&use_global_proxy, eq, a2, Operand(a3));
11247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1125d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
11267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ GetObjectType(a2, a3, a3);
1127d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com    __ Branch(&shift_arguments, ge, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
11287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
11297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ bind(&convert_to_object);
1130c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Enter an internal frame in order to preserve argument count.
1131c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    {
1132c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      FrameScope scope(masm, StackFrame::INTERNAL);
1133c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ sll(a0, a0, kSmiTagSize);  // Smi tagged.
11346f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org      __ Push(a0, a2);
1135c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1136c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ mov(a2, v0);
1137c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1138c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ pop(a0);
1139c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ sra(a0, a0, kSmiTagSize);  // Un-tag.
1140c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Leave internal frame.
1141c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
1142f6e8ed2294f2eccae83564eead8b79ea050b9f21yangguo@chromium.org
1143c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Restore the function to a1, and the flag to t0.
11447304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ sll(at, a0, kPointerSizeLog2);
11457304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ addu(at, sp, at);
11467304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ lw(a1, MemOperand(at));
1147f6e8ed2294f2eccae83564eead8b79ea050b9f21yangguo@chromium.org    __ Branch(USE_DELAY_SLOT, &patch_receiver);
1148f6e8ed2294f2eccae83564eead8b79ea050b9f21yangguo@chromium.org    __ li(t0, Operand(0, RelocInfo::NONE32));  // In delay slot.
11497304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1150f6e8ed2294f2eccae83564eead8b79ea050b9f21yangguo@chromium.org    __ bind(&use_global_proxy);
11519cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org    __ lw(a2, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
1152f6e8ed2294f2eccae83564eead8b79ea050b9f21yangguo@chromium.org    __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalProxyOffset));
11537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
11547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ bind(&patch_receiver);
11557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ sll(at, a0, kPointerSizeLog2);
11567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ addu(a3, sp, at);
11577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ sw(a2, MemOperand(a3, -kPointerSize));
11587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
11597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ Branch(&shift_arguments);
11607304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
11617304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1162c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // 3b. Check for function proxy.
1163c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ bind(&slow);
116459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ li(t0, Operand(1, RelocInfo::NONE32));  // Indicate function proxy.
1165c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ Branch(&shift_arguments, eq, a2, Operand(JS_FUNCTION_PROXY_TYPE));
1166c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1167c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ bind(&non_function);
116859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ li(t0, Operand(2, RelocInfo::NONE32));  // Indicate non-function.
1169c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1170c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // 3c. Patch the first argument when calling a non-function.  The
11717304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //     CALL_NON_FUNCTION builtin expects the non-function callee as
11727304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //     receiver, so overwrite the first argument which will ultimately
11737304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //     become the receiver.
11747304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // a0: actual number of arguments
11757304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // a1: function
1176c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // t0: call type (0: JS function, 1: function proxy, 2: non-function)
11777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ sll(at, a0, kPointerSizeLog2);
11787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ addu(a2, sp, at);
11797304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ sw(a1, MemOperand(a2, -kPointerSize));
11807304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
11817304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // 4. Shift arguments and return address one slot down on the stack
11827304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //    (overwriting the original receiver).  Adjust argument count to make
11837304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //    the original first argument the new receiver.
11847304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // a0: actual number of arguments
11857304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // a1: function
1186c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // t0: call type (0: JS function, 1: function proxy, 2: non-function)
11877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ bind(&shift_arguments);
11887304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  { Label loop;
11897304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // Calculate the copy start address (destination). Copy end address is sp.
11907304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ sll(at, a0, kPointerSizeLog2);
11917304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ addu(a2, sp, at);
11927304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
11937304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ bind(&loop);
11947304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ lw(at, MemOperand(a2, -kPointerSize));
11957304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ sw(at, MemOperand(a2));
11967304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ Subu(a2, a2, Operand(kPointerSize));
11977304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ Branch(&loop, ne, a2, Operand(sp));
11987304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // Adjust the actual number of arguments and remove the top element
11997304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // (which is a copy of the last argument).
12007304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ Subu(a0, a0, Operand(1));
12017304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ Pop();
12027304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
12037304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1204c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin,
1205c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  //     or a function proxy via CALL_FUNCTION_PROXY.
12067304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // a0: actual number of arguments
12077304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // a1: function
1208c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // t0: call type (0: JS function, 1: function proxy, 2: non-function)
1209c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  { Label function, non_proxy;
1210c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Branch(&function, eq, t0, Operand(zero_reg));
1211c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Expected number of arguments is 0 for CALL_NON_FUNCTION.
1212c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ mov(a2, zero_reg);
1213c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Branch(&non_proxy, ne, t0, Operand(1));
1214c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1215c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(a1);  // Re-add proxy object as additional argument.
1216c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Addu(a0, a0, Operand(1));
121726ca35cc4ec47151d9c6d3890b0f052fc79cb8afmachenbach@chromium.org    __ GetBuiltinFunction(a1, Builtins::CALL_FUNCTION_PROXY);
1218c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1219c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com            RelocInfo::CODE_TARGET);
1220c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1221c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&non_proxy);
122226ca35cc4ec47151d9c6d3890b0f052fc79cb8afmachenbach@chromium.org    __ GetBuiltinFunction(a1, Builtins::CALL_NON_FUNCTION);
12237304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
12247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org            RelocInfo::CODE_TARGET);
12257304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ bind(&function);
12267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
12277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
12287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // 5b. Get the code to call from the function and check that the number of
12297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //     expected arguments matches what we're providing.  If so, jump
12307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //     (tail-call) to the code in register edx without checking arguments.
12317304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // a0: actual number of arguments
12327304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // a1: function
12337304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ lw(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
12347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ lw(a2,
12357304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org         FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset));
12367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ sra(a2, a2, kSmiTagSize);
12377304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Check formal and actual parameter counts.
12387304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
12397304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org          RelocInfo::CODE_TARGET, ne, a2, Operand(a0));
12407304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
124126ca35cc4ec47151d9c6d3890b0f052fc79cb8afmachenbach@chromium.org  __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
12427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  ParameterCount expected(0);
1243e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  __ InvokeCode(a3, expected, expected, JUMP_FUNCTION, NullCallWrapper());
12445c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
12455c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12465c838251403b0be9a882540f1922577abba4c872ager@chromium.org
12475c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Builtins::Generate_FunctionApply(MacroAssembler* masm) {
12487ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  const int kIndexOffset    =
12497ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org      StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize);
12507ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  const int kLimitOffset    =
12517ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org      StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize);
12527ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  const int kArgsOffset     = 2 * kPointerSize;
12537ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  const int kRecvOffset     = 3 * kPointerSize;
12547ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  const int kFunctionOffset = 4 * kPointerSize;
12557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1256c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {
1257c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    FrameScope frame_scope(masm, StackFrame::INTERNAL);
1258c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ lw(a0, MemOperand(fp, kFunctionOffset));  // Get the function.
1259c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(a0);
1260c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ lw(a0, MemOperand(fp, kArgsOffset));  // Get the args array.
1261c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(a0);
1262c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Returns (in v0) number of arguments to copy to stack as Smi.
1263c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
1264c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1265c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Check the stack for overflow. We are not trying to catch
1266c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // interruptions (e.g. debug break and preemption) here, so the "real stack
1267c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // limit" is checked.
1268c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label okay;
1269c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ LoadRoot(a2, Heap::kRealStackLimitRootIndex);
1270c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Make a2 the space we have left. The stack might already be overflowed
1271c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // here which will cause a2 to become negative.
1272c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ subu(a2, sp, a2);
1273c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Check if the arguments will overflow the stack.
1274c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ sll(t3, v0, kPointerSizeLog2 - kSmiTagSize);
1275c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Branch(&okay, gt, a2, Operand(t3));  // Signed comparison.
1276c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1277c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Out of stack space.
1278c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ lw(a1, MemOperand(fp, kFunctionOffset));
1279057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org    __ Push(a1, v0);
1280e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1281c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // End of stack check.
1282c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1283c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Push current limit and index.
1284c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&okay);
12856f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org    __ mov(a1, zero_reg);
12866f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org    __ Push(v0, a1);  // Limit and initial index.
12877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1288c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Get the receiver.
1289c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ lw(a0, MemOperand(fp, kRecvOffset));
12907304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1291c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Check that the function is a JS function (otherwise it must be a proxy).
1292c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label push_receiver;
1293c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ lw(a1, MemOperand(fp, kFunctionOffset));
1294c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ GetObjectType(a1, a2, a2);
1295c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Branch(&push_receiver, ne, a2, Operand(JS_FUNCTION_TYPE));
12967304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1297c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Change context eagerly to get the right global object if necessary.
1298c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
1299c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Load the shared function info while the function is still in a1.
1300c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
13017304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1302c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Compute the receiver.
1303c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Do not transform the receiver for strict mode functions.
1304f6e8ed2294f2eccae83564eead8b79ea050b9f21yangguo@chromium.org    Label call_to_object, use_global_proxy;
1305c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kCompilerHintsOffset));
1306c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ And(t3, a2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
1307c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                 kSmiTagSize)));
1308c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Branch(&push_receiver, ne, t3, Operand(zero_reg));
1309c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1310c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Do not transform the receiver for native (Compilerhints already in a2).
1311c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ And(t3, a2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
1312c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Branch(&push_receiver, ne, t3, Operand(zero_reg));
1313c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1314486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    // Compute the receiver in sloppy mode.
1315c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    __ JumpIfSmi(a0, &call_to_object);
1316c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ LoadRoot(a1, Heap::kNullValueRootIndex);
1317f6e8ed2294f2eccae83564eead8b79ea050b9f21yangguo@chromium.org    __ Branch(&use_global_proxy, eq, a0, Operand(a1));
1318c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
1319f6e8ed2294f2eccae83564eead8b79ea050b9f21yangguo@chromium.org    __ Branch(&use_global_proxy, eq, a0, Operand(a2));
1320c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1321c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Check if the receiver is already a JavaScript object.
1322c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // a0: receiver
1323c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1324c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ GetObjectType(a0, a1, a1);
1325c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Branch(&push_receiver, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
1326c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1327c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Convert the receiver to a regular object.
1328c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // a0: receiver
1329c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&call_to_object);
1330c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(a0);
1331c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1332c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ mov(a0, v0);  // Put object in a0 to match other paths to push_receiver.
1333c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Branch(&push_receiver);
1334c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1335f6e8ed2294f2eccae83564eead8b79ea050b9f21yangguo@chromium.org    __ bind(&use_global_proxy);
13369cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org    __ lw(a0, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
1337f6e8ed2294f2eccae83564eead8b79ea050b9f21yangguo@chromium.org    __ lw(a0, FieldMemOperand(a0, GlobalObject::kGlobalProxyOffset));
1338c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1339c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Push the receiver.
1340c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // a0: receiver
1341c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&push_receiver);
1342c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(a0);
1343c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1344c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Copy all arguments from the array to the stack.
1345c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label entry, loop;
1346c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ lw(a0, MemOperand(fp, kIndexOffset));
1347c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Branch(&entry);
1348c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1349c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Load the current argument from the arguments array and push it to the
1350c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // stack.
1351c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // a0: current argument index
1352c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&loop);
1353c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ lw(a1, MemOperand(fp, kArgsOffset));
1354057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org    __ Push(a1, a0);
1355c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1356c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Call the runtime to access the property in the arguments array.
1357c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CallRuntime(Runtime::kGetProperty, 2);
1358c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(v0);
1359c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1360c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Use inline caching to access the arguments.
1361c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ lw(a0, MemOperand(fp, kIndexOffset));
1362c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Addu(a0, a0, Operand(1 << kSmiTagSize));
1363c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ sw(a0, MemOperand(fp, kIndexOffset));
1364c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1365c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Test if the copy loop has finished copying all the elements from the
1366c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // arguments object.
1367c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&entry);
1368c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ lw(a1, MemOperand(fp, kLimitOffset));
1369c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Branch(&loop, ne, a0, Operand(a1));
1370c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1371e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org    // Call the function.
1372c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label call_proxy;
1373c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ParameterCount actual(a0);
1374c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ sra(a0, a0, kSmiTagSize);
1375c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ lw(a1, MemOperand(fp, kFunctionOffset));
1376c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ GetObjectType(a1, a2, a2);
1377c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Branch(&call_proxy, ne, a2, Operand(JS_FUNCTION_TYPE));
1378c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1379e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org    __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
1380c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1381c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    frame_scope.GenerateLeaveFrame();
1382c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Ret(USE_DELAY_SLOT);
1383c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Addu(sp, sp, Operand(3 * kPointerSize));  // In delay slot.
1384c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1385e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org    // Call the function proxy.
1386c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&call_proxy);
1387c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(a1);  // Add function proxy as last argument.
1388c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Addu(a0, a0, Operand(1));
138959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ li(a2, Operand(0, RelocInfo::NONE32));
139026ca35cc4ec47151d9c6d3890b0f052fc79cb8afmachenbach@chromium.org    __ GetBuiltinFunction(a1, Builtins::CALL_FUNCTION_PROXY);
1391c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1392c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com            RelocInfo::CODE_TARGET);
1393c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Tear down the internal frame and remove function, receiver and args.
1394c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
1395c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1396c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ Ret(USE_DELAY_SLOT);
1397c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ Addu(sp, sp, Operand(3 * kPointerSize));  // In delay slot.
13987304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org}
13997304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
14007304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1401731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.orgstatic void ArgumentAdaptorStackCheck(MacroAssembler* masm,
1402731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org                                      Label* stack_overflow) {
1403731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  // ----------- S t a t e -------------
1404731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  //  -- a0 : actual number of arguments
1405731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  //  -- a1 : function (passed through to callee)
1406731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  //  -- a2 : expected number of arguments
1407731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  // -----------------------------------
1408731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  // Check the stack for overflow. We are not trying to catch
1409731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  // interruptions (e.g. debug break and preemption) here, so the "real stack
1410731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  // limit" is checked.
1411731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  __ LoadRoot(t1, Heap::kRealStackLimitRootIndex);
1412731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  // Make t1 the space we have left. The stack might already be overflowed
1413731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  // here which will cause t1 to become negative.
1414731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  __ subu(t1, sp, t1);
1415731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  // Check if the arguments will overflow the stack.
1416731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  __ sll(at, a2, kPointerSizeLog2);
1417731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  // Signed comparison.
1418731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  __ Branch(stack_overflow, le, t1, Operand(at));
1419731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org}
1420731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org
1421731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org
14227304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgstatic void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
14237304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ sll(a0, a0, kSmiTagSize);
14247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ li(t0, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
14257304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ MultiPush(a0.bit() | a1.bit() | t0.bit() | fp.bit() | ra.bit());
14267ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ Addu(fp, sp,
14277ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org      Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize));
14287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org}
14297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
14307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
14317304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgstatic void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
14327304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // ----------- S t a t e -------------
14337304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- v0 : result being passed through
14347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // -----------------------------------
14357304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Get the number of arguments passed (as a smi), tear down the frame and
14367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // then tear down the parameters.
14377ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ lw(a1, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp +
14387ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org                             kPointerSize)));
14397304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ mov(sp, fp);
14407304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ MultiPop(fp.bit() | ra.bit());
14417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ sll(t0, a1, kPointerSizeLog2 - kSmiTagSize);
14427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Addu(sp, sp, t0);
14437304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Adjust for the receiver.
14447304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Addu(sp, sp, Operand(kPointerSize));
14455c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
14465c838251403b0be9a882540f1922577abba4c872ager@chromium.org
14475c838251403b0be9a882540f1922577abba4c872ager@chromium.org
14485c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
14497304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // State setup as expected by MacroAssembler::InvokePrologue.
14507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // ----------- S t a t e -------------
14517304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- a0: actual arguments count
14527304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- a1: function (passed through to callee)
14537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  //  -- a2: expected arguments count
14547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // -----------------------------------
14557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1456731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  Label stack_overflow;
1457731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  ArgumentAdaptorStackCheck(masm, &stack_overflow);
14587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Label invoke, dont_adapt_arguments;
14597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
14607304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Label enough, too_few;
146126ca35cc4ec47151d9c6d3890b0f052fc79cb8afmachenbach@chromium.org  __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
14627304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Branch(&dont_adapt_arguments, eq,
14637304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      a2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
14647304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // We use Uless as the number of argument should always be greater than 0.
14657304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Branch(&too_few, Uless, a0, Operand(a2));
14667304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
14677304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  {  // Enough parameters: actual >= expected.
14687304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a0: actual number of arguments as a smi
14697304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a1: function
14707304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a2: expected number of arguments
14717304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a3: code entry to call
14727304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ bind(&enough);
14737304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    EnterArgumentsAdaptorFrame(masm);
14747304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
14757304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // Calculate copy start address into a0 and copy end address into a2.
14767304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ sll(a0, a0, kPointerSizeLog2 - kSmiTagSize);
14777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ Addu(a0, fp, a0);
14787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // Adjust for return address and receiver.
14797304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ Addu(a0, a0, Operand(2 * kPointerSize));
14807304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // Compute copy end address.
14817304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ sll(a2, a2, kPointerSizeLog2);
14827304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ subu(a2, a0, a2);
14837304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
14847304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // Copy the arguments (including the receiver) to the new stack frame.
14857304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a0: copy start address
14867304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a1: function
14877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a2: copy end address
14887304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a3: code entry to call
14897304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
14907304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Label copy;
14917304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ bind(&copy);
14927304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ lw(t0, MemOperand(a0));
14937304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ push(t0);
14947304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ Branch(USE_DELAY_SLOT, &copy, ne, a0, Operand(a2));
14957304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ addiu(a0, a0, -kPointerSize);  // In delay slot.
14967304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
14977304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ jmp(&invoke);
14987304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
14997304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
15007304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  {  // Too few parameters: Actual < expected.
15017304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ bind(&too_few);
15027304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    EnterArgumentsAdaptorFrame(masm);
15037304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
15047304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // Calculate copy start address into a0 and copy end address is fp.
15057304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a0: actual number of arguments as a smi
15067304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a1: function
15077304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a2: expected number of arguments
15087304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a3: code entry to call
15097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ sll(a0, a0, kPointerSizeLog2 - kSmiTagSize);
15107304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ Addu(a0, fp, a0);
15117304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // Adjust for return address and receiver.
15127304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ Addu(a0, a0, Operand(2 * kPointerSize));
15137304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // Compute copy end address. Also adjust for return address.
1514d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com    __ Addu(t3, fp, kPointerSize);
15157304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
15167304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // Copy the arguments (including the receiver) to the new stack frame.
15177304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a0: copy start address
15187304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a1: function
15197304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a2: expected number of arguments
15207304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a3: code entry to call
1521d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com    // t3: copy end address
15227304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Label copy;
15237304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ bind(&copy);
15247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ lw(t0, MemOperand(a0));  // Adjusted above for return addr and receiver.
1525bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    __ Subu(sp, sp, kPointerSize);
15267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ Subu(a0, a0, kPointerSize);
1527bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    __ Branch(USE_DELAY_SLOT, &copy, ne, a0, Operand(t3));
1528bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    __ sw(t0, MemOperand(sp));  // In the delay slot.
15297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
15307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // Fill the remaining expected arguments with undefined.
15317304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a1: function
15327304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a2: expected number of arguments
15337304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // a3: code entry to call
15347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ LoadRoot(t0, Heap::kUndefinedValueRootIndex);
15357304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ sll(t2, a2, kPointerSizeLog2);
15367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ Subu(a2, fp, Operand(t2));
15377ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org    // Adjust for frame.
15387ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org    __ Subu(a2, a2, Operand(StandardFrameConstants::kFixedFrameSizeFromFp +
15397ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org                            2 * kPointerSize));
15407304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
15417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Label fill;
15427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ bind(&fill);
1543bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    __ Subu(sp, sp, kPointerSize);
1544bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    __ Branch(USE_DELAY_SLOT, &fill, ne, sp, Operand(a2));
1545bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    __ sw(t0, MemOperand(sp));
15467304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
15477304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
15487304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Call the entry point.
15497304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ bind(&invoke);
15507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
15517304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Call(a3);
15527304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1553812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // Store offset of return address for deoptimizer.
1554fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
1555812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
15567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Exit frame and return.
15577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  LeaveArgumentsAdaptorFrame(masm);
15587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Ret();
15597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
15607304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
15617304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // -------------------------------------------
15627304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Don't adapt arguments.
15637304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // -------------------------------------------
15647304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ bind(&dont_adapt_arguments);
15657304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ Jump(a3);
1566731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org
1567731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  __ bind(&stack_overflow);
1568731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  {
1569731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org    FrameScope frame(masm, StackFrame::MANUAL);
1570731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org    EnterArgumentsAdaptorFrame(masm);
1571731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org    __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1572731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org    __ break_(0xCC);
1573731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  }
15745c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
15755c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15765c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15775c838251403b0be9a882540f1922577abba4c872ager@chromium.org#undef __
15785c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15795c838251403b0be9a882540f1922577abba4c872ager@chromium.org} }  // namespace v8::internal
15805c838251403b0be9a882540f1922577abba4c872ager@chromium.org
15819dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com#endif  // V8_TARGET_ARCH_MIPS
1582