builtins-arm.cc revision a7e24c173cf37484693b9abb38e494fa7bd7baeb
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
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // TODO(428): Don't pass the function in a static variable.
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ip, Operand(ExternalReference::builtin_passed_function()));
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r1, MemOperand(ip, 0));
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The actual argument count has already been loaded into register
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0, but JumpToRuntime expects r0 to contain the number of
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // arguments including the receiver.
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r0, r0, Operand(1));
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ JumpToRuntime(ExternalReference(id));
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load the built-in Array function from the current context.
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) {
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the global context.
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(result,
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(result, GlobalObject::kGlobalContextOffset));
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the Array function from the global context.
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(result,
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         MemOperand(result,
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This constant has the same value as JSArray::kPreallocatedArrayElements and
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// if JSArray::kPreallocatedArrayElements is changed handling of loop unfolding
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// below should be reconsidered.
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kLoopUnfoldLimit = 4;
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Allocate an empty JSArray. The allocated array is put into the result
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register. An elements backing store is allocated with size initial_capacity
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and filled with the hole values.
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void AllocateEmptyJSArray(MacroAssembler* masm,
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register array_function,
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register result,
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register scratch1,
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register scratch2,
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register scratch3,
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 int initial_capacity,
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Label* gc_required) {
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(initial_capacity > 0);
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map from the array function.
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(scratch1, FieldMemOperand(array_function,
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   JSFunction::kPrototypeOrInitialMapOffset));
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate the JSArray object together with space for a fixed array with the
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // requested elements.
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int size = JSArray::kSize + FixedArray::SizeFor(initial_capacity);
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ AllocateInNewSpace(size / kPointerSize,
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        result,
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        scratch2,
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        scratch3,
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        gc_required,
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        TAG_OBJECT);
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocated the JSArray. Now initialize the fields except for the elements
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array.
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch1: initial map
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch2: start of next object
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch1, FieldMemOperand(result, JSObject::kMapOffset));
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex);
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch1, FieldMemOperand(result, JSArray::kPropertiesOffset));
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Field JSArray::kElementsOffset is initialized later.
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(scratch3,  Operand(0));
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch3, FieldMemOperand(result, JSArray::kLengthOffset));
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the location of the elements array and set elements array member
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // of the JSArray.
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch2: start of next object
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ lea(scratch1, MemOperand(result, JSArray::kSize));
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch1, FieldMemOperand(result, JSArray::kElementsOffset));
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the heap tag on the elements array.
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(scratch1, scratch1, Operand(~kHeapObjectTagMask));
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Initialize the FixedArray and fill it with holes. FixedArray length is not
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // stored as a smi.
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch1: elements array (untagged)
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch2: start of next object
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(scratch3, Heap::kFixedArrayMapRootIndex);
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset);
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(scratch3,  Operand(initial_capacity));
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the FixedArray with the hole value.
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(initial_capacity <= kLoopUnfoldLimit);
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex);
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < initial_capacity; i++) {
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Allocate a JSArray with the number of elements stored in a register. The
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register array_function holds the built-in Array function and the register
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// array_size holds the size of the array as a smi. The allocated array is put
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// into the result register and beginning and end of the FixedArray elements
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// storage is put into registers elements_array_storage and elements_array_end
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (see  below for when that is not the case). If the parameter fill_with_holes
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// is true the allocated elements backing store is filled with the hole values
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// otherwise it is left uninitialized. When the backing store is filled the
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register elements_array_storage is scratched.
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void AllocateJSArray(MacroAssembler* masm,
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register array_function,  // Array function.
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register array_size,  // As a smi.
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register result,
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register elements_array_storage,
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register elements_array_end,
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register scratch1,
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register scratch2,
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            bool fill_with_hole,
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Label* gc_required) {
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label not_empty, allocated;
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map from the array function.
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(elements_array_storage,
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(array_function,
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         JSFunction::kPrototypeOrInitialMapOffset));
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check whether an empty sized array is requested.
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(array_size, array_size);
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(nz, &not_empty);
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If an empty array is requested allocate a small elements array anyway. This
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // keeps the code below free of special casing for the empty array.
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int size = JSArray::kSize +
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ AllocateInNewSpace(size / kPointerSize,
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        result,
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        elements_array_end,
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        scratch1,
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        gc_required,
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        TAG_OBJECT);
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&allocated);
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate the JSArray object together with space for a FixedArray with the
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // requested number of elements.
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&not_empty);
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(elements_array_end,
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Operand((JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize));
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(elements_array_end,
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         elements_array_end,
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Operand(array_size, ASR, kSmiTagSize));
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ AllocateInNewSpace(elements_array_end,
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        result,
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        scratch1,
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        scratch2,
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        gc_required,
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        TAG_OBJECT);
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocated the JSArray. Now initialize the fields except for the elements
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array.
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_storage: initial map
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array_size: size of array (smi)
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&allocated);
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(elements_array_storage, FieldMemOperand(result, JSObject::kMapOffset));
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(elements_array_storage, Heap::kEmptyFixedArrayRootIndex);
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(elements_array_storage,
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(result, JSArray::kPropertiesOffset));
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Field JSArray::kElementsOffset is initialized later.
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(array_size, FieldMemOperand(result, JSArray::kLengthOffset));
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the location of the elements array and set elements array member
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // of the JSArray.
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array_size: size of array (smi)
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(elements_array_storage, result, Operand(JSArray::kSize));
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(elements_array_storage,
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(result, JSArray::kElementsOffset));
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the heap tag on the elements array.
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(elements_array_storage,
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          elements_array_storage,
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Operand(~kHeapObjectTagMask));
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Initialize the fixed array and fill it with holes. FixedArray length is not
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // stored as a smi.
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_storage: elements array (untagged)
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array_size: size of array (smi)
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kSmiTag == 0);
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(scratch1, Heap::kFixedArrayMapRootIndex);
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset);
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch1, MemOperand(elements_array_storage, kPointerSize, PostIndex));
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Convert array_size from smi to value.
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(array_size,
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Operand(array_size, ASR, kSmiTagSize));
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(array_size, array_size);
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Length of the FixedArray is the number of pre-allocated elements if
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the actual JSArray has length 0 and the size of the JSArray for non-empty
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // JSArrays. The length of a FixedArray is not stored as a smi.
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(array_size, Operand(JSArray::kPreallocatedArrayElements), LeaveCC, eq);
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(array_size,
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         MemOperand(elements_array_storage, kPointerSize, PostIndex));
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate elements array and elements array end.
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_storage: elements array element storage
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array_size: size of elements array
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(elements_array_end,
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         elements_array_storage,
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Operand(array_size, LSL, kPointerSizeLog2));
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the allocated FixedArray with the hole value if requested.
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_storage: elements array element storage
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_end: start of next object
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (fill_with_hole) {
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label loop, entry;
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(scratch1, Heap::kTheHoleValueRootIndex);
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ jmp(&entry);
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&loop);
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(scratch1,
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           MemOperand(elements_array_storage, kPointerSize, PostIndex));
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&entry);
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(elements_array_storage, elements_array_end);
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(lt, &loop);
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Create a new array for the built-in Array function. This function allocates
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the JSArray object and the FixedArray elements array and initializes these.
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// If the Array cannot be constructed in native code the runtime is called. This
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// function assumes the following state:
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   r0: argc
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   r1: constructor (built-in Array function)
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   lr: return address
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   sp[0]: last argument
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This function is used for both construct and normal calls of Array. The only
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// difference between handling a construct call and a normal call is that for a
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// construct call the constructor function in r1 needs to be preserved for
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// entering the generic code. In both cases argc in r0 needs to be preserved.
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Both registers are preserved by this code so no need to differentiate between
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// construct call and normal call.
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ArrayNativeCode(MacroAssembler* masm,
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Label *call_generic_code) {
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label argc_one_or_more, argc_two_or_more;
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for array construction with zero arguments or one.
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, Operand(0));
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &argc_one_or_more);
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle construction of an empty array.
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AllocateEmptyJSArray(masm,
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       r1,
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       r2,
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       r3,
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       r4,
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       r5,
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       JSArray::kPreallocatedArrayElements,
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       call_generic_code);
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::array_function_native, 1, r3, r4);
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setup return value, remove receiver from stack and return.
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, r2);
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for one argument. Bail out if argument is not smi or if it is
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // negative.
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&argc_one_or_more);
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, Operand(1));
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &argc_two_or_more);
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kSmiTag == 0);
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, MemOperand(sp));  // Get the argument from the stack.
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(r3, r2, Operand(kIntptrSignBit | kSmiTagMask), SetCC);
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, call_generic_code);
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle construction of an empty array of a certain size. Bail out if size
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is too large to actually allocate an elements array.
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kSmiTag == 0);
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, Operand(JSObject::kInitialMaxFastElementArray << kSmiTagSize));
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ge, call_generic_code);
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: array_size (smi)
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: argument
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AllocateJSArray(masm,
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r1,
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r2,
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r3,
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r4,
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r5,
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r6,
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r7,
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  true,
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  call_generic_code);
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::array_function_native, 1, r2, r4);
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setup return value, remove receiver and argument from stack and return.
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, r3);
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(2 * kPointerSize));
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle construction of an array from a list of arguments.
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&argc_two_or_more);
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r2, Operand(r0, LSL, kSmiTagSize));  // Convet argc to a smi.
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: array_size (smi)
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: last argument
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AllocateJSArray(masm,
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r1,
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r2,
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r3,
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r4,
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r5,
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r6,
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r7,
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  false,
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  call_generic_code);
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::array_function_native, 1, r2, r6);
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill arguments as array elements. Copy from the top of the stack (last
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // element) to the array backing store filling it backwards. Note:
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_end points after the backing store therefore PreIndex is
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // used when filling the backing store.
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: JSArray
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: elements_array storage start (untagged)
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r5: elements_array_end (untagged)
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: last argument
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label loop, entry;
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&entry);
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&loop);
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, MemOperand(sp, kPointerSize, PostIndex));
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r2, MemOperand(r5, -kPointerSize, PreIndex));
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&entry);
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r4, r5);
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(lt, &loop);
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove caller arguments and receiver from the stack, setup return value and
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // return.
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: JSArray
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, r3);
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArrayCode(MacroAssembler* masm) {
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0     : number of arguments
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr     : return address
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[...]: constructor arguments
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the Array function.
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadArrayFunction(masm, r1);
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_debug_code) {
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Initial map for the builtin Array function shoud be a map.
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r2, Operand(kSmiTagMask));
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(ne, "Unexpected initial map for Array function");
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CompareObjectType(r2, r3, r4, MAP_TYPE);
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(eq, "Unexpected initial map for Array function");
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run the native code for the Array function called as a normal function.
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ArrayNativeCode(masm, &generic_array_code);
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the generic array code if the specialized code cannot handle
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the construction.
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&generic_array_code);
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Code* code = Builtins::builtin(Builtins::ArrayCodeGeneric);
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> array_code(code);
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(array_code, RelocInfo::CODE_TARGET);
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) {
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0     : number of arguments
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r1     : constructor function
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr     : return address
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[...]: constructor arguments
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label generic_constructor;
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_debug_code) {
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The array construct code is only set for the builtin Array function which
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // always have a map.
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    GenerateLoadArrayFunction(masm, r2);
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r1, r2);
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(eq, "Unexpected Array function");
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Initial map for the builtin Array function should be a map.
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r2, Operand(kSmiTagMask));
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(ne, "Unexpected initial map for Array function");
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CompareObjectType(r2, r3, r4, MAP_TYPE);
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(eq, "Unexpected initial map for Array function");
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run the native code for the Array function called as a constructor.
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ArrayNativeCode(masm, &generic_constructor);
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the generic construct code in case the specialized code cannot
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // handle the construction.
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&generic_constructor);
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric);
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> generic_construct_stub(code);
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0     : number of arguments
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r1     : constructor function
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr     : return address
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[...]: constructor arguments
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label non_function_call;
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function is not a smi.
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(r1, Operand(kSmiTagMask));
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &non_function_call);
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function is a JSFunction.
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &non_function_call);
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the function-specific construct stub.
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kConstructStubOffset));
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(pc, r2, Operand(Code::kHeaderSize - kHeapObjectTag));
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: number of arguments
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: called object
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&non_function_call);
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set expected number of arguments to zero (not changing r0).
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r2, Operand(0));
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          RelocInfo::CODE_TARGET);
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enter a construct frame.
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ EnterConstructFrame();
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Preserve the two incoming parameters on the stack.
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(r0, LSL, kSmiTagSize));
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);  // Smi-tagged arguments count.
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);  // Constructor function.
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use r7 for holding undefined which is used in several places below.
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Try to allocate the object without transitioning into C code. If any of the
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // preconditions is not met, the code bails out to the runtime call.
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label rt_call, allocated;
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_inline_new) {
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label undo_allocation;
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ExternalReference debug_step_in_fp =
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ExternalReference::debug_step_in_fp_address();
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r2, Operand(debug_step_in_fp));
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, MemOperand(r2));
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r2, r2);
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(nz, &rt_call);
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Load the initial map and verify that it is in fact a map.
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r7: undefined
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r2, Operand(kSmiTagMask));
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &rt_call);
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CompareObjectType(r2, r3, r4, MAP_TYPE);
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &rt_call);
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check that the constructor is not constructing a JSFunction (see comments
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // in Runtime_NewObject in runtime.cc). In which case the initial map's
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // instance type would be JS_FUNCTION_TYPE.
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: initial map
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r7: undefined
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE);
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &rt_call);
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Now allocate the JSObject on the heap.
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: initial map
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r7: undefined
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, NO_ALLOCATION_FLAGS);
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Allocated the JSObject, now initialize the fields. Map is set to initial
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // map and properties and elements are set to empty fixed array.
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: initial map
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: object size
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject (not tagged)
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r7: undefined
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r5, r4);
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Fill all the in-object properties with undefined.
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: initial map
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: object size (in words)
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject (not tagged)
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r5: First in-object property of JSObject (not tagged)
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r7: undefined
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    { Label loop, entry;
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(&entry);
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&loop);
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r7, MemOperand(r5, kPointerSize, PostIndex));
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&entry);
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmp(r5, Operand(r6));
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(lt, &loop);
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Add the object tag to make the JSObject real, so that we can continue and
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // jump into the continuation code at any time from now on. Any failures
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // need to undo the allocation, so that the heap is in a consistent state
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // and verifiable.
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r4, r4, Operand(kHeapObjectTag));
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check if a non-empty properties array is needed. Continue with allocated
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // object if not fall through to runtime call if it is.
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r5: start of next object (not tagged)
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r7: undefined
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset));
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The field instance sizes contains both pre-allocated property fields and
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // in-object properties.
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ and_(r6,
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            r0,
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            Operand(0x000000FF << Map::kPreAllocatedPropertyFieldsByte * 8));
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r3, r3, Operand(r6, LSR, Map::kPreAllocatedPropertyFieldsByte * 8));
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ and_(r6, r0, Operand(0x000000FF << Map::kInObjectPropertiesByte * 8));
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r3, r3, Operand(r6, LSR, Map::kInObjectPropertiesByte * 8), SetCC);
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Done if no extra properties are to be allocated.
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &allocated);
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(pl, "Property allocation count failed.");
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Scale the number of elements by pointer size and add the header for
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // FixedArrays to the start of the next object calculation from above.
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: number of elements in properties array
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r5: start of next object
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r7: undefined
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize));
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ AllocateInNewSpace(r0,
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          r5,
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          r6,
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          r2,
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          &undo_allocation,
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          RESULT_CONTAINS_TOP);
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Initialize the FixedArray.
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: number of elements in properties array
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r5: FixedArray (not tagged)
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r7: undefined
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex);
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r2, r5);
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r6, MemOperand(r2, kPointerSize, PostIndex));
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(1 * kPointerSize, Array::kLengthOffset);
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r3, MemOperand(r2, kPointerSize, PostIndex));
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Initialize the fields to undefined.
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: First element of FixedArray (not tagged)
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: number of elements in properties array
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r5: FixedArray (not tagged)
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r7: undefined
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    { Label loop, entry;
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(&entry);
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&loop);
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r7, MemOperand(r2, kPointerSize, PostIndex));
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&entry);
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmp(r2, Operand(r6));
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(lt, &loop);
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Store the initialized FixedArray into the properties field of
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // the JSObject
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r5: FixedArray (not tagged)
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r5, r5, Operand(kHeapObjectTag));  // Add the heap tag.
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r5, FieldMemOperand(r4, JSObject::kPropertiesOffset));
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Continue with JSObject being successfully allocated
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ jmp(&allocated);
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Undo the setting of the new top so that the heap is verifiable. For
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // example, the map's unused properties potentially do not match the
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // allocated objects unused properties.
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject (previous new top)
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&undo_allocation);
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ UndoAllocationInNewSpace(r4, r5);
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate the new receiver object using the runtime call.
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&rt_call);
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);  // argument for Runtime_NewObject
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CallRuntime(Runtime::kNewObject, 1);
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r4, r0);
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Receiver for constructor call allocated.
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: JSObject
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&allocated);
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r4);
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push the function and the allocated receiver from the stack.
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver (newly allocated object)
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[1]: constructor function
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: number of arguments (smi-tagged)
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(sp, kPointerSize));
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);  // Constructor function.
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r4);  // Receiver.
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reload the number of arguments from the stack.
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[1]: constructor function
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: receiver
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[3]: constructor function
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[4]: number of arguments (smi-tagged)
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r3, MemOperand(sp, 4 * kPointerSize));
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setup pointer to last argument.
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setup number of arguments for function call below
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(r3, LSR, kSmiTagSize));
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Copy arguments and receiver to the expression stack.
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: number of arguments
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: address of last argument (caller sp)
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: number of arguments (smi-tagged)
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[1]: constructor function
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: receiver
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[3]: constructor function
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[4]: number of arguments (smi-tagged)
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label loop, entry;
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(&entry);
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&loop);
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1));
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ip);
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&entry);
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(r3, r3, Operand(2), SetCC);
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ge, &loop);
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call the function.
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: number of arguments
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount actual(r0);
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ InvokeFunction(r1, actual, CALL_FUNCTION);
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Pop the function from the stack.
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: constructor function
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: receiver
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[3]: constructor function
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[4]: number of arguments (smi-tagged)
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop();
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore context from the frame.
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: result
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[1]: constructor function
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: number of arguments (smi-tagged)
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the result is an object (in the ECMA sense), we should get rid
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // of the receiver and use the result; see ECMA-262 section 13.2.2-7
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // on page 74.
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label use_receiver, exit;
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the result is a smi, it is *not* an object in the ECMA sense.
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: result
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver (newly allocated object)
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[1]: constructor function
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: number of arguments (smi-tagged)
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(r0, Operand(kSmiTagMask));
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &use_receiver);
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the type of the result (stored in its map) is less than
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // FIRST_JS_OBJECT_TYPE, it is not an object in the ECMA sense.
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareObjectType(r0, r3, r3, FIRST_JS_OBJECT_TYPE);
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ge, &exit);
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Throw away the result of the constructor invocation and use the
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // on-stack receiver as the result.
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&use_receiver);
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(sp));
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove receiver from the stack, remove caller arguments, and
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // return.
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&exit);
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: result
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver (newly allocated object)
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[1]: constructor function
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: number of arguments (smi-tagged)
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(sp, 2 * kPointerSize));
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LeaveConstructFrame();
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ IncrementCounter(&Counters::constructed_objects, 1, r1, r2);
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             bool is_construct) {
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Called from Generate_JS_Entry
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: code entry
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: function
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: receiver
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: argc
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: argv
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r5-r7, cp may be clobbered
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the context before we push it when entering the JS frame.
797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(cp, Operand(0));
798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enter an internal frame.
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ EnterInternalFrame();
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set up the context from the function argument.
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set up the roots register.
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference roots_address = ExternalReference::roots_address();
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r10, Operand(roots_address));
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push the function and the receiver onto the stack.
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r2);
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Copy arguments to the stack in a loop.
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: function
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: argc
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: argv, i.e. points to first arg
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label loop, entry;
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2));
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2 points past last arg.
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(&entry);
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&loop);
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex));  // read next parameter
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(r0));  // dereference handle
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);  // push parameter
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&entry);
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r4, Operand(r2));
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &loop);
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Initialize all JavaScript callee-saved registers, since they will be seen
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // by the garbage collector as part of handlers.
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r5, Operand(r4));
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r6, Operand(r4));
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r7, Operand(r4));
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (kR9Available == 1) {
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r9, Operand(r4));
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the code and pass argc as r0.
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(r3));
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (is_construct) {
842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)),
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            RelocInfo::CODE_TARGET);
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ParameterCount actual(r0);
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ InvokeFunction(r1, actual, CALL_FUNCTION);
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Exit the JS frame and remove the parameters (except function), and return.
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Respect ABI stack constraint.
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LeaveInternalFrame();
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: result
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Generate_JSEntryTrampolineHelper(masm, false);
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Generate_JSEntryTrampolineHelper(masm, true);
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_FunctionCall(MacroAssembler* masm) {
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 1. Make sure we have at least one argument.
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: actual number of argument
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { Label done;
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r0, Operand(r0));
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &done);
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(r2);
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, r0, Operand(1));
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&done);
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 2. Get the function to call from the stack.
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: actual number of argument
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { Label done, non_function, function;
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r1, Operand(kSmiTagMask));
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &non_function);
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &function);
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Non-function called: Clear the function to force exception.
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&non_function);
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r1, Operand(0));
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(&done);
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Change the context eagerly because it will be used below to get the
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // right global object.
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&function);
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&done);
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 3. Make sure first argument is an object; convert if necessary.
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: actual number of arguments
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: function
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { Label call_to_object, use_global_receiver, patch_receiver, done;
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, MemOperand(r2, -kPointerSize));
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0: actual number of arguments
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: first argument
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r2, Operand(kSmiTagMask));
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &call_to_object);
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(r3, Heap::kNullValueRootIndex);
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r2, r3);
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &use_global_receiver);
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r2, r3);
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &use_global_receiver);
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CompareObjectType(r2, r3, r3, FIRST_JS_OBJECT_TYPE);
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(lt, &call_to_object);
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r3, Operand(LAST_JS_OBJECT_TYPE));
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(le, &done);
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&call_to_object);
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ EnterInternalFrame();
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Store number of arguments and function across the call into the runtime.
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r0, Operand(r0, LSL, kSmiTagSize));
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(r0);
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(r1);
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(r2);
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r2, r0);
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Restore number of arguments and function.
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ pop(r1);
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ pop(r0);
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r0, Operand(r0, ASR, kSmiTagSize));
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LeaveInternalFrame();
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(&patch_receiver);
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Use the global receiver object from the called function as the receiver.
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&use_global_receiver);
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const int kGlobalIndex =
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, FieldMemOperand(cp, kGlobalIndex));
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&patch_receiver);
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2));
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r2, MemOperand(r3, -kPointerSize));
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&done);
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 4. Shift stuff one slot down the stack
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: actual number of arguments (including call() receiver)
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: function
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { Label loop;
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Calculate the copy start address (destination). Copy end address is sp.
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r2, r2, Operand(kPointerSize));  // copy receiver too
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&loop);
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(ip, MemOperand(r2, -kPointerSize));
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(ip, MemOperand(r2));
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r2, r2, Operand(kPointerSize));
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r2, sp);
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &loop);
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 5. Adjust the actual number of arguments and remove the top element.
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: actual number of arguments (including call() receiver)
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: function
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(r0, r0, Operand(1));
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 6. Get the code for the function or the non-function builtin.
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //    If number of expected arguments matches, then call. Otherwise restart
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //    the arguments adaptor stub.
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: actual number of arguments
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: function
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { Label invoke;
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r1, r1);
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &invoke);
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r2, Operand(0));  // expected arguments is 0 for CALL_NON_FUNCTION
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         RelocInfo::CODE_TARGET);
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&invoke);
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2,
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           FieldMemOperand(r3,
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           SharedFunctionInfo::kFormalParameterCountOffset));
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r3,
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           MemOperand(r3, SharedFunctionInfo::kCodeOffset - kHeapObjectTag));
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r2, r0);  // Check formal and actual parameter counts.
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         RelocInfo::CODE_TARGET, ne);
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // 7. Jump to the code in r3 without checking arguments.
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ParameterCount expected(0);
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ InvokeCode(r3, expected, expected, JUMP_FUNCTION);
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kIndexOffset    = -5 * kPointerSize;
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kLimitOffset    = -4 * kPointerSize;
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kArgsOffset     =  2 * kPointerSize;
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kRecvOffset     =  3 * kPointerSize;
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kFunctionOffset =  4 * kPointerSize;
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ EnterInternalFrame();
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(fp, kFunctionOffset));  // get the function
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(fp, kArgsOffset));  // get the args array
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_JS);
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label no_preemption, retry_preemption;
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&retry_preemption);
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference stack_guard_limit_address =
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ExternalReference::address_of_stack_guard_limit();
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r2, Operand(stack_guard_limit_address));
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, MemOperand(r2));
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(sp, r2);
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(hi, &no_preemption);
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We have encountered a preemption or stack overflow already before we push
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the array contents.  Save r0 which is the Smi-tagged length of the array.
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Runtime routines expect at least one argument, so give it a Smi.
1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(Smi::FromInt(0)));
1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CallRuntime(Runtime::kStackGuard, 1);
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Since we returned, it wasn't a stack overflow.  Restore r0 and try again.
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(r0);
1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(&retry_preemption);
1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&no_preemption);
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Eagerly check for stack-overflow before starting to push the arguments.
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: number of arguments.
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: stack limit.
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label okay;
1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(r2, sp, r2);
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(hi, &okay);
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Out of stack space.
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(fp, kFunctionOffset));
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);
1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_JS);
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push current limit and index.
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&okay);
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);  // limit
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r1, Operand(0));  // initial index
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Change context eagerly to get the right global object if necessary.
1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(fp, kFunctionOffset));
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(cp, FieldMemOperand(r0, JSFunction::kContextOffset));
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the receiver.
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label call_to_object, use_global_receiver, push_receiver;
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(fp, kRecvOffset));
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(r0, Operand(kSmiTagMask));
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &call_to_object);
1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(r1, Heap::kNullValueRootIndex);
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, r1);
1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &use_global_receiver);
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, r1);
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &use_global_receiver);
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if the receiver is already a JavaScript object.
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: receiver
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE);
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(lt, &call_to_object);
1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE));
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(le, &push_receiver);
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Convert the receiver to a regular object.
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: receiver
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&call_to_object);
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(&push_receiver);
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use the current global receiver object as the receiver.
1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&use_global_receiver);
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kGlobalOffset =
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, FieldMemOperand(cp, kGlobalOffset));
1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push the receiver.
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: receiver
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&push_receiver);
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Copy all arguments from the array to the stack.
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label entry, loop;
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(fp, kIndexOffset));
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(&entry);
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the current argument from the arguments array and push it to the
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // stack.
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: current argument index
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&loop);
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(fp, kArgsOffset));
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);
1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call the runtime to access the property in the arguments array.
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CallRuntime(Runtime::kGetProperty, 2);
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use inline caching to access the arguments.
1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(fp, kIndexOffset));
1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r0, r0, Operand(1 << kSmiTagSize));
1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r0, MemOperand(fp, kIndexOffset));
1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test if the copy loop has finished copying all the elements from the
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // arguments object.
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&entry);
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(fp, kLimitOffset));
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, r1);
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &loop);
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the function.
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount actual(r0);
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(r0, ASR, kSmiTagSize));
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(fp, kFunctionOffset));
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ InvokeFunction(r1, actual, CALL_FUNCTION);
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tear down the internal frame and remove function, receiver and args.
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LeaveInternalFrame();
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(3 * kPointerSize));
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(r0, LSL, kSmiTagSize));
1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() | fp.bit() | lr.bit());
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(fp, sp, Operand(3 * kPointerSize));
1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0 : result being passed through
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the number of arguments passed (as a smi), tear down the frame and
1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // then tear down the parameters.
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(fp, -3 * kPointerSize));
1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(sp, fp);
1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldm(ia_w, sp, fp.bit() | lr.bit());
1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));  // adjust for receiver
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0 : actual number of arguments
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r1 : function (passed through to callee)
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2 : expected number of arguments
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r3 : code entry to call
1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label invoke, dont_adapt_arguments;
1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label enough, too_few;
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, Operand(r2));
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(lt, &too_few);
1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &dont_adapt_arguments);
1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {  // Enough parameters: actual >= expected
1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&enough);
1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    EnterArgumentsAdaptorFrame(masm);
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Calculate copy start address into r0 and copy end address into r2.
1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0: actual number of arguments as a smi
1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: expected number of arguments
1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: code entry to call
1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // adjust for return address and receiver
1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, r0, Operand(2 * kPointerSize));
1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r2, r0, Operand(r2, LSL, kPointerSizeLog2));
1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Copy the arguments (including the receiver) to the new stack frame.
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0: copy start address
1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: copy end address
1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: code entry to call
1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label copy;
1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&copy);
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(ip, MemOperand(r0, 0));
1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(ip);
1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r0, r2);  // Compare before moving to next argument.
1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r0, r0, Operand(kPointerSize));
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &copy);
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(&invoke);
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {  // Too few parameters: Actual < expected
1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&too_few);
1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    EnterArgumentsAdaptorFrame(masm);
1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Calculate copy start address into r0 and copy end address is fp.
1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0: actual number of arguments as a smi
1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: expected number of arguments
1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: code entry to call
1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Copy the arguments (including the receiver) to the new stack frame.
1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0: copy start address
1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: expected number of arguments
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: code entry to call
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label copy;
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&copy);
1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Adjust load for return address and receiver.
1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(ip, MemOperand(r0, 2 * kPointerSize));
1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(ip);
1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r0, fp);  // Compare before moving to next argument.
1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r0, r0, Operand(kPointerSize));
1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &copy);
1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Fill the remaining expected arguments with undefined.
1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: expected number of arguments
1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: code entry to call
1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r2, fp, Operand(r2, LSL, kPointerSizeLog2));
1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r2, r2, Operand(4 * kPointerSize));  // Adjust for frame.
1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label fill;
1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&fill);
1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(ip);
1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(sp, r2);
1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &fill);
1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call the entry point.
1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&invoke);
1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Call(r3);
1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Exit frame and return.
1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LeaveArgumentsAdaptorFrame(masm);
1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -------------------------------------------
1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Dont adapt arguments.
1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -------------------------------------------
1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&dont_adapt_arguments);
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(r3);
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
1288