builtins-arm.cc revision 3fb3ca8c7ca439d408449a395897395c0faae8d1
18b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Copyright 2011 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
30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_ARM)
31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "codegen.h"
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "debug.h"
34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "deoptimizer.h"
35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "full-codegen.h"
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "runtime.h"
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm)
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
45e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_Adaptor(MacroAssembler* masm,
46e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                CFunctionId id,
47e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                BuiltinExtraArguments extra_args) {
48e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // ----------- S t a t e -------------
49e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- r0                 : number of arguments excluding receiver
50e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- r1                 : called function (only guaranteed when
51e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //                          extra_args requires it)
52e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- cp                 : context
53e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- sp[0]              : last argument
54e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- ...
55e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- sp[4 * (argc - 1)] : first argument (argc == r0)
56e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  //  -- sp[4 * argc]       : receiver
57e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // -----------------------------------
58e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
59e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Insert extra arguments.
60e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  int num_extra_args = 0;
61e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (extra_args == NEEDS_CALLED_FUNCTION) {
62e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    num_extra_args = 1;
63e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ push(r1);
64e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
65e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(extra_args == NO_EXTRA_ARGUMENTS);
66e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
67e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // JumpToExternalReference expects r0 to contain the number of arguments
69e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // including the receiver and the extra arguments.
70e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  __ add(r0, r0, Operand(num_extra_args + 1));
7144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ JumpToExternalReference(ExternalReference(id, masm->isolate()));
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load the built-in Array function from the current context.
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) {
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the global context.
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(result,
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(result, GlobalObject::kGlobalContextOffset));
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the Array function from the global context.
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(result,
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         MemOperand(result,
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This constant has the same value as JSArray::kPreallocatedArrayElements and
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// if JSArray::kPreallocatedArrayElements is changed handling of loop unfolding
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// below should be reconsidered.
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kLoopUnfoldLimit = 4;
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Allocate an empty JSArray. The allocated array is put into the result
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register. An elements backing store is allocated with size initial_capacity
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and filled with the hole values.
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void AllocateEmptyJSArray(MacroAssembler* masm,
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register array_function,
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register result,
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register scratch1,
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register scratch2,
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register scratch3,
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 int initial_capacity,
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Label* gc_required) {
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(initial_capacity > 0);
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map from the array function.
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(scratch1, FieldMemOperand(array_function,
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   JSFunction::kPrototypeOrInitialMapOffset));
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate the JSArray object together with space for a fixed array with the
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // requested elements.
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int size = JSArray::kSize + FixedArray::SizeFor(initial_capacity);
11425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  __ AllocateInNewSpace(size,
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        result,
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        scratch2,
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        scratch3,
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        gc_required,
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        TAG_OBJECT);
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocated the JSArray. Now initialize the fields except for the elements
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array.
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch1: initial map
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch2: start of next object
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch1, FieldMemOperand(result, JSObject::kMapOffset));
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex);
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch1, FieldMemOperand(result, JSArray::kPropertiesOffset));
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Field JSArray::kElementsOffset is initialized later.
1309ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  __ mov(scratch3,  Operand(0, RelocInfo::NONE));
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch3, FieldMemOperand(result, JSArray::kLengthOffset));
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the location of the elements array and set elements array member
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // of the JSArray.
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch2: start of next object
137f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(scratch1, result, Operand(JSArray::kSize));
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch1, FieldMemOperand(result, JSArray::kElementsOffset));
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the heap tag on the elements array.
1419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ASSERT(kSmiTag == 0);
1429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ sub(scratch1, scratch1, Operand(kHeapObjectTag));
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Initialize the FixedArray and fill it with holes. FixedArray length is
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // stored as a smi.
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch1: elements array (untagged)
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch2: start of next object
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(scratch3, Heap::kFixedArrayMapRootIndex);
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset);
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
1527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(scratch3,  Operand(Smi::FromInt(initial_capacity)));
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the FixedArray with the hole value.
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(initial_capacity <= kLoopUnfoldLimit);
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex);
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < initial_capacity; i++) {
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Allocate a JSArray with the number of elements stored in a register. The
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register array_function holds the built-in Array function and the register
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// array_size holds the size of the array as a smi. The allocated array is put
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// into the result register and beginning and end of the FixedArray elements
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// storage is put into registers elements_array_storage and elements_array_end
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (see  below for when that is not the case). If the parameter fill_with_holes
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// is true the allocated elements backing store is filled with the hole values
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// otherwise it is left uninitialized. When the backing store is filled the
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register elements_array_storage is scratched.
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void AllocateJSArray(MacroAssembler* masm,
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register array_function,  // Array function.
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register array_size,  // As a smi.
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register result,
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register elements_array_storage,
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register elements_array_end,
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register scratch1,
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register scratch2,
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            bool fill_with_hole,
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Label* gc_required) {
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label not_empty, allocated;
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map from the array function.
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(elements_array_storage,
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(array_function,
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         JSFunction::kPrototypeOrInitialMapOffset));
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check whether an empty sized array is requested.
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(array_size, array_size);
1931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ b(ne, &not_empty);
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If an empty array is requested allocate a small elements array anyway. This
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // keeps the code below free of special casing for the empty array.
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int size = JSArray::kSize +
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
19925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  __ AllocateInNewSpace(size,
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        result,
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        elements_array_end,
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        scratch1,
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        gc_required,
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        TAG_OBJECT);
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&allocated);
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate the JSArray object together with space for a FixedArray with the
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // requested number of elements.
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&not_empty);
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(elements_array_end,
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Operand((JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize));
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(elements_array_end,
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         elements_array_end,
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Operand(array_size, ASR, kSmiTagSize));
21625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  __ AllocateInNewSpace(
21725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      elements_array_end,
21825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      result,
21925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      scratch1,
22025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      scratch2,
22125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      gc_required,
22225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocated the JSArray. Now initialize the fields except for the elements
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array.
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_storage: initial map
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array_size: size of array (smi)
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&allocated);
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(elements_array_storage, FieldMemOperand(result, JSObject::kMapOffset));
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(elements_array_storage, Heap::kEmptyFixedArrayRootIndex);
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(elements_array_storage,
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(result, JSArray::kPropertiesOffset));
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Field JSArray::kElementsOffset is initialized later.
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(array_size, FieldMemOperand(result, JSArray::kLengthOffset));
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the location of the elements array and set elements array member
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // of the JSArray.
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array_size: size of array (smi)
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(elements_array_storage, result, Operand(JSArray::kSize));
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(elements_array_storage,
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(result, JSArray::kElementsOffset));
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the heap tag on the elements array.
2469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  ASSERT(kSmiTag == 0);
2479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ sub(elements_array_storage,
2489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen         elements_array_storage,
2499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen         Operand(kHeapObjectTag));
2507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Initialize the fixed array and fill it with holes. FixedArray length is
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // stored as a smi.
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_storage: elements array (untagged)
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array_size: size of array (smi)
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(scratch1, Heap::kFixedArrayMapRootIndex);
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset);
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch1, MemOperand(elements_array_storage, kPointerSize, PostIndex));
2587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(kSmiTag == 0);
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ tst(array_size, array_size);
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Length of the FixedArray is the number of pre-allocated elements if
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the actual JSArray has length 0 and the size of the JSArray for non-empty
2627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // JSArrays. The length of a FixedArray is stored as a smi.
2637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(array_size,
2647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch         Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements)),
2657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch         LeaveCC,
2667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch         eq);
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(array_size,
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         MemOperand(elements_array_storage, kPointerSize, PostIndex));
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate elements array and elements array end.
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_storage: elements array element storage
2747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // array_size: smi-tagged size of elements array
2757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(elements_array_end,
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         elements_array_storage,
2787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch         Operand(array_size, LSL, kPointerSizeLog2 - kSmiTagSize));
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the allocated FixedArray with the hole value if requested.
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_storage: elements array element storage
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_end: start of next object
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (fill_with_hole) {
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label loop, entry;
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(scratch1, Heap::kTheHoleValueRootIndex);
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ jmp(&entry);
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&loop);
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(scratch1,
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           MemOperand(elements_array_storage, kPointerSize, PostIndex));
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&entry);
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(elements_array_storage, elements_array_end);
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(lt, &loop);
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Create a new array for the built-in Array function. This function allocates
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the JSArray object and the FixedArray elements array and initializes these.
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// If the Array cannot be constructed in native code the runtime is called. This
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// function assumes the following state:
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   r0: argc
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   r1: constructor (built-in Array function)
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   lr: return address
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   sp[0]: last argument
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This function is used for both construct and normal calls of Array. The only
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// difference between handling a construct call and a normal call is that for a
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// construct call the constructor function in r1 needs to be preserved for
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// entering the generic code. In both cases argc in r0 needs to be preserved.
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Both registers are preserved by this code so no need to differentiate between
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// construct call and normal call.
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ArrayNativeCode(MacroAssembler* masm,
312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                            Label* call_generic_code) {
31344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm->isolate()->counters();
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label argc_one_or_more, argc_two_or_more;
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for array construction with zero arguments or one.
3179ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  __ cmp(r0, Operand(0, RelocInfo::NONE));
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &argc_one_or_more);
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle construction of an empty array.
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AllocateEmptyJSArray(masm,
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       r1,
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       r2,
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       r3,
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       r4,
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       r5,
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       JSArray::kPreallocatedArrayElements,
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       call_generic_code);
32944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->array_function_native(), 1, r3, r4);
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setup return value, remove receiver from stack and return.
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, r2);
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for one argument. Bail out if argument is not smi or if it is
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // negative.
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&argc_one_or_more);
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, Operand(1));
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &argc_two_or_more);
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kSmiTag == 0);
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, MemOperand(sp));  // Get the argument from the stack.
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(r3, r2, Operand(kIntptrSignBit | kSmiTagMask), SetCC);
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, call_generic_code);
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle construction of an empty array of a certain size. Bail out if size
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is too large to actually allocate an elements array.
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(kSmiTag == 0);
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, Operand(JSObject::kInitialMaxFastElementArray << kSmiTagSize));
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ge, call_generic_code);
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: array_size (smi)
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: argument
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AllocateJSArray(masm,
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r1,
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r2,
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r3,
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r4,
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r5,
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r6,
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r7,
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  true,
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  call_generic_code);
36544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->array_function_native(), 1, r2, r4);
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setup return value, remove receiver and argument from stack and return.
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, r3);
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(2 * kPointerSize));
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle construction of an array from a list of arguments.
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&argc_two_or_more);
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r2, Operand(r0, LSL, kSmiTagSize));  // Convet argc to a smi.
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: array_size (smi)
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: last argument
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AllocateJSArray(masm,
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r1,
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r2,
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r3,
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r4,
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r5,
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r6,
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r7,
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  false,
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  call_generic_code);
38944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->array_function_native(), 1, r2, r6);
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill arguments as array elements. Copy from the top of the stack (last
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // element) to the array backing store filling it backwards. Note:
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_end points after the backing store therefore PreIndex is
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // used when filling the backing store.
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: JSArray
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: elements_array storage start (untagged)
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r5: elements_array_end (untagged)
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: last argument
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label loop, entry;
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&entry);
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&loop);
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, MemOperand(sp, kPointerSize, PostIndex));
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r2, MemOperand(r5, -kPointerSize, PreIndex));
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&entry);
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r4, r5);
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(lt, &loop);
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove caller arguments and receiver from the stack, setup return value and
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // return.
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: JSArray
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, r3);
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArrayCode(MacroAssembler* masm) {
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0     : number of arguments
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr     : return address
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[...]: constructor arguments
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the Array function.
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadArrayFunction(masm, r1);
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_debug_code) {
432e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Initial map for the builtin Array functions should be maps.
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r2, Operand(kSmiTagMask));
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(ne, "Unexpected initial map for Array function");
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CompareObjectType(r2, r3, r4, MAP_TYPE);
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(eq, "Unexpected initial map for Array function");
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run the native code for the Array function called as a normal function.
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ArrayNativeCode(masm, &generic_array_code);
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the generic array code if the specialized code cannot handle
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the construction.
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&generic_array_code);
44644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
44744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> array_code =
44844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      masm->isolate()->builtins()->ArrayCodeGeneric();
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(array_code, RelocInfo::CODE_TARGET);
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) {
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0     : number of arguments
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r1     : constructor function
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr     : return address
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[...]: constructor arguments
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label generic_constructor;
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_debug_code) {
463e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // The array construct code is only set for the builtin and internal
464e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Array functions which always have a map.
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Initial map for the builtin Array function should be a map.
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r2, Operand(kSmiTagMask));
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(ne, "Unexpected initial map for Array function");
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CompareObjectType(r2, r3, r4, MAP_TYPE);
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(eq, "Unexpected initial map for Array function");
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run the native code for the Array function called as a constructor.
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ArrayNativeCode(masm, &generic_constructor);
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the generic construct code in case the specialized code cannot
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // handle the construction.
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&generic_constructor);
47944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> generic_construct_stub =
48044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      masm->isolate()->builtins()->JSConstructStubGeneric();
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
48580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
4868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // ----------- S t a t e -------------
4878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- r0                     : number of arguments
4888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- r1                     : constructor function
4898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- lr                     : return address
4908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
4918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[argc * 4]           : receiver
4928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // -----------------------------------
49344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm->isolate()->counters();
49444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->string_ctor_calls(), 1, r2, r3);
4958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register function = r1;
4978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (FLAG_debug_code) {
4988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, r2);
4998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ cmp(function, Operand(r2));
5008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ Assert(eq, "Unexpected String function");
5018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
5028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the first arguments in r0 and get rid of the rest.
5048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label no_arguments;
505b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ cmp(r0, Operand(0, RelocInfo::NONE));
5068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(eq, &no_arguments);
5078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // First args = sp[(argc - 1) * 4].
5088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ sub(r0, r0, Operand(1));
5098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(r0, MemOperand(sp, r0, LSL, kPointerSizeLog2, PreIndex));
5108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // sp now point to args[0], drop args[0] + receiver.
5118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Drop(2);
5128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register argument = r2;
5148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label not_cached, argument_is_string;
5158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  NumberToStringStub::GenerateLookupNumberStringCache(
5168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      masm,
5178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      r0,        // Input.
5188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      argument,  // Result.
5198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      r3,        // Scratch.
5208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      r4,        // Scratch.
5218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      r5,        // Scratch.
5228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      false,     // Is it a Smi?
5238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      &not_cached);
52444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->string_ctor_cached_number(), 1, r3, r4);
5258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&argument_is_string);
5268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // ----------- S t a t e -------------
5288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- r2     : argument converted to string
5298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- r1     : constructor function
5308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- lr     : return address
5318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // -----------------------------------
5328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label gc_required;
5348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ AllocateInNewSpace(JSValue::kSize,
5358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                        r0,  // Result.
5368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                        r3,  // Scratch.
5378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                        r4,  // Scratch.
5388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                        &gc_required,
5398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                        TAG_OBJECT);
5408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Initialising the String Object.
5428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register map = r3;
5438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ LoadGlobalFunctionInitialMap(function, map, r4);
5448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (FLAG_debug_code) {
5458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldrb(r4, FieldMemOperand(map, Map::kInstanceSizeOffset));
5468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ cmp(r4, Operand(JSValue::kSize >> kPointerSizeLog2));
5478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ Assert(eq, "Unexpected string wrapper instance size");
5488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldrb(r4, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset));
549b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ cmp(r4, Operand(0, RelocInfo::NONE));
5508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ Assert(eq, "Unexpected unused properties of string wrapper");
5518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
5528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ str(map, FieldMemOperand(r0, HeapObject::kMapOffset));
5538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex);
5558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset));
5568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset));
5578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ str(argument, FieldMemOperand(r0, JSValue::kValueOffset));
5598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Ensure the object is fully initialized.
5618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
5628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Ret();
5648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // The argument was not found in the number to string cache. Check
5668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // if it's a string already before calling the conversion builtin.
5678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label convert_argument;
5688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&not_cached);
5691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, &convert_argument);
5708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Is it a String?
5728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
5738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceTypeOffset));
5748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  ASSERT(kNotStringTag != 0);
5758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ tst(r3, Operand(kIsNotStringMask));
5768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(ne, &convert_argument);
5778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(argument, r0);
57844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4);
5798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&argument_is_string);
5808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Invoke the conversion builtin and put the result into r2.
5828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&convert_argument);
5838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(function);  // Preserve the function.
58444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4);
5858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ EnterInternalFrame();
5868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(r0);
587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
5888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ LeaveInternalFrame();
5898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ pop(function);
5908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(argument, r0);
5918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&argument_is_string);
5928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the empty string into r2, remove the receiver from the
5948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // stack, and jump back to the case where the argument is a string.
5958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&no_arguments);
5968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ LoadRoot(argument, Heap::kEmptyStringRootIndex);
5978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Drop(1);
5988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&argument_is_string);
5998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // At this point the argument is already a string. Call runtime to
6018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // create a string wrapper.
6028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&gc_required);
60344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->string_ctor_gc_required(), 1, r3, r4);
6048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ EnterInternalFrame();
6058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(argument);
6068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ CallRuntime(Runtime::kNewStringWrapper, 1);
6078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ LeaveInternalFrame();
6088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Ret();
60980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
61080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
61180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0     : number of arguments
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r1     : constructor function
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr     : return address
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[...]: constructor arguments
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label non_function_call;
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function is not a smi.
6223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(r1, &non_function_call);
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the function is a JSFunction.
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &non_function_call);
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the function-specific construct stub.
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kConstructStubOffset));
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(pc, r2, Operand(Code::kHeaderSize - kHeapObjectTag));
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: number of arguments
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: called object
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&non_function_call);
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set expected number of arguments to zero (not changing r0).
6369ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  __ mov(r2, Operand(0, RelocInfo::NONE));
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ SetCallKind(r5, CALL_AS_METHOD);
63944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          RelocInfo::CODE_TARGET);
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkestatic void Generate_JSConstructStubHelper(MacroAssembler* masm,
6450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                           bool is_api_function,
6460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                           bool count_constructions) {
6470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Should never count constructions for api objects.
6480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!is_api_function || !count_constructions);
6490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
65044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = masm->isolate();
65144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enter a construct frame.
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ EnterConstructFrame();
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Preserve the two incoming parameters on the stack.
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(r0, LSL, kSmiTagSize));
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);  // Smi-tagged arguments count.
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);  // Constructor function.
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Try to allocate the object without transitioning into C code. If any of the
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // preconditions is not met, the code bails out to the runtime call.
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label rt_call, allocated;
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_inline_new) {
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label undo_allocation;
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ExternalReference debug_step_in_fp =
66744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ExternalReference::debug_step_in_fp_address(isolate);
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r2, Operand(debug_step_in_fp));
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, MemOperand(r2));
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r2, r2);
6711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(ne, &rt_call);
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Load the initial map and verify that it is in fact a map.
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
6773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(r2, &rt_call);
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CompareObjectType(r2, r3, r4, MAP_TYPE);
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &rt_call);
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check that the constructor is not constructing a JSFunction (see comments
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // in Runtime_NewObject in runtime.cc). In which case the initial map's
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // instance type would be JS_FUNCTION_TYPE.
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: initial map
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE);
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &rt_call);
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (count_constructions) {
6900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      Label allocate;
6910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Decrease generous allocation count.
6920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
6930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      MemOperand constructor_count =
6940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          FieldMemOperand(r3, SharedFunctionInfo::kConstructionCountOffset);
6950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ ldrb(r4, constructor_count);
6960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ sub(r4, r4, Operand(1), SetCC);
6970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ strb(r4, constructor_count);
6980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ b(ne, &allocate);
6990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
7000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ Push(r1, r2);
7010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
7020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ push(r1);  // constructor
7030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // The call will replace the stub, so the countdown is only done once.
7040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
7050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
7060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ pop(r2);
7070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ pop(r1);
7080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
7090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      __ bind(&allocate);
7100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
7110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Now allocate the JSObject on the heap.
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: initial map
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
71625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS);
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Allocated the JSObject, now initialize the fields. Map is set to initial
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // map and properties and elements are set to empty fixed array.
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: initial map
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: object size
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject (not tagged)
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r5, r4);
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // Fill all the in-object properties with the appropriate filler.
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: initial map
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: object size (in words)
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject (not tagged)
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r5: First in-object property of JSObject (not tagged)
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    { Label loop, entry;
7420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      if (count_constructions) {
7430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        // To allow for truncation.
7440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        __ LoadRoot(r7, Heap::kOnePointerFillerMapRootIndex);
7450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      } else {
7460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
7470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(&entry);
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&loop);
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r7, MemOperand(r5, kPointerSize, PostIndex));
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&entry);
7526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ cmp(r5, r6);
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(lt, &loop);
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Add the object tag to make the JSObject real, so that we can continue and
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // jump into the continuation code at any time from now on. Any failures
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // need to undo the allocation, so that the heap is in a consistent state
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // and verifiable.
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r4, r4, Operand(kHeapObjectTag));
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check if a non-empty properties array is needed. Continue with allocated
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // object if not fall through to runtime call if it is.
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r5: start of next object (not tagged)
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset));
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The field instance sizes contains both pre-allocated property fields and
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // in-object properties.
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
7719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    __ Ubfx(r6, r0, Map::kPreAllocatedPropertyFieldsByte * 8, 8);
7729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    __ add(r3, r3, Operand(r6));
7739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    __ Ubfx(r6, r0, Map::kInObjectPropertiesByte * 8, 8);
7749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    __ sub(r3, r3, Operand(r6), SetCC);
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Done if no extra properties are to be allocated.
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &allocated);
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(pl, "Property allocation count failed.");
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Scale the number of elements by pointer size and add the header for
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // FixedArrays to the start of the next object calculation from above.
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: number of elements in properties array
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r5: start of next object
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize));
78725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    __ AllocateInNewSpace(
78825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        r0,
78925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        r5,
79025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        r6,
79125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        r2,
79225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        &undo_allocation,
79325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS));
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Initialize the FixedArray.
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor
797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: number of elements in properties array
798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject
799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r5: FixedArray (not tagged)
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex);
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r2, r5);
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r6, MemOperand(r2, kPointerSize, PostIndex));
8047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
8057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ mov(r0, Operand(r3, LSL, kSmiTagSize));
8067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ str(r0, MemOperand(r2, kPointerSize, PostIndex));
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Initialize the fields to undefined.
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: First element of FixedArray (not tagged)
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: number of elements in properties array
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r5: FixedArray (not tagged)
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    { Label loop, entry;
8170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      if (count_constructions) {
8180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
8190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      } else if (FLAG_debug_code) {
8200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        __ LoadRoot(r8, Heap::kUndefinedValueRootIndex);
8210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        __ cmp(r7, r8);
8220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        __ Assert(eq, "Undefined value not loaded.");
8230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(&entry);
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&loop);
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ str(r7, MemOperand(r2, kPointerSize, PostIndex));
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&entry);
8286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ cmp(r2, r6);
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(lt, &loop);
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Store the initialized FixedArray into the properties field of
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // the JSObject
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r5: FixedArray (not tagged)
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r5, r5, Operand(kHeapObjectTag));  // Add the heap tag.
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r5, FieldMemOperand(r4, JSObject::kPropertiesOffset));
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Continue with JSObject being successfully allocated
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ jmp(&allocated);
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Undo the setting of the new top so that the heap is verifiable. For
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // example, the map's unused properties potentially do not match the
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // allocated objects unused properties.
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject (previous new top)
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&undo_allocation);
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ UndoAllocationInNewSpace(r4, r5);
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate the new receiver object using the runtime call.
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&rt_call);
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);  // argument for Runtime_NewObject
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CallRuntime(Runtime::kNewObject, 1);
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r4, r0);
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Receiver for constructor call allocated.
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: JSObject
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&allocated);
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r4);
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push the function and the allocated receiver from the stack.
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver (newly allocated object)
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[1]: constructor function
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: number of arguments (smi-tagged)
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(sp, kPointerSize));
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);  // Constructor function.
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r4);  // Receiver.
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reload the number of arguments from the stack.
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[1]: constructor function
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: receiver
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[3]: constructor function
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[4]: number of arguments (smi-tagged)
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r3, MemOperand(sp, 4 * kPointerSize));
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setup pointer to last argument.
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setup number of arguments for function call below
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(r3, LSR, kSmiTagSize));
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Copy arguments and receiver to the expression stack.
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: number of arguments
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: address of last argument (caller sp)
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: number of arguments (smi-tagged)
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[1]: constructor function
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: receiver
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[3]: constructor function
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[4]: number of arguments (smi-tagged)
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label loop, entry;
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(&entry);
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&loop);
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1));
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(ip);
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&entry);
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(r3, r3, Operand(2), SetCC);
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ge, &loop);
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call the function.
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: number of arguments
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor function
910e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (is_api_function) {
911e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
91244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<Code> code =
91344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        masm->isolate()->builtins()->HandleApiCallConstruct();
914e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ParameterCount expected(0);
915e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ InvokeCode(code, expected, expected,
916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  RelocInfo::CODE_TARGET, CALL_FUNCTION, CALL_AS_METHOD);
917e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else {
918e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ParameterCount actual(r0);
919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ InvokeFunction(r1, actual, CALL_FUNCTION,
920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      NullCallWrapper(), CALL_AS_METHOD);
921e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Pop the function from the stack.
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: constructor function
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: receiver
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[3]: constructor function
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[4]: number of arguments (smi-tagged)
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop();
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore context from the frame.
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: result
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[1]: constructor function
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: number of arguments (smi-tagged)
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the result is an object (in the ECMA sense), we should get rid
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // of the receiver and use the result; see ECMA-262 section 13.2.2-7
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // on page 74.
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label use_receiver, exit;
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the result is a smi, it is *not* an object in the ECMA sense.
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: result
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver (newly allocated object)
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[1]: constructor function
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: number of arguments (smi-tagged)
9473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(r0, &use_receiver);
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the type of the result (stored in its map) is less than
9503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
9513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CompareObjectType(r0, r3, r3, FIRST_SPEC_OBJECT_TYPE);
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ge, &exit);
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Throw away the result of the constructor invocation and use the
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // on-stack receiver as the result.
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&use_receiver);
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(sp));
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove receiver from the stack, remove caller arguments, and
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // return.
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&exit);
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: result
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver (newly allocated object)
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[1]: constructor function
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[2]: number of arguments (smi-tagged)
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(sp, 2 * kPointerSize));
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LeaveConstructFrame();
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));
97044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2);
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9750d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
9760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Generate_JSConstructStubHelper(masm, false, true);
9770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
9780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
9790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
980e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
9810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Generate_JSConstructStubHelper(masm, false, false);
982e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
983e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
984e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
985e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
9860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Generate_JSConstructStubHelper(masm, true, false);
987e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
988e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
989e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             bool is_construct) {
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Called from Generate_JS_Entry
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: code entry
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: function
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: receiver
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: argc
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: argv
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r5-r7, cp may be clobbered
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the context before we push it when entering the JS frame.
10019ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  __ mov(cp, Operand(0, RelocInfo::NONE));
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enter an internal frame.
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ EnterInternalFrame();
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set up the context from the function argument.
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set up the roots register.
101044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference roots_address =
101144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::roots_address(masm->isolate());
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r10, Operand(roots_address));
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push the function and the receiver onto the stack.
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r2);
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Copy arguments to the stack in a loop.
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: function
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: argc
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: argv, i.e. points to first arg
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label loop, entry;
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2));
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2 points past last arg.
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(&entry);
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&loop);
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex));  // read next parameter
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(r0));  // dereference handle
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);  // push parameter
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&entry);
10316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(r4, r2);
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &loop);
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Initialize all JavaScript callee-saved registers, since they will be seen
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // by the garbage collector as part of handlers.
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r5, Operand(r4));
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r6, Operand(r4));
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r7, Operand(r4));
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (kR9Available == 1) {
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r9, Operand(r4));
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the code and pass argc as r0.
1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(r3));
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (is_construct) {
10473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ Call(masm->isolate()->builtins()->JSConstructCall());
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ParameterCount actual(r0);
1050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ InvokeFunction(r1, actual, CALL_FUNCTION,
1051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      NullCallWrapper(), CALL_AS_METHOD);
1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Exit the JS frame and remove the parameters (except function), and return.
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Respect ABI stack constraint.
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LeaveInternalFrame();
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: result
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Generate_JSEntryTrampolineHelper(masm, false);
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Generate_JSEntryTrampolineHelper(masm, true);
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1073756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid Builtins::Generate_LazyCompile(MacroAssembler* masm) {
1074756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Enter an internal frame.
1075756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ EnterInternalFrame();
1076756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1077756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Preserve the function.
1078756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ push(r1);
1079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Push call kind information.
1080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ push(r5);
1081756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1082756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Push the function on the stack as the argument to the runtime function.
1083756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ push(r1);
1084756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ CallRuntime(Runtime::kLazyCompile, 1);
1085756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Calculate the entry point.
1086756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
1087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Restore call kind information.
1089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ pop(r5);
1090756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Restore saved function.
1091756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ pop(r1);
1092756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1093756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Tear down temporary frame.
1094756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ LeaveInternalFrame();
1095756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1096756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Do a tail-call of the compiled function.
1097756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ Jump(r2);
1098756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
1099756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1100756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_LazyRecompile(MacroAssembler* masm) {
1102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Enter an internal frame.
1103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ EnterInternalFrame();
1104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Preserve the function.
1106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ push(r1);
1107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Push call kind information.
1108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ push(r5);
1109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Push the function on the stack as the argument to the runtime function.
1111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ push(r1);
1112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ CallRuntime(Runtime::kLazyRecompile, 1);
1113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Calculate the entry point.
1114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
1115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Restore call kind information.
1117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ pop(r5);
1118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Restore saved function.
1119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ pop(r1);
1120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Tear down temporary frame.
1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ LeaveInternalFrame();
1123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Do a tail-call of the compiled function.
1125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ Jump(r2);
1126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
1130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             Deoptimizer::BailoutType type) {
1131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ EnterInternalFrame();
1132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Pass the function and deoptimization type to the runtime system.
1133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(r0, Operand(Smi::FromInt(static_cast<int>(type))));
1134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ push(r0);
1135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
1136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ LeaveInternalFrame();
1137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Get the full codegen state from the stack and untag it -> r6.
1139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ ldr(r6, MemOperand(sp, 0 * kPointerSize));
1140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ SmiUntag(r6);
1141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Switch on the state.
1142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label with_tos_register, unknown_state;
1143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ cmp(r6, Operand(FullCodeGenerator::NO_REGISTERS));
1144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ b(ne, &with_tos_register);
1145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ add(sp, sp, Operand(1 * kPointerSize));  // Remove state.
1146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ Ret();
1147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&with_tos_register);
1149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ ldr(r0, MemOperand(sp, 1 * kPointerSize));
1150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ cmp(r6, Operand(FullCodeGenerator::TOS_REG));
1151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ b(ne, &unknown_state);
1152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ add(sp, sp, Operand(2 * kPointerSize));  // Remove state.
1153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ Ret();
1154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&unknown_state);
1156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ stop("no cases left");
1157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
1161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
1162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
1166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
1167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_NotifyOSR(MacroAssembler* masm) {
11711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // For now, we are relying on the fact that Runtime::NotifyOSR
11721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // doesn't do any garbage collection which allows us to save/restore
11731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // the registers without worrying about which of them contain
11741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // pointers. This seems a bit fragile.
11751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ stm(db_w, sp, kJSCallerSaved | kCalleeSaved | lr.bit() | fp.bit());
11761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ EnterInternalFrame();
11771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ CallRuntime(Runtime::kNotifyOSR, 0);
11781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ LeaveInternalFrame();
11791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ldm(ia_w, sp, kJSCallerSaved | kCalleeSaved | lr.bit() | fp.bit());
11801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ Ret();
1181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
11858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CpuFeatures::TryForceFeatureScope scope(VFP3);
11868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (!CpuFeatures::IsSupported(VFP3)) {
11878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ Abort("Unreachable code: Cannot optimize without VFP3 support.");
11888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return;
11898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
11901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
11911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Lookup the function in the JavaScript frame and push it as an
11921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // argument to the on-stack replacement function.
11931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
11941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ EnterInternalFrame();
11951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ push(r0);
11961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
11971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ LeaveInternalFrame();
11981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
11991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // If the result was -1 it means that we couldn't optimize the
12001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // function. Just return and continue in the unoptimized version.
12011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Label skip;
12021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ cmp(r0, Operand(Smi::FromInt(-1)));
12031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ b(ne, &skip);
12041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ Ret();
12051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&skip);
12071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Untag the AST id and push it on the stack.
12081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ SmiUntag(r0);
12091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ push(r0);
12101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Generate the code for doing the frame-to-frame translation using
12121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // the deoptimizer infrastructure.
12131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR);
12141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  generator.Generate();
1215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_FunctionCall(MacroAssembler* masm) {
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 1. Make sure we have at least one argument.
1220402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r0: actual number of arguments
1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { Label done;
1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r0, Operand(r0));
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &done);
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(r2);
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, r0, Operand(1));
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&done);
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1230402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // 2. Get the function to call (passed as receiver) from the stack, check
1231402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //    if it is a function.
1232402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r0: actual number of arguments
1233402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Label non_function;
1234402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
12353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(r1, &non_function);
1236402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
1237402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ b(ne, &non_function);
1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1239402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // 3a. Patch the first argument if necessary when calling a function.
1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: actual number of arguments
1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: function
1242402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Label shift_arguments;
1243402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  { Label convert_to_object, use_global_receiver, patch_receiver;
1244402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Change context eagerly in case we need the global receiver.
1245402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1246402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1247e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Do not transform the receiver for strict mode functions.
1248e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ ldr(r3, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset));
1250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ tst(r3, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
1251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                             kSmiTagSize)));
1252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ b(ne, &shift_arguments);
1253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Do not transform the receiver for native (Compilerhints already in r3).
12553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ tst(r3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
1256e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ b(ne, &shift_arguments);
1257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1258e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Compute the receiver in non-strict mode.
1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, MemOperand(r2, -kPointerSize));
1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0: actual number of arguments
1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: first argument
12643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(r2, &convert_to_object);
1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r2, r3);
1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &use_global_receiver);
1269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(r3, Heap::kNullValueRootIndex);
1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r2, r3);
1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &use_global_receiver);
1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
12743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ CompareObjectType(r2, r3, r3, FIRST_SPEC_OBJECT_TYPE);
1275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ b(ge, &shift_arguments);
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1277402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ bind(&convert_to_object);
1278402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ EnterInternalFrame();  // In order to preserve argument count.
1279402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ mov(r0, Operand(r0, LSL, kSmiTagSize));  // Smi-tagged.
1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(r0);
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(r2);
1283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r2, r0);
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ pop(r0);
1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r0, Operand(r0, ASR, kSmiTagSize));
1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LeaveInternalFrame();
1289402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Restore the function to r1.
1290402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
1291402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ jmp(&patch_receiver);
1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1293402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Use the global receiver object from the called function as the
1294402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // receiver.
1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&use_global_receiver);
1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const int kGlobalIndex =
1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, FieldMemOperand(cp, kGlobalIndex));
1299d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalContextOffset));
1300d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(r2, FieldMemOperand(r2, kGlobalIndex));
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&patch_receiver);
1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2));
1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r2, MemOperand(r3, -kPointerSize));
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1307402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ jmp(&shift_arguments);
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1310402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // 3b. Patch the first argument when calling a non-function.  The
1311402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //     CALL_NON_FUNCTION builtin expects the non-function callee as
1312402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //     receiver, so overwrite the first argument which will ultimately
1313402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //     become the receiver.
1314402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r0: actual number of arguments
1315402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r1: function
1316402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ bind(&non_function);
1317402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
1318402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ str(r1, MemOperand(r2, -kPointerSize));
1319402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Clear r1 to indicate a non-function being called.
13209ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  __ mov(r1, Operand(0, RelocInfo::NONE));
1321402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1322402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // 4. Shift arguments and return address one slot down on the stack
1323402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //    (overwriting the original receiver).  Adjust argument count to make
1324402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //    the original first argument the new receiver.
1325402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r0: actual number of arguments
1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: function
1327402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ bind(&shift_arguments);
1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { Label loop;
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Calculate the copy start address (destination). Copy end address is sp.
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&loop);
1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(ip, MemOperand(r2, -kPointerSize));
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(ip, MemOperand(r2));
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r2, r2, Operand(kPointerSize));
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r2, sp);
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &loop);
1338402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Adjust the actual number of arguments and remove the top element
1339402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // (which is a copy of the last argument).
1340402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ sub(r0, r0, Operand(1));
1341402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ pop();
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1344402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin.
1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: actual number of arguments
1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: function
1347402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  { Label function;
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r1, r1);
1349402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ b(ne, &function);
13509ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // Expected number of arguments is 0 for CALL_NON_FUNCTION.
13519ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    __ mov(r2, Operand(0, RelocInfo::NONE));
1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
1353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ SetCallKind(r5, CALL_AS_METHOD);
135444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
135544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            RelocInfo::CODE_TARGET);
1356402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ bind(&function);
1357402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1359402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // 5b. Get the code to call from the function and check that the number of
1360402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //     expected arguments matches what we're providing.  If so, jump
1361402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //     (tail-call) to the code in register edx without checking arguments.
1362402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r0: actual number of arguments
1363402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r1: function
1364402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1365402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ ldr(r2,
1366402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu         FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
13677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(r2, Operand(r2, ASR, kSmiTagSize));
1368791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
1369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ SetCallKind(r5, CALL_AS_METHOD);
1370402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ cmp(r2, r0);  // Check formal and actual parameter counts.
137144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
137244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          RelocInfo::CODE_TARGET,
137344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ne);
1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1375402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ParameterCount expected(0);
1376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeCode(r3, expected, expected, JUMP_FUNCTION,
1377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                NullCallWrapper(), CALL_AS_METHOD);
1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kIndexOffset    = -5 * kPointerSize;
1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kLimitOffset    = -4 * kPointerSize;
1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kArgsOffset     =  2 * kPointerSize;
1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kRecvOffset     =  3 * kPointerSize;
1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kFunctionOffset =  4 * kPointerSize;
1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ EnterInternalFrame();
1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(fp, kFunctionOffset));  // get the function
1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(fp, kArgsOffset));  // get the args array
1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1396d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Check the stack for overflow. We are not trying need to catch
1397d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // interruptions (e.g. debug break and preemption) here, so the "real stack
1398d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // limit" is checked.
1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label okay;
1400d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ LoadRoot(r2, Heap::kRealStackLimitRootIndex);
1401d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Make r2 the space we have left. The stack might already be overflowed
1402d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // here which will cause r2 to become negative.
1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(r2, sp, r2);
1404d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Check if the arguments will overflow the stack.
1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
1406d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ b(gt, &okay);  // Signed comparison.
1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Out of stack space.
1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(fp, kFunctionOffset));
1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);
1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
1413d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // End of stack check.
1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push current limit and index.
1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&okay);
1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);  // limit
14189ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  __ mov(r1, Operand(0, RelocInfo::NONE));  // initial index
1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);
1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Change context eagerly to get the right global object if necessary.
1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(fp, kFunctionOffset));
1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(cp, FieldMemOperand(r0, JSFunction::kContextOffset));
1424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Load the shared function info while the function is still in r0.
1425e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ ldr(r1, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset));
1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the receiver.
1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label call_to_object, use_global_receiver, push_receiver;
1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(fp, kRecvOffset));
1430e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1431e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Do not transform the receiver for strict mode functions.
1432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ldr(r2, FieldMemOperand(r1, SharedFunctionInfo::kCompilerHintsOffset));
1433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ tst(r2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
1434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           kSmiTagSize)));
1435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ b(ne, &push_receiver);
1436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Do not transform the receiver for strict mode functions.
14383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ tst(r2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
1439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ b(ne, &push_receiver);
1440e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1441e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Compute the receiver in non-strict mode.
14423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(r0, &call_to_object);
1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(r1, Heap::kNullValueRootIndex);
1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, r1);
1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &use_global_receiver);
1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, r1);
1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &use_global_receiver);
1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if the receiver is already a JavaScript object.
1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: receiver
14523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
14533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
1454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ b(ge, &push_receiver);
1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Convert the receiver to a regular object.
1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: receiver
1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&call_to_object);
1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(&push_receiver);
1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use the current global receiver object as the receiver.
1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&use_global_receiver);
1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kGlobalOffset =
1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, FieldMemOperand(cp, kGlobalOffset));
1468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset));
1469d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ ldr(r0, FieldMemOperand(r0, kGlobalOffset));
1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push the receiver.
1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: receiver
1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&push_receiver);
1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Copy all arguments from the array to the stack.
1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label entry, loop;
1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(fp, kIndexOffset));
1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(&entry);
1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the current argument from the arguments array and push it to the
1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // stack.
1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: current argument index
1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&loop);
1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(fp, kArgsOffset));
1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r1);
1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call the runtime to access the property in the arguments array.
1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CallRuntime(Runtime::kGetProperty, 2);
1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);
1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use inline caching to access the arguments.
1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(fp, kIndexOffset));
1496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r0, r0, Operand(1 << kSmiTagSize));
1497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r0, MemOperand(fp, kIndexOffset));
1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test if the copy loop has finished copying all the elements from the
1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // arguments object.
1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&entry);
1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(fp, kLimitOffset));
1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, r1);
1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &loop);
1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the function.
1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParameterCount actual(r0);
1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(r0, ASR, kSmiTagSize));
1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(fp, kFunctionOffset));
1510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeFunction(r1, actual, CALL_FUNCTION,
1511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    NullCallWrapper(), CALL_AS_METHOD);
1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tear down the internal frame and remove function, receiver and args.
1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LeaveInternalFrame();
1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(3 * kPointerSize));
1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(r0, LSL, kSmiTagSize));
1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() | fp.bit() | lr.bit());
1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(fp, sp, Operand(3 * kPointerSize));
1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0 : result being passed through
1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the number of arguments passed (as a smi), tear down the frame and
1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // then tear down the parameters.
1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(fp, -3 * kPointerSize));
1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(sp, fp);
1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldm(ia_w, sp, fp.bit() | lr.bit());
1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));
1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));  // adjust for receiver
1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0 : actual number of arguments
1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r1 : function (passed through to callee)
1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2 : expected number of arguments
1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r3 : code entry to call
1548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r5 : call kind information
1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label invoke, dont_adapt_arguments;
1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label enough, too_few;
15546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(r0, r2);
1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(lt, &too_few);
1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &dont_adapt_arguments);
1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {  // Enough parameters: actual >= expected
1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&enough);
1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    EnterArgumentsAdaptorFrame(masm);
1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Calculate copy start address into r0 and copy end address into r2.
1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0: actual number of arguments as a smi
1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: expected number of arguments
1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: code entry to call
1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // adjust for return address and receiver
1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, r0, Operand(2 * kPointerSize));
1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r2, r0, Operand(r2, LSL, kPointerSizeLog2));
1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Copy the arguments (including the receiver) to the new stack frame.
1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0: copy start address
1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: copy end address
1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: code entry to call
1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label copy;
1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&copy);
1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(ip, MemOperand(r0, 0));
1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(ip);
1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r0, r2);  // Compare before moving to next argument.
1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r0, r0, Operand(kPointerSize));
1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &copy);
1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(&invoke);
1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {  // Too few parameters: Actual < expected
1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&too_few);
1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    EnterArgumentsAdaptorFrame(masm);
1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Calculate copy start address into r0 and copy end address is fp.
1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0: actual number of arguments as a smi
1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: expected number of arguments
1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: code entry to call
1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Copy the arguments (including the receiver) to the new stack frame.
1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0: copy start address
1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: expected number of arguments
1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: code entry to call
1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label copy;
1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&copy);
1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Adjust load for return address and receiver.
1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(ip, MemOperand(r0, 2 * kPointerSize));
1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(ip);
1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r0, fp);  // Compare before moving to next argument.
1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r0, r0, Operand(kPointerSize));
1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &copy);
1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Fill the remaining expected arguments with undefined.
1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: expected number of arguments
1618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: code entry to call
1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r2, fp, Operand(r2, LSL, kPointerSizeLog2));
1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r2, r2, Operand(4 * kPointerSize));  // Adjust for frame.
1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label fill;
1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&fill);
1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(ip);
1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(sp, r2);
1627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &fill);
1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call the entry point.
1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&invoke);
1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Call(r3);
1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Exit frame and return.
1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LeaveArgumentsAdaptorFrame(masm);
1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -------------------------------------------
1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Dont adapt arguments.
1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -------------------------------------------
1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&dont_adapt_arguments);
1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(r3);
1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
1650f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1651f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_ARM
1652