builtins-arm.cc revision 5d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0b
1c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch// Copyright 2012 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
75c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch// Load the built-in InternalArray function from the current context.
76c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochstatic void GenerateLoadInternalArrayFunction(MacroAssembler* masm,
77c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                              Register result) {
78c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Load the global context.
79c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
80c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  __ ldr(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
81c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  __ ldr(result,
82c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch         FieldMemOperand(result, GlobalObject::kGlobalContextOffset));
83c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Load the InternalArray function from the global context.
84c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  __ ldr(result,
85c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch         MemOperand(result,
86c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                    Context::SlotOffset(
87c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                        Context::INTERNAL_ARRAY_FUNCTION_INDEX)));
88c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch}
89c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
90c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load the built-in Array function from the current context.
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) {
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the global context.
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(result,
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(result, GlobalObject::kGlobalContextOffset));
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the Array function from the global context.
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(result,
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         MemOperand(result,
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Allocate an empty JSArray. The allocated array is put into the result
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register. An elements backing store is allocated with size initial_capacity
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and filled with the hole values.
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void AllocateEmptyJSArray(MacroAssembler* masm,
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register array_function,
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register result,
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register scratch1,
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register scratch2,
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Register scratch3,
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Label* gc_required) {
115592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  const int initial_capacity = JSArray::kPreallocatedArrayElements;
116592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  STATIC_ASSERT(initial_capacity >= 0);
1175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  __ LoadInitialArrayMap(array_function, scratch2, scratch1);
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate the JSArray object together with space for a fixed array with the
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // requested elements.
121592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  int size = JSArray::kSize;
122592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (initial_capacity > 0) {
123592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    size += FixedArray::SizeFor(initial_capacity);
124592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
12525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  __ AllocateInNewSpace(size,
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        result,
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        scratch2,
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        scratch3,
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        gc_required,
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        TAG_OBJECT);
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocated the JSArray. Now initialize the fields except for the elements
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array.
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch1: initial map
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch2: start of next object
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch1, FieldMemOperand(result, JSObject::kMapOffset));
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex);
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch1, FieldMemOperand(result, JSArray::kPropertiesOffset));
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Field JSArray::kElementsOffset is initialized later.
1419ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  __ mov(scratch3,  Operand(0, RelocInfo::NONE));
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch3, FieldMemOperand(result, JSArray::kLengthOffset));
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
144592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (initial_capacity == 0) {
145592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ str(scratch1, FieldMemOperand(result, JSArray::kElementsOffset));
146592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return;
147592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
148592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the location of the elements array and set elements array member
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // of the JSArray.
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch2: start of next object
153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  __ add(scratch1, result, Operand(JSArray::kSize));
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch1, FieldMemOperand(result, JSArray::kElementsOffset));
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the heap tag on the elements array.
1579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ sub(scratch1, scratch1, Operand(kHeapObjectTag));
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Initialize the FixedArray and fill it with holes. FixedArray length is
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // stored as a smi.
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch1: elements array (untagged)
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch2: start of next object
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(scratch3, Heap::kFixedArrayMapRootIndex);
165592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  STATIC_ASSERT(0 * kPointerSize == FixedArray::kMapOffset);
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
1677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(scratch3,  Operand(Smi::FromInt(initial_capacity)));
168592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  STATIC_ASSERT(1 * kPointerSize == FixedArray::kLengthOffset);
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
171592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Fill the FixedArray with the hole value. Inline the code if short.
172592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  STATIC_ASSERT(2 * kPointerSize == FixedArray::kHeaderSize);
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex);
174592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  static const int kLoopUnfoldLimit = 4;
175592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (initial_capacity <= kLoopUnfoldLimit) {
176592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    for (int i = 0; i < initial_capacity; i++) {
177592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
178592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
179592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  } else {
180592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label loop, entry;
181592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ add(scratch2, scratch1, Operand(initial_capacity * kPointerSize));
182592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ b(&entry);
183592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&loop);
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
185592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&entry);
186592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ cmp(scratch1, scratch2);
187592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ b(lt, &loop);
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Allocate a JSArray with the number of elements stored in a register. The
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register array_function holds the built-in Array function and the register
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// array_size holds the size of the array as a smi. The allocated array is put
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// into the result register and beginning and end of the FixedArray elements
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// storage is put into registers elements_array_storage and elements_array_end
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (see  below for when that is not the case). If the parameter fill_with_holes
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// is true the allocated elements backing store is filled with the hole values
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// otherwise it is left uninitialized. When the backing store is filled the
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register elements_array_storage is scratched.
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void AllocateJSArray(MacroAssembler* masm,
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register array_function,  // Array function.
202592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                            Register array_size,  // As a smi, cannot be 0.
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register result,
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register elements_array_storage,
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register elements_array_end,
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register scratch1,
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Register scratch2,
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            bool fill_with_hole,
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Label* gc_required) {
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load the initial map from the array function.
2115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  __ LoadInitialArrayMap(array_function, scratch2, elements_array_storage);
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
213592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (FLAG_debug_code) {  // Assert that array size is not zero.
214592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ tst(array_size, array_size);
215592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Assert(ne, "array size is unexpectedly 0");
216592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate the JSArray object together with space for a FixedArray with the
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // requested number of elements.
22069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(elements_array_end,
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Operand((JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize));
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(elements_array_end,
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         elements_array_end,
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         Operand(array_size, ASR, kSmiTagSize));
22625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  __ AllocateInNewSpace(
22725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      elements_array_end,
22825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      result,
22925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      scratch1,
23025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      scratch2,
23125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      gc_required,
23225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocated the JSArray. Now initialize the fields except for the elements
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array.
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_storage: initial map
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array_size: size of array (smi)
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(elements_array_storage, FieldMemOperand(result, JSObject::kMapOffset));
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(elements_array_storage, Heap::kEmptyFixedArrayRootIndex);
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(elements_array_storage,
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(result, JSArray::kPropertiesOffset));
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Field JSArray::kElementsOffset is initialized later.
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(array_size, FieldMemOperand(result, JSArray::kLengthOffset));
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the location of the elements array and set elements array member
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // of the JSArray.
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array_size: size of array (smi)
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(elements_array_storage, result, Operand(JSArray::kSize));
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(elements_array_storage,
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         FieldMemOperand(result, JSArray::kElementsOffset));
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the heap tag on the elements array.
25569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
2569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  __ sub(elements_array_storage,
2579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen         elements_array_storage,
2589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen         Operand(kHeapObjectTag));
2597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Initialize the fixed array and fill it with holes. FixedArray length is
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // stored as a smi.
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_storage: elements array (untagged)
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // array_size: size of array (smi)
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(scratch1, Heap::kFixedArrayMapRootIndex);
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset);
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch1, MemOperand(elements_array_storage, kPointerSize, PostIndex));
26769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(array_size,
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         MemOperand(elements_array_storage, kPointerSize, PostIndex));
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate elements array and elements array end.
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_storage: elements array element storage
2757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // array_size: smi-tagged size of elements array
27669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(elements_array_end,
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         elements_array_storage,
2797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch         Operand(array_size, LSL, kPointerSizeLog2 - kSmiTagSize));
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill the allocated FixedArray with the hole value if requested.
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result: JSObject
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_storage: elements array element storage
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_end: start of next object
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (fill_with_hole) {
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label loop, entry;
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(scratch1, Heap::kTheHoleValueRootIndex);
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ jmp(&entry);
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&loop);
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(scratch1,
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           MemOperand(elements_array_storage, kPointerSize, PostIndex));
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&entry);
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(elements_array_storage, elements_array_end);
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(lt, &loop);
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Create a new array for the built-in Array function. This function allocates
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the JSArray object and the FixedArray elements array and initializes these.
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// If the Array cannot be constructed in native code the runtime is called. This
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// function assumes the following state:
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   r0: argc
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   r1: constructor (built-in Array function)
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   lr: return address
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   sp[0]: last argument
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This function is used for both construct and normal calls of Array. The only
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// difference between handling a construct call and a normal call is that for a
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// construct call the constructor function in r1 needs to be preserved for
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// entering the generic code. In both cases argc in r0 needs to be preserved.
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Both registers are preserved by this code so no need to differentiate between
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// construct call and normal call.
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ArrayNativeCode(MacroAssembler* masm,
313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                            Label* call_generic_code) {
31444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm->isolate()->counters();
315c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  Label argc_one_or_more, argc_two_or_more, not_empty_array, empty_array,
3165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      has_non_smi_element, finish, cant_transition_map, not_double;
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for array construction with zero arguments or one.
3199ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  __ cmp(r0, Operand(0, RelocInfo::NONE));
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &argc_one_or_more);
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle construction of an empty array.
323592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ bind(&empty_array);
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AllocateEmptyJSArray(masm,
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       r1,
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       r2,
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       r3,
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       r4,
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       r5,
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       call_generic_code);
33144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->array_function_native(), 1, r3, r4);
332c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Set up return value, remove receiver from stack and return.
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, r2);
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for one argument. Bail out if argument is not smi or if it is
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // negative.
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&argc_one_or_more);
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, Operand(1));
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &argc_two_or_more);
34269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r2, MemOperand(sp));  // Get the argument from the stack.
344592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ tst(r2, r2);
345592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ b(ne, &not_empty_array);
346592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Drop(1);  // Adjust stack.
347592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ mov(r0, Operand(0));  // Treat this as a call with argc of zero.
348592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ b(&empty_array);
349592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
350592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ bind(&not_empty_array);
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(r3, r2, Operand(kIntptrSignBit | kSmiTagMask), SetCC);
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, call_generic_code);
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle construction of an empty array of a certain size. Bail out if size
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is too large to actually allocate an elements array.
35669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, Operand(JSObject::kInitialMaxFastElementArray << kSmiTagSize));
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ge, call_generic_code);
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: array_size (smi)
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: argument
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AllocateJSArray(masm,
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r1,
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r2,
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r3,
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r4,
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r5,
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r6,
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r7,
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  true,
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  call_generic_code);
37444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->array_function_native(), 1, r2, r4);
375c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Set up return value, remove receiver and argument from stack and return.
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, r3);
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(2 * kPointerSize));
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle construction of an array from a list of arguments.
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&argc_two_or_more);
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r2, Operand(r0, LSL, kSmiTagSize));  // Convet argc to a smi.
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: constructor
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: array_size (smi)
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: last argument
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AllocateJSArray(masm,
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r1,
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r2,
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r3,
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r4,
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r5,
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r6,
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  r7,
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  false,
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  call_generic_code);
39844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->array_function_native(), 1, r2, r6);
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill arguments as array elements. Copy from the top of the stack (last
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // element) to the array backing store filling it backwards. Note:
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements_array_end points after the backing store therefore PreIndex is
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // used when filling the backing store.
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: JSArray
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: elements_array storage start (untagged)
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r5: elements_array_end (untagged)
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: last argument
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label loop, entry;
410c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  __ mov(r7, sp);
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&entry);
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&loop);
413c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  __ ldr(r2, MemOperand(r7, kPointerSize, PostIndex));
414c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  if (FLAG_smi_only_arrays) {
415c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    __ JumpIfNotSmi(r2, &has_non_smi_element);
416c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  }
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r2, MemOperand(r5, -kPointerSize, PreIndex));
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&entry);
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r4, r5);
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(lt, &loop);
4215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
4225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  __ bind(&finish);
423c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  __ mov(sp, r7);
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove caller arguments and receiver from the stack, setup return value and
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // return.
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: argc
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: JSArray
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sp[0]: receiver
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, r3);
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
433c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
434c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  __ bind(&has_non_smi_element);
4355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // Double values are handled by the runtime.
4365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  __ CheckMap(
4375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      r2, r9, Heap::kHeapNumberMapRootIndex, &not_double, DONT_DO_SMI_CHECK);
4385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  __ bind(&cant_transition_map);
439c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  __ UndoAllocationInNewSpace(r3, r4);
440c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  __ b(call_generic_code);
4415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
4425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  __ bind(&not_double);
4435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // Transition FAST_SMI_ONLY_ELEMENTS to FAST_ELEMENTS.
4445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // r3: JSArray
4455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
4465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
4475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                         FAST_ELEMENTS,
4485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                         r2,
4495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                         r9,
4505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                         &cant_transition_map);
4515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  __ str(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
4525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  __ RecordWriteField(r3,
4535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                      HeapObject::kMapOffset,
4545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                      r2,
4555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                      r9,
4565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                      kLRHasNotBeenSaved,
4575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                      kDontSaveFPRegs,
4585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                      EMIT_REMEMBERED_SET,
4595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                      OMIT_SMI_CHECK);
4605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  Label loop2;
4615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  __ sub(r7, r7, Operand(kPointerSize));
4625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  __ bind(&loop2);
4635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  __ ldr(r2, MemOperand(r7, kPointerSize, PostIndex));
4645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  __ str(r2, MemOperand(r5, -kPointerSize, PreIndex));
4655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  __ cmp(r4, r5);
4665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  __ b(lt, &loop2);
4675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  __ b(&finish);
468c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch}
469c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
470c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
471c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochvoid Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
472c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // ----------- S t a t e -------------
473c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  //  -- r0     : number of arguments
474c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  //  -- lr     : return address
475c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  //  -- sp[...]: constructor arguments
476c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // -----------------------------------
477c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
478c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
479c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Get the InternalArray function.
480c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  GenerateLoadInternalArrayFunction(masm, r1);
481c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
482c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  if (FLAG_debug_code) {
483c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    // Initial map for the builtin InternalArray functions should be maps.
484c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
485c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    __ tst(r2, Operand(kSmiTagMask));
486c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    __ Assert(ne, "Unexpected initial map for InternalArray function");
487c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    __ CompareObjectType(r2, r3, r4, MAP_TYPE);
488c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    __ Assert(eq, "Unexpected initial map for InternalArray function");
489c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  }
490c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
491c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Run the native code for the InternalArray function called as a normal
492c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // function.
493c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  ArrayNativeCode(masm, &generic_array_code);
494c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
495c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // Jump to the generic array code if the specialized code cannot handle the
496c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  // construction.
497c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  __ bind(&generic_array_code);
498c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
499c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  Handle<Code> array_code =
500c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      masm->isolate()->builtins()->InternalArrayCodeGeneric();
501c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  __ Jump(array_code, RelocInfo::CODE_TARGET);
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArrayCode(MacroAssembler* masm) {
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0     : number of arguments
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr     : return address
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[...]: constructor arguments
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the Array function.
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GenerateLoadArrayFunction(masm, r1);
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_debug_code) {
517e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Initial map for the builtin Array functions should be maps.
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r2, Operand(kSmiTagMask));
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(ne, "Unexpected initial map for Array function");
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CompareObjectType(r2, r3, r4, MAP_TYPE);
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(eq, "Unexpected initial map for Array function");
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run the native code for the Array function called as a normal function.
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ArrayNativeCode(masm, &generic_array_code);
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the generic array code if the specialized code cannot handle
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the construction.
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&generic_array_code);
53144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
53244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> array_code =
53344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      masm->isolate()->builtins()->ArrayCodeGeneric();
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(array_code, RelocInfo::CODE_TARGET);
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) {
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0     : number of arguments
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r1     : constructor function
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr     : return address
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[...]: constructor arguments
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label generic_constructor;
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_debug_code) {
548e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // The array construct code is only set for the builtin and internal
549e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Array functions which always have a map.
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Initial map for the builtin Array function should be a map.
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ tst(r2, Operand(kSmiTagMask));
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(ne, "Unexpected initial map for Array function");
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ CompareObjectType(r2, r3, r4, MAP_TYPE);
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ Assert(eq, "Unexpected initial map for Array function");
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run the native code for the Array function called as a constructor.
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ArrayNativeCode(masm, &generic_constructor);
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to the generic construct code in case the specialized code cannot
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // handle the construction.
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&generic_constructor);
56444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> generic_construct_stub =
56544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      masm->isolate()->builtins()->JSConstructStubGeneric();
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
57080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
5718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // ----------- S t a t e -------------
5728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- r0                     : number of arguments
5738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- r1                     : constructor function
5748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- lr                     : return address
5758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
5768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- sp[argc * 4]           : receiver
5778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // -----------------------------------
57844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = masm->isolate()->counters();
57944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->string_ctor_calls(), 1, r2, r3);
5808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register function = r1;
5828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (FLAG_debug_code) {
5838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, r2);
5848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ cmp(function, Operand(r2));
5858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ Assert(eq, "Unexpected String function");
5868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
5878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the first arguments in r0 and get rid of the rest.
5898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label no_arguments;
590b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __ cmp(r0, Operand(0, RelocInfo::NONE));
5918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(eq, &no_arguments);
5928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // First args = sp[(argc - 1) * 4].
5938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ sub(r0, r0, Operand(1));
5948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(r0, MemOperand(sp, r0, LSL, kPointerSizeLog2, PreIndex));
5958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // sp now point to args[0], drop args[0] + receiver.
5968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Drop(2);
5978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register argument = r2;
5998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label not_cached, argument_is_string;
6008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  NumberToStringStub::GenerateLookupNumberStringCache(
6018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      masm,
6028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      r0,        // Input.
6038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      argument,  // Result.
6048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      r3,        // Scratch.
6058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      r4,        // Scratch.
6068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      r5,        // Scratch.
6078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      false,     // Is it a Smi?
6088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      &not_cached);
60944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->string_ctor_cached_number(), 1, r3, r4);
6108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&argument_is_string);
6118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // ----------- S t a t e -------------
6138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- r2     : argument converted to string
6148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- r1     : constructor function
6158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //  -- lr     : return address
6168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // -----------------------------------
6178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label gc_required;
6198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ AllocateInNewSpace(JSValue::kSize,
6208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                        r0,  // Result.
6218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                        r3,  // Scratch.
6228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                        r4,  // Scratch.
6238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                        &gc_required,
6248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                        TAG_OBJECT);
6258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Initialising the String Object.
6278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Register map = r3;
6288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ LoadGlobalFunctionInitialMap(function, map, r4);
6298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (FLAG_debug_code) {
6308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldrb(r4, FieldMemOperand(map, Map::kInstanceSizeOffset));
6318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ cmp(r4, Operand(JSValue::kSize >> kPointerSizeLog2));
6328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ Assert(eq, "Unexpected string wrapper instance size");
6338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ ldrb(r4, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset));
634b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __ cmp(r4, Operand(0, RelocInfo::NONE));
6358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    __ Assert(eq, "Unexpected unused properties of string wrapper");
6368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
6378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ str(map, FieldMemOperand(r0, HeapObject::kMapOffset));
6388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex);
6408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset));
6418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset));
6428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ str(argument, FieldMemOperand(r0, JSValue::kValueOffset));
6448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Ensure the object is fully initialized.
6468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
6478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Ret();
6498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // The argument was not found in the number to string cache. Check
6518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // if it's a string already before calling the conversion builtin.
6528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Label convert_argument;
6538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&not_cached);
6541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ JumpIfSmi(r0, &convert_argument);
6558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Is it a String?
6578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
6588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceTypeOffset));
65969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kNotStringTag != 0);
6608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ tst(r3, Operand(kIsNotStringMask));
6618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(ne, &convert_argument);
6628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(argument, r0);
66344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4);
6648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&argument_is_string);
6658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Invoke the conversion builtin and put the result into r2.
6678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&convert_argument);
6688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ push(function);  // Preserve the function.
66944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4);
670592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
671592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
672592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r0);
673592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
674592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
6758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ pop(function);
6768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ mov(argument, r0);
6778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&argument_is_string);
6788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Load the empty string into r2, remove the receiver from the
6808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // stack, and jump back to the case where the argument is a string.
6818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&no_arguments);
6828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ LoadRoot(argument, Heap::kEmptyStringRootIndex);
6838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Drop(1);
6848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ b(&argument_is_string);
6858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // At this point the argument is already a string. Call runtime to
6878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // create a string wrapper.
6888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ bind(&gc_required);
68944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->string_ctor_gc_required(), 1, r3, r4);
690592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
691592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
692592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(argument);
693592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ CallRuntime(Runtime::kNewStringWrapper, 1);
694592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
6958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Ret();
69680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
69780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
69880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
6995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochstatic void Generate_JSConstructStubHelper(MacroAssembler* masm,
7005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                           bool is_api_function,
7015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                           bool count_constructions) {
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0     : number of arguments
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r1     : constructor function
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- lr     : return address
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- sp[...]: constructor arguments
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Should never count constructions for api objects.
7100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(!is_api_function || !count_constructions);
7110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
71244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = masm->isolate();
71344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enter a construct frame.
715592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
716592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope scope(masm, StackFrame::CONSTRUCT);
717592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
718592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Preserve the two incoming parameters on the stack.
719592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(r0, Operand(r0, LSL, kSmiTagSize));
720592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r0);  // Smi-tagged arguments count.
721592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r1);  // Constructor function.
722592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
723592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Try to allocate the object without transitioning into C code. If any of
724592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // the preconditions is not met, the code bails out to the runtime call.
725592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label rt_call, allocated;
726592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (FLAG_inline_new) {
727592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      Label undo_allocation;
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
729592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ExternalReference debug_step_in_fp =
730592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          ExternalReference::debug_step_in_fp_address(isolate);
731592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ mov(r2, Operand(debug_step_in_fp));
732592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ ldr(r2, MemOperand(r2));
733592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ tst(r2, r2);
734592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ b(ne, &rt_call);
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
737592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Load the initial map and verify that it is in fact a map.
738592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r1: constructor function
739592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
740592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ JumpIfSmi(r2, &rt_call);
741592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ CompareObjectType(r2, r3, r4, MAP_TYPE);
742592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ b(ne, &rt_call);
743592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
744592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Check that the constructor is not constructing a JSFunction (see
745592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // comments in Runtime_NewObject in runtime.cc). In which case the
746592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // initial map's instance type would be JS_FUNCTION_TYPE.
747592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r1: constructor function
748592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r2: initial map
749592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE);
750592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ b(eq, &rt_call);
7510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
752592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (count_constructions) {
753592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        Label allocate;
754592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // Decrease generous allocation count.
755592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
756592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        MemOperand constructor_count =
757592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            FieldMemOperand(r3, SharedFunctionInfo::kConstructionCountOffset);
758592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ ldrb(r4, constructor_count);
759592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ sub(r4, r4, Operand(1), SetCC);
760592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ strb(r4, constructor_count);
761592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ b(ne, &allocate);
762592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
763592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ Push(r1, r2);
764592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
765592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ push(r1);  // constructor
766592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // The call will replace the stub, so the countdown is only done once.
767592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
768592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
769592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ pop(r2);
770592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ pop(r1);
771592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
772592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ bind(&allocate);
773592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      }
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
775592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Now allocate the JSObject on the heap.
776592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r1: constructor function
777592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r2: initial map
778592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
779592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS);
780592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
781592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Allocated the JSObject, now initialize the fields. Map is set to
782592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // initial map and properties and elements are set to empty fixed array.
783592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r1: constructor function
784592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r2: initial map
785592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r3: object size
786592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r4: JSObject (not tagged)
787592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
788592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ mov(r5, r4);
789592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
790592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
791592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
792592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
793592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
794592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
795592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
796592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Fill all the in-object properties with the appropriate filler.
797592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r1: constructor function
798592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r2: initial map
799592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r3: object size (in words)
800592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r4: JSObject (not tagged)
801592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r5: First in-object property of JSObject (not tagged)
802592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
803592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
804592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
8050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      if (count_constructions) {
806592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
807592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ Ubfx(r0, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
808592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                kBitsPerByte);
809592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ add(r0, r5, Operand(r0, LSL, kPointerSizeLog2));
810592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // r0: offset of first field after pre-allocated fields
811592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        if (FLAG_debug_code) {
812592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          __ cmp(r0, r6);
813592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          __ Assert(le, "Unexpected number of pre-allocated property fields.");
814592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        }
815592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ InitializeFieldsWithFiller(r5, r0, r7);
8160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        // To allow for truncation.
8170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        __ LoadRoot(r7, Heap::kOnePointerFillerMapRootIndex);
8180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
819592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ InitializeFieldsWithFiller(r5, r6, r7);
820592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
821592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Add the object tag to make the JSObject real, so that we can continue
822592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // and jump into the continuation code at any time from now on. Any
823592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // failures need to undo the allocation, so that the heap is in a
824592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // consistent state and verifiable.
825592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ add(r4, r4, Operand(kHeapObjectTag));
826592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
827592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Check if a non-empty properties array is needed. Continue with
828592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // allocated object if not fall through to runtime call if it is.
829592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r1: constructor function
830592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r4: JSObject
831592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r5: start of next object (not tagged)
832592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset));
833592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // The field instance sizes contains both pre-allocated property fields
834592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // and in-object properties.
835592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
836592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ Ubfx(r6, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
837592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch              kBitsPerByte);
838592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ add(r3, r3, Operand(r6));
839592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ Ubfx(r6, r0, Map::kInObjectPropertiesByte * kBitsPerByte,
840592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch              kBitsPerByte);
841592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ sub(r3, r3, Operand(r6), SetCC);
842592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
843592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Done if no extra properties are to be allocated.
844592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ b(eq, &allocated);
845592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ Assert(pl, "Property allocation count failed.");
846592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
847592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Scale the number of elements by pointer size and add the header for
848592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // FixedArrays to the start of the next object calculation from above.
849592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r1: constructor
850592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r3: number of elements in properties array
851592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r4: JSObject
852592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r5: start of next object
853592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize));
854592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ AllocateInNewSpace(
855592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          r0,
856592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          r5,
857592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          r6,
858592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          r2,
859592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          &undo_allocation,
860592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS));
861592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
862592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Initialize the FixedArray.
863592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r1: constructor
864592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r3: number of elements in properties array
865592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r4: JSObject
866592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r5: FixedArray (not tagged)
867592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex);
868592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ mov(r2, r5);
869592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
870592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ str(r6, MemOperand(r2, kPointerSize, PostIndex));
871592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
872592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ mov(r0, Operand(r3, LSL, kSmiTagSize));
873592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ str(r0, MemOperand(r2, kPointerSize, PostIndex));
874592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
875592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Initialize the fields to undefined.
876592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r1: constructor function
877592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r2: First element of FixedArray (not tagged)
878592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r3: number of elements in properties array
879592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r4: JSObject
880592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r5: FixedArray (not tagged)
881592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
882592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
883592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      { Label loop, entry;
884592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        if (count_constructions) {
885592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
886592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        } else if (FLAG_debug_code) {
887592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          __ LoadRoot(r8, Heap::kUndefinedValueRootIndex);
888592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          __ cmp(r7, r8);
889592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          __ Assert(eq, "Undefined value not loaded.");
890592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        }
891592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ b(&entry);
892592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ bind(&loop);
893592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ str(r7, MemOperand(r2, kPointerSize, PostIndex));
894592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ bind(&entry);
895592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ cmp(r2, r6);
896592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ b(lt, &loop);
897592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      }
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
899592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Store the initialized FixedArray into the properties field of
900592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // the JSObject
901592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r1: constructor function
902592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r4: JSObject
903592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r5: FixedArray (not tagged)
904592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ add(r5, r5, Operand(kHeapObjectTag));  // Add the heap tag.
905592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ str(r5, FieldMemOperand(r4, JSObject::kPropertiesOffset));
906592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
907592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Continue with JSObject being successfully allocated
908592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r1: constructor function
909592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r4: JSObject
910592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ jmp(&allocated);
911592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
912592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Undo the setting of the new top so that the heap is verifiable. For
913592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // example, the map's unused properties potentially do not match the
914592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // allocated objects unused properties.
915592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // r4: JSObject (previous new top)
916592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ bind(&undo_allocation);
917592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ UndoAllocationInNewSpace(r4, r5);
918592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
920592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Allocate the new receiver object using the runtime call.
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
922592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&rt_call);
923592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r1);  // argument for Runtime_NewObject
924592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ CallRuntime(Runtime::kNewObject, 1);
925592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(r4, r0);
926592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
927592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Receiver for constructor call allocated.
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r4: JSObject
929592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&allocated);
930592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r4);
9315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    __ push(r4);
932592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
9335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // Reload the number of arguments and the constructor from the stack.
934592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[0]: receiver
9355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // sp[1]: receiver
9365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // sp[2]: constructor function
9375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // sp[3]: number of arguments (smi-tagged)
9385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    __ ldr(r1, MemOperand(sp, 2 * kPointerSize));
9395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    __ ldr(r3, MemOperand(sp, 3 * kPointerSize));
940592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
941c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    // Set up pointer to last argument.
942592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
943592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
944c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    // Set up number of arguments for function call below
945592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(r0, Operand(r3, LSR, kSmiTagSize));
946592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
947592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Copy arguments and receiver to the expression stack.
948592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // r0: number of arguments
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
9505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // r2: address of last argument (caller sp)
951592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // r3: number of arguments (smi-tagged)
952592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[0]: receiver
9535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // sp[1]: receiver
9545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // sp[2]: constructor function
9555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // sp[3]: number of arguments (smi-tagged)
956592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label loop, entry;
957592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ b(&entry);
958592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&loop);
959592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1));
960592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(ip);
961592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&entry);
962592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ sub(r3, r3, Operand(2), SetCC);
963592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ b(ge, &loop);
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
965592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Call the function.
966592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // r0: number of arguments
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
968592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (is_api_function) {
969592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
970592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      Handle<Code> code =
971592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          masm->isolate()->builtins()->HandleApiCallConstruct();
972592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ParameterCount expected(0);
973592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ InvokeCode(code, expected, expected,
974592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                    RelocInfo::CODE_TARGET, CALL_FUNCTION, CALL_AS_METHOD);
975592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    } else {
976592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ParameterCount actual(r0);
977592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ InvokeFunction(r1, actual, CALL_FUNCTION,
978592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        NullCallWrapper(), CALL_AS_METHOD);
979592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // Store offset of return address for deoptimizer.
9825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (!is_api_function && !count_constructions) {
9835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
9845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
986592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Restore context from the frame.
987592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // r0: result
988592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[0]: receiver
989592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[1]: constructor function
990592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[2]: number of arguments (smi-tagged)
991592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
992592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
993592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // If the result is an object (in the ECMA sense), we should get rid
994592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // of the receiver and use the result; see ECMA-262 section 13.2.2-7
995592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // on page 74.
996592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label use_receiver, exit;
997592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
998592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // If the result is a smi, it is *not* an object in the ECMA sense.
999592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // r0: result
1000592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[0]: receiver (newly allocated object)
1001592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[1]: constructor function
1002592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[2]: number of arguments (smi-tagged)
1003592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ JumpIfSmi(r0, &use_receiver);
1004592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1005592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // If the type of the result (stored in its map) is less than
1006592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
1007592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ CompareObjectType(r0, r3, r3, FIRST_SPEC_OBJECT_TYPE);
1008592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ b(ge, &exit);
1009592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1010592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Throw away the result of the constructor invocation and use the
1011592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // on-stack receiver as the result.
1012592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&use_receiver);
1013592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(r0, MemOperand(sp));
1014592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1015592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Remove receiver from the stack, remove caller arguments, and
1016592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // return.
1017592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&exit);
1018592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // r0: result
1019592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[0]: receiver (newly allocated object)
1020592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[1]: constructor function
1021592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[2]: number of arguments (smi-tagged)
1022592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(r1, MemOperand(sp, 2 * kPointerSize));
1023592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1024592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Leave construct frame.
1025e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));
102944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2);
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10340d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
10350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Generate_JSConstructStubHelper(masm, false, true);
10360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
10370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
10380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
1039e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
10400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Generate_JSConstructStubHelper(masm, false, false);
1041e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1042e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1043e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1044e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
10450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Generate_JSConstructStubHelper(masm, true, false);
1046e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1047e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1048e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             bool is_construct) {
1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Called from Generate_JS_Entry
1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: code entry
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: function
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r2: receiver
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r3: argc
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r4: argv
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r5-r7, cp may be clobbered
1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1059592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Clear the context before we push it when entering the internal frame.
10609ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  __ mov(cp, Operand(0, RelocInfo::NONE));
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enter an internal frame.
1063592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
1064592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1066592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Set up the context from the function argument.
1067592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1069c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    __ InitializeRootRegister();
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1071592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Push the function and the receiver onto the stack.
1072592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r1);
1073592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r2);
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1075592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Copy arguments to the stack in a loop.
1076592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // r1: function
1077592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // r3: argc
1078592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // r4: argv, i.e. points to first arg
1079592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label loop, entry;
1080592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2));
1081592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // r2 points past last arg.
1082592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ b(&entry);
1083592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&loop);
1084592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex));  // read next parameter
1085592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(r0, MemOperand(r0));  // dereference handle
1086592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r0);  // push parameter
1087592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&entry);
1088592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ cmp(r4, r2);
1089592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ b(ne, &loop);
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1091592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Initialize all JavaScript callee-saved registers, since they will be seen
1092592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // by the garbage collector as part of handlers.
1093592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
1094592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(r5, Operand(r4));
1095592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(r6, Operand(r4));
1096592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(r7, Operand(r4));
1097592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (kR9Available == 1) {
1098592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ mov(r9, Operand(r4));
1099592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1101592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Invoke the code and pass argc as r0.
1102592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(r0, Operand(r3));
1103592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (is_construct) {
11045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
11055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      __ CallStub(&stub);
1106592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    } else {
1107592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ParameterCount actual(r0);
1108592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ InvokeFunction(r1, actual, CALL_FUNCTION,
1109592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        NullCallWrapper(), CALL_AS_METHOD);
1110592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
1111592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Exit the JS frame and remove the parameters (except function), and
1112592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // return.
1113592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Respect ABI stack constraint.
1114592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: result
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Generate_JSEntryTrampolineHelper(masm, false);
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Generate_JSEntryTrampolineHelper(masm, true);
1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1131756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid Builtins::Generate_LazyCompile(MacroAssembler* masm) {
1132756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Enter an internal frame.
1133592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
1134592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
1135756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1136592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Preserve the function.
1137592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r1);
1138592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Push call kind information.
1139592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r5);
1140756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1141592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Push the function on the stack as the argument to the runtime function.
1142592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r1);
1143592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ CallRuntime(Runtime::kLazyCompile, 1);
1144592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Calculate the entry point.
1145592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
1146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1147592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Restore call kind information.
1148592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ pop(r5);
1149592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Restore saved function.
1150592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ pop(r1);
1151756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1152592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Tear down internal frame.
1153592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
1154756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1155756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Do a tail-call of the compiled function.
1156756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  __ Jump(r2);
1157756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
1158756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1159756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_LazyRecompile(MacroAssembler* masm) {
1161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Enter an internal frame.
1162592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
1163592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
1164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1165592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Preserve the function.
1166592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r1);
1167592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Push call kind information.
1168592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r5);
1169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1170592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Push the function on the stack as the argument to the runtime function.
1171592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r1);
1172592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ CallRuntime(Runtime::kLazyRecompile, 1);
1173592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Calculate the entry point.
1174592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
1175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1176592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Restore call kind information.
1177592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ pop(r5);
1178592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Restore saved function.
1179592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ pop(r1);
1180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1181592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Tear down internal frame.
1182592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
1183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Do a tail-call of the compiled function.
1185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ Jump(r2);
1186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
1190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             Deoptimizer::BailoutType type) {
1191592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
1192592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
1193592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Pass the function and deoptimization type to the runtime system.
1194592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(r0, Operand(Smi::FromInt(static_cast<int>(type))));
1195592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r0);
1196592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
1197592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
1198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Get the full codegen state from the stack and untag it -> r6.
1200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ ldr(r6, MemOperand(sp, 0 * kPointerSize));
1201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ SmiUntag(r6);
1202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Switch on the state.
1203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label with_tos_register, unknown_state;
1204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ cmp(r6, Operand(FullCodeGenerator::NO_REGISTERS));
1205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ b(ne, &with_tos_register);
1206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ add(sp, sp, Operand(1 * kPointerSize));  // Remove state.
1207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ Ret();
1208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&with_tos_register);
1210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ ldr(r0, MemOperand(sp, 1 * kPointerSize));
1211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ cmp(r6, Operand(FullCodeGenerator::TOS_REG));
1212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ b(ne, &unknown_state);
1213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ add(sp, sp, Operand(2 * kPointerSize));  // Remove state.
1214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ Ret();
1215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&unknown_state);
1217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ stop("no cases left");
1218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
1222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
1223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
1227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
1228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_NotifyOSR(MacroAssembler* masm) {
12321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // For now, we are relying on the fact that Runtime::NotifyOSR
12331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // doesn't do any garbage collection which allows us to save/restore
12341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // the registers without worrying about which of them contain
12351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // pointers. This seems a bit fragile.
12361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ stm(db_w, sp, kJSCallerSaved | kCalleeSaved | lr.bit() | fp.bit());
1237592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
1238592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
1239592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ CallRuntime(Runtime::kNotifyOSR, 0);
1240592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
12411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ldm(ia_w, sp, kJSCallerSaved | kCalleeSaved | lr.bit() | fp.bit());
12421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ Ret();
1243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
12478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CpuFeatures::TryForceFeatureScope scope(VFP3);
12488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (!CpuFeatures::IsSupported(VFP3)) {
12498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ Abort("Unreachable code: Cannot optimize without VFP3 support.");
12508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return;
12518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
12521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Lookup the function in the JavaScript frame and push it as an
12541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // argument to the on-stack replacement function.
12551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1256592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
1257592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
1258592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r0);
1259592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
1260592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
12611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // If the result was -1 it means that we couldn't optimize the
12631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // function. Just return and continue in the unoptimized version.
12641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Label skip;
12651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ cmp(r0, Operand(Smi::FromInt(-1)));
12661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ b(ne, &skip);
12671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ Ret();
12681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&skip);
12701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Untag the AST id and push it on the stack.
12711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ SmiUntag(r0);
12721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ push(r0);
12731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
12741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Generate the code for doing the frame-to-frame translation using
12751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // the deoptimizer infrastructure.
12761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR);
12771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  generator.Generate();
1278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_FunctionCall(MacroAssembler* masm) {
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 1. Make sure we have at least one argument.
1283402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r0: actual number of arguments
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { Label done;
12855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    __ cmp(r0, Operand(0));
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &done);
1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(r2);
1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, r0, Operand(1));
1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&done);
1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1293402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // 2. Get the function to call (passed as receiver) from the stack, check
1294402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //    if it is a function.
1295402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r0: actual number of arguments
1296589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Label slow, non_function;
1297402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
12983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ JumpIfSmi(r1, &non_function);
1299402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
1300589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ b(ne, &slow);
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1302402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // 3a. Patch the first argument if necessary when calling a function.
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: actual number of arguments
1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: function
1305402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  Label shift_arguments;
1306589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ mov(r4, Operand(0, RelocInfo::NONE));  // indicate regular JS_FUNCTION
1307402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  { Label convert_to_object, use_global_receiver, patch_receiver;
1308402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Change context eagerly in case we need the global receiver.
1309402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1310402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Do not transform the receiver for strict mode functions.
1312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ ldr(r3, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset));
1314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ tst(r3, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
1315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                             kSmiTagSize)));
1316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ b(ne, &shift_arguments);
1317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Do not transform the receiver for native (Compilerhints already in r3).
13193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ tst(r3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
1320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    __ b(ne, &shift_arguments);
1321e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1322e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Compute the receiver in non-strict mode.
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, MemOperand(r2, -kPointerSize));
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0: actual number of arguments
1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: first argument
13283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ JumpIfSmi(r2, &convert_to_object);
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r2, r3);
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &use_global_receiver);
1333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(r3, Heap::kNullValueRootIndex);
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r2, r3);
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &use_global_receiver);
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
13383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ CompareObjectType(r2, r3, r3, FIRST_SPEC_OBJECT_TYPE);
1339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ b(ge, &shift_arguments);
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1341402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ bind(&convert_to_object);
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1343592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    {
1344592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Enter an internal frame in order to preserve argument count.
1345592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      FrameScope scope(masm, StackFrame::INTERNAL);
1346592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ mov(r0, Operand(r0, LSL, kSmiTagSize));  // Smi-tagged.
1347592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ push(r0);
1348592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1349592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ push(r2);
1350592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1351592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ mov(r2, r0);
1352592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1353592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ pop(r0);
1354592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ mov(r0, Operand(r0, ASR, kSmiTagSize));
1355592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1356592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Exit the internal frame.
1357592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1359589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Restore the function to r1, and the flag to r4.
1360402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
1361589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ mov(r4, Operand(0, RelocInfo::NONE));
1362402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ jmp(&patch_receiver);
1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1364402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Use the global receiver object from the called function as the
1365402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // receiver.
1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&use_global_receiver);
1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const int kGlobalIndex =
1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, FieldMemOperand(cp, kGlobalIndex));
1370d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalContextOffset));
1371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    __ ldr(r2, FieldMemOperand(r2, kGlobalIndex));
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&patch_receiver);
1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2));
1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r2, MemOperand(r3, -kPointerSize));
1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1378402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ jmp(&shift_arguments);
1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1381589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // 3b. Check for function proxy.
1382589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ bind(&slow);
1383589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ mov(r4, Operand(1, RelocInfo::NONE));  // indicate function proxy
1384589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ cmp(r2, Operand(JS_FUNCTION_PROXY_TYPE));
1385589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ b(eq, &shift_arguments);
1386589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ bind(&non_function);
1387589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ mov(r4, Operand(2, RelocInfo::NONE));  // indicate non-function
1388589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1389589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // 3c. Patch the first argument when calling a non-function.  The
1390402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //     CALL_NON_FUNCTION builtin expects the non-function callee as
1391402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //     receiver, so overwrite the first argument which will ultimately
1392402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //     become the receiver.
1393402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r0: actual number of arguments
1394402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r1: function
1395589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // r4: call type (0: JS function, 1: function proxy, 2: non-function)
1396402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
1397402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ str(r1, MemOperand(r2, -kPointerSize));
1398402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1399402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // 4. Shift arguments and return address one slot down on the stack
1400402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //    (overwriting the original receiver).  Adjust argument count to make
1401402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //    the original first argument the new receiver.
1402402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r0: actual number of arguments
1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: function
1404589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // r4: call type (0: JS function, 1: function proxy, 2: non-function)
1405402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ bind(&shift_arguments);
1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { Label loop;
1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Calculate the copy start address (destination). Copy end address is sp.
1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&loop);
1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(ip, MemOperand(r2, -kPointerSize));
1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(ip, MemOperand(r2));
1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r2, r2, Operand(kPointerSize));
1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r2, sp);
1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &loop);
1416402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Adjust the actual number of arguments and remove the top element
1417402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // (which is a copy of the last argument).
1418402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ sub(r0, r0, Operand(1));
1419402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ pop();
1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1422589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin,
1423589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  //     or a function proxy via CALL_FUNCTION_PROXY.
1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0: actual number of arguments
1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r1: function
1426589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // r4: call type (0: JS function, 1: function proxy, 2: non-function)
1427589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  { Label function, non_proxy;
1428589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ tst(r4, r4);
1429589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ b(eq, &function);
14309ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // Expected number of arguments is 0 for CALL_NON_FUNCTION.
14319ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    __ mov(r2, Operand(0, RelocInfo::NONE));
1432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ SetCallKind(r5, CALL_AS_METHOD);
1433589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ cmp(r4, Operand(1));
1434589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ b(ne, &non_proxy);
1435589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1436589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ push(r1);  // re-add proxy object as additional argument
1437589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ add(r0, r0, Operand(1));
1438589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY);
1439589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1440589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            RelocInfo::CODE_TARGET);
1441589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1442589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ bind(&non_proxy);
1443589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
144444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
144544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            RelocInfo::CODE_TARGET);
1446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    __ bind(&function);
1447402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // 5b. Get the code to call from the function and check that the number of
1450402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //     expected arguments matches what we're providing.  If so, jump
1451402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  //     (tail-call) to the code in register edx without checking arguments.
1452402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r0: actual number of arguments
1453402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // r1: function
1454402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1455402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ ldr(r2,
1456402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu         FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
14577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(r2, Operand(r2, ASR, kSmiTagSize));
1458791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
1459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ SetCallKind(r5, CALL_AS_METHOD);
1460402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ cmp(r2, r0);  // Check formal and actual parameter counts.
146144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
146244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          RelocInfo::CODE_TARGET,
146344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          ne);
1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1465402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ParameterCount expected(0);
1466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ InvokeCode(r3, expected, expected, JUMP_FUNCTION,
1467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                NullCallWrapper(), CALL_AS_METHOD);
1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kIndexOffset    = -5 * kPointerSize;
1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kLimitOffset    = -4 * kPointerSize;
1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kArgsOffset     =  2 * kPointerSize;
1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kRecvOffset     =  3 * kPointerSize;
1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kFunctionOffset =  4 * kPointerSize;
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1478592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
1479592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope frame_scope(masm, StackFrame::INTERNAL);
1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1481592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(r0, MemOperand(fp, kFunctionOffset));  // get the function
1482592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r0);
1483592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(r0, MemOperand(fp, kArgsOffset));  // get the args array
1484592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r0);
1485592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
1486592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1487592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Check the stack for overflow. We are not trying to catch
1488592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // interruptions (e.g. debug break and preemption) here, so the "real stack
1489592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // limit" is checked.
1490592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label okay;
1491592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ LoadRoot(r2, Heap::kRealStackLimitRootIndex);
1492592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Make r2 the space we have left. The stack might already be overflowed
1493592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // here which will cause r2 to become negative.
1494592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ sub(r2, sp, r2);
1495592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Check if the arguments will overflow the stack.
1496592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
1497592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ b(gt, &okay);  // Signed comparison.
1498592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1499592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Out of stack space.
1500592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(r1, MemOperand(fp, kFunctionOffset));
1501592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r1);
1502592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r0);
1503592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
1504592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // End of stack check.
1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1506592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Push current limit and index.
1507592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&okay);
1508592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r0);  // limit
1509592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(r1, Operand(0, RelocInfo::NONE));  // initial index
1510592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r1);
1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1512592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Get the receiver.
1513592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(r0, MemOperand(fp, kRecvOffset));
1514589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1515592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Check that the function is a JS function (otherwise it must be a proxy).
1516592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label push_receiver;
1517592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(r1, MemOperand(fp, kFunctionOffset));
1518592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
1519592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ b(ne, &push_receiver);
1520589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1521592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Change context eagerly to get the right global object if necessary.
1522592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1523592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Load the shared function info while the function is still in r1.
1524592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1526592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Compute the receiver.
1527592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Do not transform the receiver for strict mode functions.
1528592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label call_to_object, use_global_receiver;
1529592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset));
1530592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ tst(r2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
1531592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                             kSmiTagSize)));
1532592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ b(ne, &push_receiver);
1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1534592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Do not transform the receiver for strict mode functions.
1535592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ tst(r2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
1536592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ b(ne, &push_receiver);
1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1538592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Compute the receiver in non-strict mode.
1539592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ JumpIfSmi(r0, &call_to_object);
1540592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ LoadRoot(r1, Heap::kNullValueRootIndex);
1541592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ cmp(r0, r1);
1542592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ b(eq, &use_global_receiver);
1543592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
1544592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ cmp(r0, r1);
1545592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ b(eq, &use_global_receiver);
1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1547592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Check if the receiver is already a JavaScript object.
1548592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // r0: receiver
1549592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1550592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
1551592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ b(ge, &push_receiver);
1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1553592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Convert the receiver to a regular object.
1554592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // r0: receiver
1555592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&call_to_object);
1556592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r0);
1557592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1558592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ b(&push_receiver);
1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1560592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Use the current global receiver object as the receiver.
1561592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&use_global_receiver);
1562592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    const int kGlobalOffset =
1563592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
1564592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(r0, FieldMemOperand(cp, kGlobalOffset));
1565592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset));
1566592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(r0, FieldMemOperand(r0, kGlobalOffset));
1567592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
1568592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1569592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Push the receiver.
1570592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // r0: receiver
1571592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&push_receiver);
1572592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r0);
1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1574592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Copy all arguments from the array to the stack.
1575592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label entry, loop;
1576592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(r0, MemOperand(fp, kIndexOffset));
1577592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ b(&entry);
1578589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1579592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Load the current argument from the arguments array and push it to the
1580592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // stack.
1581592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // r0: current argument index
1582592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&loop);
1583592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(r1, MemOperand(fp, kArgsOffset));
1584592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r1);
1585592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r0);
1586592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1587592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Call the runtime to access the property in the arguments array.
1588592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ CallRuntime(Runtime::kGetProperty, 2);
1589592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r0);
1590589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1591592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Use inline caching to access the arguments.
1592592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(r0, MemOperand(fp, kIndexOffset));
1593592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ add(r0, r0, Operand(1 << kSmiTagSize));
1594592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ str(r0, MemOperand(fp, kIndexOffset));
1595592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1596592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Test if the copy loop has finished copying all the elements from the
1597592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // arguments object.
1598592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&entry);
1599592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(r1, MemOperand(fp, kLimitOffset));
1600592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ cmp(r0, r1);
1601592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ b(ne, &loop);
1602592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1603592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Invoke the function.
1604592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label call_proxy;
1605592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ParameterCount actual(r0);
1606592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(r0, Operand(r0, ASR, kSmiTagSize));
1607592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ ldr(r1, MemOperand(fp, kFunctionOffset));
1608592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
1609592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ b(ne, &call_proxy);
1610592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ InvokeFunction(r1, actual, CALL_FUNCTION,
1611592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                      NullCallWrapper(), CALL_AS_METHOD);
1612592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1613592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    frame_scope.GenerateLeaveFrame();
1614592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ add(sp, sp, Operand(3 * kPointerSize));
1615592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Jump(lr);
1616592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1617592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Invoke the function proxy.
1618592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&call_proxy);
1619592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(r1);  // add function proxy as last argument
1620592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ add(r0, r0, Operand(1));
1621592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(r2, Operand(0, RelocInfo::NONE));
1622592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ SetCallKind(r5, CALL_AS_METHOD);
1623592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY);
1624592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1625592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            RelocInfo::CODE_TARGET);
1626592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1627592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Tear down the internal frame and remove function, receiver and args.
1628592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
1629589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ add(sp, sp, Operand(3 * kPointerSize));
1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(r0, LSL, kSmiTagSize));
1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() | fp.bit() | lr.bit());
1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(fp, sp, Operand(3 * kPointerSize));
1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0 : result being passed through
1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the number of arguments passed (as a smi), tear down the frame and
1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // then tear down the parameters.
1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(fp, -3 * kPointerSize));
1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(sp, fp);
1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldm(ia_w, sp, fp.bit() | lr.bit());
1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));
1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(sp, sp, Operand(kPointerSize));  // adjust for receiver
1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ----------- S t a t e -------------
1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r0 : actual number of arguments
1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r1 : function (passed through to callee)
1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r2 : expected number of arguments
1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  -- r3 : code entry to call
1662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- r5 : call kind information
1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------
1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label invoke, dont_adapt_arguments;
1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label enough, too_few;
16686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ cmp(r0, r2);
1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(lt, &too_few);
1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &dont_adapt_arguments);
1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {  // Enough parameters: actual >= expected
1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&enough);
1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    EnterArgumentsAdaptorFrame(masm);
1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Calculate copy start address into r0 and copy end address into r2.
1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0: actual number of arguments as a smi
1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: expected number of arguments
1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: code entry to call
1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // adjust for return address and receiver
1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, r0, Operand(2 * kPointerSize));
1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r2, r0, Operand(r2, LSL, kPointerSizeLog2));
1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Copy the arguments (including the receiver) to the new stack frame.
1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0: copy start address
1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: copy end address
1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: code entry to call
1692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label copy;
1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&copy);
1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(ip, MemOperand(r0, 0));
1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(ip);
1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r0, r2);  // Compare before moving to next argument.
1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r0, r0, Operand(kPointerSize));
1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &copy);
1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(&invoke);
1702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {  // Too few parameters: Actual < expected
1705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&too_few);
1706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    EnterArgumentsAdaptorFrame(masm);
1707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Calculate copy start address into r0 and copy end address is fp.
1709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0: actual number of arguments as a smi
1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: expected number of arguments
1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: code entry to call
1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
1714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Copy the arguments (including the receiver) to the new stack frame.
1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0: copy start address
1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: expected number of arguments
1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: code entry to call
1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label copy;
1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&copy);
1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Adjust load for return address and receiver.
1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(ip, MemOperand(r0, 2 * kPointerSize));
1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(ip);
1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r0, fp);  // Compare before moving to next argument.
1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r0, r0, Operand(kPointerSize));
1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &copy);
1728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Fill the remaining expected arguments with undefined.
1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: function
1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2: expected number of arguments
1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r3: code entry to call
1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r2, fp, Operand(r2, LSL, kPointerSizeLog2));
1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r2, r2, Operand(4 * kPointerSize));  // Adjust for frame.
1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label fill;
1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&fill);
1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ push(ip);
1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(sp, r2);
1741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &fill);
1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call the entry point.
1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&invoke);
1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Call(r3);
1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  // Store offset of return address for deoptimizer.
1749c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
17505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Exit frame and return.
1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LeaveArgumentsAdaptorFrame(masm);
1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(lr);
1754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -------------------------------------------
1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Dont adapt arguments.
1758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -------------------------------------------
1759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&dont_adapt_arguments);
1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Jump(r3);
1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
1767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_ARM
1769