builtins-arm.cc revision 25f6136652d8341ed047e7fc1a450af5bd218ea9
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2009 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "codegen-inl.h"
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "debug.h"
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "runtime.h"
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm)
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
41e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_Adaptor(MacroAssembler* masm,
42e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                CFunctionId id,
43e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                BuiltinExtraArguments extra_args) {
44e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // ----------- S t a t e -------------
45e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- r0                 : number of arguments excluding receiver
46e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- r1                 : called function (only guaranteed when
47e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //                          extra_args requires it)
48e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- cp                 : context
49e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- sp[0]              : last argument
50e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ...
51e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- sp[4 * (argc - 1)] : first argument (argc == r0)
52e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- sp[4 * argc]       : receiver
53e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // -----------------------------------
54e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
55e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Insert extra arguments.
56e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  int num_extra_args = 0;
57e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (extra_args == NEEDS_CALLED_FUNCTION) {
58e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    num_extra_args = 1;
59e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(r1);
60e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
61e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(extra_args == NO_EXTRA_ARGUMENTS);
62e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
63e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // JumpToExternalReference expects r0 to contain the number of arguments
65e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // including the receiver and the extra arguments.
66e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ add(r0, r0, Operand(num_extra_args + 1));
676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ JumpToExternalReference(ExternalReference(id));
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load the built-in Array function from the current context.
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) {
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the global context.
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(result,
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(result, GlobalObject::kGlobalContextOffset));
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the Array function from the global context.
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(result,
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         MemOperand(result,
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This constant has the same value as JSArray::kPreallocatedArrayElements and
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// if JSArray::kPreallocatedArrayElements is changed handling of loop unfolding
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// below should be reconsidered.
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kLoopUnfoldLimit = 4;
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Allocate an empty JSArray. The allocated array is put into the result
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register. An elements backing store is allocated with size initial_capacity
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and filled with the hole values.
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void AllocateEmptyJSArray(MacroAssembler* masm,
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register array_function,
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register result,
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register scratch1,
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register scratch2,
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register scratch3,
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 int initial_capacity,
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Label* gc_required) {
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(initial_capacity > 0);
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map from the array function.
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(scratch1, FieldMemOperand(array_function,
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   JSFunction::kPrototypeOrInitialMapOffset));
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate the JSArray object together with space for a fixed array with the
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // requested elements.
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int size = JSArray::kSize + FixedArray::SizeFor(initial_capacity);
11025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  __ AllocateInNewSpace(size,
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        result,
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        scratch2,
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        scratch3,
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        gc_required,
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        TAG_OBJECT);
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocated the JSArray. Now initialize the fields except for the elements
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array.
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch1: initial map
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch2: start of next object
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch1, FieldMemOperand(result, JSObject::kMapOffset));
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex);
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch1, FieldMemOperand(result, JSArray::kPropertiesOffset));
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Field JSArray::kElementsOffset is initialized later.
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(scratch3,  Operand(0));
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch3, FieldMemOperand(result, JSArray::kLengthOffset));
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the location of the elements array and set elements array member
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // of the JSArray.
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch2: start of next object
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ lea(scratch1, MemOperand(result, JSArray::kSize));
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch1, FieldMemOperand(result, JSArray::kElementsOffset));
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the heap tag on the elements array.
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(scratch1, scratch1, Operand(~kHeapObjectTagMask));
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Initialize the FixedArray and fill it with holes. FixedArray length is not
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // stored as a smi.
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch1: elements array (untagged)
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch2: start of next object
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(scratch3, Heap::kFixedArrayMapRootIndex);
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset);
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(scratch3,  Operand(initial_capacity));
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the FixedArray with the hole value.
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(initial_capacity <= kLoopUnfoldLimit);
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex);
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < initial_capacity; i++) {
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Allocate a JSArray with the number of elements stored in a register. The
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register array_function holds the built-in Array function and the register
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// array_size holds the size of the array as a smi. The allocated array is put
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// into the result register and beginning and end of the FixedArray elements
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// storage is put into registers elements_array_storage and elements_array_end
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (see  below for when that is not the case). If the parameter fill_with_holes
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// is true the allocated elements backing store is filled with the hole values
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// otherwise it is left uninitialized. When the backing store is filled the
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register elements_array_storage is scratched.
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void AllocateJSArray(MacroAssembler* masm,
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register array_function,  // Array function.
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register array_size,  // As a smi.
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register result,
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register elements_array_storage,
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register elements_array_end,
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register scratch1,
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register scratch2,
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            bool fill_with_hole,
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Label* gc_required) {
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label not_empty, allocated;
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map from the array function.
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(elements_array_storage,
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(array_function,
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         JSFunction::kPrototypeOrInitialMapOffset));
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check whether an empty sized array is requested.
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(array_size, array_size);
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(nz, &not_empty);
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If an empty array is requested allocate a small elements array anyway. This
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // keeps the code below free of special casing for the empty array.
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int size = JSArray::kSize +
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
19425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  __ AllocateInNewSpace(size,
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        result,
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        elements_array_end,
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        scratch1,
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        gc_required,
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        TAG_OBJECT);
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&allocated);
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate the JSArray object together with space for a FixedArray with the
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // requested number of elements.
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&not_empty);
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(elements_array_end,
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Operand((JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize));
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(elements_array_end,
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         elements_array_end,
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Operand(array_size, ASR, kSmiTagSize));
21125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  __ AllocateInNewSpace(
21225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      elements_array_end,
21325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      result,
21425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      scratch1,
21525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      scratch2,
21625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      gc_required,
21725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocated the JSArray. Now initialize the fields except for the elements
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array.
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_storage: initial map
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array_size: size of array (smi)
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&allocated);
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(elements_array_storage, FieldMemOperand(result, JSObject::kMapOffset));
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(elements_array_storage, Heap::kEmptyFixedArrayRootIndex);
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(elements_array_storage,
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(result, JSArray::kPropertiesOffset));
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Field JSArray::kElementsOffset is initialized later.
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(array_size, FieldMemOperand(result, JSArray::kLengthOffset));
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the location of the elements array and set elements array member
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // of the JSArray.
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array_size: size of array (smi)
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(elements_array_storage, result, Operand(JSArray::kSize));
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(elements_array_storage,
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(result, JSArray::kElementsOffset));
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the heap tag on the elements array.
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(elements_array_storage,
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          elements_array_storage,
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Operand(~kHeapObjectTagMask));
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Initialize the fixed array and fill it with holes. FixedArray length is not
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // stored as a smi.
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_storage: elements array (untagged)
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array_size: size of array (smi)
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kSmiTag == 0);
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(scratch1, Heap::kFixedArrayMapRootIndex);
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset);
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch1, MemOperand(elements_array_storage, kPointerSize, PostIndex));
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Convert array_size from smi to value.
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(array_size,
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Operand(array_size, ASR, kSmiTagSize));
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(array_size, array_size);
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Length of the FixedArray is the number of pre-allocated elements if
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the actual JSArray has length 0 and the size of the JSArray for non-empty
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // JSArrays. The length of a FixedArray is not stored as a smi.
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(array_size, Operand(JSArray::kPreallocatedArrayElements), LeaveCC, eq);
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(array_size,
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         MemOperand(elements_array_storage, kPointerSize, PostIndex));
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate elements array and elements array end.
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_storage: elements array element storage
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array_size: size of elements array
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(elements_array_end,
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         elements_array_storage,
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Operand(array_size, LSL, kPointerSizeLog2));
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the allocated FixedArray with the hole value if requested.
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_storage: elements array element storage
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_end: start of next object
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (fill_with_hole) {
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label loop, entry;
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(scratch1, Heap::kTheHoleValueRootIndex);
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ jmp(&entry);
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&loop);
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(scratch1,
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           MemOperand(elements_array_storage, kPointerSize, PostIndex));
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&entry);
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(elements_array_storage, elements_array_end);
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(lt, &loop);
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Create a new array for the built-in Array function. This function allocates
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the JSArray object and the FixedArray elements array and initializes these.
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// If the Array cannot be constructed in native code the runtime is called. This
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// function assumes the following state:
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   r0: argc
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   r1: constructor (built-in Array function)
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   lr: return address
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   sp[0]: last argument
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This function is used for both construct and normal calls of Array. The only
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// difference between handling a construct call and a normal call is that for a
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// construct call the constructor function in r1 needs to be preserved for
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// entering the generic code. In both cases argc in r0 needs to be preserved.
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Both registers are preserved by this code so no need to differentiate between
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// construct call and normal call.
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ArrayNativeCode(MacroAssembler* masm,
305d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                            Label* call_generic_code) {
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label argc_one_or_more, argc_two_or_more;
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for array construction with zero arguments or one.
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, Operand(0));
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &argc_one_or_more);
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle construction of an empty array.
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AllocateEmptyJSArray(masm,
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       r1,
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       r2,
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       r3,
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       r4,
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       r5,
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       JSArray::kPreallocatedArrayElements,
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       call_generic_code);
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::array_function_native, 1, r3, r4);
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setup return value, remove receiver from stack and return.
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, r2);
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for one argument. Bail out if argument is not smi or if it is
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // negative.
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&argc_one_or_more);
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, Operand(1));
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &argc_two_or_more);
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kSmiTag == 0);
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, MemOperand(sp));  // Get the argument from the stack.
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(r3, r2, Operand(kIntptrSignBit | kSmiTagMask), SetCC);
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, call_generic_code);
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle construction of an empty array of a certain size. Bail out if size
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is too large to actually allocate an elements array.
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kSmiTag == 0);
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, Operand(JSObject::kInitialMaxFastElementArray << kSmiTagSize));
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ge, call_generic_code);
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: array_size (smi)
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: argument
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AllocateJSArray(masm,
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r1,
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r2,
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r3,
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r4,
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r5,
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r6,
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r7,
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  true,
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  call_generic_code);
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::array_function_native, 1, r2, r4);
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setup return value, remove receiver and argument from stack and return.
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, r3);
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(2 * kPointerSize));
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle construction of an array from a list of arguments.
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&argc_two_or_more);
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r2, Operand(r0, LSL, kSmiTagSize));  // Convet argc to a smi.
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: array_size (smi)
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: last argument
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AllocateJSArray(masm,
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r1,
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r2,
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r3,
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r4,
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r5,
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r6,
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r7,
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  false,
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  call_generic_code);
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::array_function_native, 1, r2, r6);
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill arguments as array elements. Copy from the top of the stack (last
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // element) to the array backing store filling it backwards. Note:
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_end points after the backing store therefore PreIndex is
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // used when filling the backing store.
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: JSArray
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: elements_array storage start (untagged)
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r5: elements_array_end (untagged)
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: last argument
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label loop, entry;
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&entry);
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&loop);
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, MemOperand(sp, kPointerSize, PostIndex));
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r2, MemOperand(r5, -kPointerSize, PreIndex));
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&entry);
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r4, r5);
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(lt, &loop);
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove caller arguments and receiver from the stack, setup return value and
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // return.
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: JSArray
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, r3);
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArrayCode(MacroAssembler* masm) {
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0     : number of arguments
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr     : return address
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[...]: constructor arguments
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the Array function.
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadArrayFunction(masm, r1);
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_debug_code) {
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Initial map for the builtin Array function shoud be a map.
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r2, Operand(kSmiTagMask));
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(ne, "Unexpected initial map for Array function");
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CompareObjectType(r2, r3, r4, MAP_TYPE);
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(eq, "Unexpected initial map for Array function");
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run the native code for the Array function called as a normal function.
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ArrayNativeCode(masm, &generic_array_code);
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the generic array code if the specialized code cannot handle
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the construction.
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&generic_array_code);
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Code* code = Builtins::builtin(Builtins::ArrayCodeGeneric);
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> array_code(code);
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(array_code, RelocInfo::CODE_TARGET);
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) {
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0     : number of arguments
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r1     : constructor function
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr     : return address
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[...]: constructor arguments
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label generic_constructor;
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_debug_code) {
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The array construct code is only set for the builtin Array function which
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // always have a map.
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    GenerateLoadArrayFunction(masm, r2);
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r1, r2);
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(eq, "Unexpected Array function");
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Initial map for the builtin Array function should be a map.
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r2, Operand(kSmiTagMask));
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(ne, "Unexpected initial map for Array function");
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CompareObjectType(r2, r3, r4, MAP_TYPE);
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(eq, "Unexpected initial map for Array function");
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run the native code for the Array function called as a constructor.
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ArrayNativeCode(masm, &generic_constructor);
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the generic construct code in case the specialized code cannot
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // handle the construction.
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&generic_constructor);
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric);
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> generic_construct_stub(code);
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0     : number of arguments
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r1     : constructor function
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr     : return address
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[...]: constructor arguments
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label non_function_call;
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function is not a smi.
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(r1, Operand(kSmiTagMask));
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &non_function_call);
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function is a JSFunction.
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &non_function_call);
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the function-specific construct stub.
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kConstructStubOffset));
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(pc, r2, Operand(Code::kHeaderSize - kHeapObjectTag));
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: number of arguments
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: called object
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&non_function_call);
503402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // CALL_NON_FUNCTION expects the non-function constructor as receiver
504402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // (instead of the original receiver from the call site).  The receiver is
505402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // stack element argc.
506402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ str(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set expected number of arguments to zero (not changing r0).
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r2, Operand(0));
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          RelocInfo::CODE_TARGET);
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkestatic void Generate_JSConstructStubHelper(MacroAssembler* masm,
516e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                           bool is_api_function) {
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enter a construct frame.
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ EnterConstructFrame();
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Preserve the two incoming parameters on the stack.
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(r0, LSL, kSmiTagSize));
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);  // Smi-tagged arguments count.
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);  // Constructor function.
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use r7 for holding undefined which is used in several places below.
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Try to allocate the object without transitioning into C code. If any of the
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // preconditions is not met, the code bails out to the runtime call.
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label rt_call, allocated;
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_inline_new) {
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label undo_allocation;
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ExternalReference debug_step_in_fp =
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ExternalReference::debug_step_in_fp_address();
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r2, Operand(debug_step_in_fp));
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, MemOperand(r2));
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r2, r2);
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(nz, &rt_call);
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Load the initial map and verify that it is in fact a map.
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r7: undefined
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r2, Operand(kSmiTagMask));
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &rt_call);
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CompareObjectType(r2, r3, r4, MAP_TYPE);
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &rt_call);
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check that the constructor is not constructing a JSFunction (see comments
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // in Runtime_NewObject in runtime.cc). In which case the initial map's
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // instance type would be JS_FUNCTION_TYPE.
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: initial map
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r7: undefined
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE);
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &rt_call);
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Now allocate the JSObject on the heap.
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: initial map
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r7: undefined
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
56525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS);
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Allocated the JSObject, now initialize the fields. Map is set to initial
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // map and properties and elements are set to empty fixed array.
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: initial map
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: object size
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject (not tagged)
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r7: undefined
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r5, r4);
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Fill all the in-object properties with undefined.
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: initial map
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: object size (in words)
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject (not tagged)
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r5: First in-object property of JSObject (not tagged)
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r7: undefined
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    { Label loop, entry;
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(&entry);
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&loop);
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r7, MemOperand(r5, kPointerSize, PostIndex));
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&entry);
5976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ cmp(r5, r6);
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(lt, &loop);
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Add the object tag to make the JSObject real, so that we can continue and
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // jump into the continuation code at any time from now on. Any failures
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // need to undo the allocation, so that the heap is in a consistent state
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // and verifiable.
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r4, r4, Operand(kHeapObjectTag));
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check if a non-empty properties array is needed. Continue with allocated
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // object if not fall through to runtime call if it is.
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r5: start of next object (not tagged)
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r7: undefined
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset));
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The field instance sizes contains both pre-allocated property fields and
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // in-object properties.
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ and_(r6,
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            r0,
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            Operand(0x000000FF << Map::kPreAllocatedPropertyFieldsByte * 8));
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r3, r3, Operand(r6, LSR, Map::kPreAllocatedPropertyFieldsByte * 8));
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ and_(r6, r0, Operand(0x000000FF << Map::kInObjectPropertiesByte * 8));
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r3, r3, Operand(r6, LSR, Map::kInObjectPropertiesByte * 8), SetCC);
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Done if no extra properties are to be allocated.
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &allocated);
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(pl, "Property allocation count failed.");
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Scale the number of elements by pointer size and add the header for
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // FixedArrays to the start of the next object calculation from above.
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: number of elements in properties array
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r5: start of next object
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r7: undefined
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize));
63625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ AllocateInNewSpace(
63725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        r0,
63825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        r5,
63925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        r6,
64025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        r2,
64125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        &undo_allocation,
64225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS));
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Initialize the FixedArray.
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: number of elements in properties array
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r5: FixedArray (not tagged)
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r7: undefined
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex);
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r2, r5);
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r6, MemOperand(r2, kPointerSize, PostIndex));
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(1 * kPointerSize, Array::kLengthOffset);
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r3, MemOperand(r2, kPointerSize, PostIndex));
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Initialize the fields to undefined.
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: First element of FixedArray (not tagged)
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: number of elements in properties array
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r5: FixedArray (not tagged)
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r7: undefined
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    { Label loop, entry;
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(&entry);
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&loop);
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r7, MemOperand(r2, kPointerSize, PostIndex));
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&entry);
6716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ cmp(r2, r6);
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(lt, &loop);
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Store the initialized FixedArray into the properties field of
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // the JSObject
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r5: FixedArray (not tagged)
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r5, r5, Operand(kHeapObjectTag));  // Add the heap tag.
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r5, FieldMemOperand(r4, JSObject::kPropertiesOffset));
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Continue with JSObject being successfully allocated
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ jmp(&allocated);
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Undo the setting of the new top so that the heap is verifiable. For
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // example, the map's unused properties potentially do not match the
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // allocated objects unused properties.
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject (previous new top)
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&undo_allocation);
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ UndoAllocationInNewSpace(r4, r5);
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate the new receiver object using the runtime call.
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&rt_call);
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);  // argument for Runtime_NewObject
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CallRuntime(Runtime::kNewObject, 1);
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r4, r0);
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Receiver for constructor call allocated.
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: JSObject
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&allocated);
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r4);
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push the function and the allocated receiver from the stack.
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver (newly allocated object)
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[1]: constructor function
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: number of arguments (smi-tagged)
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(sp, kPointerSize));
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);  // Constructor function.
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r4);  // Receiver.
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reload the number of arguments from the stack.
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[1]: constructor function
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: receiver
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[3]: constructor function
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[4]: number of arguments (smi-tagged)
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r3, MemOperand(sp, 4 * kPointerSize));
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setup pointer to last argument.
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setup number of arguments for function call below
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(r3, LSR, kSmiTagSize));
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Copy arguments and receiver to the expression stack.
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: number of arguments
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: address of last argument (caller sp)
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: number of arguments (smi-tagged)
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[1]: constructor function
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: receiver
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[3]: constructor function
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[4]: number of arguments (smi-tagged)
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label loop, entry;
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(&entry);
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&loop);
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1));
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ip);
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&entry);
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(r3, r3, Operand(2), SetCC);
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ge, &loop);
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call the function.
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: number of arguments
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
753e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (is_api_function) {
754e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
755e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Handle<Code> code = Handle<Code>(
756e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        Builtins::builtin(Builtins::HandleApiCallConstruct));
757e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ParameterCount expected(0);
758e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ InvokeCode(code, expected, expected,
759e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                  RelocInfo::CODE_TARGET, CALL_FUNCTION);
760e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
761e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ParameterCount actual(r0);
762e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ InvokeFunction(r1, actual, CALL_FUNCTION);
763e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Pop the function from the stack.
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: constructor function
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: receiver
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[3]: constructor function
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[4]: number of arguments (smi-tagged)
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop();
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore context from the frame.
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: result
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[1]: constructor function
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: number of arguments (smi-tagged)
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the result is an object (in the ECMA sense), we should get rid
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // of the receiver and use the result; see ECMA-262 section 13.2.2-7
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // on page 74.
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label use_receiver, exit;
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the result is a smi, it is *not* an object in the ECMA sense.
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: result
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver (newly allocated object)
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[1]: constructor function
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: number of arguments (smi-tagged)
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(r0, Operand(kSmiTagMask));
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &use_receiver);
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the type of the result (stored in its map) is less than
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // FIRST_JS_OBJECT_TYPE, it is not an object in the ECMA sense.
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareObjectType(r0, r3, r3, FIRST_JS_OBJECT_TYPE);
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ge, &exit);
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Throw away the result of the constructor invocation and use the
798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // on-stack receiver as the result.
799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&use_receiver);
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(sp));
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove receiver from the stack, remove caller arguments, and
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // return.
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&exit);
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: result
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver (newly allocated object)
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[1]: constructor function
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: number of arguments (smi-tagged)
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(sp, 2 * kPointerSize));
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LeaveConstructFrame();
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::constructed_objects, 1, r1, r2);
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
818e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
819e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Generate_JSConstructStubHelper(masm, false);
820e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
821e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
822e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
823e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
824e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Generate_JSConstructStubHelper(masm, true);
825e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
826e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
827e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             bool is_construct) {
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Called from Generate_JS_Entry
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: code entry
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: function
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: receiver
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: argc
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: argv
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r5-r7, cp may be clobbered
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the context before we push it when entering the JS frame.
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(cp, Operand(0));
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enter an internal frame.
842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ EnterInternalFrame();
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set up the context from the function argument.
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set up the roots register.
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference roots_address = ExternalReference::roots_address();
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r10, Operand(roots_address));
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push the function and the receiver onto the stack.
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r2);
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Copy arguments to the stack in a loop.
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: function
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: argc
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: argv, i.e. points to first arg
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label loop, entry;
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2));
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2 points past last arg.
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(&entry);
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&loop);
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex));  // read next parameter
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(r0));  // dereference handle
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);  // push parameter
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&entry);
8686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(r4, r2);
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &loop);
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Initialize all JavaScript callee-saved registers, since they will be seen
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // by the garbage collector as part of handlers.
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r5, Operand(r4));
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r6, Operand(r4));
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r7, Operand(r4));
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (kR9Available == 1) {
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r9, Operand(r4));
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the code and pass argc as r0.
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(r3));
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (is_construct) {
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)),
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            RelocInfo::CODE_TARGET);
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ParameterCount actual(r0);
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ InvokeFunction(r1, actual, CALL_FUNCTION);
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Exit the JS frame and remove the parameters (except function), and return.
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Respect ABI stack constraint.
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LeaveInternalFrame();
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: result
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Generate_JSEntryTrampolineHelper(masm, false);
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Generate_JSEntryTrampolineHelper(masm, true);
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_FunctionCall(MacroAssembler* masm) {
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 1. Make sure we have at least one argument.
912402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r0: actual number of arguments
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { Label done;
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r0, Operand(r0));
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &done);
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(r2);
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, r0, Operand(1));
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&done);
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
922402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // 2. Get the function to call (passed as receiver) from the stack, check
923402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //    if it is a function.
924402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r0: actual number of arguments
925402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Label non_function;
926402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
927402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ tst(r1, Operand(kSmiTagMask));
928402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ b(eq, &non_function);
929402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
930402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ b(ne, &non_function);
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
932402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // 3a. Patch the first argument if necessary when calling a function.
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: actual number of arguments
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: function
935402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Label shift_arguments;
936402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  { Label convert_to_object, use_global_receiver, patch_receiver;
937402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Change context eagerly in case we need the global receiver.
938402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
939402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, MemOperand(r2, -kPointerSize));
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0: actual number of arguments
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: first argument
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r2, Operand(kSmiTagMask));
946402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ b(eq, &convert_to_object);
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(r3, Heap::kNullValueRootIndex);
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r2, r3);
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &use_global_receiver);
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r2, r3);
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &use_global_receiver);
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CompareObjectType(r2, r3, r3, FIRST_JS_OBJECT_TYPE);
956402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ b(lt, &convert_to_object);
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r3, Operand(LAST_JS_OBJECT_TYPE));
958402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ b(le, &shift_arguments);
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
960402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ bind(&convert_to_object);
961402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ EnterInternalFrame();  // In order to preserve argument count.
962402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ mov(r0, Operand(r0, LSL, kSmiTagSize));  // Smi-tagged.
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(r0);
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(r2);
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r2, r0);
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ pop(r0);
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r0, Operand(r0, ASR, kSmiTagSize));
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LeaveInternalFrame();
972402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Restore the function to r1.
973402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
974402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ jmp(&patch_receiver);
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
976402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Use the global receiver object from the called function as the
977402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // receiver.
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&use_global_receiver);
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const int kGlobalIndex =
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, FieldMemOperand(cp, kGlobalIndex));
982d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalContextOffset));
983d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(r2, FieldMemOperand(r2, kGlobalIndex));
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&patch_receiver);
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2));
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r2, MemOperand(r3, -kPointerSize));
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
990402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ jmp(&shift_arguments);
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
993402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // 3b. Patch the first argument when calling a non-function.  The
994402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //     CALL_NON_FUNCTION builtin expects the non-function callee as
995402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //     receiver, so overwrite the first argument which will ultimately
996402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //     become the receiver.
997402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r0: actual number of arguments
998402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r1: function
999402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ bind(&non_function);
1000402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
1001402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ str(r1, MemOperand(r2, -kPointerSize));
1002402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Clear r1 to indicate a non-function being called.
1003402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ mov(r1, Operand(0));
1004402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1005402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // 4. Shift arguments and return address one slot down on the stack
1006402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //    (overwriting the original receiver).  Adjust argument count to make
1007402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //    the original first argument the new receiver.
1008402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r0: actual number of arguments
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: function
1010402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ bind(&shift_arguments);
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { Label loop;
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Calculate the copy start address (destination). Copy end address is sp.
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&loop);
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(ip, MemOperand(r2, -kPointerSize));
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(ip, MemOperand(r2));
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r2, r2, Operand(kPointerSize));
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r2, sp);
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &loop);
1021402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Adjust the actual number of arguments and remove the top element
1022402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // (which is a copy of the last argument).
1023402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ sub(r0, r0, Operand(1));
1024402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ pop();
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1027402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin.
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: actual number of arguments
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: function
1030402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  { Label function;
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r1, r1);
1032402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ b(ne, &function);
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r2, Operand(0));  // expected arguments is 0 for CALL_NON_FUNCTION
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         RelocInfo::CODE_TARGET);
1037402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ bind(&function);
1038402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1040402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // 5b. Get the code to call from the function and check that the number of
1041402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //     expected arguments matches what we're providing.  If so, jump
1042402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //     (tail-call) to the code in register edx without checking arguments.
1043402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r0: actual number of arguments
1044402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r1: function
1045402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1046402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ ldr(r2,
1047402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu         FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
1048402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kCodeOffset));
1049402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
1050402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ cmp(r2, r0);  // Check formal and actual parameter counts.
1051402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
1052402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu          RelocInfo::CODE_TARGET, ne);
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1054402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ParameterCount expected(0);
1055402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ InvokeCode(r3, expected, expected, JUMP_FUNCTION);
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kIndexOffset    = -5 * kPointerSize;
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kLimitOffset    = -4 * kPointerSize;
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kArgsOffset     =  2 * kPointerSize;
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kRecvOffset     =  3 * kPointerSize;
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kFunctionOffset =  4 * kPointerSize;
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ EnterInternalFrame();
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(fp, kFunctionOffset));  // get the function
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(fp, kArgsOffset));  // get the args array
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_JS);
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1074d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Check the stack for overflow. We are not trying need to catch
1075d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // interruptions (e.g. debug break and preemption) here, so the "real stack
1076d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // limit" is checked.
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label okay;
1078d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ LoadRoot(r2, Heap::kRealStackLimitRootIndex);
1079d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Make r2 the space we have left. The stack might already be overflowed
1080d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // here which will cause r2 to become negative.
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(r2, sp, r2);
1082d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Check if the arguments will overflow the stack.
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
1084d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ b(gt, &okay);  // Signed comparison.
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Out of stack space.
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(fp, kFunctionOffset));
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_JS);
1091d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // End of stack check.
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push current limit and index.
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&okay);
1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);  // limit
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r1, Operand(0));  // initial index
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Change context eagerly to get the right global object if necessary.
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(fp, kFunctionOffset));
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(cp, FieldMemOperand(r0, JSFunction::kContextOffset));
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the receiver.
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label call_to_object, use_global_receiver, push_receiver;
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(fp, kRecvOffset));
1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(r0, Operand(kSmiTagMask));
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &call_to_object);
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(r1, Heap::kNullValueRootIndex);
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, r1);
1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &use_global_receiver);
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, r1);
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &use_global_receiver);
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if the receiver is already a JavaScript object.
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: receiver
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE);
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(lt, &call_to_object);
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE));
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(le, &push_receiver);
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Convert the receiver to a regular object.
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: receiver
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&call_to_object);
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(&push_receiver);
1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use the current global receiver object as the receiver.
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&use_global_receiver);
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kGlobalOffset =
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, FieldMemOperand(cp, kGlobalOffset));
1134d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset));
1135d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ ldr(r0, FieldMemOperand(r0, kGlobalOffset));
1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push the receiver.
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: receiver
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&push_receiver);
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Copy all arguments from the array to the stack.
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label entry, loop;
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(fp, kIndexOffset));
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(&entry);
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the current argument from the arguments array and push it to the
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // stack.
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: current argument index
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&loop);
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(fp, kArgsOffset));
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call the runtime to access the property in the arguments array.
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CallRuntime(Runtime::kGetProperty, 2);
1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use inline caching to access the arguments.
1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(fp, kIndexOffset));
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r0, r0, Operand(1 << kSmiTagSize));
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r0, MemOperand(fp, kIndexOffset));
1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test if the copy loop has finished copying all the elements from the
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // arguments object.
1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&entry);
1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(fp, kLimitOffset));
1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, r1);
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &loop);
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the function.
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount actual(r0);
1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(r0, ASR, kSmiTagSize));
1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(fp, kFunctionOffset));
1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ InvokeFunction(r1, actual, CALL_FUNCTION);
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tear down the internal frame and remove function, receiver and args.
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LeaveInternalFrame();
1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(3 * kPointerSize));
1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(r0, LSL, kSmiTagSize));
1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() | fp.bit() | lr.bit());
1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(fp, sp, Operand(3 * kPointerSize));
1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0 : result being passed through
1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the number of arguments passed (as a smi), tear down the frame and
1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // then tear down the parameters.
1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(fp, -3 * kPointerSize));
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(sp, fp);
1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldm(ia_w, sp, fp.bit() | lr.bit());
1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));
1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));  // adjust for receiver
1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0 : actual number of arguments
1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r1 : function (passed through to callee)
1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2 : expected number of arguments
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r3 : code entry to call
1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label invoke, dont_adapt_arguments;
1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label enough, too_few;
12186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(r0, r2);
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(lt, &too_few);
1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &dont_adapt_arguments);
1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {  // Enough parameters: actual >= expected
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&enough);
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    EnterArgumentsAdaptorFrame(masm);
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Calculate copy start address into r0 and copy end address into r2.
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0: actual number of arguments as a smi
1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: expected number of arguments
1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: code entry to call
1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // adjust for return address and receiver
1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, r0, Operand(2 * kPointerSize));
1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r2, r0, Operand(r2, LSL, kPointerSizeLog2));
1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Copy the arguments (including the receiver) to the new stack frame.
1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0: copy start address
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: copy end address
1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: code entry to call
1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label copy;
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&copy);
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(ip, MemOperand(r0, 0));
1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(ip);
1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r0, r2);  // Compare before moving to next argument.
1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r0, r0, Operand(kPointerSize));
1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &copy);
1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(&invoke);
1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {  // Too few parameters: Actual < expected
1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&too_few);
1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    EnterArgumentsAdaptorFrame(masm);
1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Calculate copy start address into r0 and copy end address is fp.
1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0: actual number of arguments as a smi
1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: expected number of arguments
1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: code entry to call
1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Copy the arguments (including the receiver) to the new stack frame.
1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0: copy start address
1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: expected number of arguments
1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: code entry to call
1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label copy;
1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&copy);
1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Adjust load for return address and receiver.
1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(ip, MemOperand(r0, 2 * kPointerSize));
1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(ip);
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r0, fp);  // Compare before moving to next argument.
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r0, r0, Operand(kPointerSize));
1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &copy);
1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Fill the remaining expected arguments with undefined.
1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: expected number of arguments
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: code entry to call
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r2, fp, Operand(r2, LSL, kPointerSizeLog2));
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r2, r2, Operand(4 * kPointerSize));  // Adjust for frame.
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label fill;
1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&fill);
1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(ip);
1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(sp, r2);
1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &fill);
1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call the entry point.
1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&invoke);
1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Call(r3);
1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Exit frame and return.
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LeaveArgumentsAdaptorFrame(masm);
1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -------------------------------------------
1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Dont adapt arguments.
1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -------------------------------------------
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&dont_adapt_arguments);
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(r3);
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
1314