1fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Redistribution and use in source and binary forms, with or without
343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// modification, are permitted provided that the following conditions are
443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// met:
543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//
643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//     * Redistributions of source code must retain the above copyright
743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       notice, this list of conditions and the following disclaimer.
843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//     * Redistributions in binary form must reproduce the above
943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       copyright notice, this list of conditions and the following
1043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       disclaimer in the documentation and/or other materials provided
1143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       with the distribution.
1243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//     * Neither the name of Google Inc. nor the names of its
1343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       contributors may be used to endorse or promote products derived
1443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       from this software without specific prior written permission.
1543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//
1643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "v8.h"
2943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3093a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_ARM
319dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org#include "codegen.h"
3343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "debug.h"
34a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#include "deoptimizer.h"
35a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#include "full-codegen.h"
3643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "runtime.h"
3743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3871affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace v8 {
3971affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace internal {
4043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4265dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org#define __ ACCESS_MASM(masm)
4343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
45b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid Builtins::Generate_Adaptor(MacroAssembler* masm,
46b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org                                CFunctionId id,
47b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org                                BuiltinExtraArguments extra_args) {
48b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // ----------- S t a t e -------------
49b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  //  -- r0                 : number of arguments excluding receiver
50b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  //  -- r1                 : called function (only guaranteed when
51b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  //                          extra_args requires it)
52b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  //  -- cp                 : context
53b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  //  -- sp[0]              : last argument
54b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  //  -- ...
55b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  //  -- sp[4 * (argc - 1)] : first argument (argc == r0)
56b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  //  -- sp[4 * argc]       : receiver
57b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // -----------------------------------
58b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
59b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Insert extra arguments.
60b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  int num_extra_args = 0;
61b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  if (extra_args == NEEDS_CALLED_FUNCTION) {
62b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    num_extra_args = 1;
63b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    __ push(r1);
64b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  } else {
65b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    ASSERT(extra_args == NO_EXTRA_ARGUMENTS);
66b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
67b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
68ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  // JumpToExternalReference expects r0 to contain the number of arguments
69b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // including the receiver and the extra arguments.
70b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  __ add(r0, r0, Operand(num_extra_args + 1));
71ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ JumpToExternalReference(ExternalReference(id, masm->isolate()));
72c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org}
73c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org
74c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org
753c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org// Load the built-in InternalArray function from the current context.
763c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.orgstatic void GenerateLoadInternalArrayFunction(MacroAssembler* masm,
773c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org                                              Register result) {
7846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Load the native context.
793c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org
803c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org  __ ldr(result,
8146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org         MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
8246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ ldr(result,
8346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org         FieldMemOperand(result, GlobalObject::kNativeContextOffset));
8446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Load the InternalArray function from the native context.
853c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org  __ ldr(result,
863c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org         MemOperand(result,
873c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org                    Context::SlotOffset(
883c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org                        Context::INTERNAL_ARRAY_FUNCTION_INDEX)));
893c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org}
903c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org
913c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org
92c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org// Load the built-in Array function from the current context.
93c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.orgstatic void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) {
9446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Load the native context.
95c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org
96c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  __ ldr(result,
9746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org         MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
9846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ ldr(result,
9946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org         FieldMemOperand(result, GlobalObject::kNativeContextOffset));
10046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Load the Array function from the native context.
101c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  __ ldr(result,
102c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org         MemOperand(result,
103c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org                    Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
104c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org}
105c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org
106c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org
1073c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.orgvoid Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
1083c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org  // ----------- S t a t e -------------
1093c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org  //  -- r0     : number of arguments
1103c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org  //  -- lr     : return address
1113c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org  //  -- sp[...]: constructor arguments
1123c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org  // -----------------------------------
1133c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org  Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
1143c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org
1153c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org  // Get the InternalArray function.
1163c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org  GenerateLoadInternalArrayFunction(masm, r1);
1173c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org
1183c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org  if (FLAG_debug_code) {
1193c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org    // Initial map for the builtin InternalArray functions should be maps.
1203c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org    __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
121bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org    __ SmiTst(r2);
122594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(ne, kUnexpectedInitialMapForInternalArrayFunction);
1233c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org    __ CompareObjectType(r2, r3, r4, MAP_TYPE);
124594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(eq, kUnexpectedInitialMapForInternalArrayFunction);
1253c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org  }
1263c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org
1273c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org  // Run the native code for the InternalArray function called as a normal
1283c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org  // function.
1291510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // tail call a stub
1301510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  InternalArrayConstructorStub stub(masm->isolate());
1311510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ TailCallStub(&stub);
1323c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org}
1333c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org
1343c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org
1352bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.comvoid Builtins::Generate_ArrayCode(MacroAssembler* masm) {
136c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // ----------- S t a t e -------------
137c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  //  -- r0     : number of arguments
138c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  //  -- lr     : return address
139c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  //  -- sp[...]: constructor arguments
140c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // -----------------------------------
141c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
142c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org
143c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // Get the Array function.
144c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  GenerateLoadArrayFunction(masm, r1);
145c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org
146c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  if (FLAG_debug_code) {
1478f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    // Initial map for the builtin Array functions should be maps.
148c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
149bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org    __ SmiTst(r2);
150594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(ne, kUnexpectedInitialMapForArrayFunction);
151c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    __ CompareObjectType(r2, r3, r4, MAP_TYPE);
152594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(eq, kUnexpectedInitialMapForArrayFunction);
153c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  }
154c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org
155c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // Run the native code for the Array function called as a normal function.
1561510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // tail call a stub
1571510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  Handle<Object> undefined_sentinel(
1581510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      masm->isolate()->heap()->undefined_value(),
1591510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      masm->isolate());
1601510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ mov(r2, Operand(undefined_sentinel));
1611510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  ArrayConstructorStub stub(masm->isolate());
1621510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ TailCallStub(&stub);
1632bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com}
1642bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com
1652bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com
166d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.orgvoid Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
167beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  // ----------- S t a t e -------------
168beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  //  -- r0                     : number of arguments
169beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  //  -- r1                     : constructor function
170beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  //  -- lr                     : return address
171beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
172beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  //  -- sp[argc * 4]           : receiver
173beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  // -----------------------------------
1747979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Counters* counters = masm->isolate()->counters();
1757979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_ctor_calls(), 1, r2, r3);
176beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org
177beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  Register function = r1;
178beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  if (FLAG_debug_code) {
179beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org    __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, r2);
180beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org    __ cmp(function, Operand(r2));
181594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(eq, kUnexpectedStringFunction);
182beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  }
183beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org
184beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  // Load the first arguments in r0 and get rid of the rest.
185beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  Label no_arguments;
18659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ cmp(r0, Operand::Zero());
187beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ b(eq, &no_arguments);
188beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  // First args = sp[(argc - 1) * 4].
189beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ sub(r0, r0, Operand(1));
190beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ ldr(r0, MemOperand(sp, r0, LSL, kPointerSizeLog2, PreIndex));
191beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  // sp now point to args[0], drop args[0] + receiver.
192beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ Drop(2);
193beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org
194beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  Register argument = r2;
195beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  Label not_cached, argument_is_string;
196528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ LookupNumberStringCache(r0,        // Input.
197528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                             argument,  // Result.
198528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                             r3,        // Scratch.
199528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                             r4,        // Scratch.
200528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                             r5,        // Scratch.
201528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                             &not_cached);
2027979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_ctor_cached_number(), 1, r3, r4);
203beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ bind(&argument_is_string);
204beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org
205beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  // ----------- S t a t e -------------
206beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  //  -- r2     : argument converted to string
207beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  //  -- r1     : constructor function
208beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  //  -- lr     : return address
209beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  // -----------------------------------
210beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org
211beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  Label gc_required;
2122bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  __ Allocate(JSValue::kSize,
2132bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org              r0,  // Result.
2142bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org              r3,  // Scratch.
2152bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org              r4,  // Scratch.
2162bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org              &gc_required,
2172bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org              TAG_OBJECT);
218beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org
219beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  // Initialising the String Object.
220beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  Register map = r3;
221beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ LoadGlobalFunctionInitialMap(function, map, r4);
222beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  if (FLAG_debug_code) {
223beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org    __ ldrb(r4, FieldMemOperand(map, Map::kInstanceSizeOffset));
224beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org    __ cmp(r4, Operand(JSValue::kSize >> kPointerSizeLog2));
225594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(eq, kUnexpectedStringWrapperInstanceSize);
226beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org    __ ldrb(r4, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset));
22759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ cmp(r4, Operand::Zero());
228594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(eq, kUnexpectedUnusedPropertiesOfStringWrapper);
229beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  }
230beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ str(map, FieldMemOperand(r0, HeapObject::kMapOffset));
231beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org
232beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex);
233beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset));
234beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset));
235beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org
236beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ str(argument, FieldMemOperand(r0, JSValue::kValueOffset));
237beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org
238beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  // Ensure the object is fully initialized.
239beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
240beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org
241beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ Ret();
242beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org
243beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  // The argument was not found in the number to string cache. Check
244beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  // if it's a string already before calling the conversion builtin.
245beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  Label convert_argument;
246beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ bind(&not_cached);
247378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ JumpIfSmi(r0, &convert_argument);
248beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org
249beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  // Is it a String?
250beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
251beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceTypeOffset));
25280c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  STATIC_ASSERT(kNotStringTag != 0);
253beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ tst(r3, Operand(kIsNotStringMask));
254beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ b(ne, &convert_argument);
255beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ mov(argument, r0);
2567979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4);
257beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ b(&argument_is_string);
258beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org
259beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  // Invoke the conversion builtin and put the result into r2.
260beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ bind(&convert_argument);
261beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ push(function);  // Preserve the function.
2627979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4);
263c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {
264c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    FrameScope scope(masm, StackFrame::INTERNAL);
265c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(r0);
266c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
267c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
268beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ pop(function);
269beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ mov(argument, r0);
270beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ b(&argument_is_string);
271beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org
272beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  // Load the empty string into r2, remove the receiver from the
273beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  // stack, and jump back to the case where the argument is a string.
274beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ bind(&no_arguments);
2754a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ LoadRoot(argument, Heap::kempty_stringRootIndex);
276beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ Drop(1);
277beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ b(&argument_is_string);
278beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org
279beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  // At this point the argument is already a string. Call runtime to
280beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  // create a string wrapper.
281beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ bind(&gc_required);
2827979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_ctor_gc_required(), 1, r3, r4);
283c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {
284c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    FrameScope scope(masm, StackFrame::INTERNAL);
285c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(argument);
286c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CallRuntime(Runtime::kNewStringWrapper, 1);
287c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
288beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org  __ Ret();
289d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org}
290d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
291d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
2924a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.orgstatic void CallRuntimePassFunction(MacroAssembler* masm,
2934a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org                                    Runtime::FunctionId function_id) {
2944a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  FrameScope scope(masm, StackFrame::INTERNAL);
2954a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  // Push a copy of the function onto the stack.
2964a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ push(r1);
297057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  // Push call kind information and function as parameter to the runtime call.
298057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org  __ Push(r5, r1);
2994a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org
3004a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ CallRuntime(function_id, 1);
3014a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  // Restore call kind information.
3024a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ pop(r5);
3034a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  // Restore receiver.
3044a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ pop(r1);
3054a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org}
3064a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org
3074a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org
308304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.orgstatic void GenerateTailCallToSharedCode(MacroAssembler* masm) {
309304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
310304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCodeOffset));
311304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  __ add(r2, r2, Operand(Code::kHeaderSize - kHeapObjectTag));
3124a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ Jump(r2);
313304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org}
314304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
315304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
316304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.orgvoid Builtins::Generate_InRecompileQueue(MacroAssembler* masm) {
3174a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  // Checking whether the queued function is ready for install is optional,
3184a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  // since we come across interrupts and stack checks elsewhere.  However,
3194a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  // not checking may delay installing ready functions, and always checking
3204a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  // would be quite expensive.  A good compromise is to first check against
3214a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  // stack limit as a cue for an interrupt signal.
3224a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  Label ok;
3234a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ LoadRoot(ip, Heap::kStackLimitRootIndex);
3244a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ cmp(sp, Operand(ip));
3254a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ b(hs, &ok);
3264a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org
3274a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  CallRuntimePassFunction(masm, Runtime::kTryInstallRecompiledCode);
3284a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  // Tail call to returned code.
3294a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ add(r0, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
3304a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ Jump(r0);
3314a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org
3324a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ bind(&ok);
333304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  GenerateTailCallToSharedCode(masm);
334304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org}
335304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
336304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
3379259716434187c932704601f700375e53d865de8rossberg@chromium.orgvoid Builtins::Generate_ConcurrentRecompile(MacroAssembler* masm) {
3384a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  CallRuntimePassFunction(masm, Runtime::kConcurrentRecompile);
339304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  GenerateTailCallToSharedCode(masm);
340304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org}
341304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
342304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
343fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.orgstatic void Generate_JSConstructStubHelper(MacroAssembler* masm,
344fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org                                           bool is_api_function,
345fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org                                           bool count_constructions) {
346b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  // ----------- S t a t e -------------
347b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  //  -- r0     : number of arguments
348b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  //  -- r1     : constructor function
349b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  //  -- lr     : return address
350b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  //  -- sp[...]: constructor arguments
351b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  // -----------------------------------
352b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
3534a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  // Should never count constructions for api objects.
3544a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  ASSERT(!is_api_function || !count_constructions);
3554a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
3567979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Isolate* isolate = masm->isolate();
3577979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
3587c537e2abe09729ed6cb827b4dd206470d8c4a42ager@chromium.org  // Enter a construct frame.
359c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {
360c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    FrameScope scope(masm, StackFrame::CONSTRUCT);
361c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
362c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Preserve the two incoming parameters on the stack.
363bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org    __ SmiTag(r0);
364c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(r0);  // Smi-tagged arguments count.
365c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(r1);  // Constructor function.
366c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
367c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Try to allocate the object without transitioning into C code. If any of
368c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // the preconditions is not met, the code bails out to the runtime call.
369c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label rt_call, allocated;
370c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (FLAG_inline_new) {
371c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Label undo_allocation;
372a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org#ifdef ENABLE_DEBUGGER_SUPPORT
373c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ExternalReference debug_step_in_fp =
374c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          ExternalReference::debug_step_in_fp_address(isolate);
375c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ mov(r2, Operand(debug_step_in_fp));
376c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ ldr(r2, MemOperand(r2));
377c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ tst(r2, r2);
378c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ b(ne, &rt_call);
379a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org#endif
380a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org
381c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Load the initial map and verify that it is in fact a map.
382c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r1: constructor function
383c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
384c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ JumpIfSmi(r2, &rt_call);
385c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ CompareObjectType(r2, r3, r4, MAP_TYPE);
386c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ b(ne, &rt_call);
387c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
388c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Check that the constructor is not constructing a JSFunction (see
389c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // comments in Runtime_NewObject in runtime.cc). In which case the
390c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // initial map's instance type would be JS_FUNCTION_TYPE.
391c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r1: constructor function
392c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r2: initial map
393c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE);
394c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ b(eq, &rt_call);
3954a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
396c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      if (count_constructions) {
397c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        Label allocate;
398c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        // Decrease generous allocation count.
399c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
400c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        MemOperand constructor_count =
401c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com            FieldMemOperand(r3, SharedFunctionInfo::kConstructionCountOffset);
402c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ ldrb(r4, constructor_count);
403c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ sub(r4, r4, Operand(1), SetCC);
404c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ strb(r4, constructor_count);
405c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ b(ne, &allocate);
406c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
407057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org        __ push(r1);
408c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
409057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org        __ Push(r2, r1);  // r1 = constructor
410c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        // The call will replace the stub, so the countdown is only done once.
411c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
412c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
413c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ pop(r2);
414c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ pop(r1);
415c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
416c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ bind(&allocate);
417c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
418a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org
419c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Now allocate the JSObject on the heap.
420c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r1: constructor function
421c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r2: initial map
422c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
423f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      __ Allocate(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS);
424c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
425c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Allocated the JSObject, now initialize the fields. Map is set to
426c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // initial map and properties and elements are set to empty fixed array.
427c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r1: constructor function
428c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r2: initial map
429c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r3: object size
430c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r4: JSObject (not tagged)
431c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
432c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ mov(r5, r4);
433c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
434c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
435c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
436c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
437c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
438c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
439c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
440c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Fill all the in-object properties with the appropriate filler.
441c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r1: constructor function
442c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r2: initial map
443c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r3: object size (in words)
444c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r4: JSObject (not tagged)
445c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r5: First in-object property of JSObject (not tagged)
446c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
4473d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org      __ LoadRoot(r6, Heap::kUndefinedValueRootIndex);
4484a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      if (count_constructions) {
449c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
450c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ Ubfx(r0, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
451c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                kBitsPerByte);
452c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ add(r0, r5, Operand(r0, LSL, kPointerSizeLog2));
453c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        // r0: offset of first field after pre-allocated fields
454c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        if (FLAG_debug_code) {
4553d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org          __ add(ip, r4, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
4563d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org          __ cmp(r0, ip);
457594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org          __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields);
458c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        }
4593d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org        __ InitializeFieldsWithFiller(r5, r0, r6);
4604a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        // To allow for truncation.
4613d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org        __ LoadRoot(r6, Heap::kOnePointerFillerMapRootIndex);
4624a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      }
4633d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org      __ add(r0, r4, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
4643d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org      __ InitializeFieldsWithFiller(r5, r0, r6);
465c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
466c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Add the object tag to make the JSObject real, so that we can continue
467c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // and jump into the continuation code at any time from now on. Any
468c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // failures need to undo the allocation, so that the heap is in a
469c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // consistent state and verifiable.
470c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ add(r4, r4, Operand(kHeapObjectTag));
471c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
472c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Check if a non-empty properties array is needed. Continue with
473c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // allocated object if not fall through to runtime call if it is.
474c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r1: constructor function
475c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r4: JSObject
476c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r5: start of next object (not tagged)
477c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset));
478c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // The field instance sizes contains both pre-allocated property fields
479c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // and in-object properties.
480c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
481c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ Ubfx(r6, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
482c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com              kBitsPerByte);
483c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ add(r3, r3, Operand(r6));
484c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ Ubfx(r6, r0, Map::kInObjectPropertiesByte * kBitsPerByte,
485c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com              kBitsPerByte);
486c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ sub(r3, r3, Operand(r6), SetCC);
487c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
488c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Done if no extra properties are to be allocated.
489c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ b(eq, &allocated);
490594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      __ Assert(pl, kPropertyAllocationCountFailed);
491c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
492c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Scale the number of elements by pointer size and add the header for
493c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // FixedArrays to the start of the next object calculation from above.
494c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r1: constructor
495c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r3: number of elements in properties array
496c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r4: JSObject
497c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r5: start of next object
498c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize));
499f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      __ Allocate(
500c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          r0,
501c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          r5,
502c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          r6,
503c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          r2,
504c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          &undo_allocation,
505c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS));
506c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
507c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Initialize the FixedArray.
508c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r1: constructor
509c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r3: number of elements in properties array
510c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r4: JSObject
511c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r5: FixedArray (not tagged)
512c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex);
513c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ mov(r2, r5);
514c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
515c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ str(r6, MemOperand(r2, kPointerSize, PostIndex));
516c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
517bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org      __ SmiTag(r0, r3);
518c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ str(r0, MemOperand(r2, kPointerSize, PostIndex));
519c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
520c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Initialize the fields to undefined.
521c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r1: constructor function
522c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r2: First element of FixedArray (not tagged)
523c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r3: number of elements in properties array
524c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r4: JSObject
525c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r5: FixedArray (not tagged)
526c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
527c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
528c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      { Label loop, entry;
5293d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org        __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
530c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ b(&entry);
531c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ bind(&loop);
5323d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org        __ str(r0, MemOperand(r2, kPointerSize, PostIndex));
533c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ bind(&entry);
534c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ cmp(r2, r6);
535c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ b(lt, &loop);
536c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
537a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org
538c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Store the initialized FixedArray into the properties field of
539c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // the JSObject
540c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r1: constructor function
541c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r4: JSObject
542c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r5: FixedArray (not tagged)
543c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ add(r5, r5, Operand(kHeapObjectTag));  // Add the heap tag.
544c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ str(r5, FieldMemOperand(r4, JSObject::kPropertiesOffset));
545c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
546c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Continue with JSObject being successfully allocated
547c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r1: constructor function
548c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r4: JSObject
549c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ jmp(&allocated);
550c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
551c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Undo the setting of the new top so that the heap is verifiable. For
552c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // example, the map's unused properties potentially do not match the
553c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // allocated objects unused properties.
554c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // r4: JSObject (previous new top)
555c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ bind(&undo_allocation);
556c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ UndoAllocationInNewSpace(r4, r5);
557c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
558a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org
559c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Allocate the new receiver object using the runtime call.
560a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org    // r1: constructor function
561c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&rt_call);
562c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(r1);  // argument for Runtime_NewObject
563c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CallRuntime(Runtime::kNewObject, 1);
564c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ mov(r4, r0);
565c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
566c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Receiver for constructor call allocated.
567a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org    // r4: JSObject
568c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&allocated);
569c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(r4);
57078d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    __ push(r4);
571c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
57278d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    // Reload the number of arguments and the constructor from the stack.
573c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // sp[0]: receiver
57478d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    // sp[1]: receiver
57578d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    // sp[2]: constructor function
57678d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    // sp[3]: number of arguments (smi-tagged)
57778d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    __ ldr(r1, MemOperand(sp, 2 * kPointerSize));
57878d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    __ ldr(r3, MemOperand(sp, 3 * kPointerSize));
579c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
580f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com    // Set up pointer to last argument.
581c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
582c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
583f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com    // Set up number of arguments for function call below
584bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org    __ SmiUntag(r0, r3);
585c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
586c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Copy arguments and receiver to the expression stack.
587c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // r0: number of arguments
588a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org    // r1: constructor function
58978d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    // r2: address of last argument (caller sp)
590c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // r3: number of arguments (smi-tagged)
591c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // sp[0]: receiver
59278d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    // sp[1]: receiver
59378d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    // sp[2]: constructor function
59478d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org    // sp[3]: number of arguments (smi-tagged)
595c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label loop, entry;
596c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ b(&entry);
597c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&loop);
598c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1));
599c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(ip);
600c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&entry);
601c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ sub(r3, r3, Operand(2), SetCC);
602c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ b(ge, &loop);
603a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org
604c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Call the function.
605c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // r0: number of arguments
606a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org    // r1: constructor function
607c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (is_api_function) {
608c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
609c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Handle<Code> code =
610c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          masm->isolate()->builtins()->HandleApiCallConstruct();
611c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ParameterCount expected(0);
612c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ InvokeCode(code, expected, expected,
613c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                    RelocInfo::CODE_TARGET, CALL_FUNCTION, CALL_AS_METHOD);
614c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    } else {
615c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ParameterCount actual(r0);
616c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ InvokeFunction(r1, actual, CALL_FUNCTION,
617c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                        NullCallWrapper(), CALL_AS_METHOD);
618c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
61943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
620967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org    // Store offset of return address for deoptimizer.
621967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org    if (!is_api_function && !count_constructions) {
622967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org      masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
623967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org    }
624967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org
625c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Restore context from the frame.
626c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // r0: result
627c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // sp[0]: receiver
628c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // sp[1]: constructor function
629c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // sp[2]: number of arguments (smi-tagged)
630c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
631c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
632c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // If the result is an object (in the ECMA sense), we should get rid
633c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // of the receiver and use the result; see ECMA-262 section 13.2.2-7
634c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // on page 74.
635c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label use_receiver, exit;
636c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
637c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // If the result is a smi, it is *not* an object in the ECMA sense.
638c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // r0: result
639c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // sp[0]: receiver (newly allocated object)
640c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // sp[1]: constructor function
641c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // sp[2]: number of arguments (smi-tagged)
642c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ JumpIfSmi(r0, &use_receiver);
643c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
644c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // If the type of the result (stored in its map) is less than
645c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
6464a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ CompareObjectType(r0, r1, r3, FIRST_SPEC_OBJECT_TYPE);
647c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ b(ge, &exit);
648c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
649c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Throw away the result of the constructor invocation and use the
650c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // on-stack receiver as the result.
651c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&use_receiver);
652c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(r0, MemOperand(sp));
653c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
654c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Remove receiver from the stack, remove caller arguments, and
655c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // return.
656c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&exit);
657c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // r0: result
658c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // sp[0]: receiver (newly allocated object)
659c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // sp[1]: constructor function
660c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // sp[2]: number of arguments (smi-tagged)
661c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(r1, MemOperand(sp, 2 * kPointerSize));
662c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
663c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Leave construct frame.
664b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
66543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
666b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
667b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  __ add(sp, sp, Operand(kPointerSize));
6687979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2);
6699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  __ Jump(lr);
67043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
67143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
67243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
6734a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
6744a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  Generate_JSConstructStubHelper(masm, false, true);
6754a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org}
6764a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
6774a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
678b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
6794a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  Generate_JSConstructStubHelper(masm, false, false);
680b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
681b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
682b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
683b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
6844a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  Generate_JSConstructStubHelper(masm, true, false);
685b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
686b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
687b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
68843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenstatic void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
68943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                             bool is_construct) {
69043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Called from Generate_JS_Entry
69143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // r0: code entry
69243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // r1: function
69343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // r2: receiver
69443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // r3: argc
69543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // r4: argv
696cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org  // r5-r6, r8 (if not FLAG_enable_ool_constant_pool) and cp may be clobbered
6971510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  ProfileEntryHookStub::MaybeCallEntryHook(masm);
69843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
699c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Clear the context before we push it when entering the internal frame.
70059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ mov(cp, Operand::Zero());
701b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
702b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  // Enter an internal frame.
703c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {
704c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    FrameScope scope(masm, StackFrame::INTERNAL);
70543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
706c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Set up the context from the function argument.
707c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
70843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
709f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com    __ InitializeRootRegister();
710ab99eea3d9d0cc20698ebb39bf0fb80e3e66bffcager@chromium.org
711c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Push the function and the receiver onto the stack.
712c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(r1);
713c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(r2);
71443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
715c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Copy arguments to the stack in a loop.
716c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // r1: function
717c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // r3: argc
718c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // r4: argv, i.e. points to first arg
719c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label loop, entry;
720c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2));
721c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // r2 points past last arg.
722c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ b(&entry);
723c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&loop);
724c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex));  // read next parameter
725c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(r0, MemOperand(r0));  // dereference handle
726c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(r0);  // push parameter
727c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&entry);
728c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ cmp(r4, r2);
729c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ b(ne, &loop);
73043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
731c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Initialize all JavaScript callee-saved registers, since they will be seen
732c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // by the garbage collector as part of handlers.
733c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
734c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ mov(r5, Operand(r4));
735c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ mov(r6, Operand(r4));
7363d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org    if (!FLAG_enable_ool_constant_pool) {
737cc536058448cdb26fedf76ce62f2ce91480f2ae3yangguo@chromium.org      __ mov(r8, Operand(r4));
7383d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org    }
739c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (kR9Available == 1) {
740c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ mov(r9, Operand(r4));
741c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
74243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
743c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Invoke the code and pass argc as r0.
744c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ mov(r0, Operand(r3));
745c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (is_construct) {
7464a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      // No type feedback cell is available
7474a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      Handle<Object> undefined_sentinel(
7484a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org          masm->isolate()->heap()->undefined_value(), masm->isolate());
7494a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      __ mov(r2, Operand(undefined_sentinel));
750fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org      CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
751fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org      __ CallStub(&stub);
752c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    } else {
753c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ParameterCount actual(r0);
754c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ InvokeFunction(r1, actual, CALL_FUNCTION,
755c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                        NullCallWrapper(), CALL_AS_METHOD);
756c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
757c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Exit the JS frame and remove the parameters (except function), and
758c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // return.
759c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Respect ABI stack constraint.
760c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
7619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  __ Jump(lr);
76243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
76343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // r0: result
76443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
76543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
76643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
76743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
76843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Generate_JSEntryTrampolineHelper(masm, false);
76943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
77043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
77143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
77243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
77343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Generate_JSEntryTrampolineHelper(masm, true);
77443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
77543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
77643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
777ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.orgvoid Builtins::Generate_LazyCompile(MacroAssembler* masm) {
7784a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  CallRuntimePassFunction(masm, Runtime::kLazyCompile);
779ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org  // Do a tail-call of the compiled function.
7804a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
781ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org  __ Jump(r2);
782ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org}
783ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org
784ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org
785a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid Builtins::Generate_LazyRecompile(MacroAssembler* masm) {
7864a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  CallRuntimePassFunction(masm, Runtime::kLazyRecompile);
787a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Do a tail-call of the compiled function.
7884a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
789a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ Jump(r2);
790a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
791a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
792a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
793e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.orgstatic void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) {
794e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  // For now, we are relying on the fact that make_code_young doesn't do any
795e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  // garbage collection which allows us to save/restore the registers without
796e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  // worrying about which of them contain pointers. We also don't build an
797e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  // internal frame to make the code faster, since we shouldn't have to do stack
798e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  // crawls in MakeCodeYoung. This seems a bit fragile.
799e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org
800e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  // The following registers must be saved and restored when calling through to
801e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  // the runtime:
802e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  //   r0 - contains return address (beginning of patch sequence)
803528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  //   r1 - isolate
804e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  FrameScope scope(masm, StackFrame::MANUAL);
805e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  __ stm(db_w, sp, r0.bit() | r1.bit() | fp.bit() | lr.bit());
806528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ PrepareCallCFunction(1, 0, r2);
807528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ mov(r1, Operand(ExternalReference::isolate_address(masm->isolate())));
808e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  __ CallCFunction(
809528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org      ExternalReference::get_make_code_young_function(masm->isolate()), 2);
810e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  __ ldm(ia_w, sp, r0.bit() | r1.bit() | fp.bit() | lr.bit());
811e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  __ mov(pc, r0);
812e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org}
813e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org
814e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org#define DEFINE_CODE_AGE_BUILTIN_GENERATOR(C)                 \
815e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.orgvoid Builtins::Generate_Make##C##CodeYoungAgainEvenMarking(  \
816e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org    MacroAssembler* masm) {                                  \
817e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  GenerateMakeCodeYoungAgainCommon(masm);                    \
818e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org}                                                            \
819e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.orgvoid Builtins::Generate_Make##C##CodeYoungAgainOddMarking(   \
820e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org    MacroAssembler* masm) {                                  \
821e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  GenerateMakeCodeYoungAgainCommon(masm);                    \
822e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org}
823e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.orgCODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR)
824e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org#undef DEFINE_CODE_AGE_BUILTIN_GENERATOR
825e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org
826e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org
827c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.orgvoid Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) {
828c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // For now, as in GenerateMakeCodeYoungAgainCommon, we are relying on the fact
829c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // that make_code_young doesn't do any garbage collection which allows us to
830c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // save/restore the registers without worrying about which of them contain
831c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // pointers.
832c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
833c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // The following registers must be saved and restored when calling through to
834c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // the runtime:
835c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  //   r0 - contains return address (beginning of patch sequence)
836c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  //   r1 - isolate
837c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  FrameScope scope(masm, StackFrame::MANUAL);
838c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ stm(db_w, sp, r0.bit() | r1.bit() | fp.bit() | lr.bit());
839c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ PrepareCallCFunction(1, 0, r2);
840c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ mov(r1, Operand(ExternalReference::isolate_address(masm->isolate())));
841c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ CallCFunction(ExternalReference::get_mark_code_as_executed_function(
842c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org        masm->isolate()), 2);
843c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ ldm(ia_w, sp, r0.bit() | r1.bit() | fp.bit() | lr.bit());
844c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
845c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // Perform prologue operations usually performed by the young code stub.
846c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
8477ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
848c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
849c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  // Jump to point after the code-age stub.
850c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ add(r0, r0, Operand(kNoCodeAgeSequenceLength * Assembler::kInstrSize));
851c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  __ mov(pc, r0);
852c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org}
853c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
854c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
855c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.orgvoid Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) {
856c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org  GenerateMakeCodeYoungAgainCommon(masm);
857c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org}
858c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
859c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org
860f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgstatic void Generate_NotifyStubFailureHelper(MacroAssembler* masm,
861f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                             SaveFPRegsMode save_doubles) {
862a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  {
863a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
864a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
865a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    // Preserve registers across notification, this is important for compiled
866a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    // stubs that tail call the runtime on deopts passing their parameters in
867a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    // registers.
868a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    __ stm(db_w, sp, kJSCallerSaved | kCalleeSaved);
869a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    // Pass the function and deoptimization type to the runtime system.
870f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    __ CallRuntime(Runtime::kNotifyStubFailure, 0, save_doubles);
871a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    __ ldm(ia_w, sp, kJSCallerSaved | kCalleeSaved);
872a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
873a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
874a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  __ add(sp, sp, Operand(kPointerSize));  // Ignore state
875068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org  __ mov(pc, lr);  // Jump to miss handler
876a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
877a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
878a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
879f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgvoid Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) {
880f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Generate_NotifyStubFailureHelper(masm, kDontSaveFPRegs);
881f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org}
882f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org
883f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org
884f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgvoid Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) {
885f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  Generate_NotifyStubFailureHelper(masm, kSaveFPRegs);
886f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org}
887f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org
888f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org
889a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgstatic void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
890a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                                             Deoptimizer::BailoutType type) {
891c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {
892c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    FrameScope scope(masm, StackFrame::INTERNAL);
893c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Pass the function and deoptimization type to the runtime system.
894c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ mov(r0, Operand(Smi::FromInt(static_cast<int>(type))));
895c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(r0);
896c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
897c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
898a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
899a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Get the full codegen state from the stack and untag it -> r6.
900a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ldr(r6, MemOperand(sp, 0 * kPointerSize));
901a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ SmiUntag(r6);
902a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Switch on the state.
903a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  Label with_tos_register, unknown_state;
904a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ cmp(r6, Operand(FullCodeGenerator::NO_REGISTERS));
905a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ b(ne, &with_tos_register);
906a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ add(sp, sp, Operand(1 * kPointerSize));  // Remove state.
907a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ Ret();
908a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
909a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&with_tos_register);
910a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ldr(r0, MemOperand(sp, 1 * kPointerSize));
911a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ cmp(r6, Operand(FullCodeGenerator::TOS_REG));
912a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ b(ne, &unknown_state);
913a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ add(sp, sp, Operand(2 * kPointerSize));  // Remove state.
914a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ Ret();
915a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
916a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&unknown_state);
917a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ stop("no cases left");
918a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
919a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
920a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
921a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
922a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
923a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
924a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
925a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
926aefd6076246d134fe4e1bf0641f0a4d4e35a09c2danno@chromium.orgvoid Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) {
927aefd6076246d134fe4e1bf0641f0a4d4e35a09c2danno@chromium.org  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
928aefd6076246d134fe4e1bf0641f0a4d4e35a09c2danno@chromium.org}
929aefd6076246d134fe4e1bf0641f0a4d4e35a09c2danno@chromium.org
930aefd6076246d134fe4e1bf0641f0a4d4e35a09c2danno@chromium.org
931a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
932a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
933a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
934a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
935a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
936a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
937e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org  // Lookup the function in the JavaScript frame.
938496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
939c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {
940c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    FrameScope scope(masm, StackFrame::INTERNAL);
941e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org    // Lookup and calculate pc offset.
942e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org    __ ldr(r1, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
943e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org    __ ldr(r2, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset));
944e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org    __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCodeOffset));
945e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org    __ sub(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag));
946e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org    __ sub(r1, r1, r2);
947e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org    __ SmiTag(r1);
948e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org
949e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org    // Pass both function and pc offset as arguments.
950c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(r0);
951e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org    __ push(r1);
952e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org    __ CallRuntime(Runtime::kCompileForOnStackReplacement, 2);
953c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
954496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
955c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // If the code object is null, just return to the unoptimized code.
956496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  Label skip;
957c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ cmp(r0, Operand(Smi::FromInt(0)));
958496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  __ b(ne, &skip);
959496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  __ Ret();
960496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
961496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  __ bind(&skip);
962c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
963c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // Load deoptimization data from the code object.
964c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // <deopt_data> = <code>[#deoptimization_data_offset]
965c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ ldr(r1, MemOperand(r0, Code::kDeoptimizationDataOffset - kHeapObjectTag));
966c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
967c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // Load the OSR entrypoint offset from the deoptimization data.
968c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // <osr_offset> = <deopt_data>[#header_size + #osr_pc_offset]
969c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ ldr(r1, MemOperand(r1, FixedArray::OffsetOfElementAt(
970c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org      DeoptimizationInputData::kOsrPcOffsetIndex) - kHeapObjectTag));
971c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
972c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // Compute the target address = code_obj + header_size + osr_offset
973c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // <entry_addr> = <code_obj> + #header_size + <osr_offset>
974c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ add(r0, r0, Operand::SmiUntag(r1));
975c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ add(lr, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
976c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
977c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // And "return" to the OSR entry point of the function.
978c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ Ret();
979a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
980a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
981a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
9828e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.orgvoid Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) {
9838e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  // We check the stack limit as indicator that recompilation might be done.
9848e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  Label ok;
9858e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  __ LoadRoot(ip, Heap::kStackLimitRootIndex);
9868e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  __ cmp(sp, Operand(ip));
9878e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  __ b(hs, &ok);
9888e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  {
9898e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
9908e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org    __ CallRuntime(Runtime::kStackGuard, 0);
9918e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  }
9928e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  __ Jump(masm->isolate()->builtins()->OnStackReplacement(),
9938e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org          RelocInfo::CODE_TARGET);
9948e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org
9958e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  __ bind(&ok);
9968e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  __ Ret();
9978e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org}
9988e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org
9998e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org
1000b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.orgvoid Builtins::Generate_FunctionCall(MacroAssembler* masm) {
1001b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  // 1. Make sure we have at least one argument.
10025c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // r0: actual number of arguments
1003b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  { Label done;
100459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ cmp(r0, Operand::Zero());
1005b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ b(ne, &done);
1006ab99eea3d9d0cc20698ebb39bf0fb80e3e66bffcager@chromium.org    __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
1007b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ push(r2);
1008b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ add(r0, r0, Operand(1));
1009b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ bind(&done);
1010b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  }
1011b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
10125c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // 2. Get the function to call (passed as receiver) from the stack, check
10135c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //    if it is a function.
10145c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // r0: actual number of arguments
101534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  Label slow, non_function;
10165c838251403b0be9a882540f1922577abba4c872ager@chromium.org  __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
10177b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfSmi(r1, &non_function);
10185c838251403b0be9a882540f1922577abba4c872ager@chromium.org  __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
101934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ b(ne, &slow);
1020b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
10215c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // 3a. Patch the first argument if necessary when calling a function.
1022b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  // r0: actual number of arguments
1023b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  // r1: function
10245c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Label shift_arguments;
102559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ mov(r4, Operand::Zero());  // indicate regular JS_FUNCTION
10265c838251403b0be9a882540f1922577abba4c872ager@chromium.org  { Label convert_to_object, use_global_receiver, patch_receiver;
10275c838251403b0be9a882540f1922577abba4c872ager@chromium.org    // Change context eagerly in case we need the global receiver.
10285c838251403b0be9a882540f1922577abba4c872ager@chromium.org    __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
10295c838251403b0be9a882540f1922577abba4c872ager@chromium.org
103049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org    // Do not transform the receiver for strict mode functions.
103149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org    __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
10321c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ ldr(r3, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset));
10331c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ tst(r3, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
103449edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org                             kSmiTagSize)));
103549edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org    __ b(ne, &shift_arguments);
103649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
10376fe7a8e00388b38f66fc0127f3fe797d54b25492ricow@chromium.org    // Do not transform the receiver for native (Compilerhints already in r3).
1038d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    __ tst(r3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
10396fe7a8e00388b38f66fc0127f3fe797d54b25492ricow@chromium.org    __ b(ne, &shift_arguments);
10401c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
104149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org    // Compute the receiver in non-strict mode.
1042b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
1043b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ ldr(r2, MemOperand(r2, -kPointerSize));
1044b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r0: actual number of arguments
1045b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r1: function
1046b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r2: first argument
10477b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org    __ JumpIfSmi(r2, &convert_to_object);
1048b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
10496fe7a8e00388b38f66fc0127f3fe797d54b25492ricow@chromium.org    __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
1050b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ cmp(r2, r3);
1051b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ b(eq, &use_global_receiver);
10521c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ LoadRoot(r3, Heap::kNullValueRootIndex);
1053b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ cmp(r2, r3);
1054b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ b(eq, &use_global_receiver);
1055b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1056d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1057d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    __ CompareObjectType(r2, r3, r3, FIRST_SPEC_OBJECT_TYPE);
105840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    __ b(ge, &shift_arguments);
1059b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
10605c838251403b0be9a882540f1922577abba4c872ager@chromium.org    __ bind(&convert_to_object);
1061b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1062c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    {
1063c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Enter an internal frame in order to preserve argument count.
1064c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      FrameScope scope(masm, StackFrame::INTERNAL);
1065bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org      __ SmiTag(r0);
1066c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ push(r0);
1067c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1068c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ push(r2);
1069c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1070c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ mov(r2, r0);
1071c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1072c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ pop(r0);
1073bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org      __ SmiUntag(r0);
1074c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1075c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Exit the internal frame.
1076c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
1077b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
107834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    // Restore the function to r1, and the flag to r4.
10795c838251403b0be9a882540f1922577abba4c872ager@chromium.org    __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
108059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ mov(r4, Operand::Zero());
10815c838251403b0be9a882540f1922577abba4c872ager@chromium.org    __ jmp(&patch_receiver);
1082b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
10835c838251403b0be9a882540f1922577abba4c872ager@chromium.org    // Use the global receiver object from the called function as the
10845c838251403b0be9a882540f1922577abba4c872ager@chromium.org    // receiver.
1085b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ bind(&use_global_receiver);
1086b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    const int kGlobalIndex =
108746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org        Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
1088b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ ldr(r2, FieldMemOperand(cp, kGlobalIndex));
108946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    __ ldr(r2, FieldMemOperand(r2, GlobalObject::kNativeContextOffset));
10903811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    __ ldr(r2, FieldMemOperand(r2, kGlobalIndex));
10915a8ca6c70c6fc9716f18f6223c98d1fef5752cf6kasperl@chromium.org    __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
1092b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1093b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ bind(&patch_receiver);
1094b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2));
1095b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ str(r2, MemOperand(r3, -kPointerSize));
1096b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
10975c838251403b0be9a882540f1922577abba4c872ager@chromium.org    __ jmp(&shift_arguments);
1098b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  }
1099b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
110034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // 3b. Check for function proxy.
110134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ bind(&slow);
110259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ mov(r4, Operand(1, RelocInfo::NONE32));  // indicate function proxy
110334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ cmp(r2, Operand(JS_FUNCTION_PROXY_TYPE));
110434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ b(eq, &shift_arguments);
110534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ bind(&non_function);
110659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ mov(r4, Operand(2, RelocInfo::NONE32));  // indicate non-function
110734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
110834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // 3c. Patch the first argument when calling a non-function.  The
11095c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //     CALL_NON_FUNCTION builtin expects the non-function callee as
11105c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //     receiver, so overwrite the first argument which will ultimately
11115c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //     become the receiver.
11125c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // r0: actual number of arguments
11135c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // r1: function
111434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // r4: call type (0: JS function, 1: function proxy, 2: non-function)
11155c838251403b0be9a882540f1922577abba4c872ager@chromium.org  __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
11165c838251403b0be9a882540f1922577abba4c872ager@chromium.org  __ str(r1, MemOperand(r2, -kPointerSize));
11175c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11185c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // 4. Shift arguments and return address one slot down on the stack
11195c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //    (overwriting the original receiver).  Adjust argument count to make
11205c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //    the original first argument the new receiver.
11215c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // r0: actual number of arguments
1122b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  // r1: function
112334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // r4: call type (0: JS function, 1: function proxy, 2: non-function)
11245c838251403b0be9a882540f1922577abba4c872ager@chromium.org  __ bind(&shift_arguments);
1125b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  { Label loop;
1126b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // Calculate the copy start address (destination). Copy end address is sp.
1127b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
1128b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1129b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ bind(&loop);
1130b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ ldr(ip, MemOperand(r2, -kPointerSize));
1131b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ str(ip, MemOperand(r2));
1132b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ sub(r2, r2, Operand(kPointerSize));
1133b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ cmp(r2, sp);
1134b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ b(ne, &loop);
11355c838251403b0be9a882540f1922577abba4c872ager@chromium.org    // Adjust the actual number of arguments and remove the top element
11365c838251403b0be9a882540f1922577abba4c872ager@chromium.org    // (which is a copy of the last argument).
11375c838251403b0be9a882540f1922577abba4c872ager@chromium.org    __ sub(r0, r0, Operand(1));
11385c838251403b0be9a882540f1922577abba4c872ager@chromium.org    __ pop();
1139b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  }
1140b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
114134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin,
114234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  //     or a function proxy via CALL_FUNCTION_PROXY.
1143b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  // r0: actual number of arguments
1144b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  // r1: function
114534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // r4: call type (0: JS function, 1: function proxy, 2: non-function)
114634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  { Label function, non_proxy;
114734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    __ tst(r4, r4);
114834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    __ b(eq, &function);
11495b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org    // Expected number of arguments is 0 for CALL_NON_FUNCTION.
115059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ mov(r2, Operand::Zero());
115140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    __ SetCallKind(r5, CALL_AS_METHOD);
115234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    __ cmp(r4, Operand(1));
115334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    __ b(ne, &non_proxy);
115434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
115534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    __ push(r1);  // re-add proxy object as additional argument
115634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    __ add(r0, r0, Operand(1));
115734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY);
115834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
115934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org            RelocInfo::CODE_TARGET);
116034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
116134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    __ bind(&non_proxy);
116234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
11637979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
11647979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org            RelocInfo::CODE_TARGET);
11655c838251403b0be9a882540f1922577abba4c872ager@chromium.org    __ bind(&function);
11665c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
1167b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
11685c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // 5b. Get the code to call from the function and check that the number of
11695c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //     expected arguments matches what we're providing.  If so, jump
11705c838251403b0be9a882540f1922577abba4c872ager@chromium.org  //     (tail-call) to the code in register edx without checking arguments.
11715c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // r0: actual number of arguments
11725c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // r1: function
11735c838251403b0be9a882540f1922577abba4c872ager@chromium.org  __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
11745c838251403b0be9a882540f1922577abba4c872ager@chromium.org  __ ldr(r2,
11755c838251403b0be9a882540f1922577abba4c872ager@chromium.org         FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
1176bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiUntag(r2);
1177145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com  __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
117840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  __ SetCallKind(r5, CALL_AS_METHOD);
11795c838251403b0be9a882540f1922577abba4c872ager@chromium.org  __ cmp(r2, r0);  // Check formal and actual parameter counts.
11807979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
11817979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org          RelocInfo::CODE_TARGET,
11827979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org          ne);
1183b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
11845c838251403b0be9a882540f1922577abba4c872ager@chromium.org  ParameterCount expected(0);
1185d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org  __ InvokeCode(r3, expected, expected, JUMP_FUNCTION,
1186d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org                NullCallWrapper(), CALL_AS_METHOD);
1187b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org}
1188b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1189b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
119043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid Builtins::Generate_FunctionApply(MacroAssembler* masm) {
11917ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  const int kIndexOffset    =
11927ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org      StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize);
11937ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  const int kLimitOffset    =
11947ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org      StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize);
11957ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  const int kArgsOffset     = 2 * kPointerSize;
11967ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  const int kRecvOffset     = 3 * kPointerSize;
11977ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  const int kFunctionOffset = 4 * kPointerSize;
1198b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1199c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {
1200c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    FrameScope frame_scope(masm, StackFrame::INTERNAL);
1201b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1202c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(r0, MemOperand(fp, kFunctionOffset));  // get the function
1203c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(r0);
1204c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(r0, MemOperand(fp, kArgsOffset));  // get the args array
1205c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(r0);
1206c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
1207c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1208c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Check the stack for overflow. We are not trying to catch
1209c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // interruptions (e.g. debug break and preemption) here, so the "real stack
1210c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // limit" is checked.
1211c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label okay;
1212c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ LoadRoot(r2, Heap::kRealStackLimitRootIndex);
1213c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Make r2 the space we have left. The stack might already be overflowed
1214c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // here which will cause r2 to become negative.
1215c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ sub(r2, sp, r2);
1216c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Check if the arguments will overflow the stack.
1217bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org    __ cmp(r2, Operand::PointerOffsetFromSmiKey(r0));
1218c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ b(gt, &okay);  // Signed comparison.
1219c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1220c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Out of stack space.
1221c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(r1, MemOperand(fp, kFunctionOffset));
1222057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org    __ Push(r1, r0);
1223c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
1224c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // End of stack check.
1225b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1226c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Push current limit and index.
1227c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&okay);
1228c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(r0);  // limit
122959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ mov(r1, Operand::Zero());  // initial index
1230c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(r1);
1231b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1232c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Get the receiver.
1233c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(r0, MemOperand(fp, kRecvOffset));
123434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
1235c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Check that the function is a JS function (otherwise it must be a proxy).
1236c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label push_receiver;
1237c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(r1, MemOperand(fp, kFunctionOffset));
1238c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
1239c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ b(ne, &push_receiver);
124034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
1241c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Change context eagerly to get the right global object if necessary.
1242c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1243c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Load the shared function info while the function is still in r1.
1244c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1245b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1246c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Compute the receiver.
1247c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Do not transform the receiver for strict mode functions.
1248c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label call_to_object, use_global_receiver;
1249c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset));
1250c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ tst(r2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
1251c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                             kSmiTagSize)));
1252c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ b(ne, &push_receiver);
1253b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1254c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Do not transform the receiver for strict mode functions.
1255c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ tst(r2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
1256c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ b(ne, &push_receiver);
1257b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1258c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Compute the receiver in non-strict mode.
1259c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ JumpIfSmi(r0, &call_to_object);
1260c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ LoadRoot(r1, Heap::kNullValueRootIndex);
1261c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ cmp(r0, r1);
1262c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ b(eq, &use_global_receiver);
1263c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
1264c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ cmp(r0, r1);
1265c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ b(eq, &use_global_receiver);
1266b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1267c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Check if the receiver is already a JavaScript object.
1268c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // r0: receiver
1269c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1270c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
1271c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ b(ge, &push_receiver);
1272b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1273c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Convert the receiver to a regular object.
1274c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // r0: receiver
1275c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&call_to_object);
1276c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(r0);
1277c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1278c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ b(&push_receiver);
1279b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1280c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Use the current global receiver object as the receiver.
1281c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&use_global_receiver);
1282c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    const int kGlobalOffset =
128346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org        Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
1284c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(r0, FieldMemOperand(cp, kGlobalOffset));
128546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    __ ldr(r0, FieldMemOperand(r0, GlobalObject::kNativeContextOffset));
1286c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(r0, FieldMemOperand(r0, kGlobalOffset));
1287c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
1288c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1289c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Push the receiver.
1290c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // r0: receiver
1291c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&push_receiver);
1292c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(r0);
1293b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1294c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Copy all arguments from the array to the stack.
1295c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label entry, loop;
1296c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(r0, MemOperand(fp, kIndexOffset));
1297c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ b(&entry);
129834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
1299c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Load the current argument from the arguments array and push it to the
1300c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // stack.
1301c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // r0: current argument index
1302c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&loop);
1303c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(r1, MemOperand(fp, kArgsOffset));
1304057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org    __ Push(r1, r0);
1305c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1306c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Call the runtime to access the property in the arguments array.
1307c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CallRuntime(Runtime::kGetProperty, 2);
1308c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(r0);
1309c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1310c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Use inline caching to access the arguments.
1311c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(r0, MemOperand(fp, kIndexOffset));
1312c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(r0, r0, Operand(1 << kSmiTagSize));
1313c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ str(r0, MemOperand(fp, kIndexOffset));
131434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
1315c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Test if the copy loop has finished copying all the elements from the
1316c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // arguments object.
1317c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&entry);
1318c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(r1, MemOperand(fp, kLimitOffset));
1319c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ cmp(r0, r1);
1320c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ b(ne, &loop);
1321c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1322c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Invoke the function.
1323c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label call_proxy;
1324c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ParameterCount actual(r0);
1325bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org    __ SmiUntag(r0);
1326c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(r1, MemOperand(fp, kFunctionOffset));
1327c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
1328c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ b(ne, &call_proxy);
1329c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ InvokeFunction(r1, actual, CALL_FUNCTION,
1330c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      NullCallWrapper(), CALL_AS_METHOD);
1331c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1332c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    frame_scope.GenerateLeaveFrame();
1333c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(sp, sp, Operand(3 * kPointerSize));
1334c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Jump(lr);
1335c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1336c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Invoke the function proxy.
1337c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&call_proxy);
1338c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(r1);  // add function proxy as last argument
1339c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(r0, r0, Operand(1));
134059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ mov(r2, Operand::Zero());
1341c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ SetCallKind(r5, CALL_AS_METHOD);
1342c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY);
1343c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1344c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com            RelocInfo::CODE_TARGET);
1345c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1346c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Tear down the internal frame and remove function, receiver and args.
1347c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
134834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ add(sp, sp, Operand(3 * kPointerSize));
13499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  __ Jump(lr);
1350b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org}
1351b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1352b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1353b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.orgstatic void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1354bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiTag(r0);
135518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ mov(r4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1356b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() | fp.bit() | lr.bit());
13577ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ add(fp, sp,
13587ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org         Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize));
1359b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org}
1360b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1361b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
13627c537e2abe09729ed6cb827b4dd206470d8c4a42ager@chromium.orgstatic void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1363b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  // ----------- S t a t e -------------
1364b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  //  -- r0 : result being passed through
1365b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  // -----------------------------------
1366b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  // Get the number of arguments passed (as a smi), tear down the frame and
1367b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  // then tear down the parameters.
13687ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  __ ldr(r1, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp +
13697ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org                              kPointerSize)));
1370b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  __ mov(sp, fp);
1371b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  __ ldm(ia_w, sp, fp.bit() | lr.bit());
1372bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ add(sp, sp, Operand::PointerOffsetFromSmiKey(r1));
1373b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  __ add(sp, sp, Operand(kPointerSize));  // adjust for receiver
137443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
137543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
137643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
137743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1378b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  // ----------- S t a t e -------------
1379b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  //  -- r0 : actual number of arguments
1380b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  //  -- r1 : function (passed through to callee)
1381b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  //  -- r2 : expected number of arguments
1382b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  //  -- r3 : code entry to call
138340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  //  -- r5 : call kind information
1384b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  // -----------------------------------
1385b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1386b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  Label invoke, dont_adapt_arguments;
1387b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1388b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  Label enough, too_few;
1389013f3e12d3af426bf5545b5f457aa08ee98bdca2fschneider@chromium.org  __ cmp(r0, r2);
1390b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  __ b(lt, &too_few);
1391b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  __ cmp(r2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
1392b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  __ b(eq, &dont_adapt_arguments);
1393b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
13943291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  {  // Enough parameters: actual >= expected
1395b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ bind(&enough);
1396b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    EnterArgumentsAdaptorFrame(masm);
1397b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1398b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // Calculate copy start address into r0 and copy end address into r2.
1399b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r0: actual number of arguments as a smi
1400b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r1: function
1401b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r2: expected number of arguments
1402b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r3: code entry to call
1403bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org    __ add(r0, fp, Operand::PointerOffsetFromSmiKey(r0));
1404b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // adjust for return address and receiver
1405b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ add(r0, r0, Operand(2 * kPointerSize));
1406b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ sub(r2, r0, Operand(r2, LSL, kPointerSizeLog2));
1407b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1408b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // Copy the arguments (including the receiver) to the new stack frame.
1409b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r0: copy start address
1410b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r1: function
1411b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r2: copy end address
1412b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r3: code entry to call
1413b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1414b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    Label copy;
1415b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ bind(&copy);
1416b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ ldr(ip, MemOperand(r0, 0));
1417b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ push(ip);
1418b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ cmp(r0, r2);  // Compare before moving to next argument.
1419b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ sub(r0, r0, Operand(kPointerSize));
1420b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ b(ne, &copy);
1421b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1422b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ b(&invoke);
1423b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  }
1424b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1425b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  {  // Too few parameters: Actual < expected
1426b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ bind(&too_few);
1427b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    EnterArgumentsAdaptorFrame(masm);
1428b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1429b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // Calculate copy start address into r0 and copy end address is fp.
1430b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r0: actual number of arguments as a smi
1431b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r1: function
1432b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r2: expected number of arguments
1433b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r3: code entry to call
1434bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org    __ add(r0, fp, Operand::PointerOffsetFromSmiKey(r0));
1435b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1436b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // Copy the arguments (including the receiver) to the new stack frame.
1437b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r0: copy start address
1438b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r1: function
1439b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r2: expected number of arguments
1440b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r3: code entry to call
1441b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    Label copy;
1442b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ bind(&copy);
1443b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // Adjust load for return address and receiver.
1444b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ ldr(ip, MemOperand(r0, 2 * kPointerSize));
1445b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ push(ip);
1446b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ cmp(r0, fp);  // Compare before moving to next argument.
1447b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ sub(r0, r0, Operand(kPointerSize));
1448b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ b(ne, &copy);
1449b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1450b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // Fill the remaining expected arguments with undefined.
1451b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r1: function
1452b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r2: expected number of arguments
1453b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    // r3: code entry to call
1454ab99eea3d9d0cc20698ebb39bf0fb80e3e66bffcager@chromium.org    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1455b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ sub(r2, fp, Operand(r2, LSL, kPointerSizeLog2));
14567ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org    // Adjust for frame.
14577ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org    __ sub(r2, r2, Operand(StandardFrameConstants::kFixedFrameSizeFromFp +
14587ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org                           2 * kPointerSize));
1459b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1460b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    Label fill;
1461b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ bind(&fill);
1462b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ push(ip);
1463b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ cmp(sp, r2);
1464b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    __ b(ne, &fill);
1465b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  }
146643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1467b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  // Call the entry point.
1468b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  __ bind(&invoke);
1469b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  __ Call(r3);
147043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1471967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org  // Store offset of return address for deoptimizer.
1472659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org  masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
1473967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org
14747c537e2abe09729ed6cb827b4dd206470d8c4a42ager@chromium.org  // Exit frame and return.
14757c537e2abe09729ed6cb827b4dd206470d8c4a42ager@chromium.org  LeaveArgumentsAdaptorFrame(masm);
14769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  __ Jump(lr);
1477b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1478b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
1479b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  // -------------------------------------------
1480b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  // Dont adapt arguments.
1481b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  // -------------------------------------------
1482b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  __ bind(&dont_adapt_arguments);
14839085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  __ Jump(r3);
148443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
148543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
148643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
148743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#undef __
148843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
148943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} }  // namespace v8::internal
14909dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
14919dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com#endif  // V8_TARGET_ARCH_ARM
1492