builtins-mips.cc revision 592a9fc1d8ea420377a2e7efd0600e20b058be2b
1257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
23100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Redistribution and use in source and binary forms, with or without
33100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// modification, are permitted provided that the following conditions are
43100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// met:
53100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//
63100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//     * Redistributions of source code must retain the above copyright
73100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       notice, this list of conditions and the following disclaimer.
83100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//     * Redistributions in binary form must reproduce the above
93100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       copyright notice, this list of conditions and the following
103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       disclaimer in the documentation and/or other materials provided
113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       with the distribution.
123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//     * Neither the name of Google Inc. nor the names of its
133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       contributors may be used to endorse or promote products derived
143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//       from this software without specific prior written permission.
153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu//
163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "v8.h"
313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
32f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_MIPS)
33f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
34257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "codegen.h"
353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "debug.h"
3644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "deoptimizer.h"
3744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "full-codegen.h"
383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "runtime.h"
393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace v8 {
413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace internal {
423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define __ ACCESS_MASM(masm)
453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Builtins::Generate_Adaptor(MacroAssembler* masm,
483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                CFunctionId id,
493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                                BuiltinExtraArguments extra_args) {
50257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
51257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0                 : number of arguments excluding receiver
52257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1                 : called function (only guaranteed when
53257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  --                      extra_args requires it)
54257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- cp                 : context
55257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[0]              : last argument
56257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ...
57257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[4 * (argc - 1)] : first argument
58257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[4 * agrc]       : receiver
59257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
60257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
61257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Insert extra arguments.
62257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int num_extra_args = 0;
63257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (extra_args == NEEDS_CALLED_FUNCTION) {
64257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    num_extra_args = 1;
65257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ push(a1);
66257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
67257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(extra_args == NO_EXTRA_ARGUMENTS);
68257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
69257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
70257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // JumpToExternalReference expects a0 to contain the number of arguments
71257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // including the receiver and the extra arguments.
72257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(a0, a0, Operand(num_extra_args + 1));
73257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpToExternalReference(ExternalReference(id, masm->isolate()));
74257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
75257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
76257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
77257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Load the built-in Array function from the current context.
78257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) {
79257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the global context.
80257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
81257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
82257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(result,
83257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         FieldMemOperand(result, GlobalObject::kGlobalContextOffset));
84257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the Array function from the global context.
85257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(result,
86257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         MemOperand(result,
87257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
88257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
89257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
90257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
91257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Allocate an empty JSArray. The allocated array is put into the result
92257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// register. An elements backing store is allocated with size initial_capacity
93257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// and filled with the hole values.
94257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void AllocateEmptyJSArray(MacroAssembler* masm,
95257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Register array_function,
96257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Register result,
97257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Register scratch1,
98257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Register scratch2,
99257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Register scratch3,
100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Label* gc_required) {
101592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  const int initial_capacity = JSArray::kPreallocatedArrayElements;
102592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  STATIC_ASSERT(initial_capacity >= 0);
103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the initial map from the array function.
104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(scratch1, FieldMemOperand(array_function,
105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                  JSFunction::kPrototypeOrInitialMapOffset));
106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Allocate the JSArray object together with space for a fixed array with the
108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // requested elements.
109592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  int size = JSArray::kSize;
110592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (initial_capacity > 0) {
111592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    size += FixedArray::SizeFor(initial_capacity);
112592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ AllocateInNewSpace(size,
114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        result,
115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        scratch2,
116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        scratch3,
117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        gc_required,
118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        TAG_OBJECT);
119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Allocated the JSArray. Now initialize the fields except for the elements
120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // array.
121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // result: JSObject
122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // scratch1: initial map
123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // scratch2: start of next object
124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(scratch1, FieldMemOperand(result, JSObject::kMapOffset));
125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex);
126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(scratch1, FieldMemOperand(result, JSArray::kPropertiesOffset));
127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Field JSArray::kElementsOffset is initialized later.
128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(scratch3,  zero_reg);
129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(scratch3, FieldMemOperand(result, JSArray::kLengthOffset));
130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
131592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (initial_capacity == 0) {
132592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ sw(scratch1, FieldMemOperand(result, JSArray::kElementsOffset));
133592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return;
134592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
135592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Calculate the location of the elements array and set elements array member
137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // of the JSArray.
138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // result: JSObject
139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // scratch2: start of next object
140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(scratch1, result, Operand(JSArray::kSize));
141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(scratch1, FieldMemOperand(result, JSArray::kElementsOffset));
142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Clear the heap tag on the elements array.
144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ And(scratch1, scratch1, Operand(~kHeapObjectTagMask));
145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Initialize the FixedArray and fill it with holes. FixedArray length is
147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // stored as a smi.
148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // result: JSObject
149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // scratch1: elements array (untagged)
150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // scratch2: start of next object
151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(scratch3, Heap::kFixedArrayMapRootIndex);
152592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  STATIC_ASSERT(0 * kPointerSize == FixedArray::kMapOffset);
153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(scratch3, MemOperand(scratch1));
154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(scratch1, scratch1, kPointerSize);
155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ li(scratch3,  Operand(Smi::FromInt(initial_capacity)));
156592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  STATIC_ASSERT(1 * kPointerSize == FixedArray::kLengthOffset);
157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(scratch3, MemOperand(scratch1));
158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(scratch1, scratch1, kPointerSize);
159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
160592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Fill the FixedArray with the hole value. Inline the code if short.
161592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  STATIC_ASSERT(2 * kPointerSize == FixedArray::kHeaderSize);
162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex);
163592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  static const int kLoopUnfoldLimit = 4;
164592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (initial_capacity <= kLoopUnfoldLimit) {
165592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    for (int i = 0; i < initial_capacity; i++) {
166592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ sw(scratch3, MemOperand(scratch1, i * kPointerSize));
167592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
168592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  } else {
169592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label loop, entry;
170592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Addu(scratch2, scratch1, Operand(initial_capacity * kPointerSize));
171592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Branch(&entry);
172592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&loop);
173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sw(scratch3, MemOperand(scratch1));
174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Addu(scratch1, scratch1, kPointerSize);
175592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&entry);
176592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Branch(&loop, lt, scratch1, Operand(scratch2));
177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Allocate a JSArray with the number of elements stored in a register. The
182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// register array_function holds the built-in Array function and the register
183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// array_size holds the size of the array as a smi. The allocated array is put
184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// into the result register and beginning and end of the FixedArray elements
185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// storage is put into registers elements_array_storage and elements_array_end
186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// (see  below for when that is not the case). If the parameter fill_with_holes
187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// is true the allocated elements backing store is filled with the hole values
188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// otherwise it is left uninitialized. When the backing store is filled the
189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// register elements_array_storage is scratched.
190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void AllocateJSArray(MacroAssembler* masm,
191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register array_function,  // Array function.
192592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                            Register array_size,  // As a smi, cannot be 0.
193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register result,
194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register elements_array_storage,
195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register elements_array_end,
196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register scratch1,
197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register scratch2,
198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            bool fill_with_hole,
199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* gc_required) {
200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the initial map from the array function.
201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(elements_array_storage,
202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         FieldMemOperand(array_function,
203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                         JSFunction::kPrototypeOrInitialMapOffset));
204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
205592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (FLAG_debug_code) {  // Assert that array size is not zero.
206592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Assert(
207592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        ne, "array size is unexpectedly 0", array_size, Operand(zero_reg));
208592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Allocate the JSArray object together with space for a FixedArray with the
211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // requested number of elements.
212589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ li(elements_array_end,
214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        (JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize);
215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sra(scratch1, array_size, kSmiTagSize);
216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(elements_array_end, elements_array_end, scratch1);
217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ AllocateInNewSpace(
218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      elements_array_end,
219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      result,
220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      scratch1,
221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      scratch2,
222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      gc_required,
223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Allocated the JSArray. Now initialize the fields except for the elements
226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // array.
227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // result: JSObject
228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // elements_array_storage: initial map
229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // array_size: size of array (smi)
230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(elements_array_storage, FieldMemOperand(result, JSObject::kMapOffset));
231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(elements_array_storage, Heap::kEmptyFixedArrayRootIndex);
232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(elements_array_storage,
233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         FieldMemOperand(result, JSArray::kPropertiesOffset));
234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Field JSArray::kElementsOffset is initialized later.
235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(array_size, FieldMemOperand(result, JSArray::kLengthOffset));
236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Calculate the location of the elements array and set elements array member
238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // of the JSArray.
239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // result: JSObject
240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // array_size: size of array (smi)
241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(elements_array_storage, result, Operand(JSArray::kSize));
242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(elements_array_storage,
243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         FieldMemOperand(result, JSArray::kElementsOffset));
244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Clear the heap tag on the elements array.
246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ And(elements_array_storage,
247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          elements_array_storage,
248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Operand(~kHeapObjectTagMask));
249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Initialize the fixed array and fill it with holes. FixedArray length is
250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // stored as a smi.
251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // result: JSObject
252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // elements_array_storage: elements array (untagged)
253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // array_size: size of array (smi)
254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(scratch1, Heap::kFixedArrayMapRootIndex);
255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset);
256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(scratch1, MemOperand(elements_array_storage));
257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(elements_array_storage, elements_array_storage, kPointerSize);
258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Length of the FixedArray is the number of pre-allocated elements if
260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // the actual JSArray has length 0 and the size of the JSArray for non-empty
261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // JSArrays. The length of a FixedArray is stored as a smi.
262589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(array_size, MemOperand(elements_array_storage));
266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(elements_array_storage, elements_array_storage, kPointerSize);
267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Calculate elements array and elements array end.
269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // result: JSObject
270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // elements_array_storage: elements array element storage
271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // array_size: smi-tagged size of elements array
272589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(elements_array_end, array_size, kPointerSizeLog2 - kSmiTagSize);
274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(elements_array_end, elements_array_storage, elements_array_end);
275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Fill the allocated FixedArray with the hole value if requested.
277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // result: JSObject
278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // elements_array_storage: elements array element storage
279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // elements_array_end: start of next object
280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (fill_with_hole) {
281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label loop, entry;
282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(scratch1, Heap::kTheHoleValueRootIndex);
283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&entry);
284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&loop);
285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sw(scratch1, MemOperand(elements_array_storage));
286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Addu(elements_array_storage, elements_array_storage, kPointerSize);
287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&entry);
289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&loop, lt, elements_array_storage, Operand(elements_array_end));
290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Create a new array for the built-in Array function. This function allocates
295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// the JSArray object and the FixedArray elements array and initializes these.
296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// If the Array cannot be constructed in native code the runtime is called. This
297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// function assumes the following state:
298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//   a0: argc
299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//   a1: constructor (built-in Array function)
300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//   ra: return address
301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//   sp[0]: last argument
302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// This function is used for both construct and normal calls of Array. The only
303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// difference between handling a construct call and a normal call is that for a
304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// construct call the constructor function in a1 needs to be preserved for
305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// entering the generic code. In both cases argc in a0 needs to be preserved.
306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Both registers are preserved by this code so no need to differentiate between
307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// construct call and normal call.
308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void ArrayNativeCode(MacroAssembler* masm,
309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* call_generic_code) {
310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = masm->isolate()->counters();
311592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Label argc_one_or_more, argc_two_or_more, not_empty_array, empty_array;
312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check for array construction with zero arguments or one.
314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&argc_one_or_more, ne, a0, Operand(zero_reg));
315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle construction of an empty array.
316592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ bind(&empty_array);
317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  AllocateEmptyJSArray(masm,
318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       a1,
319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       a2,
320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       a3,
321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       t0,
322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       t1,
323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       call_generic_code);
324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->array_function_native(), 1, a3, t0);
325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Setup return value, remove receiver from stack and return.
326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(v0, a2);
327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(sp, sp, Operand(kPointerSize));
328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check for one argument. Bail out if argument is not smi or if it is
331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // negative.
332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&argc_one_or_more);
333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&argc_two_or_more, ne, a0, Operand(1));
334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
335589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a2, MemOperand(sp));  // Get the argument from the stack.
337592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Branch(&not_empty_array, ne, a2, Operand(zero_reg));
338592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Drop(1);  // Adjust stack.
339592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ mov(a0, zero_reg);  // Treat this as a call with argc of zero.
340592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Branch(&empty_array);
341592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
342592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ bind(&not_empty_array);
343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ And(a3, a2, Operand(kIntptrSignBit | kSmiTagMask));
344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(call_generic_code, eq, a3, Operand(zero_reg));
345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle construction of an empty array of a certain size. Bail out if size
347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // is too large to actually allocate an elements array.
348589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
3493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Branch(call_generic_code, Ugreater_equal, a2,
350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            Operand(JSObject::kInitialMaxFastElementArray << kSmiTagSize));
351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: argc
353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: constructor
354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a2: array_size (smi)
355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // sp[0]: argument
356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  AllocateJSArray(masm,
357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  a1,
358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  a2,
359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  a3,
360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  t0,
361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  t1,
362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  t2,
363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  t3,
364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  true,
365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  call_generic_code);
366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->array_function_native(), 1, a2, t0);
367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Setup return value, remove receiver and argument from stack and return.
369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(v0, a3);
370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(sp, sp, Operand(2 * kPointerSize));
371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle construction of an array from a list of arguments.
374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&argc_two_or_more);
375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(a2, a0, kSmiTagSize);  // Convert argc to a smi.
376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: argc
378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: constructor
379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a2: array_size (smi)
380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // sp[0]: last argument
381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  AllocateJSArray(masm,
382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  a1,
383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  a2,
384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  a3,
385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  t0,
386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  t1,
387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  t2,
388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  t3,
389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  false,
390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  call_generic_code);
391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->array_function_native(), 1, a2, t2);
392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Fill arguments as array elements. Copy from the top of the stack (last
394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // element) to the array backing store filling it backwards. Note:
395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // elements_array_end points after the backing store.
396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: argc
397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a3: JSArray
398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // t0: elements_array storage start (untagged)
399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // t1: elements_array_end (untagged)
400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // sp[0]: last argument
401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label loop, entry;
403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&entry);
404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&loop);
405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ pop(a2);
406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(t1, t1, -kPointerSize);
407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(a2, MemOperand(t1));
408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&entry);
409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&loop, lt, t0, Operand(t1));
410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Remove caller arguments and receiver from the stack, setup return value and
412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // return.
413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: argc
414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a3: JSArray
415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // sp[0]: receiver
416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(sp, sp, Operand(kPointerSize));
417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(v0, a3);
418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
4193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
4203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Builtins::Generate_ArrayCode(MacroAssembler* masm) {
423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0     : number of arguments
425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra     : return address
426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[...]: constructor arguments
427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label generic_array_code;
429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the Array function.
431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadArrayFunction(masm, a1);
432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (FLAG_debug_code) {
434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Initial map for the builtin Array functions should be maps.
435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ And(t0, a2, Operand(kSmiTagMask));
437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Assert(ne, "Unexpected initial map for Array function (1)",
438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              t0, Operand(zero_reg));
439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ GetObjectType(a2, a3, t0);
440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Assert(eq, "Unexpected initial map for Array function (2)",
441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              t0, Operand(MAP_TYPE));
442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Run the native code for the Array function called as a normal function.
445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ArrayNativeCode(masm, &generic_array_code);
446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Jump to the generic array code if the specialized code cannot handle
448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // the construction.
449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&generic_array_code);
450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> array_code =
452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->ArrayCodeGeneric();
453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(array_code, RelocInfo::CODE_TARGET);
4543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
4553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) {
458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0     : number of arguments
460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1     : constructor function
461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra     : return address
462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[...]: constructor arguments
463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label generic_constructor;
465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (FLAG_debug_code) {
467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // The array construct code is only set for the builtin and internal
468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Array functions which always have a map.
469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Initial map for the builtin Array function should be a map.
470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ And(t0, a2, Operand(kSmiTagMask));
472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Assert(ne, "Unexpected initial map for Array function (3)",
473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              t0, Operand(zero_reg));
474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ GetObjectType(a2, a3, t0);
475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Assert(eq, "Unexpected initial map for Array function (4)",
476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              t0, Operand(MAP_TYPE));
477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Run the native code for the Array function called as a constructor.
480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ArrayNativeCode(masm, &generic_constructor);
481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Jump to the generic construct code in case the specialized code cannot
483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // handle the construction.
484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&generic_constructor);
485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> generic_construct_stub =
487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->JSConstructStubGeneric();
488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
4893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
4903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
4913100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
49244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0                     : number of arguments
495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1                     : constructor function
496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra                     : return address
497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[argc * 4]           : receiver
499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = masm->isolate()->counters();
501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->string_ctor_calls(), 1, a2, a3);
502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register function = a1;
504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (FLAG_debug_code) {
505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, a2);
506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Assert(eq, "Unexpected String function", function, Operand(a2));
507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the first arguments in a0 and get rid of the rest.
510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label no_arguments;
511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&no_arguments, eq, a0, Operand(zero_reg));
512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // First args = sp[(argc - 1) * 4].
513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Subu(a0, a0, Operand(1));
514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(a0, a0, kPointerSizeLog2);
515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(sp, a0, sp);
516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a0, MemOperand(sp));
517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // sp now point to args[0], drop args[0] + receiver.
518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Drop(2);
519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register argument = a2;
521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label not_cached, argument_is_string;
522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  NumberToStringStub::GenerateLookupNumberStringCache(
523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm,
524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      a0,        // Input.
525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      argument,  // Result.
526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      a3,        // Scratch.
527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      t0,        // Scratch.
528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      t1,        // Scratch.
529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      false,     // Is it a Smi?
530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      &not_cached);
531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->string_ctor_cached_number(), 1, a3, t0);
532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&argument_is_string);
533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2     : argument converted to string
536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1     : constructor function
537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra     : return address
538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label gc_required;
541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ AllocateInNewSpace(JSValue::kSize,
542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        v0,  // Result.
543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        a3,  // Scratch.
544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        t0,  // Scratch.
545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        &gc_required,
546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        TAG_OBJECT);
547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Initialising the String Object.
549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register map = a3;
550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadGlobalFunctionInitialMap(function, map, t0);
551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (FLAG_debug_code) {
552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lbu(t0, FieldMemOperand(map, Map::kInstanceSizeOffset));
553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Assert(eq, "Unexpected string wrapper instance size",
554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        t0, Operand(JSValue::kSize >> kPointerSizeLog2));
555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lbu(t0, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset));
556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Assert(eq, "Unexpected unused properties of string wrapper",
557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        t0, Operand(zero_reg));
558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(map, FieldMemOperand(v0, HeapObject::kMapOffset));
560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex);
562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset));
563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(a3, FieldMemOperand(v0, JSObject::kElementsOffset));
564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(argument, FieldMemOperand(v0, JSValue::kValueOffset));
566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Ensure the object is fully initialized.
568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // The argument was not found in the number to string cache. Check
573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // if it's a string already before calling the conversion builtin.
574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label convert_argument;
575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&not_cached);
576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(a0, &convert_argument);
577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Is it a String?
579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a2, FieldMemOperand(a0, HeapObject::kMapOffset));
580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset));
581589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  STATIC_ASSERT(kNotStringTag != 0);
582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ And(t0, a3, Operand(kIsNotStringMask));
583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&convert_argument, ne, t0, Operand(zero_reg));
584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(argument, a0);
585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->string_ctor_conversions(), 1, a3, t0);
586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&argument_is_string);
587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Invoke the conversion builtin and put the result into a2.
589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&convert_argument);
590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ push(function);  // Preserve the function.
591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->string_ctor_conversions(), 1, a3, t0);
592592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
593592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
594592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(v0);
595592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
596592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ pop(function);
598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(argument, v0);
599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&argument_is_string);
600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the empty string into a2, remove the receiver from the
602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // stack, and jump back to the case where the argument is a string.
603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&no_arguments);
604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(argument, Heap::kEmptyStringRootIndex);
605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Drop(1);
606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&argument_is_string);
607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // At this point the argument is already a string. Call runtime to
609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // create a string wrapper.
610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&gc_required);
611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->string_ctor_gc_required(), 1, a3, t0);
612592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
613592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
614592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(argument);
615592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ CallRuntime(Runtime::kNewStringWrapper, 1);
616592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
61844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
61944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
62044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0     : number of arguments
624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1     : constructor function
625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra     : return address
626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[...]: constructor arguments
627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
629592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Label slow, non_function_call;
630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the function is not a smi.
631592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ JumpIfSmi(a1, &non_function_call);
632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that the function is a JSFunction.
633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ GetObjectType(a1, a2, a2);
634592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Branch(&slow, ne, a2, Operand(JS_FUNCTION_TYPE));
635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Jump to the function-specific construct stub.
637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kConstructStubOffset));
639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(t9, a2, Operand(Code::kHeaderSize - kHeapObjectTag));
6403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Jump(t9);
641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: number of arguments
643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: called object
644592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // a2: object type
645592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Label do_call;
646592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ bind(&slow);
647592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Branch(&non_function_call, ne, a2, Operand(JS_FUNCTION_PROXY_TYPE));
648592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
649592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ jmp(&do_call);
650592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&non_function_call);
652592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
653592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ bind(&do_call);
654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // CALL_NON_FUNCTION expects the non-function constructor as receiver
655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // (instead of the original receiver from the call site). The receiver is
656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // stack element argc.
657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Set expected number of arguments to zero (not changing a0).
658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(a2, zero_reg);
659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ SetCallKind(t1, CALL_AS_METHOD);
660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          RelocInfo::CODE_TARGET);
662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void Generate_JSConstructStubHelper(MacroAssembler* masm,
666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                           bool is_api_function,
667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                           bool count_constructions) {
668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Should never count constructions for api objects.
669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!is_api_function || !count_constructions);
670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Isolate* isolate = masm->isolate();
672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0     : number of arguments
675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1     : constructor function
676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra     : return address
677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[...]: constructor arguments
678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Enter a construct frame.
681592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
682592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope scope(masm, StackFrame::CONSTRUCT);
683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
684592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Preserve the two incoming parameters on the stack.
685592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ sll(a0, a0, kSmiTagSize);  // Tag arguments count.
686592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ MultiPushReversed(a0.bit() | a1.bit());
687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
688592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Use t7 to hold undefined, which is used in several places below.
689592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
691592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label rt_call, allocated;
692592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Try to allocate the object without transitioning into C code. If any of
693592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // the preconditions is not met, the code bails out to the runtime call.
694592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (FLAG_inline_new) {
695592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      Label undo_allocation;
696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef ENABLE_DEBUGGER_SUPPORT
697592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ExternalReference debug_step_in_fp =
698592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          ExternalReference::debug_step_in_fp_address(isolate);
699592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ li(a2, Operand(debug_step_in_fp));
700592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ lw(a2, MemOperand(a2));
701592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ Branch(&rt_call, ne, a2, Operand(zero_reg));
702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
704592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Load the initial map and verify that it is in fact a map.
705592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a1: constructor function
706592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
707592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ JumpIfSmi(a2, &rt_call);
708592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ GetObjectType(a2, a3, t4);
709592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ Branch(&rt_call, ne, t4, Operand(MAP_TYPE));
710592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
711592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Check that the constructor is not constructing a JSFunction (see
712592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // comments in Runtime_NewObject in runtime.cc). In which case the
713592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // initial map's instance type would be JS_FUNCTION_TYPE.
714592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a1: constructor function
715592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a2: initial map
716592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset));
717592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ Branch(&rt_call, eq, a3, Operand(JS_FUNCTION_TYPE));
718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
719592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (count_constructions) {
720592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        Label allocate;
721592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // Decrease generous allocation count.
722592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ lw(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
723592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        MemOperand constructor_count =
724592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch           FieldMemOperand(a3, SharedFunctionInfo::kConstructionCountOffset);
725592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ lbu(t0, constructor_count);
726592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ Subu(t0, t0, Operand(1));
727592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ sb(t0, constructor_count);
728592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ Branch(&allocate, ne, t0, Operand(zero_reg));
729592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
730592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ Push(a1, a2);
731592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
732592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ push(a1);  // Constructor.
733592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // The call will replace the stub, so the countdown is only done once.
734592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
735592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
736592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ pop(a2);
737592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ pop(a1);
738592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
739592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ bind(&allocate);
740592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      }
741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
742592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Now allocate the JSObject on the heap.
743592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a1: constructor function
744592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a2: initial map
745592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset));
746592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ AllocateInNewSpace(a3, t4, t5, t6, &rt_call, SIZE_IN_WORDS);
747592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
748592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Allocated the JSObject, now initialize the fields. Map is set to
749592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // initial map and properties and elements are set to empty fixed array.
750592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a1: constructor function
751592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a2: initial map
752592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a3: object size
753592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // t4: JSObject (not tagged)
754592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ LoadRoot(t6, Heap::kEmptyFixedArrayRootIndex);
755592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ mov(t5, t4);
756592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ sw(a2, MemOperand(t5, JSObject::kMapOffset));
757592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ sw(t6, MemOperand(t5, JSObject::kPropertiesOffset));
758592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ sw(t6, MemOperand(t5, JSObject::kElementsOffset));
759592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ Addu(t5, t5, Operand(3*kPointerSize));
760592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
761592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
762592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
763592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
764592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Fill all the in-object properties with appropriate filler.
765592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a1: constructor function
766592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a2: initial map
767592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a3: object size (in words)
768592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // t4: JSObject (not tagged)
769592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // t5: First in-object property of JSObject (not tagged)
770592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ sll(t0, a3, kPointerSizeLog2);
771592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ addu(t6, t4, t0);   // End of object.
772592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
773592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (count_constructions) {
775592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ lw(a0, FieldMemOperand(a2, Map::kInstanceSizesOffset));
776592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ Ext(a0, a0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
777592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                kBitsPerByte);
778592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ sll(t0, a0, kPointerSizeLog2);
779592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ addu(a0, t5, t0);
780592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // a0: offset of first field after pre-allocated fields
781592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        if (FLAG_debug_code) {
782592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          __ Assert(le, "Unexpected number of pre-allocated property fields.",
783592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch              a0, Operand(t6));
784592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        }
785592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ InitializeFieldsWithFiller(t5, a0, t7);
786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // To allow for truncation.
787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ LoadRoot(t7, Heap::kOnePointerFillerMapRootIndex);
788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
789592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ InitializeFieldsWithFiller(t5, t6, t7);
790592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
791592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Add the object tag to make the JSObject real, so that we can continue
792592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // and jump into the continuation code at any time from now on. Any
793592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // failures need to undo the allocation, so that the heap is in a
794592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // consistent state and verifiable.
795592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ Addu(t4, t4, Operand(kHeapObjectTag));
796592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
797592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Check if a non-empty properties array is needed. Continue with
798592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // allocated object if not fall through to runtime call if it is.
799592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a1: constructor function
800592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // t4: JSObject
801592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // t5: start of next object (not tagged)
802592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ lbu(a3, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset));
803592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // The field instance sizes contains both pre-allocated property fields
804592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // and in-object properties.
805592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ lw(a0, FieldMemOperand(a2, Map::kInstanceSizesOffset));
806592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ Ext(t6, a0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
807592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch             kBitsPerByte);
808592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ Addu(a3, a3, Operand(t6));
809592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ Ext(t6, a0, Map::kInObjectPropertiesByte * kBitsPerByte,
810592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch              kBitsPerByte);
811592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ subu(a3, a3, t6);
812592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
813592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Done if no extra properties are to be allocated.
814592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ Branch(&allocated, eq, a3, Operand(zero_reg));
815592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ Assert(greater_equal, "Property allocation count failed.",
816592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          a3, Operand(zero_reg));
817592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
818592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Scale the number of elements by pointer size and add the header for
819592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // FixedArrays to the start of the next object calculation from above.
820592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a1: constructor
821592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a3: number of elements in properties array
822592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // t4: JSObject
823592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // t5: start of next object
824592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ Addu(a0, a3, Operand(FixedArray::kHeaderSize / kPointerSize));
825592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ AllocateInNewSpace(
826592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          a0,
827592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          t5,
828592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          t6,
829592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          a2,
830592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          &undo_allocation,
831592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS));
832592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
833592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Initialize the FixedArray.
834592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a1: constructor
835592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a3: number of elements in properties array (un-tagged)
836592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // t4: JSObject
837592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // t5: start of next object
838592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ LoadRoot(t6, Heap::kFixedArrayMapRootIndex);
839592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ mov(a2, t5);
840592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ sw(t6, MemOperand(a2, JSObject::kMapOffset));
841592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ sll(a0, a3, kSmiTagSize);
842592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ sw(a0, MemOperand(a2, FixedArray::kLengthOffset));
843592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ Addu(a2, a2, Operand(2 * kPointerSize));
844592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
845592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
846592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
847592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
848592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Initialize the fields to undefined.
849592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a1: constructor
850592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a2: First element of FixedArray (not tagged)
851592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a3: number of elements in properties array
852592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // t4: JSObject
853592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // t5: FixedArray (not tagged)
854592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ sll(t3, a3, kPointerSizeLog2);
855592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ addu(t6, a2, t3);  // End of object.
856592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
857592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      { Label loop, entry;
858592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        if (count_constructions) {
859592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          __ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
860592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        } else if (FLAG_debug_code) {
861592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          __ LoadRoot(t8, Heap::kUndefinedValueRootIndex);
862592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          __ Assert(eq, "Undefined value not loaded.", t7, Operand(t8));
863592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        }
864592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ jmp(&entry);
865592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ bind(&loop);
866592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ sw(t7, MemOperand(a2));
867592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ addiu(a2, a2, kPointerSize);
868592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ bind(&entry);
869592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        __ Branch(&loop, less, a2, Operand(t6));
870257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
871592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
872592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Store the initialized FixedArray into the properties field of
873592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // the JSObject.
874592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a1: constructor function
875592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // t4: JSObject
876592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // t5: FixedArray (not tagged)
877592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ Addu(t5, t5, Operand(kHeapObjectTag));  // Add the heap tag.
878592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ sw(t5, FieldMemOperand(t4, JSObject::kPropertiesOffset));
879592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
880592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Continue with JSObject being successfully allocated.
881592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a1: constructor function
882592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // a4: JSObject
883592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ jmp(&allocated);
884592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
885592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Undo the setting of the new top so that the heap is verifiable. For
886592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // example, the map's unused properties potentially do not match the
887592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // allocated objects unused properties.
888592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // t4: JSObject (previous new top)
889592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ bind(&undo_allocation);
890592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ UndoAllocationInNewSpace(t4, t5);
891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
893592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&rt_call);
894592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Allocate the new receiver object using the runtime call.
895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a1: constructor function
896592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(a1);  // Argument for Runtime_NewObject.
897592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ CallRuntime(Runtime::kNewObject, 1);
898592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(t4, v0);
899592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
900592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Receiver for constructor call allocated.
901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // t4: JSObject
902592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&allocated);
903592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(t4);
904592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
905592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Push the function and the allocated receiver from the stack.
906592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[0]: receiver (newly allocated object)
907592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[1]: constructor function
908592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[2]: number of arguments (smi-tagged)
909592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(a1, MemOperand(sp, kPointerSize));
910592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ MultiPushReversed(a1.bit() | t4.bit());
911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
912592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Reload the number of arguments from the stack.
913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a1: constructor function
914592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[0]: receiver
915592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[1]: constructor function
916592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[2]: receiver
917592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[3]: constructor function
918592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[4]: number of arguments (smi-tagged)
919592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(a3, MemOperand(sp, 4 * kPointerSize));
920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
921592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Setup pointer to last argument.
922592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Addu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
924592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Setup number of arguments for function call below.
925592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ srl(a0, a3, kSmiTagSize);
926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
927592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Copy arguments and receiver to the expression stack.
928592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // a0: number of arguments
929592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // a1: constructor function
930592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // a2: address of last argument (caller sp)
931592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // a3: number of arguments (smi-tagged)
932592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[0]: receiver
933592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[1]: constructor function
934592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[2]: receiver
935592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[3]: constructor function
936592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[4]: number of arguments (smi-tagged)
937592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label loop, entry;
938592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ jmp(&entry);
939592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&loop);
940592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ sll(t0, a3, kPointerSizeLog2 - kSmiTagSize);
941592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Addu(t0, a2, Operand(t0));
942592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(t1, MemOperand(t0));
943592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(t1);
944592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&entry);
945592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Addu(a3, a3, Operand(-2));
946592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Branch(&loop, greater_equal, a3, Operand(zero_reg));
947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
948592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Call the function.
949592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // a0: number of arguments
950592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // a1: constructor function
951592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (is_api_function) {
952592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
953592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      Handle<Code> code =
954592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          masm->isolate()->builtins()->HandleApiCallConstruct();
955592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ParameterCount expected(0);
956592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ InvokeCode(code, expected, expected,
957592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                    RelocInfo::CODE_TARGET, CALL_FUNCTION, CALL_AS_METHOD);
958592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    } else {
959592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ParameterCount actual(a0);
960592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ InvokeFunction(a1, actual, CALL_FUNCTION,
961592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        NullCallWrapper(), CALL_AS_METHOD);
962592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
964592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Pop the function from the stack.
965592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // v0: result
966592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[0]: constructor function
967592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[2]: receiver
968592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[3]: constructor function
969592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[4]: number of arguments (smi-tagged)
970592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Pop();
971592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
972592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Restore context from the frame.
973592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
974592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
975592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // If the result is an object (in the ECMA sense), we should get rid
976592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // of the receiver and use the result; see ECMA-262 section 13.2.2-7
977592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // on page 74.
978592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label use_receiver, exit;
979592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
980592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // If the result is a smi, it is *not* an object in the ECMA sense.
981592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // v0: result
982592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[0]: receiver (newly allocated object)
983592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[1]: constructor function
984592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[2]: number of arguments (smi-tagged)
985592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ JumpIfSmi(v0, &use_receiver);
986592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
987592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // If the type of the result (stored in its map) is less than
988592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
989592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ GetObjectType(v0, a3, a3);
990592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Branch(&exit, greater_equal, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
991592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
992592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Throw away the result of the constructor invocation and use the
993592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // on-stack receiver as the result.
994592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&use_receiver);
995592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(v0, MemOperand(sp));
996592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
997592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Remove receiver from the stack, remove caller arguments, and
998592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // return.
999592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&exit);
1000592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // v0: result
1001592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[0]: receiver (newly allocated object)
1002592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[1]: constructor function
1003592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // sp[2]: number of arguments (smi-tagged)
1004592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(a1, MemOperand(sp, 2 * kPointerSize));
1005592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1006592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Leave construct frame.
1007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(t0, a1, kPointerSizeLog2 - 1);
1010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(sp, sp, t0);
1011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(sp, sp, kPointerSize);
1012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(isolate->counters()->constructed_objects(), 1, a1, a2);
1013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
10143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
10153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
101744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
1018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Generate_JSConstructStubHelper(masm, false, true);
10193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
10203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
102244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
1023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Generate_JSConstructStubHelper(masm, false, false);
10243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
10253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
102744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
1028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Generate_JSConstructStubHelper(masm, true, false);
1029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
1033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             bool is_construct) {
1034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Called from JSEntryStub::GenerateBody
1035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
1037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0: code entry
1038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1: function
1039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2: reveiver_pointer
1040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a3: argc
1041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- s0: argv
1042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
1043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Clear the context before we push it when entering the JS frame.
1045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(cp, zero_reg);
1046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Enter an internal frame.
1048592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
1049592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
1050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1051592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Set up the context from the function argument.
1052592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
1053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1054592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Set up the roots register.
1055592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ExternalReference roots_array_start =
1056592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        ExternalReference::roots_array_start(masm->isolate());
1057592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ li(s6, Operand(roots_array_start));
1058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1059592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Push the function and the receiver onto the stack.
1060592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Push(a1, a2);
1061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1062592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Copy arguments to the stack in a loop.
1063592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // a3: argc
1064592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // s0: argv, ie points to first arg
1065592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label loop, entry;
1066592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ sll(t0, a3, kPointerSizeLog2);
1067592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ addu(t2, s0, t0);
1068592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ b(&entry);
1069592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ nop();   // Branch delay slot nop.
1070592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // t2 points past last arg.
1071592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&loop);
1072592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(t0, MemOperand(s0));  // Read next parameter.
1073592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ addiu(s0, s0, kPointerSize);
1074592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(t0, MemOperand(t0));  // Dereference handle.
1075592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(t0);  // Push parameter.
1076592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&entry);
1077592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Branch(&loop, ne, s0, Operand(t2));
1078592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1079592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Initialize all JavaScript callee-saved registers, since they will be seen
1080592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // by the garbage collector as part of handlers.
1081592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ LoadRoot(t0, Heap::kUndefinedValueRootIndex);
1082592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(s1, t0);
1083592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(s2, t0);
1084592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(s3, t0);
1085592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(s4, t0);
1086592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(s5, t0);
1087592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // s6 holds the root address. Do not clobber.
1088592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // s7 is cp. Do not init.
1089592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1090592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Invoke the code and pass argc as a0.
1091592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(a0, a3);
1092592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (is_construct) {
1093592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ Call(masm->isolate()->builtins()->JSConstructCall());
1094592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    } else {
1095592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ParameterCount actual(a0);
1096592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ InvokeFunction(a1, actual, CALL_FUNCTION,
1097592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                        NullCallWrapper(), CALL_AS_METHOD);
1098592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
1099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1100592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Leave internal frame.
1101592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
1102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(ra);
11043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
11053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
1108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Generate_JSEntryTrampolineHelper(masm, false);
11093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
11103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
1113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Generate_JSEntryTrampolineHelper(masm, true);
111444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
111544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
111644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
111744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Generate_LazyCompile(MacroAssembler* masm) {
1118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Enter an internal frame.
1119592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
1120592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
1121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1122592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Preserve the function.
1123592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(a1);
1124592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Push call kind information.
1125592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(t1);
1126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1127592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Push the function on the stack as the argument to the runtime function.
1128592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(a1);
1129592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Call the runtime function.
1130592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ CallRuntime(Runtime::kLazyCompile, 1);
1131592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Calculate the entry point.
1132592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ addiu(t9, v0, Code::kHeaderSize - kHeapObjectTag);
1133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1134592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Restore call kind information.
1135592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ pop(t1);
1136592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Restore saved function.
1137592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ pop(a1);
1138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1139592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Tear down temporary frame.
1140592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
1141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Do a tail-call of the compiled function.
1143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(t9);
114444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
114544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
114644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
114744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Generate_LazyRecompile(MacroAssembler* masm) {
1148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Enter an internal frame.
1149592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
1150592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
1151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1152592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Preserve the function.
1153592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(a1);
1154592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Push call kind information.
1155592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(t1);
1156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1157592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Push the function on the stack as the argument to the runtime function.
1158592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(a1);
1159592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ CallRuntime(Runtime::kLazyRecompile, 1);
1160592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Calculate the entry point.
1161592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Addu(t9, v0, Operand(Code::kHeaderSize - kHeapObjectTag));
1162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1163592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Restore call kind information.
1164592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ pop(t1);
1165592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Restore saved function.
1166592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ pop(a1);
1167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1168592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Tear down temporary frame.
1169592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
1170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Do a tail-call of the compiled function.
1172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(t9);
117344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
117444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
117544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1176592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochstatic void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
1177592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                             Deoptimizer::BailoutType type) {
1178592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
1179592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
1180592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Pass the function and deoptimization type to the runtime system.
1181592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ li(a0, Operand(Smi::FromInt(static_cast<int>(type))));
1182592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(a0);
1183592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
1184592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
1185592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1186592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Get the full codegen state from the stack and untag it -> t2.
1187592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ lw(t2, MemOperand(sp, 0 * kPointerSize));
1188592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ SmiUntag(t2);
1189592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Switch on the state.
1190592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Label with_tos_register, unknown_state;
1191592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Branch(&with_tos_register,
1192592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            ne, t2, Operand(FullCodeGenerator::NO_REGISTERS));
1193592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Addu(sp, sp, Operand(1 * kPointerSize));  // Remove state.
1194592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Ret();
1195592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1196592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ bind(&with_tos_register);
1197592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ lw(v0, MemOperand(sp, 1 * kPointerSize));
1198592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Branch(&unknown_state, ne, t2, Operand(FullCodeGenerator::TOS_REG));
1199592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1200592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Addu(sp, sp, Operand(2 * kPointerSize));  // Remove state.
1201592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Ret();
1202592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1203592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ bind(&unknown_state);
1204592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ stop("no cases left");
1205592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
1206592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1207592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
120844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
1209592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
121044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
121144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
121244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
121344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
1214592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
121544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
121644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
121744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
121844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Generate_NotifyOSR(MacroAssembler* masm) {
1219592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // For now, we are relying on the fact that Runtime::NotifyOSR
1220592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // doesn't do any garbage collection which allows us to save/restore
1221592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // the registers without worrying about which of them contain
1222592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // pointers. This seems a bit fragile.
1223592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  RegList saved_regs =
1224592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      (kJSCallerSaved | kCalleeSaved | ra.bit() | fp.bit()) & ~sp.bit();
1225592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ MultiPush(saved_regs);
1226592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
1227592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
1228592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ CallRuntime(Runtime::kNotifyOSR, 0);
1229592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
1230592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ MultiPop(saved_regs);
1231592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Ret();
123244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
123344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
123444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
123544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1236592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  CpuFeatures::TryForceFeatureScope scope(VFP3);
1237592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (!CpuFeatures::IsSupported(FPU)) {
1238592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Abort("Unreachable code: Cannot optimize without FPU support.");
1239592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return;
1240592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
1241592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1242592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Lookup the function in the JavaScript frame and push it as an
1243592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // argument to the on-stack replacement function.
1244592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ lw(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1245592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
1246592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
1247592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(a0);
1248592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
1249592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
1250592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1251592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // If the result was -1 it means that we couldn't optimize the
1252592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // function. Just return and continue in the unoptimized version.
1253592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Ret(eq, v0, Operand(Smi::FromInt(-1)));
1254592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1255592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Untag the AST id and push it on the stack.
1256592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ SmiUntag(v0);
1257592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ push(v0);
1258592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1259592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Generate the code for doing the frame-to-frame translation using
1260592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // the deoptimizer infrastructure.
1261592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR);
1262592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  generator.Generate();
12633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
12643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
12663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Builtins::Generate_FunctionCall(MacroAssembler* masm) {
1267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // 1. Make sure we have at least one argument.
1268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: actual number of arguments
1269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  { Label done;
1270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&done, ne, a0, Operand(zero_reg));
1271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(t2, Heap::kUndefinedValueRootIndex);
1272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ push(t2);
1273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Addu(a0, a0, Operand(1));
1274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&done);
1275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // 2. Get the function to call (passed as receiver) from the stack, check
1278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //    if it is a function.
1279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: actual number of arguments
1280592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Label slow, non_function;
1281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(at, a0, kPointerSizeLog2);
1282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ addu(at, sp, at);
1283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a1, MemOperand(at));
1284592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ JumpIfSmi(a1, &non_function);
1285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ GetObjectType(a1, a2, a2);
1286592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Branch(&slow, ne, a2, Operand(JS_FUNCTION_TYPE));
1287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // 3a. Patch the first argument if necessary when calling a function.
1289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: actual number of arguments
1290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: function
1291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label shift_arguments;
1292592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ li(t0, Operand(0, RelocInfo::NONE));  // Indicate regular JS_FUNCTION.
1293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  { Label convert_to_object, use_global_receiver, patch_receiver;
1294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Change context eagerly in case we need the global receiver.
1295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
1296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Do not transform the receiver for strict mode functions.
1298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
1299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a3, FieldMemOperand(a2, SharedFunctionInfo::kCompilerHintsOffset));
1300592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ And(t3, a3, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
1301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 kSmiTagSize)));
1302592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Branch(&shift_arguments, ne, t3, Operand(zero_reg));
1303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Do not transform the receiver for native (Compilerhints already in a3).
1305592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ And(t3, a3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
1306592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Branch(&shift_arguments, ne, t3, Operand(zero_reg));
1307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Compute the receiver in non-strict mode.
1309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Load first argument in a2. a2 = -kPointerSize(sp + n_args << 2).
1310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(at, a0, kPointerSizeLog2);
1311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ addu(a2, sp, at);
1312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a2, MemOperand(a2, -kPointerSize));
1313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a0: actual number of arguments
1314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a1: function
1315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a2: first argument
1316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ JumpIfSmi(a2, &convert_to_object, t2);
1317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(a3, Heap::kUndefinedValueRootIndex);
1319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&use_global_receiver, eq, a2, Operand(a3));
1320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(a3, Heap::kNullValueRootIndex);
1321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&use_global_receiver, eq, a2, Operand(a3));
1322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
13233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ GetObjectType(a2, a3, a3);
13253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ Branch(&shift_arguments, ge, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
1326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&convert_to_object);
1328592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Enter an internal frame in order to preserve argument count.
1329592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    {
1330592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      FrameScope scope(masm, StackFrame::INTERNAL);
1331592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ sll(a0, a0, kSmiTagSize);  // Smi tagged.
1332592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ push(a0);
1333592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1334592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ push(a2);
1335592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1336592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ mov(a2, v0);
1337592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1338592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ pop(a0);
1339592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      __ sra(a0, a0, kSmiTagSize);  // Un-tag.
1340592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // Leave internal frame.
1341592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
1342592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Restore the function to a1, and the flag to t0.
1343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(at, a0, kPointerSizeLog2);
1344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ addu(at, sp, at);
1345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a1, MemOperand(at));
1346592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ li(t0, Operand(0, RelocInfo::NONE));
1347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&patch_receiver);
1348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Use the global receiver object from the called function as the
1350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // receiver.
1351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&use_global_receiver);
1352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    const int kGlobalIndex =
1353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
1354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a2, FieldMemOperand(cp, kGlobalIndex));
1355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalContextOffset));
1356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a2, FieldMemOperand(a2, kGlobalIndex));
1357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset));
1358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&patch_receiver);
1360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(at, a0, kPointerSizeLog2);
1361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ addu(a3, sp, at);
1362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sw(a2, MemOperand(a3, -kPointerSize));
1363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&shift_arguments);
1365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1367592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // 3b. Check for function proxy.
1368592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ bind(&slow);
1369592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ li(t0, Operand(1, RelocInfo::NONE));  // Indicate function proxy.
1370592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Branch(&shift_arguments, eq, a2, Operand(JS_FUNCTION_PROXY_TYPE));
1371592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1372592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ bind(&non_function);
1373592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ li(t0, Operand(2, RelocInfo::NONE));  // Indicate non-function.
1374592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1375592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // 3c. Patch the first argument when calling a non-function.  The
1376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //     CALL_NON_FUNCTION builtin expects the non-function callee as
1377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //     receiver, so overwrite the first argument which will ultimately
1378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //     become the receiver.
1379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: actual number of arguments
1380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: function
1381592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // t0: call type (0: JS function, 1: function proxy, 2: non-function)
1382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(at, a0, kPointerSizeLog2);
1383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ addu(a2, sp, at);
1384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(a1, MemOperand(a2, -kPointerSize));
1385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // 4. Shift arguments and return address one slot down on the stack
1387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //    (overwriting the original receiver).  Adjust argument count to make
1388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //    the original first argument the new receiver.
1389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: actual number of arguments
1390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: function
1391592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // t0: call type (0: JS function, 1: function proxy, 2: non-function)
1392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&shift_arguments);
1393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  { Label loop;
1394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Calculate the copy start address (destination). Copy end address is sp.
1395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(at, a0, kPointerSizeLog2);
1396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ addu(a2, sp, at);
1397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&loop);
1399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(at, MemOperand(a2, -kPointerSize));
1400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sw(at, MemOperand(a2));
1401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Subu(a2, a2, Operand(kPointerSize));
1402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&loop, ne, a2, Operand(sp));
1403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Adjust the actual number of arguments and remove the top element
1404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // (which is a copy of the last argument).
1405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Subu(a0, a0, Operand(1));
1406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Pop();
1407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1409592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin,
1410592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  //     or a function proxy via CALL_FUNCTION_PROXY.
1411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: actual number of arguments
1412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: function
1413592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // t0: call type (0: JS function, 1: function proxy, 2: non-function)
1414592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  { Label function, non_proxy;
1415592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Branch(&function, eq, t0, Operand(zero_reg));
1416592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Expected number of arguments is 0 for CALL_NON_FUNCTION.
1417592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(a2, zero_reg);
1418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ SetCallKind(t1, CALL_AS_METHOD);
1419592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Branch(&non_proxy, ne, t0, Operand(1));
1420592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1421592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(a1);  // Re-add proxy object as additional argument.
1422592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Addu(a0, a0, Operand(1));
1423592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY);
1424592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1425592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            RelocInfo::CODE_TARGET);
1426592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1427592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&non_proxy);
1428592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION);
1429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            RelocInfo::CODE_TARGET);
1431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&function);
1432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // 5b. Get the code to call from the function and check that the number of
1435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //     expected arguments matches what we're providing.  If so, jump
1436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //     (tail-call) to the code in register edx without checking arguments.
1437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: actual number of arguments
1438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: function
1439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
1440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a2,
1441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset));
1442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sra(a2, a2, kSmiTagSize);
1443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
1444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ SetCallKind(t1, CALL_AS_METHOD);
1445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check formal and actual parameter counts.
1446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          RelocInfo::CODE_TARGET, ne, a2, Operand(a0));
1448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ParameterCount expected(0);
14503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ InvokeCode(a3, expected, expected, JUMP_FUNCTION,
14513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                NullCallWrapper(), CALL_AS_METHOD);
14523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
14533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
14543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
14553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kIndexOffset    = -5 * kPointerSize;
1457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kLimitOffset    = -4 * kPointerSize;
1458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kArgsOffset     =  2 * kPointerSize;
1459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kRecvOffset     =  3 * kPointerSize;
1460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kFunctionOffset =  4 * kPointerSize;
1461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1462592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  {
1463592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    FrameScope frame_scope(masm, StackFrame::INTERNAL);
1464592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(a0, MemOperand(fp, kFunctionOffset));  // Get the function.
1465592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(a0);
1466592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(a0, MemOperand(fp, kArgsOffset));  // Get the args array.
1467592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(a0);
1468592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Returns (in v0) number of arguments to copy to stack as Smi.
1469592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
1470592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1471592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Check the stack for overflow. We are not trying to catch
1472592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // interruptions (e.g. debug break and preemption) here, so the "real stack
1473592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // limit" is checked.
1474592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label okay;
1475592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ LoadRoot(a2, Heap::kRealStackLimitRootIndex);
1476592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Make a2 the space we have left. The stack might already be overflowed
1477592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // here which will cause a2 to become negative.
1478592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ subu(a2, sp, a2);
1479592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Check if the arguments will overflow the stack.
1480592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ sll(t3, v0, kPointerSizeLog2 - kSmiTagSize);
1481592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Branch(&okay, gt, a2, Operand(t3));  // Signed comparison.
1482592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1483592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Out of stack space.
1484592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(a1, MemOperand(fp, kFunctionOffset));
1485592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(a1);
1486592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(v0);
1487592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
1488592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // End of stack check.
1489592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1490592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Push current limit and index.
1491592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&okay);
1492592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(v0);  // Limit.
1493592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(a1, zero_reg);  // Initial index.
1494592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(a1);
1495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1496592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Get the receiver.
1497592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(a0, MemOperand(fp, kRecvOffset));
1498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1499592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Check that the function is a JS function (otherwise it must be a proxy).
1500592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label push_receiver;
1501592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(a1, MemOperand(fp, kFunctionOffset));
1502592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ GetObjectType(a1, a2, a2);
1503592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Branch(&push_receiver, ne, a2, Operand(JS_FUNCTION_TYPE));
1504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1505592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Change context eagerly to get the right global object if necessary.
1506592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
1507592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Load the shared function info while the function is still in a1.
1508592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
1509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1510592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Compute the receiver.
1511592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Do not transform the receiver for strict mode functions.
1512592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label call_to_object, use_global_receiver;
1513592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kCompilerHintsOffset));
1514592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ And(t3, a2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
1515592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                 kSmiTagSize)));
1516592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Branch(&push_receiver, ne, t3, Operand(zero_reg));
1517592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1518592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Do not transform the receiver for native (Compilerhints already in a2).
1519592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ And(t3, a2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
1520592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Branch(&push_receiver, ne, t3, Operand(zero_reg));
1521592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1522592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Compute the receiver in non-strict mode.
1523592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ JumpIfSmi(a0, &call_to_object);
1524592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ LoadRoot(a1, Heap::kNullValueRootIndex);
1525592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Branch(&use_global_receiver, eq, a0, Operand(a1));
1526592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
1527592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Branch(&use_global_receiver, eq, a0, Operand(a2));
1528592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1529592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Check if the receiver is already a JavaScript object.
1530592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // a0: receiver
1531592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1532592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ GetObjectType(a0, a1, a1);
1533592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Branch(&push_receiver, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
1534592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1535592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Convert the receiver to a regular object.
1536592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // a0: receiver
1537592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&call_to_object);
1538592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(a0);
1539592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1540592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ mov(a0, v0);  // Put object in a0 to match other paths to push_receiver.
1541592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Branch(&push_receiver);
1542592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1543592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Use the current global receiver object as the receiver.
1544592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&use_global_receiver);
1545592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    const int kGlobalOffset =
1546592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
1547592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(a0, FieldMemOperand(cp, kGlobalOffset));
1548592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(a0, FieldMemOperand(a0, GlobalObject::kGlobalContextOffset));
1549592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(a0, FieldMemOperand(a0, kGlobalOffset));
1550592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(a0, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset));
1551592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1552592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Push the receiver.
1553592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // a0: receiver
1554592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&push_receiver);
1555592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(a0);
1556592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1557592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Copy all arguments from the array to the stack.
1558592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label entry, loop;
1559592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(a0, MemOperand(fp, kIndexOffset));
1560592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Branch(&entry);
1561592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1562592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Load the current argument from the arguments array and push it to the
1563592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // stack.
1564592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // a0: current argument index
1565592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&loop);
1566592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(a1, MemOperand(fp, kArgsOffset));
1567592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(a1);
1568592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(a0);
1569592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1570592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Call the runtime to access the property in the arguments array.
1571592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ CallRuntime(Runtime::kGetProperty, 2);
1572592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(v0);
1573592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1574592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Use inline caching to access the arguments.
1575592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(a0, MemOperand(fp, kIndexOffset));
1576592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Addu(a0, a0, Operand(1 << kSmiTagSize));
1577592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ sw(a0, MemOperand(fp, kIndexOffset));
1578592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1579592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Test if the copy loop has finished copying all the elements from the
1580592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // arguments object.
1581592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&entry);
1582592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(a1, MemOperand(fp, kLimitOffset));
1583592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Branch(&loop, ne, a0, Operand(a1));
1584592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1585592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Invoke the function.
1586592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    Label call_proxy;
1587592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ParameterCount actual(a0);
1588592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ sra(a0, a0, kSmiTagSize);
1589592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ lw(a1, MemOperand(fp, kFunctionOffset));
1590592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ GetObjectType(a1, a2, a2);
1591592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Branch(&call_proxy, ne, a2, Operand(JS_FUNCTION_TYPE));
1592592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1593592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ InvokeFunction(a1, actual, CALL_FUNCTION,
1594592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                      NullCallWrapper(), CALL_AS_METHOD);
1595592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1596592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    frame_scope.GenerateLeaveFrame();
1597592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Ret(USE_DELAY_SLOT);
1598592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Addu(sp, sp, Operand(3 * kPointerSize));  // In delay slot.
1599592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1600592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Invoke the function proxy.
1601592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ bind(&call_proxy);
1602592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ push(a1);  // Add function proxy as last argument.
1603592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Addu(a0, a0, Operand(1));
1604592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ li(a2, Operand(0, RelocInfo::NONE));
1605592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ SetCallKind(t1, CALL_AS_METHOD);
1606592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY);
1607592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1608592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            RelocInfo::CODE_TARGET);
1609592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Tear down the internal frame and remove function, receiver and args.
1610592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
1611592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1612592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Ret(USE_DELAY_SLOT);
1613592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  __ Addu(sp, sp, Operand(3 * kPointerSize));  // In delay slot.
1614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(a0, a0, kSmiTagSize);
1619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ li(t0, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ MultiPush(a0.bit() | a1.bit() | t0.bit() | fp.bit() | ra.bit());
1621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(fp, sp, Operand(3 * kPointerSize));
1622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
1627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- v0 : result being passed through
1628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
1629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the number of arguments passed (as a smi), tear down the frame and
1630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // then tear down the parameters.
1631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a1, MemOperand(fp, -3 * kPointerSize));
1632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(sp, fp);
1633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ MultiPop(fp.bit() | ra.bit());
1634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(t0, a1, kPointerSizeLog2 - kSmiTagSize);
1635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(sp, sp, t0);
1636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Adjust for the receiver.
1637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(sp, sp, Operand(kPointerSize));
16383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
16393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // State setup as expected by MacroAssembler::InvokePrologue.
1643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
1644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0: actual arguments count
1645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1: function (passed through to callee)
1646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2: expected arguments count
1647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a3: callee code entry
1648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- t1: call kind information
1649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
1650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label invoke, dont_adapt_arguments;
1652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label enough, too_few;
1654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&dont_adapt_arguments, eq,
1655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      a2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
1656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We use Uless as the number of argument should always be greater than 0.
1657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&too_few, Uless, a0, Operand(a2));
1658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  {  // Enough parameters: actual >= expected.
1660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a0: actual number of arguments as a smi
1661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a1: function
1662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a2: expected number of arguments
1663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a3: code entry to call
1664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&enough);
1665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    EnterArgumentsAdaptorFrame(masm);
1666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Calculate copy start address into a0 and copy end address into a2.
1668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(a0, a0, kPointerSizeLog2 - kSmiTagSize);
1669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Addu(a0, fp, a0);
1670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Adjust for return address and receiver.
1671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Addu(a0, a0, Operand(2 * kPointerSize));
1672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Compute copy end address.
1673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(a2, a2, kPointerSizeLog2);
1674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ subu(a2, a0, a2);
1675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Copy the arguments (including the receiver) to the new stack frame.
1677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a0: copy start address
1678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a1: function
1679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a2: copy end address
1680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a3: code entry to call
1681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label copy;
1683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&copy);
1684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(t0, MemOperand(a0));
1685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ push(t0);
1686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(USE_DELAY_SLOT, &copy, ne, a0, Operand(a2));
1687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ addiu(a0, a0, -kPointerSize);  // In delay slot.
1688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ jmp(&invoke);
1690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  {  // Too few parameters: Actual < expected.
1693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&too_few);
1694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    EnterArgumentsAdaptorFrame(masm);
1695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // TODO(MIPS): Optimize these loops.
1697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Calculate copy start address into a0 and copy end address is fp.
1699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a0: actual number of arguments as a smi
1700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a1: function
1701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a2: expected number of arguments
1702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a3: code entry to call
1703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(a0, a0, kPointerSizeLog2 - kSmiTagSize);
1704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Addu(a0, fp, a0);
1705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Adjust for return address and receiver.
1706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Addu(a0, a0, Operand(2 * kPointerSize));
1707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Compute copy end address. Also adjust for return address.
17083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ Addu(t3, fp, kPointerSize);
1709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Copy the arguments (including the receiver) to the new stack frame.
1711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a0: copy start address
1712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a1: function
1713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a2: expected number of arguments
1714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a3: code entry to call
17153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // t3: copy end address
1716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label copy;
1717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&copy);
1718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(t0, MemOperand(a0));  // Adjusted above for return addr and receiver.
1719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ push(t0);
1720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Subu(a0, a0, kPointerSize);
17213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ Branch(&copy, ne, a0, Operand(t3));
1722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Fill the remaining expected arguments with undefined.
1724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a1: function
1725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a2: expected number of arguments
1726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a3: code entry to call
1727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(t0, Heap::kUndefinedValueRootIndex);
1728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(t2, a2, kPointerSizeLog2);
1729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Subu(a2, fp, Operand(t2));
1730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Addu(a2, a2, Operand(-4 * kPointerSize));  // Adjust for frame.
1731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label fill;
1733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&fill);
1734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ push(t0);
1735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&fill, ne, sp, Operand(a2));
1736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Call the entry point.
1739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&invoke);
1740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Call(a3);
1742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Exit frame and return.
1744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  LeaveArgumentsAdaptorFrame(masm);
1745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
1746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -------------------------------------------
1749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Don't adapt arguments.
1750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -------------------------------------------
1751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&dont_adapt_arguments);
1752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(a3);
17533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
17543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17553100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#undef __
17573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
17583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} }  // namespace v8::internal
17593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_MIPS
1761