13ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Load the built-in InternalArray function from the current context.
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateLoadInternalArrayFunction(MacroAssembler* masm,
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              Register result) {
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the global context.
793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(result,
823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         FieldMemOperand(result, GlobalObject::kGlobalContextOffset));
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the InternalArray function from the global context.
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(result,
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         MemOperand(result,
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    Context::SlotOffset(
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Context::INTERNAL_ARRAY_FUNCTION_INDEX)));
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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) {
1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const int initial_capacity = JSArray::kPreallocatedArrayElements;
1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(initial_capacity >= 0);
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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.
1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int size = JSArray::kSize;
1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (initial_capacity > 0) {
1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    size += FixedArray::SizeFor(initial_capacity);
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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
1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (initial_capacity == 0) {
1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(scratch1, FieldMemOperand(result, JSArray::kElementsOffset));
1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return;
1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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);
1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(0 * kPointerSize == FixedArray::kMapOffset);
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
1677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __ mov(scratch3,  Operand(Smi::FromInt(initial_capacity)));
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(1 * kPointerSize == FixedArray::kLengthOffset);
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Fill the FixedArray with the hole value. Inline the code if short.
1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(2 * kPointerSize == FixedArray::kHeaderSize);
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex);
1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kLoopUnfoldLimit = 4;
1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (initial_capacity <= kLoopUnfoldLimit) {
1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 0; i < initial_capacity; i++) {
1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label loop, entry;
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(scratch2, scratch1, Operand(initial_capacity * kPointerSize));
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(&entry);
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&loop);
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex));
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&entry);
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(scratch1, scratch2);
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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.
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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) {
21085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // Load the initial map from the array function.
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadInitialArrayMap(array_function, scratch2, elements_array_storage);
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {  // Assert that array size is not zero.
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ tst(array_size, array_size);
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Assert(ne, "array size is unexpectedly 0");
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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();
3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label argc_one_or_more, argc_two_or_more, not_empty_array, empty_array,
3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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.
3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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);
3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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.
3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ tst(r2, r2);
3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(ne, &not_empty_array);
3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Drop(1);  // Adjust stack.
3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r0, Operand(0));  // Treat this as a call with argc of zero.
3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(&empty_array);
3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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);
3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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;
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(r7, sp);
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&entry);
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&loop);
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(r2, MemOperand(r7, kPointerSize, PostIndex));
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_smi_only_arrays) {
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfNotSmi(r2, &has_non_smi_element);
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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
4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&finish);
4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(sp, r7);
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
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);
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&has_non_smi_element);
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Double values are handled by the runtime.
4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      r2, r9, Heap::kHeapNumberMapRootIndex, &not_double, DONT_DO_SMI_CHECK);
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&cant_transition_map);
4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ UndoAllocationInNewSpace(r3, r4);
4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(call_generic_code);
4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&not_double);
4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Transition FAST_SMI_ONLY_ELEMENTS to FAST_ELEMENTS.
4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // r3: JSArray
4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         FAST_ELEMENTS,
4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         r2,
4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         r9,
4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         &cant_transition_map);
4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ str(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ RecordWriteField(r3,
4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      HeapObject::kMapOffset,
4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      r2,
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      r9,
4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kLRHasNotBeenSaved,
4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kDontSaveFPRegs,
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      EMIT_REMEMBERED_SET,
4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      OMIT_SMI_CHECK);
4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label loop2;
4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub(r7, r7, Operand(kPointerSize));
4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&loop2);
4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(r2, MemOperand(r7, kPointerSize, PostIndex));
4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ str(r2, MemOperand(r5, -kPointerSize, PreIndex));
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r4, r5);
4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(lt, &loop2);
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(&finish);
4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ----------- S t a t e -------------
4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- r0     : number of arguments
4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- lr     : return address
4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- sp[...]: constructor arguments
4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // -----------------------------------
4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the InternalArray function.
4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadInternalArrayFunction(masm, r1);
4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {
4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Initial map for the builtin InternalArray functions should be maps.
4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ tst(r2, Operand(kSmiTagMask));
4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Assert(ne, "Unexpected initial map for InternalArray function");
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareObjectType(r2, r3, r4, MAP_TYPE);
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Assert(eq, "Unexpected initial map for InternalArray function");
4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Run the native code for the InternalArray function called as a normal
4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // function.
4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ArrayNativeCode(masm, &generic_array_code);
4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Jump to the generic array code if the specialized code cannot handle the
4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // construction.
4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&generic_array_code);
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> array_code =
5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->isolate()->builtins()->InternalArrayCodeGeneric();
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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);
6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
6713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
6723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r0);
6733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
6743ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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);
6903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
6913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
6923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(argument);
6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kNewStringWrapper, 1);
6943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  __ Ret();
69680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
69780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
69880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
6993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void Generate_JSConstructStubHelper(MacroAssembler* masm,
7003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           bool is_api_function,
7013ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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.
7153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
7163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::CONSTRUCT);
7173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Preserve the two incoming parameters on the stack.
7193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(r0, Operand(r0, LSL, kSmiTagSize));
7203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r0);  // Smi-tagged arguments count.
7213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r1);  // Constructor function.
7223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Try to allocate the object without transitioning into C code. If any of
7243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // the preconditions is not met, the code bails out to the runtime call.
7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label rt_call, allocated;
7263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_inline_new) {
7273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label undo_allocation;
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
7293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExternalReference debug_step_in_fp =
7303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ExternalReference::debug_step_in_fp_address(isolate);
7313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(r2, Operand(debug_step_in_fp));
7323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(r2, MemOperand(r2));
7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ tst(r2, r2);
7343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ b(ne, &rt_call);
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Load the initial map and verify that it is in fact a map.
7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r1: constructor function
7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
7403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ JumpIfSmi(r2, &rt_call);
7413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CompareObjectType(r2, r3, r4, MAP_TYPE);
7423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ b(ne, &rt_call);
7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check that the constructor is not constructing a JSFunction (see
7453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // comments in Runtime_NewObject in runtime.cc). In which case the
7463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // initial map's instance type would be JS_FUNCTION_TYPE.
7473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r1: constructor function
7483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r2: initial map
7493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE);
7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ b(eq, &rt_call);
75185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
7523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (count_constructions) {
7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Label allocate;
7543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Decrease generous allocation count.
7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
7563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        MemOperand constructor_count =
7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            FieldMemOperand(r3, SharedFunctionInfo::kConstructionCountOffset);
7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ ldrb(r4, constructor_count);
7593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sub(r4, r4, Operand(1), SetCC);
7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ strb(r4, constructor_count);
7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ b(ne, &allocate);
7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Push(r1, r2);
7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ push(r1);  // constructor
7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The call will replace the stub, so the countdown is only done once.
7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ pop(r2);
7703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ pop(r1);
7713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&allocate);
7733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Now allocate the JSObject on the heap.
7763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r1: constructor function
7773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r2: initial map
7783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
7793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS);
7803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Allocated the JSObject, now initialize the fields. Map is set to
7823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // initial map and properties and elements are set to empty fixed array.
7833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r1: constructor function
7843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r2: initial map
7853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r3: object size
7863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r4: JSObject (not tagged)
7873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
7883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(r5, r4);
7893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
7903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
7913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
7923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
7943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
7953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Fill all the in-object properties with the appropriate filler.
7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r1: constructor function
7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r2: initial map
7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r3: object size (in words)
8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r4: JSObject (not tagged)
8013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r5: First in-object property of JSObject (not tagged)
8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
8043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
8050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      if (count_constructions) {
8063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
8073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Ubfx(r0, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                kBitsPerByte);
8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ add(r0, r5, Operand(r0, LSL, kPointerSizeLog2));
8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // r0: offset of first field after pre-allocated fields
8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (FLAG_debug_code) {
8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ cmp(r0, r6);
8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ Assert(le, "Unexpected number of pre-allocated property fields.");
8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ InitializeFieldsWithFiller(r5, r0, r7);
8160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        // To allow for truncation.
8170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        __ LoadRoot(r7, Heap::kOnePointerFillerMapRootIndex);
8180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      }
8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ InitializeFieldsWithFiller(r5, r6, r7);
8203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Add the object tag to make the JSObject real, so that we can continue
8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // and jump into the continuation code at any time from now on. Any
8233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // failures need to undo the allocation, so that the heap is in a
8243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // consistent state and verifiable.
8253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(r4, r4, Operand(kHeapObjectTag));
8263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check if a non-empty properties array is needed. Continue with
8283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // allocated object if not fall through to runtime call if it is.
8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r1: constructor function
8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r4: JSObject
8313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r5: start of next object (not tagged)
8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset));
8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // The field instance sizes contains both pre-allocated property fields
8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // and in-object properties.
8353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Ubfx(r6, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
8373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              kBitsPerByte);
8383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(r3, r3, Operand(r6));
8393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Ubfx(r6, r0, Map::kInObjectPropertiesByte * kBitsPerByte,
8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              kBitsPerByte);
8413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sub(r3, r3, Operand(r6), SetCC);
8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Done if no extra properties are to be allocated.
8443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ b(eq, &allocated);
8453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Assert(pl, "Property allocation count failed.");
8463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Scale the number of elements by pointer size and add the header for
8483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // FixedArrays to the start of the next object calculation from above.
8493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r1: constructor
8503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r3: number of elements in properties array
8513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r4: JSObject
8523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r5: start of next object
8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize));
8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ AllocateInNewSpace(
8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          r0,
8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          r5,
8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          r6,
8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          r2,
8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          &undo_allocation,
8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS));
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Initialize the FixedArray.
8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r1: constructor
8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r3: number of elements in properties array
8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r4: JSObject
8663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r5: FixedArray (not tagged)
8673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex);
8683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(r2, r5);
8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
8703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ str(r6, MemOperand(r2, kPointerSize, PostIndex));
8713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
8723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(r0, Operand(r3, LSL, kSmiTagSize));
8733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ str(r0, MemOperand(r2, kPointerSize, PostIndex));
8743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Initialize the fields to undefined.
8763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r1: constructor function
8773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r2: First element of FixedArray (not tagged)
8783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r3: number of elements in properties array
8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r4: JSObject
8803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r5: FixedArray (not tagged)
8813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
8823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
8833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      { Label loop, entry;
8843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (count_constructions) {
8853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else if (FLAG_debug_code) {
8873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ LoadRoot(r8, Heap::kUndefinedValueRootIndex);
8883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ cmp(r7, r8);
8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ Assert(eq, "Undefined value not loaded.");
8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ b(&entry);
8923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&loop);
8933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ str(r7, MemOperand(r2, kPointerSize, PostIndex));
8943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&entry);
8953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ cmp(r2, r6);
8963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ b(lt, &loop);
89785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      }
8983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the initialized FixedArray into the properties field of
9003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the JSObject
9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r1: constructor function
9023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r4: JSObject
9033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r5: FixedArray (not tagged)
9043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add(r5, r5, Operand(kHeapObjectTag));  // Add the heap tag.
9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ str(r5, FieldMemOperand(r4, JSObject::kPropertiesOffset));
9063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Continue with JSObject being successfully allocated
9083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r1: constructor function
9093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r4: JSObject
9103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&allocated);
9113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Undo the setting of the new top so that the heap is verifiable. For
9133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // example, the map's unused properties potentially do not match the
9143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // allocated objects unused properties.
9153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // r4: JSObject (previous new top)
9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&undo_allocation);
9173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ UndoAllocationInNewSpace(r4, r5);
91885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    }
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Allocate the new receiver object using the runtime call.
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1: constructor function
9223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&rt_call);
9233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r1);  // argument for Runtime_NewObject
9243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kNewObject, 1);
9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(r4, r0);
9263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Receiver for constructor call allocated.
92885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    // r4: JSObject
9293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&allocated);
9303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r4);
9313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r4);
9323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Reload the number of arguments and the constructor from the stack.
9343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[0]: receiver
9353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[1]: receiver
9363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[2]: constructor function
9373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[3]: number of arguments (smi-tagged)
9383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r1, MemOperand(sp, 2 * kPointerSize));
9393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r3, MemOperand(sp, 3 * kPointerSize));
9403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Set up pointer to last argument.
9423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
9433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Set up number of arguments for function call below
9453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(r0, Operand(r3, LSR, kSmiTagSize));
9463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Copy arguments and receiver to the expression stack.
9483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // r0: number of arguments
9493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // r1: constructor function
9503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // r2: address of last argument (caller sp)
9513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // r3: number of arguments (smi-tagged)
9523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[0]: receiver
9533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[1]: receiver
9543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[2]: constructor function
9553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[3]: number of arguments (smi-tagged)
9563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label loop, entry;
9573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(&entry);
9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&loop);
9593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1));
9603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(ip);
9613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&entry);
9623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sub(r3, r3, Operand(2), SetCC);
9633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(ge, &loop);
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Call the function.
9663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // r0: number of arguments
96785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    // r1: constructor function
9683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_api_function) {
9693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
9703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Code> code =
9713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          masm->isolate()->builtins()->HandleApiCallConstruct();
9723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ParameterCount expected(0);
9733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ InvokeCode(code, expected, expected,
9743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    RelocInfo::CODE_TARGET, CALL_FUNCTION, CALL_AS_METHOD);
9753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
9763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ParameterCount actual(r0);
9773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ InvokeFunction(r1, actual, CALL_FUNCTION,
9783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        NullCallWrapper(), CALL_AS_METHOD);
9793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Store offset of return address for deoptimizer.
9823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!is_api_function && !count_constructions) {
9833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
9843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
98585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
9863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore context from the frame.
9873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // r0: result
9883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[0]: receiver
9893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[1]: constructor function
9903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[2]: number of arguments (smi-tagged)
9913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
9923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If the result is an object (in the ECMA sense), we should get rid
9943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // of the receiver and use the result; see ECMA-262 section 13.2.2-7
9953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // on page 74.
9963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label use_receiver, exit;
9973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If the result is a smi, it is *not* an object in the ECMA sense.
9993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // r0: result
10003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[0]: receiver (newly allocated object)
10013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[1]: constructor function
10023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[2]: number of arguments (smi-tagged)
10033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(r0, &use_receiver);
10043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If the type of the result (stored in its map) is less than
10063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
10073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareObjectType(r0, r3, r3, FIRST_SPEC_OBJECT_TYPE);
10083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(ge, &exit);
10093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Throw away the result of the constructor invocation and use the
10113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // on-stack receiver as the result.
10123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&use_receiver);
10133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r0, MemOperand(sp));
10143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Remove receiver from the stack, remove caller arguments, and
10163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // return.
10173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&exit);
10183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // r0: result
10193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[0]: receiver (newly allocated object)
10203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[1]: constructor function
10213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[2]: number of arguments (smi-tagged)
10223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r1, MemOperand(sp, 2 * kPointerSize));
10233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10243ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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
10593ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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.
10633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
10643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Set up the context from the function argument.
10673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ InitializeRootRegister();
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Push the function and the receiver onto the stack.
10723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r1);
10733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r2);
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Copy arguments to the stack in a loop.
10763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // r1: function
10773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // r3: argc
10783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // r4: argv, i.e. points to first arg
10793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label loop, entry;
10803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2));
10813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // r2 points past last arg.
10823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(&entry);
10833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&loop);
10843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex));  // read next parameter
10853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r0, MemOperand(r0));  // dereference handle
10863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r0);  // push parameter
10873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&entry);
10883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(r4, r2);
10893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(ne, &loop);
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Initialize all JavaScript callee-saved registers, since they will be seen
10923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // by the garbage collector as part of handlers.
10933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
10943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(r5, Operand(r4));
10953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(r6, Operand(r4));
10963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(r7, Operand(r4));
10973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (kR9Available == 1) {
10983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(r9, Operand(r4));
10993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
110085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
11013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Invoke the code and pass argc as r0.
11023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(r0, Operand(r3));
11033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_construct) {
11043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
11053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CallStub(&stub);
11063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
11073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ParameterCount actual(r0);
11083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ InvokeFunction(r1, actual, CALL_FUNCTION,
11093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        NullCallWrapper(), CALL_AS_METHOD);
11103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
11113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Exit the JS frame and remove the parameters (except function), and
11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // return.
11133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Respect ABI stack constraint.
11143ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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.
11333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
11343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
1135756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
11363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Preserve the function.
11373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r1);
11383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Push call kind information.
11393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r5);
1140756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Push the function on the stack as the argument to the runtime function.
11423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r1);
11433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kLazyCompile, 1);
11443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Calculate the entry point.
11453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
1146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore call kind information.
11483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ pop(r5);
11493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore saved function.
11503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ pop(r1);
1151756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
11523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Tear down internal frame.
11533ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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.
11623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
11633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
1164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
11653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Preserve the function.
11663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r1);
11673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Push call kind information.
11683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r5);
1169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
11703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Push the function on the stack as the argument to the runtime function.
11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r1);
11723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kLazyRecompile, 1);
11733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Calculate the entry point.
11743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
1175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore call kind information.
11773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ pop(r5);
11783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore saved function.
11793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ pop(r1);
1180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
11813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Tear down internal frame.
11823ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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) {
11913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
11923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
11933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Pass the function and deoptimization type to the runtime system.
11943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(r0, Operand(Smi::FromInt(static_cast<int>(type))));
11953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r0);
11963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
11973ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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());
12373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
12383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
12393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kNotifyOSR, 0);
12403ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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));
12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
12573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
12583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r0);
12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
12603ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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;
12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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
13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    {
13443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Enter an internal frame in order to preserve argument count.
13453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FrameScope scope(masm, StackFrame::INTERNAL);
13463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(r0, Operand(r0, LSL, kSmiTagSize));  // Smi-tagged.
13473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(r0);
13483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(r2);
13503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
13513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(r2, r0);
13523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(r0);
13543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(r0, Operand(r0, ASR, kSmiTagSize));
13553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Exit the internal frame.
13573ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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
14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope frame_scope(masm, StackFrame::INTERNAL);
1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r0, MemOperand(fp, kFunctionOffset));  // get the function
14823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r0);
14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r0, MemOperand(fp, kArgsOffset));  // get the args array
14843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r0);
14853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
14863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check the stack for overflow. We are not trying to catch
14883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // interruptions (e.g. debug break and preemption) here, so the "real stack
14893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // limit" is checked.
14903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label okay;
14913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(r2, Heap::kRealStackLimitRootIndex);
14923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make r2 the space we have left. The stack might already be overflowed
14933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // here which will cause r2 to become negative.
14943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sub(r2, sp, r2);
14953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check if the arguments will overflow the stack.
14963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
14973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(gt, &okay);  // Signed comparison.
14983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Out of stack space.
15003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r1, MemOperand(fp, kFunctionOffset));
15013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r1);
15023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r0);
15033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
15043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // End of stack check.
1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Push current limit and index.
15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&okay);
15083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r0);  // limit
15093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(r1, Operand(0, RelocInfo::NONE));  // initial index
15103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r1);
1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Get the receiver.
15133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r0, MemOperand(fp, kRecvOffset));
1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check that the function is a JS function (otherwise it must be a proxy).
15163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label push_receiver;
15173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r1, MemOperand(fp, kFunctionOffset));
15183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
15193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(ne, &push_receiver);
1520589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
15213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Change context eagerly to get the right global object if necessary.
15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Load the shared function info while the function is still in r1.
15243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1525592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Compute the receiver.
15273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Do not transform the receiver for strict mode functions.
15283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label call_to_object, use_global_receiver;
15293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset));
15303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ tst(r2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
15313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             kSmiTagSize)));
15323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(ne, &push_receiver);
1533589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
15343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Do not transform the receiver for strict mode functions.
15353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ tst(r2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(ne, &push_receiver);
1537592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Compute the receiver in non-strict mode.
15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(r0, &call_to_object);
15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(r1, Heap::kNullValueRootIndex);
15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(r0, r1);
15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(eq, &use_global_receiver);
15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(r0, r1);
15453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(eq, &use_global_receiver);
1546592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
15473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check if the receiver is already a JavaScript object.
15483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // r0: receiver
15493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
15503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
15513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(ge, &push_receiver);
1552592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
15533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Convert the receiver to a regular object.
15543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // r0: receiver
15553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&call_to_object);
15563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r0);
15573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
15583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(&push_receiver);
1559592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
15603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Use the current global receiver object as the receiver.
15613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&use_global_receiver);
15623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const int kGlobalOffset =
15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r0, FieldMemOperand(cp, kGlobalOffset));
15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset));
15663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r0, FieldMemOperand(r0, kGlobalOffset));
15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Push the receiver.
15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // r0: receiver
15713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&push_receiver);
15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r0);
15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Copy all arguments from the array to the stack.
15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label entry, loop;
15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r0, MemOperand(fp, kIndexOffset));
15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(&entry);
15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Load the current argument from the arguments array and push it to the
15803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // stack.
15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // r0: current argument index
15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&loop);
15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r1, MemOperand(fp, kArgsOffset));
15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r1);
15853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r0);
15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Call the runtime to access the property in the arguments array.
15883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kGetProperty, 2);
15893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r0);
15903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Use inline caching to access the arguments.
15923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r0, MemOperand(fp, kIndexOffset));
15933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(r0, r0, Operand(1 << kSmiTagSize));
15943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ str(r0, MemOperand(fp, kIndexOffset));
15953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Test if the copy loop has finished copying all the elements from the
15973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // arguments object.
15983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&entry);
15993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r1, MemOperand(fp, kLimitOffset));
16003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(r0, r1);
16013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(ne, &loop);
1602592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
16033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Invoke the function.
16043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label call_proxy;
16053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ParameterCount actual(r0);
16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(r0, Operand(r0, ASR, kSmiTagSize));
16073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldr(r1, MemOperand(fp, kFunctionOffset));
16083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
16093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(ne, &call_proxy);
16103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ InvokeFunction(r1, actual, CALL_FUNCTION,
16113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      NullCallWrapper(), CALL_AS_METHOD);
16123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    frame_scope.GenerateLeaveFrame();
16143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(sp, sp, Operand(3 * kPointerSize));
16153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Jump(lr);
16163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Invoke the function proxy.
16183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&call_proxy);
16193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(r1);  // add function proxy as last argument
16203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ add(r0, r0, Operand(1));
16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(r2, Operand(0, RelocInfo::NONE));
16223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SetCallKind(r5, CALL_AS_METHOD);
16233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY);
16243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
16253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            RelocInfo::CODE_TARGET);
16263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Tear down the internal frame and remove function, receiver and args.
16283ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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
17483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Store offset of return address for deoptimizer.
17493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
17503ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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