13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 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
703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // JumpToExternalReference expects s0 to contain the number of arguments
71257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // including the receiver and the extra arguments.
723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(s0, a0, num_extra_args + 1);
733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sll(s1, s0, kPointerSizeLog2);
743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Subu(s1, s1, kPointerSize);
75257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpToExternalReference(ExternalReference(id, masm->isolate()));
76257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
77257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
78257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Load the built-in InternalArray function from the current context.
803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateLoadInternalArrayFunction(MacroAssembler* masm,
813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              Register result) {
82257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the global context.
83257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
84257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
85257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(result,
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        FieldMemOperand(result, GlobalObject::kGlobalContextOffset));
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the InternalArray function from the global context.
88257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(result,
8985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch         MemOperand(result,
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    Context::SlotOffset(
913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        Context::INTERNAL_ARRAY_FUNCTION_INDEX)));
92257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
93257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
94257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Load the built-in Array function from the current context.
963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) {
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the global context.
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result,
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        FieldMemOperand(result, GlobalObject::kGlobalContextOffset));
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the Array function from the global context.
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result,
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        MemOperand(result,
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
10785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
10885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Allocate an empty JSArray. The allocated array is put into the result
110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// register. An elements backing store is allocated with size initial_capacity
111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// and filled with the hole values.
112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void AllocateEmptyJSArray(MacroAssembler* masm,
113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Register array_function,
114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Register result,
115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Register scratch1,
116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Register scratch2,
117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Register scratch3,
118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 Label* gc_required) {
1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const int initial_capacity = JSArray::kPreallocatedArrayElements;
1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(initial_capacity >= 0);
1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadInitialArrayMap(array_function, scratch2, scratch1);
122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Allocate the JSArray object together with space for a fixed array with the
124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // requested elements.
1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int size = JSArray::kSize;
1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (initial_capacity > 0) {
1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    size += FixedArray::SizeFor(initial_capacity);
1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ AllocateInNewSpace(size,
130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        result,
131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        scratch2,
132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        scratch3,
133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        gc_required,
134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        TAG_OBJECT);
135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Allocated the JSArray. Now initialize the fields except for the elements
136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // array.
137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // result: JSObject
138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // scratch1: initial map
139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // scratch2: start of next object
140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(scratch1, FieldMemOperand(result, JSObject::kMapOffset));
141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex);
142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(scratch1, FieldMemOperand(result, JSArray::kPropertiesOffset));
143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Field JSArray::kElementsOffset is initialized later.
144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(scratch3,  zero_reg);
145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(scratch3, FieldMemOperand(result, JSArray::kLengthOffset));
146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (initial_capacity == 0) {
1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(scratch1, FieldMemOperand(result, JSArray::kElementsOffset));
1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return;
1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Calculate the location of the elements array and set elements array member
153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // of the JSArray.
154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // result: JSObject
155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // scratch2: start of next object
156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(scratch1, result, Operand(JSArray::kSize));
157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(scratch1, FieldMemOperand(result, JSArray::kElementsOffset));
158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Clear the heap tag on the elements array.
160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ And(scratch1, scratch1, Operand(~kHeapObjectTagMask));
161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Initialize the FixedArray and fill it with holes. FixedArray length is
163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // stored as a smi.
164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // result: JSObject
165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // scratch1: elements array (untagged)
166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // scratch2: start of next object
167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(scratch3, Heap::kFixedArrayMapRootIndex);
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(0 * kPointerSize == FixedArray::kMapOffset);
169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(scratch3, MemOperand(scratch1));
170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(scratch1, scratch1, kPointerSize);
171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ li(scratch3,  Operand(Smi::FromInt(initial_capacity)));
1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(1 * kPointerSize == FixedArray::kLengthOffset);
173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(scratch3, MemOperand(scratch1));
174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(scratch1, scratch1, kPointerSize);
175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Fill the FixedArray with the hole value. Inline the code if short.
1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(2 * kPointerSize == FixedArray::kHeaderSize);
178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex);
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kLoopUnfoldLimit = 4;
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (initial_capacity <= kLoopUnfoldLimit) {
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 0; i < initial_capacity; i++) {
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sw(scratch3, MemOperand(scratch1, i * kPointerSize));
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label loop, entry;
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(scratch2, scratch1, Operand(initial_capacity * kPointerSize));
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&entry);
1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&loop);
189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sw(scratch3, MemOperand(scratch1));
190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Addu(scratch1, scratch1, kPointerSize);
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&entry);
1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&loop, lt, scratch1, Operand(scratch2));
193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Allocate a JSArray with the number of elements stored in a register. The
198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// register array_function holds the built-in Array function and the register
199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// array_size holds the size of the array as a smi. The allocated array is put
200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// into the result register and beginning and end of the FixedArray elements
201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// storage is put into registers elements_array_storage and elements_array_end
202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// (see  below for when that is not the case). If the parameter fill_with_holes
203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// is true the allocated elements backing store is filled with the hole values
204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// otherwise it is left uninitialized. When the backing store is filled the
205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// register elements_array_storage is scratched.
206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void AllocateJSArray(MacroAssembler* masm,
207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register array_function,  // Array function.
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            Register array_size,  // As a smi, cannot be 0.
209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register result,
210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register elements_array_storage,
211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register elements_array_end,
212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register scratch1,
213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Register scratch2,
214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            bool fill_with_hole,
215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* gc_required) {
216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the initial map from the array function.
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadInitialArrayMap(array_function, scratch2, elements_array_storage);
21885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {  // Assert that array size is not zero.
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Assert(
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ne, "array size is unexpectedly 0", array_size, Operand(zero_reg));
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Allocate the JSArray object together with space for a FixedArray with the
225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // requested number of elements.
226589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ li(elements_array_end,
228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        (JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize);
229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sra(scratch1, array_size, kSmiTagSize);
230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(elements_array_end, elements_array_end, scratch1);
231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ AllocateInNewSpace(
232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      elements_array_end,
233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      result,
234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      scratch1,
235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      scratch2,
236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      gc_required,
237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Allocated the JSArray. Now initialize the fields except for the elements
240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // array.
241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // result: JSObject
242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // elements_array_storage: initial map
243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // array_size: size of array (smi)
244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(elements_array_storage, FieldMemOperand(result, JSObject::kMapOffset));
245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(elements_array_storage, Heap::kEmptyFixedArrayRootIndex);
246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(elements_array_storage,
247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         FieldMemOperand(result, JSArray::kPropertiesOffset));
248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Field JSArray::kElementsOffset is initialized later.
249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(array_size, FieldMemOperand(result, JSArray::kLengthOffset));
250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Calculate the location of the elements array and set elements array member
252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // of the JSArray.
253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // result: JSObject
254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // array_size: size of array (smi)
255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(elements_array_storage, result, Operand(JSArray::kSize));
256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(elements_array_storage,
257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         FieldMemOperand(result, JSArray::kElementsOffset));
258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Clear the heap tag on the elements array.
260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ And(elements_array_storage,
261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          elements_array_storage,
262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          Operand(~kHeapObjectTagMask));
263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Initialize the fixed array and fill it with holes. FixedArray length is
264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // stored as a smi.
265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // result: JSObject
266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // elements_array_storage: elements array (untagged)
267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // array_size: size of array (smi)
268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(scratch1, Heap::kFixedArrayMapRootIndex);
269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset);
270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(scratch1, MemOperand(elements_array_storage));
271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(elements_array_storage, elements_array_storage, kPointerSize);
272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Length of the FixedArray is the number of pre-allocated elements if
274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // the actual JSArray has length 0 and the size of the JSArray for non-empty
275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // JSArrays. The length of a FixedArray is stored as a smi.
276589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(array_size, MemOperand(elements_array_storage));
280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(elements_array_storage, elements_array_storage, kPointerSize);
281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Calculate elements array and elements array end.
283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // result: JSObject
284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // elements_array_storage: elements array element storage
285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // array_size: smi-tagged size of elements array
286589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(elements_array_end, array_size, kPointerSizeLog2 - kSmiTagSize);
288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(elements_array_end, elements_array_storage, elements_array_end);
289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Fill the allocated FixedArray with the hole value if requested.
291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // result: JSObject
292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // elements_array_storage: elements array element storage
293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // elements_array_end: start of next object
294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (fill_with_hole) {
295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label loop, entry;
296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(scratch1, Heap::kTheHoleValueRootIndex);
297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&entry);
298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&loop);
299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sw(scratch1, MemOperand(elements_array_storage));
300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Addu(elements_array_storage, elements_array_storage, kPointerSize);
301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&entry);
303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&loop, lt, elements_array_storage, Operand(elements_array_end));
304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Create a new array for the built-in Array function. This function allocates
309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// the JSArray object and the FixedArray elements array and initializes these.
310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// If the Array cannot be constructed in native code the runtime is called. This
311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// function assumes the following state:
312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//   a0: argc
313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//   a1: constructor (built-in Array function)
314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//   ra: return address
315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch//   sp[0]: last argument
316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// This function is used for both construct and normal calls of Array. The only
317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// difference between handling a construct call and a normal call is that for a
318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// construct call the constructor function in a1 needs to be preserved for
319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// entering the generic code. In both cases argc in a0 needs to be preserved.
320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Both registers are preserved by this code so no need to differentiate between
321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// construct call and normal call.
322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void ArrayNativeCode(MacroAssembler* masm,
323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                            Label* call_generic_code) {
324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = masm->isolate()->counters();
3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label argc_one_or_more, argc_two_or_more, not_empty_array, empty_array,
3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      has_non_smi_element, finish, cant_transition_map, not_double;
327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check for array construction with zero arguments or one.
329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&argc_one_or_more, ne, a0, Operand(zero_reg));
330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle construction of an empty array.
3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&empty_array);
332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  AllocateEmptyJSArray(masm,
333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       a1,
334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       a2,
335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       a3,
336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       t0,
337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       t1,
338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       call_generic_code);
339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->array_function_native(), 1, a3, t0);
3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up return value, remove receiver from stack and return.
341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(v0, a2);
342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(sp, sp, Operand(kPointerSize));
343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check for one argument. Bail out if argument is not smi or if it is
346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // negative.
347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&argc_one_or_more);
348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&argc_two_or_more, ne, a0, Operand(1));
349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
350589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a2, MemOperand(sp));  // Get the argument from the stack.
3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&not_empty_array, ne, a2, Operand(zero_reg));
3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Drop(1);  // Adjust stack.
3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(a0, zero_reg);  // Treat this as a call with argc of zero.
3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&empty_array);
3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&not_empty_array);
358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ And(a3, a2, Operand(kIntptrSignBit | kSmiTagMask));
359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(call_generic_code, eq, a3, Operand(zero_reg));
360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle construction of an empty array of a certain size. Bail out if size
362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // is too large to actually allocate an elements array.
363589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
3643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Branch(call_generic_code, Ugreater_equal, a2,
365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            Operand(JSObject::kInitialMaxFastElementArray << kSmiTagSize));
366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: argc
368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: constructor
369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a2: array_size (smi)
370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // sp[0]: argument
371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  AllocateJSArray(masm,
372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  a1,
373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  a2,
374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  a3,
375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  t0,
376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  t1,
377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  t2,
378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  t3,
379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  true,
380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  call_generic_code);
381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->array_function_native(), 1, a2, t0);
382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up return value, remove receiver and argument from stack and return.
384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(v0, a3);
385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(sp, sp, Operand(2 * kPointerSize));
386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle construction of an array from a list of arguments.
389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&argc_two_or_more);
390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(a2, a0, kSmiTagSize);  // Convert argc to a smi.
391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: argc
393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: constructor
394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a2: array_size (smi)
395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // sp[0]: last argument
396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  AllocateJSArray(masm,
397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  a1,
398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  a2,
399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  a3,
400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  t0,
401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  t1,
402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  t2,
403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  t3,
404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  false,
405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  call_generic_code);
406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->array_function_native(), 1, a2, t2);
407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Fill arguments as array elements. Copy from the top of the stack (last
409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // element) to the array backing store filling it backwards. Note:
410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // elements_array_end points after the backing store.
411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: argc
412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a3: JSArray
413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // t0: elements_array storage start (untagged)
414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // t1: elements_array_end (untagged)
415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // sp[0]: last argument
416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label loop, entry;
4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(USE_DELAY_SLOT, &entry);
4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(t3, sp);
420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&loop);
4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(a2, MemOperand(t3));
4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_smi_only_arrays) {
4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfNotSmi(a2, &has_non_smi_element);
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(t3, t3, kPointerSize);
426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(t1, t1, -kPointerSize);
427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(a2, MemOperand(t1));
428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&entry);
429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&loop, lt, t0, Operand(t1));
4305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&finish);
4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(sp, t3);
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Remove caller arguments and receiver from the stack, setup return value and
435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // return.
436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: argc
437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a3: JSArray
438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // sp[0]: receiver
439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(sp, sp, Operand(kPointerSize));
440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(v0, a3);
441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&has_non_smi_element);
4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Double values are handled by the runtime.
4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckMap(
4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      a2, t5, Heap::kHeapNumberMapRootIndex, &not_double, DONT_DO_SMI_CHECK);
4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&cant_transition_map);
4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ UndoAllocationInNewSpace(a3, t0);
4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(call_generic_code);
4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&not_double);
4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Transition FAST_SMI_ONLY_ELEMENTS to FAST_ELEMENTS.
4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // a3: JSArray
4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(a2, FieldMemOperand(a3, HeapObject::kMapOffset));
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         FAST_ELEMENTS,
4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         a2,
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         t5,
4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         &cant_transition_map);
4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sw(a2, FieldMemOperand(a3, HeapObject::kMapOffset));
4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ RecordWriteField(a3,
4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      HeapObject::kMapOffset,
4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      a2,
4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      t5,
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kRAHasNotBeenSaved,
4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kDontSaveFPRegs,
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      EMIT_REMEMBERED_SET,
4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      OMIT_SMI_CHECK);
4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label loop2;
4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&loop2);
4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(a2, MemOperand(t3));
4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(t3, t3, kPointerSize);
4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Subu(t1, t1, kPointerSize);
4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sw(a2, MemOperand(t1));
4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&loop2, lt, t0, Operand(t1));
4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&finish);
4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ----------- S t a t e -------------
4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- a0     : number of arguments
4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- ra     : return address
4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- sp[...]: constructor arguments
4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // -----------------------------------
4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the InternalArray function.
4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateLoadInternalArrayFunction(masm, a1);
4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {
4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Initial map for the builtin InternalArray functions should be maps.
4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(t0, a2, Operand(kSmiTagMask));
4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Assert(ne, "Unexpected initial map for InternalArray function",
4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              t0, Operand(zero_reg));
4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ GetObjectType(a2, a3, t0);
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Assert(eq, "Unexpected initial map for InternalArray function",
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              t0, Operand(MAP_TYPE));
5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Run the native code for the InternalArray function called as a normal
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // function.
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ArrayNativeCode(masm, &generic_array_code);
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Jump to the generic array code if the specialized code cannot handle the
5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // construction.
5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&generic_array_code);
5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> array_code =
5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->isolate()->builtins()->InternalArrayCodeGeneric();
5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(array_code, RelocInfo::CODE_TARGET);
5133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
5143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Builtins::Generate_ArrayCode(MacroAssembler* masm) {
517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0     : number of arguments
519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra     : return address
520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[...]: constructor arguments
521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label generic_array_code;
523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the Array function.
525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateLoadArrayFunction(masm, a1);
526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (FLAG_debug_code) {
528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Initial map for the builtin Array functions should be maps.
529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ And(t0, a2, Operand(kSmiTagMask));
531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Assert(ne, "Unexpected initial map for Array function (1)",
532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              t0, Operand(zero_reg));
533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ GetObjectType(a2, a3, t0);
534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Assert(eq, "Unexpected initial map for Array function (2)",
535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              t0, Operand(MAP_TYPE));
536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Run the native code for the Array function called as a normal function.
539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ArrayNativeCode(masm, &generic_array_code);
540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Jump to the generic array code if the specialized code cannot handle
542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // the construction.
543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&generic_array_code);
544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> array_code =
546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->ArrayCodeGeneric();
547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(array_code, RelocInfo::CODE_TARGET);
5483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
5493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) {
552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0     : number of arguments
554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1     : constructor function
555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra     : return address
556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[...]: constructor arguments
557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label generic_constructor;
559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (FLAG_debug_code) {
561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // The array construct code is only set for the builtin and internal
562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Array functions which always have a map.
563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Initial map for the builtin Array function should be a map.
564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ And(t0, a2, Operand(kSmiTagMask));
566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Assert(ne, "Unexpected initial map for Array function (3)",
567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              t0, Operand(zero_reg));
568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ GetObjectType(a2, a3, t0);
569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Assert(eq, "Unexpected initial map for Array function (4)",
570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              t0, Operand(MAP_TYPE));
571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Run the native code for the Array function called as a constructor.
574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ArrayNativeCode(masm, &generic_constructor);
575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Jump to the generic construct code in case the specialized code cannot
577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // handle the construction.
578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&generic_constructor);
579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> generic_construct_stub =
581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm->isolate()->builtins()->JSConstructStubGeneric();
582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
5833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
5843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
5853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
58644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0                     : number of arguments
589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1                     : constructor function
590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra                     : return address
591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[argc * 4]           : receiver
593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Counters* counters = masm->isolate()->counters();
595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->string_ctor_calls(), 1, a2, a3);
596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register function = a1;
598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (FLAG_debug_code) {
599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, a2);
600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Assert(eq, "Unexpected String function", function, Operand(a2));
601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the first arguments in a0 and get rid of the rest.
604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label no_arguments;
605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&no_arguments, eq, a0, Operand(zero_reg));
606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // First args = sp[(argc - 1) * 4].
607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Subu(a0, a0, Operand(1));
608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(a0, a0, kPointerSizeLog2);
609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(sp, a0, sp);
610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a0, MemOperand(sp));
611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // sp now point to args[0], drop args[0] + receiver.
612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Drop(2);
613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register argument = a2;
615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label not_cached, argument_is_string;
616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  NumberToStringStub::GenerateLookupNumberStringCache(
617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      masm,
618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      a0,        // Input.
619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      argument,  // Result.
620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      a3,        // Scratch.
621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      t0,        // Scratch.
622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      t1,        // Scratch.
623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      false,     // Is it a Smi?
624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      &not_cached);
625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->string_ctor_cached_number(), 1, a3, t0);
626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&argument_is_string);
627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2     : argument converted to string
630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1     : constructor function
631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra     : return address
632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label gc_required;
635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ AllocateInNewSpace(JSValue::kSize,
636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        v0,  // Result.
637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        a3,  // Scratch.
638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        t0,  // Scratch.
639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        &gc_required,
640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        TAG_OBJECT);
641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Initialising the String Object.
643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register map = a3;
644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadGlobalFunctionInitialMap(function, map, t0);
645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (FLAG_debug_code) {
646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lbu(t0, FieldMemOperand(map, Map::kInstanceSizeOffset));
647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Assert(eq, "Unexpected string wrapper instance size",
648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        t0, Operand(JSValue::kSize >> kPointerSizeLog2));
649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lbu(t0, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset));
650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Assert(eq, "Unexpected unused properties of string wrapper",
651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        t0, Operand(zero_reg));
652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(map, FieldMemOperand(v0, HeapObject::kMapOffset));
654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex);
656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset));
657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(a3, FieldMemOperand(v0, JSObject::kElementsOffset));
658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(argument, FieldMemOperand(v0, JSValue::kValueOffset));
660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Ensure the object is fully initialized.
662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // The argument was not found in the number to string cache. Check
667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // if it's a string already before calling the conversion builtin.
668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label convert_argument;
669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&not_cached);
670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(a0, &convert_argument);
671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Is it a String?
673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a2, FieldMemOperand(a0, HeapObject::kMapOffset));
674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset));
675589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  STATIC_ASSERT(kNotStringTag != 0);
676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ And(t0, a3, Operand(kIsNotStringMask));
677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&convert_argument, ne, t0, Operand(zero_reg));
678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(argument, a0);
679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->string_ctor_conversions(), 1, a3, t0);
680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&argument_is_string);
681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Invoke the conversion builtin and put the result into a2.
683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&convert_argument);
684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ push(function);  // Preserve the function.
685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->string_ctor_conversions(), 1, a3, t0);
6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
6873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
6883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(v0);
6893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
6903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ pop(function);
692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(argument, v0);
693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&argument_is_string);
694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Load the empty string into a2, remove the receiver from the
696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // stack, and jump back to the case where the argument is a string.
697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&no_arguments);
698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ LoadRoot(argument, Heap::kEmptyStringRootIndex);
699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Drop(1);
700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&argument_is_string);
701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // At this point the argument is already a string. Call runtime to
703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // create a string wrapper.
704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&gc_required);
705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(counters->string_ctor_gc_required(), 1, a3, t0);
7063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
7073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
7083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(argument);
7093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kNewStringWrapper, 1);
7103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
71244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
71344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
71444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void Generate_JSConstructStubHelper(MacroAssembler* masm,
7163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           bool is_api_function,
7173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           bool count_constructions) {
718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0     : number of arguments
720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1     : constructor function
721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra     : return address
722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[...]: constructor arguments
723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Should never count constructions for api objects.
726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(!is_api_function || !count_constructions);
727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Isolate* isolate = masm->isolate();
729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0     : number of arguments
732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1     : constructor function
733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- ra     : return address
734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- sp[...]: constructor arguments
735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Enter a construct frame.
7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::CONSTRUCT);
740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Preserve the two incoming parameters on the stack.
7423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sll(a0, a0, kSmiTagSize);  // Tag arguments count.
7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ MultiPushReversed(a0.bit() | a1.bit());
744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Use t7 to hold undefined, which is used in several places below.
7463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label rt_call, allocated;
7493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Try to allocate the object without transitioning into C code. If any of
7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // the preconditions is not met, the code bails out to the runtime call.
7513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_inline_new) {
7523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label undo_allocation;
753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef ENABLE_DEBUGGER_SUPPORT
7543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExternalReference debug_step_in_fp =
7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ExternalReference::debug_step_in_fp_address(isolate);
7563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ li(a2, Operand(debug_step_in_fp));
7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(a2, MemOperand(a2));
7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&rt_call, ne, a2, Operand(zero_reg));
759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Load the initial map and verify that it is in fact a map.
7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a1: constructor function
7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ JumpIfSmi(a2, &rt_call);
7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ GetObjectType(a2, a3, t4);
7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&rt_call, ne, t4, Operand(MAP_TYPE));
7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check that the constructor is not constructing a JSFunction (see
7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // comments in Runtime_NewObject in runtime.cc). In which case the
7703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // initial map's instance type would be JS_FUNCTION_TYPE.
7713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a1: constructor function
7723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a2: initial map
7733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset));
7743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&rt_call, eq, a3, Operand(JS_FUNCTION_TYPE));
775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (count_constructions) {
7773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Label allocate;
7783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Decrease generous allocation count.
7793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lw(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
7803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        MemOperand constructor_count =
7813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           FieldMemOperand(a3, SharedFunctionInfo::kConstructionCountOffset);
7823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lbu(t0, constructor_count);
7833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Subu(t0, t0, Operand(1));
7843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sb(t0, constructor_count);
7853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Branch(&allocate, ne, t0, Operand(zero_reg));
7863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Push(a1, a2);
7883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ push(a1);  // Constructor.
7903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // The call will replace the stub, so the countdown is only done once.
7913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
7923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ pop(a2);
7943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ pop(a1);
7953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&allocate);
7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
79885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Now allocate the JSObject on the heap.
8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a1: constructor function
8013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a2: initial map
8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset));
8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ AllocateInNewSpace(a3, t4, t5, t6, &rt_call, SIZE_IN_WORDS);
8043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Allocated the JSObject, now initialize the fields. Map is set to
8063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // initial map and properties and elements are set to empty fixed array.
8073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a1: constructor function
8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a2: initial map
8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a3: object size
8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // t4: JSObject (not tagged)
8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ LoadRoot(t6, Heap::kEmptyFixedArrayRootIndex);
8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(t5, t4);
8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sw(a2, MemOperand(t5, JSObject::kMapOffset));
8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sw(t6, MemOperand(t5, JSObject::kPropertiesOffset));
8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sw(t6, MemOperand(t5, JSObject::kElementsOffset));
8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(t5, t5, Operand(3*kPointerSize));
8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
8183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
8203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Fill all the in-object properties with appropriate filler.
8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a1: constructor function
8233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a2: initial map
8243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a3: object size (in words)
8253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // t4: JSObject (not tagged)
8263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // t5: First in-object property of JSObject (not tagged)
8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sll(t0, a3, kPointerSizeLog2);
8283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ addu(t6, t4, t0);   // End of object.
8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (count_constructions) {
8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lw(a0, FieldMemOperand(a2, Map::kInstanceSizesOffset));
8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Ext(a0, a0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                kBitsPerByte);
8353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sll(t0, a0, kPointerSizeLog2);
8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ addu(a0, t5, t0);
8373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // a0: offset of first field after pre-allocated fields
8383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (FLAG_debug_code) {
8393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ Assert(le, "Unexpected number of pre-allocated property fields.",
8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              a0, Operand(t6));
8413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ InitializeFieldsWithFiller(t5, a0, t7);
843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // To allow for truncation.
844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        __ LoadRoot(t7, Heap::kOnePointerFillerMapRootIndex);
845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
8463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ InitializeFieldsWithFiller(t5, t6, t7);
8473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Add the object tag to make the JSObject real, so that we can continue
8493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // and jump into the continuation code at any time from now on. Any
8503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // failures need to undo the allocation, so that the heap is in a
8513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // consistent state and verifiable.
8523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(t4, t4, Operand(kHeapObjectTag));
8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check if a non-empty properties array is needed. Continue with
8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // allocated object if not fall through to runtime call if it is.
8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a1: constructor function
8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // t4: JSObject
8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // t5: start of next object (not tagged)
8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lbu(a3, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset));
8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // The field instance sizes contains both pre-allocated property fields
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // and in-object properties.
8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(a0, FieldMemOperand(a2, Map::kInstanceSizesOffset));
8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Ext(t6, a0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             kBitsPerByte);
8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(a3, a3, Operand(t6));
8663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Ext(t6, a0, Map::kInObjectPropertiesByte * kBitsPerByte,
8673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              kBitsPerByte);
8683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ subu(a3, a3, t6);
8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Done if no extra properties are to be allocated.
8713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&allocated, eq, a3, Operand(zero_reg));
8723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Assert(greater_equal, "Property allocation count failed.",
8733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          a3, Operand(zero_reg));
8743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Scale the number of elements by pointer size and add the header for
8763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // FixedArrays to the start of the next object calculation from above.
8773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a1: constructor
8783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a3: number of elements in properties array
8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // t4: JSObject
8803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // t5: start of next object
8813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(a0, a3, Operand(FixedArray::kHeaderSize / kPointerSize));
8823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ AllocateInNewSpace(
8833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          a0,
8843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          t5,
8853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          t6,
8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          a2,
8873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          &undo_allocation,
8883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS));
8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Initialize the FixedArray.
8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a1: constructor
8923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a3: number of elements in properties array (untagged)
8933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // t4: JSObject
8943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // t5: start of next object
8953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ LoadRoot(t6, Heap::kFixedArrayMapRootIndex);
8963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(a2, t5);
8973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sw(t6, MemOperand(a2, JSObject::kMapOffset));
8983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sll(a0, a3, kSmiTagSize);
8993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sw(a0, MemOperand(a2, FixedArray::kLengthOffset));
9003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(a2, a2, Operand(2 * kPointerSize));
9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
9033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
9043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Initialize the fields to undefined.
9063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a1: constructor
9073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a2: First element of FixedArray (not tagged)
9083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a3: number of elements in properties array
9093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // t4: JSObject
9103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // t5: FixedArray (not tagged)
9113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sll(t3, a3, kPointerSizeLog2);
9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ addu(t6, a2, t3);  // End of object.
9133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
9143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      { Label loop, entry;
9153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (count_constructions) {
9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
9173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else if (FLAG_debug_code) {
9183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ LoadRoot(t8, Heap::kUndefinedValueRootIndex);
9193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ Assert(eq, "Undefined value not loaded.", t7, Operand(t8));
9203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
9213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ jmp(&entry);
9223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&loop);
9233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sw(t7, MemOperand(a2));
9243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ addiu(a2, a2, kPointerSize);
9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&entry);
9263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Branch(&loop, less, a2, Operand(t6));
92785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      }
9283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Store the initialized FixedArray into the properties field of
9303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the JSObject.
9313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a1: constructor function
9323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // t4: JSObject
9333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // t5: FixedArray (not tagged)
9343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(t5, t5, Operand(kHeapObjectTag));  // Add the heap tag.
9353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sw(t5, FieldMemOperand(t4, JSObject::kPropertiesOffset));
9363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Continue with JSObject being successfully allocated.
9383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a1: constructor function
9393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a4: JSObject
9403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&allocated);
9413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Undo the setting of the new top so that the heap is verifiable. For
9433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // example, the map's unused properties potentially do not match the
9443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // allocated objects unused properties.
9453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // t4: JSObject (previous new top)
9463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&undo_allocation);
9473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ UndoAllocationInNewSpace(t4, t5);
94885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    }
94985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
9503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&rt_call);
9513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Allocate the new receiver object using the runtime call.
952592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // a1: constructor function
9533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(a1);  // Argument for Runtime_NewObject.
9543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kNewObject, 1);
9553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(t4, v0);
9563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Receiver for constructor call allocated.
95885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    // t4: JSObject
9593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&allocated);
9603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(t4);
9613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(t4);
9623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Reload the number of arguments from the stack.
9643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[0]: receiver
9653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[1]: receiver
9663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[2]: constructor function
9673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[3]: number of arguments (smi-tagged)
9683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a1, MemOperand(sp, 2 * kPointerSize));
9693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a3, MemOperand(sp, 3 * kPointerSize));
9703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Set up pointer to last argument.
9723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
9733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Set up number of arguments for function call below.
9753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ srl(a0, a3, kSmiTagSize);
9763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Copy arguments and receiver to the expression stack.
9783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // a0: number of arguments
9793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // a1: constructor function
9803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // a2: address of last argument (caller sp)
9813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // a3: number of arguments (smi-tagged)
9823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[0]: receiver
9833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[1]: receiver
9843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[2]: constructor function
9853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[3]: number of arguments (smi-tagged)
9863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label loop, entry;
9873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&entry);
9883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&loop);
9893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sll(t0, a3, kPointerSizeLog2 - kSmiTagSize);
9903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(t0, a2, Operand(t0));
9913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(t1, MemOperand(t0));
9923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(t1);
9933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&entry);
9943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(a3, a3, Operand(-2));
9953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&loop, greater_equal, a3, Operand(zero_reg));
996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
9973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Call the function.
9983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // a0: number of arguments
999592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // a1: constructor function
10003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_api_function) {
10013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
10023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Code> code =
10033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          masm->isolate()->builtins()->HandleApiCallConstruct();
10043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ParameterCount expected(0);
10053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ InvokeCode(code, expected, expected,
10063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    RelocInfo::CODE_TARGET, CALL_FUNCTION, CALL_AS_METHOD);
10073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
10083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ParameterCount actual(a0);
10093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ InvokeFunction(a1, actual, CALL_FUNCTION,
10103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        NullCallWrapper(), CALL_AS_METHOD);
10113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Store offset of return address for deoptimizer.
10143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!is_api_function && !count_constructions) {
10153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
10163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1017592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
10183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore context from the frame.
10193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
10203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If the result is an object (in the ECMA sense), we should get rid
10223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // of the receiver and use the result; see ECMA-262 section 13.2.2-7
10233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // on page 74.
10243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label use_receiver, exit;
10253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If the result is a smi, it is *not* an object in the ECMA sense.
10273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // v0: result
10283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[0]: receiver (newly allocated object)
10293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[1]: constructor function
10303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[2]: number of arguments (smi-tagged)
10313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(v0, &use_receiver);
10323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If the type of the result (stored in its map) is less than
10343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
10353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ GetObjectType(v0, a3, a3);
10363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&exit, greater_equal, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
10373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Throw away the result of the constructor invocation and use the
10393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // on-stack receiver as the result.
10403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&use_receiver);
10413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(v0, MemOperand(sp));
10423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Remove receiver from the stack, remove caller arguments, and
10443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // return.
10453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&exit);
10463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // v0: result
10473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[0]: receiver (newly allocated object)
10483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[1]: constructor function
10493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // sp[2]: number of arguments (smi-tagged)
10503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a1, MemOperand(sp, 2 * kPointerSize));
10513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Leave construct frame.
1053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(t0, a1, kPointerSizeLog2 - 1);
1056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(sp, sp, t0);
1057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(sp, sp, kPointerSize);
1058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ IncrementCounter(isolate->counters()->constructed_objects(), 1, a1, a2);
1059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
10603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
10613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
106344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
1064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Generate_JSConstructStubHelper(masm, false, true);
10653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
10663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
106844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
1069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Generate_JSConstructStubHelper(masm, false, false);
10703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
10713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
10723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
107344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
1074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Generate_JSConstructStubHelper(masm, true, false);
1075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
1079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                             bool is_construct) {
1080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Called from JSEntryStub::GenerateBody
1081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
1083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0: code entry
1084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1: function
10853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //  -- a2: receiver_pointer
1086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a3: argc
1087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- s0: argv
1088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
1089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Clear the context before we push it when entering the JS frame.
1091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(cp, zero_reg);
1092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Enter an internal frame.
10943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
10953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
1096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
10973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Set up the context from the function argument.
10983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
1099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Push the function and the receiver onto the stack.
11013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Push(a1, a2);
1102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Copy arguments to the stack in a loop.
11043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // a3: argc
11053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // s0: argv, i.e. points to first arg
11063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label loop, entry;
11073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sll(t0, a3, kPointerSizeLog2);
11083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ addu(t2, s0, t0);
11093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ b(&entry);
11103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ nop();   // Branch delay slot nop.
11113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // t2 points past last arg.
11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&loop);
11133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(t0, MemOperand(s0));  // Read next parameter.
11143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ addiu(s0, s0, kPointerSize);
11153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(t0, MemOperand(t0));  // Dereference handle.
11163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(t0);  // Push parameter.
11173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&entry);
11183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&loop, ne, s0, Operand(t2));
1119592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
11203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Initialize all JavaScript callee-saved registers, since they will be seen
11213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // by the garbage collector as part of handlers.
11223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(t0, Heap::kUndefinedValueRootIndex);
11233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(s1, t0);
11243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(s2, t0);
11253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(s3, t0);
11263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(s4, t0);
11273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(s5, t0);
11283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // s6 holds the root address. Do not clobber.
11293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // s7 is cp. Do not init.
11303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Invoke the code and pass argc as a0.
11323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(a0, a3);
11333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_construct) {
11343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
11353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CallStub(&stub);
11363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
11373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ParameterCount actual(a0);
11383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ InvokeFunction(a1, actual, CALL_FUNCTION,
11393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        NullCallWrapper(), CALL_AS_METHOD);
11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Leave internal frame.
11433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
114485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
1145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(ra);
11463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
11473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
1150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Generate_JSEntryTrampolineHelper(masm, false);
11513100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
11523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
1155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Generate_JSEntryTrampolineHelper(masm, true);
115644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
115744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
115844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
115944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Generate_LazyCompile(MacroAssembler* masm) {
1160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Enter an internal frame.
11613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
11623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
1163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Preserve the function.
11653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(a1);
11663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Push call kind information.
11673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(t1);
1168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Push the function on the stack as the argument to the runtime function.
11703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(a1);
11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Call the runtime function.
11723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kLazyCompile, 1);
11733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Calculate the entry point.
11743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ addiu(t9, v0, Code::kHeaderSize - kHeapObjectTag);
1175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore call kind information.
11773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ pop(t1);
11783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore saved function.
11793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ pop(a1);
1180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Tear down temporary frame.
11823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Do a tail-call of the compiled function.
1185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(t9);
118644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
118744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
118844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
118944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Generate_LazyRecompile(MacroAssembler* masm) {
1190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Enter an internal frame.
11913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
11923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
1193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Preserve the function.
11953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(a1);
11963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Push call kind information.
11973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(t1);
1198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
11993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Push the function on the stack as the argument to the runtime function.
12003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(a1);
12013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kLazyRecompile, 1);
12023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Calculate the entry point.
12033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(t9, v0, Operand(Code::kHeaderSize - kHeapObjectTag));
1204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
12053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore call kind information.
12063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ pop(t1);
12073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore saved function.
12083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ pop(a1);
1209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
12103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Tear down temporary frame.
12113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Do a tail-call of the compiled function.
1214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(t9);
121544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
121644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
121744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
12183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
12193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             Deoptimizer::BailoutType type) {
12203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
12213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
12223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Pass the function and deoptimization type to the runtime system.
12233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(a0, Operand(Smi::FromInt(static_cast<int>(type))));
12243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(a0);
12253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
12263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the full codegen state from the stack and untag it -> t2.
12293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(t2, MemOperand(sp, 0 * kPointerSize));
12303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ SmiUntag(t2);
12313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Switch on the state.
12323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label with_tos_register, unknown_state;
12333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&with_tos_register,
12343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ne, t2, Operand(FullCodeGenerator::NO_REGISTERS));
12353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(sp, sp, Operand(1 * kPointerSize));  // Remove state.
12363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Ret();
12373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&with_tos_register);
12393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(v0, MemOperand(sp, 1 * kPointerSize));
12403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&unknown_state, ne, t2, Operand(FullCodeGenerator::TOS_REG));
12413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(sp, sp, Operand(2 * kPointerSize));  // Remove state.
12433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Ret();
12443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&unknown_state);
12463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ stop("no cases left");
12473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
125044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
12513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
125244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
125344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
125444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
125544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
125744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
125844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
125944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
126044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Generate_NotifyOSR(MacroAssembler* masm) {
12613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // For now, we are relying on the fact that Runtime::NotifyOSR
12623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // doesn't do any garbage collection which allows us to save/restore
12633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the registers without worrying about which of them contain
12643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // pointers. This seems a bit fragile.
12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RegList saved_regs =
12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (kJSCallerSaved | kCalleeSaved | ra.bit() | fp.bit()) & ~sp.bit();
12673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ MultiPush(saved_regs);
12683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
12693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
12703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kNotifyOSR, 0);
12713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ MultiPop(saved_regs);
12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Ret();
127444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
127544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
127644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
127744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
12783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CpuFeatures::TryForceFeatureScope scope(VFP3);
12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!CpuFeatures::IsSupported(FPU)) {
12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Abort("Unreachable code: Cannot optimize without FPU support.");
12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return;
12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Lookup the function in the JavaScript frame and push it as an
12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // argument to the on-stack replacement function.
12863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(a0);
12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the result was -1 it means that we couldn't optimize the
12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // function. Just return and continue in the unoptimized version.
12953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Ret(eq, v0, Operand(Smi::FromInt(-1)));
12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Untag the AST id and push it on the stack.
12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ SmiUntag(v0);
12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(v0);
13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Generate the code for doing the frame-to-frame translation using
13023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the deoptimizer infrastructure.
13033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR);
13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  generator.Generate();
13053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
13063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
13083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Builtins::Generate_FunctionCall(MacroAssembler* masm) {
1309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // 1. Make sure we have at least one argument.
1310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: actual number of arguments
1311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  { Label done;
1312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&done, ne, a0, Operand(zero_reg));
1313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(t2, Heap::kUndefinedValueRootIndex);
1314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ push(t2);
1315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Addu(a0, a0, Operand(1));
1316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&done);
1317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // 2. Get the function to call (passed as receiver) from the stack, check
1320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //    if it is a function.
1321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: actual number of arguments
13223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label slow, non_function;
1323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(at, a0, kPointerSizeLog2);
1324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ addu(at, sp, at);
1325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a1, MemOperand(at));
13263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(a1, &non_function);
1327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ GetObjectType(a1, a2, a2);
13283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&slow, ne, a2, Operand(JS_FUNCTION_TYPE));
1329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // 3a. Patch the first argument if necessary when calling a function.
1331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: actual number of arguments
1332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: function
1333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label shift_arguments;
13343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(t0, Operand(0, RelocInfo::NONE));  // Indicate regular JS_FUNCTION.
1335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  { Label convert_to_object, use_global_receiver, patch_receiver;
1336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Change context eagerly in case we need the global receiver.
1337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
1338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Do not transform the receiver for strict mode functions.
1340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
1341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a3, FieldMemOperand(a2, SharedFunctionInfo::kCompilerHintsOffset));
13423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(t3, a3, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
1343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 kSmiTagSize)));
13443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&shift_arguments, ne, t3, Operand(zero_reg));
1345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Do not transform the receiver for native (Compilerhints already in a3).
13473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(t3, a3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
13483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&shift_arguments, ne, t3, Operand(zero_reg));
1349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Compute the receiver in non-strict mode.
1351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Load first argument in a2. a2 = -kPointerSize(sp + n_args << 2).
1352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(at, a0, kPointerSizeLog2);
1353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ addu(a2, sp, at);
1354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a2, MemOperand(a2, -kPointerSize));
1355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a0: actual number of arguments
1356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a1: function
1357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a2: first argument
1358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ JumpIfSmi(a2, &convert_to_object, t2);
1359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(a3, Heap::kUndefinedValueRootIndex);
1361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&use_global_receiver, eq, a2, Operand(a3));
1362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(a3, Heap::kNullValueRootIndex);
1363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&use_global_receiver, eq, a2, Operand(a3));
1364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
13653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ GetObjectType(a2, a3, a3);
13673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ Branch(&shift_arguments, ge, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
1368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&convert_to_object);
13703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Enter an internal frame in order to preserve argument count.
13713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    {
13723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FrameScope scope(masm, StackFrame::INTERNAL);
13733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sll(a0, a0, kSmiTagSize);  // Smi tagged.
13743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(a0);
13753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ push(a2);
13773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(a2, v0);
13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ pop(a0);
13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sra(a0, a0, kSmiTagSize);  // Un-tag.
13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Leave internal frame.
13833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore the function to a1, and the flag to t0.
1385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(at, a0, kPointerSizeLog2);
1386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ addu(at, sp, at);
1387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a1, MemOperand(at));
13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(t0, Operand(0, RelocInfo::NONE));
1389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&patch_receiver);
1390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Use the global receiver object from the called function as the
1392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // receiver.
1393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&use_global_receiver);
1394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    const int kGlobalIndex =
1395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
1396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a2, FieldMemOperand(cp, kGlobalIndex));
1397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalContextOffset));
1398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a2, FieldMemOperand(a2, kGlobalIndex));
1399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset));
1400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&patch_receiver);
1402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(at, a0, kPointerSizeLog2);
1403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ addu(a3, sp, at);
1404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sw(a2, MemOperand(a3, -kPointerSize));
1405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&shift_arguments);
1407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
14093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // 3b. Check for function proxy.
14103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&slow);
14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(t0, Operand(1, RelocInfo::NONE));  // Indicate function proxy.
14123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&shift_arguments, eq, a2, Operand(JS_FUNCTION_PROXY_TYPE));
14133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&non_function);
14153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(t0, Operand(2, RelocInfo::NONE));  // Indicate non-function.
14163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // 3c. Patch the first argument when calling a non-function.  The
1418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //     CALL_NON_FUNCTION builtin expects the non-function callee as
1419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //     receiver, so overwrite the first argument which will ultimately
1420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //     become the receiver.
1421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: actual number of arguments
1422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: function
14233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // t0: call type (0: JS function, 1: function proxy, 2: non-function)
1424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(at, a0, kPointerSizeLog2);
1425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ addu(a2, sp, at);
1426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sw(a1, MemOperand(a2, -kPointerSize));
1427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // 4. Shift arguments and return address one slot down on the stack
1429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //    (overwriting the original receiver).  Adjust argument count to make
1430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //    the original first argument the new receiver.
1431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: actual number of arguments
1432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: function
14333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // t0: call type (0: JS function, 1: function proxy, 2: non-function)
1434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&shift_arguments);
1435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  { Label loop;
1436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Calculate the copy start address (destination). Copy end address is sp.
1437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(at, a0, kPointerSizeLog2);
1438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ addu(a2, sp, at);
1439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&loop);
1441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(at, MemOperand(a2, -kPointerSize));
1442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sw(at, MemOperand(a2));
1443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Subu(a2, a2, Operand(kPointerSize));
1444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(&loop, ne, a2, Operand(sp));
1445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Adjust the actual number of arguments and remove the top element
1446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // (which is a copy of the last argument).
1447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Subu(a0, a0, Operand(1));
1448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Pop();
1449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
14513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin,
14523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //     or a function proxy via CALL_FUNCTION_PROXY.
1453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: actual number of arguments
1454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: function
14553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // t0: call type (0: JS function, 1: function proxy, 2: non-function)
14563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  { Label function, non_proxy;
14573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&function, eq, t0, Operand(zero_reg));
14583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Expected number of arguments is 0 for CALL_NON_FUNCTION.
14593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(a2, zero_reg);
146085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    __ SetCallKind(t1, CALL_AS_METHOD);
14613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&non_proxy, ne, t0, Operand(1));
14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(a1);  // Re-add proxy object as additional argument.
14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(a0, a0, Operand(1));
14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY);
14663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
14673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            RelocInfo::CODE_TARGET);
14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&non_proxy);
14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION);
1471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            RelocInfo::CODE_TARGET);
1473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&function);
1474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // 5b. Get the code to call from the function and check that the number of
1477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //     expected arguments matches what we're providing.  If so, jump
1478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //     (tail-call) to the code in register edx without checking arguments.
1479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a0: actual number of arguments
1480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // a1: function
1481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
1482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a2,
1483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset));
1484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sra(a2, a2, kSmiTagSize);
1485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
1486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ SetCallKind(t1, CALL_AS_METHOD);
1487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check formal and actual parameter counts.
1488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          RelocInfo::CODE_TARGET, ne, a2, Operand(a0));
1490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ParameterCount expected(0);
14923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ InvokeCode(a3, expected, expected, JUMP_FUNCTION,
14933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                NullCallWrapper(), CALL_AS_METHOD);
14943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
14953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
14963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
14973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kIndexOffset    = -5 * kPointerSize;
1499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kLimitOffset    = -4 * kPointerSize;
1500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kArgsOffset     =  2 * kPointerSize;
1501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kRecvOffset     =  3 * kPointerSize;
1502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const int kFunctionOffset =  4 * kPointerSize;
1503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
15043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
15053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope frame_scope(masm, StackFrame::INTERNAL);
15063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a0, MemOperand(fp, kFunctionOffset));  // Get the function.
15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(a0);
15083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a0, MemOperand(fp, kArgsOffset));  // Get the args array.
15093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(a0);
15103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Returns (in v0) number of arguments to copy to stack as Smi.
15113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
15123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check the stack for overflow. We are not trying to catch
15143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // interruptions (e.g. debug break and preemption) here, so the "real stack
15153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // limit" is checked.
15163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label okay;
15173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(a2, Heap::kRealStackLimitRootIndex);
15183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make a2 the space we have left. The stack might already be overflowed
15193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // here which will cause a2 to become negative.
15203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ subu(a2, sp, a2);
15213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check if the arguments will overflow the stack.
15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sll(t3, v0, kPointerSizeLog2 - kSmiTagSize);
15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&okay, gt, a2, Operand(t3));  // Signed comparison.
15243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Out of stack space.
15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a1, MemOperand(fp, kFunctionOffset));
15273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(a1);
15283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(v0);
15293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
15303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // End of stack check.
15313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Push current limit and index.
15333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&okay);
15343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(v0);  // Limit.
15353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(a1, zero_reg);  // Initial index.
15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(a1);
1537592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Get the receiver.
15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a0, MemOperand(fp, kRecvOffset));
1540592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check that the function is a JS function (otherwise it must be a proxy).
15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label push_receiver;
15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a1, MemOperand(fp, kFunctionOffset));
15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ GetObjectType(a1, a2, a2);
15453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&push_receiver, ne, a2, Operand(JS_FUNCTION_TYPE));
1546592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
15473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Change context eagerly to get the right global object if necessary.
15483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
15493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Load the shared function info while the function is still in a1.
15503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
15513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Compute the receiver.
15533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Do not transform the receiver for strict mode functions.
15543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label call_to_object, use_global_receiver;
15553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kCompilerHintsOffset));
15563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(t3, a2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
15573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 kSmiTagSize)));
15583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&push_receiver, ne, t3, Operand(zero_reg));
15593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Do not transform the receiver for native (Compilerhints already in a2).
15613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(t3, a2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
15623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&push_receiver, ne, t3, Operand(zero_reg));
15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Compute the receiver in non-strict mode.
15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(a0, &call_to_object);
15663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(a1, Heap::kNullValueRootIndex);
15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&use_global_receiver, eq, a0, Operand(a1));
15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&use_global_receiver, eq, a0, Operand(a2));
15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check if the receiver is already a JavaScript object.
15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // a0: receiver
15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ GetObjectType(a0, a1, a1);
15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&push_receiver, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Convert the receiver to a regular object.
15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // a0: receiver
15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&call_to_object);
15803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(a0);
15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(a0, v0);  // Put object in a0 to match other paths to push_receiver.
15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&push_receiver);
15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Use the current global receiver object as the receiver.
15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&use_global_receiver);
15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const int kGlobalOffset =
15883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
15893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a0, FieldMemOperand(cp, kGlobalOffset));
15903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a0, FieldMemOperand(a0, GlobalObject::kGlobalContextOffset));
15913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a0, FieldMemOperand(a0, kGlobalOffset));
15923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a0, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset));
15933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Push the receiver.
15953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // a0: receiver
15963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&push_receiver);
15973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(a0);
15983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Copy all arguments from the array to the stack.
16003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label entry, loop;
16013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a0, MemOperand(fp, kIndexOffset));
16023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&entry);
16033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Load the current argument from the arguments array and push it to the
16053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // stack.
16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // a0: current argument index
16073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&loop);
16083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a1, MemOperand(fp, kArgsOffset));
16093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(a1);
16103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(a0);
16113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Call the runtime to access the property in the arguments array.
16133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallRuntime(Runtime::kGetProperty, 2);
16143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(v0);
16153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Use inline caching to access the arguments.
16173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a0, MemOperand(fp, kIndexOffset));
16183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(a0, a0, Operand(1 << kSmiTagSize));
16193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(a0, MemOperand(fp, kIndexOffset));
16203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Test if the copy loop has finished copying all the elements from the
16223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // arguments object.
16233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&entry);
16243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a1, MemOperand(fp, kLimitOffset));
16253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&loop, ne, a0, Operand(a1));
16263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Invoke the function.
16283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label call_proxy;
16293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ParameterCount actual(a0);
16303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sra(a0, a0, kSmiTagSize);
16313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(a1, MemOperand(fp, kFunctionOffset));
16323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ GetObjectType(a1, a2, a2);
16333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&call_proxy, ne, a2, Operand(JS_FUNCTION_TYPE));
16343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ InvokeFunction(a1, actual, CALL_FUNCTION,
16363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      NullCallWrapper(), CALL_AS_METHOD);
16373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    frame_scope.GenerateLeaveFrame();
16393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Ret(USE_DELAY_SLOT);
16403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(sp, sp, Operand(3 * kPointerSize));  // In delay slot.
16413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Invoke the function proxy.
16433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&call_proxy);
16443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(a1);  // Add function proxy as last argument.
16453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(a0, a0, Operand(1));
16463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ li(a2, Operand(0, RelocInfo::NONE));
16473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SetCallKind(t1, CALL_AS_METHOD);
16483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY);
16493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
16503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            RelocInfo::CODE_TARGET);
16513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Tear down the internal frame and remove function, receiver and args.
16523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
16533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Ret(USE_DELAY_SLOT);
16553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(sp, sp, Operand(3 * kPointerSize));  // In delay slot.
1656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(a0, a0, kSmiTagSize);
1661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ li(t0, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ MultiPush(a0.bit() | a1.bit() | t0.bit() | fp.bit() | ra.bit());
1663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(fp, sp, Operand(3 * kPointerSize));
1664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
1665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
1669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- v0 : result being passed through
1670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
1671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Get the number of arguments passed (as a smi), tear down the frame and
1672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // then tear down the parameters.
1673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ lw(a1, MemOperand(fp, -3 * kPointerSize));
1674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(sp, fp);
1675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ MultiPop(fp.bit() | ra.bit());
1676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ sll(t0, a1, kPointerSizeLog2 - kSmiTagSize);
1677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(sp, sp, t0);
1678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Adjust for the receiver.
1679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Addu(sp, sp, Operand(kPointerSize));
16803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
16813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16823100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
16833100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // State setup as expected by MacroAssembler::InvokePrologue.
1685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // ----------- S t a t e -------------
1686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a0: actual arguments count
1687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a1: function (passed through to callee)
1688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a2: expected arguments count
1689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- a3: callee code entry
1690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  -- t1: call kind information
1691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -----------------------------------
1692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label invoke, dont_adapt_arguments;
1694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label enough, too_few;
1696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&dont_adapt_arguments, eq,
1697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      a2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
1698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We use Uless as the number of argument should always be greater than 0.
1699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Branch(&too_few, Uless, a0, Operand(a2));
1700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  {  // Enough parameters: actual >= expected.
1702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a0: actual number of arguments as a smi
1703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a1: function
1704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a2: expected number of arguments
1705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a3: code entry to call
1706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&enough);
1707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    EnterArgumentsAdaptorFrame(masm);
1708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Calculate copy start address into a0 and copy end address into a2.
1710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(a0, a0, kPointerSizeLog2 - kSmiTagSize);
1711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Addu(a0, fp, a0);
1712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Adjust for return address and receiver.
1713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Addu(a0, a0, Operand(2 * kPointerSize));
1714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Compute copy end address.
1715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(a2, a2, kPointerSizeLog2);
1716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ subu(a2, a0, a2);
1717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Copy the arguments (including the receiver) to the new stack frame.
1719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a0: copy start address
1720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a1: function
1721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a2: copy end address
1722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a3: code entry to call
1723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label copy;
1725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&copy);
1726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(t0, MemOperand(a0));
1727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ push(t0);
1728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Branch(USE_DELAY_SLOT, &copy, ne, a0, Operand(a2));
1729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ addiu(a0, a0, -kPointerSize);  // In delay slot.
1730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ jmp(&invoke);
1732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  {  // Too few parameters: Actual < expected.
1735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&too_few);
1736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    EnterArgumentsAdaptorFrame(masm);
1737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Calculate copy start address into a0 and copy end address is fp.
1739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a0: actual number of arguments as a smi
1740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a1: function
1741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a2: expected number of arguments
1742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a3: code entry to call
1743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(a0, a0, kPointerSizeLog2 - kSmiTagSize);
1744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Addu(a0, fp, a0);
1745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Adjust for return address and receiver.
1746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Addu(a0, a0, Operand(2 * kPointerSize));
1747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Compute copy end address. Also adjust for return address.
17483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ Addu(t3, fp, kPointerSize);
1749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Copy the arguments (including the receiver) to the new stack frame.
1751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a0: copy start address
1752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a1: function
1753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a2: expected number of arguments
1754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a3: code entry to call
17553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // t3: copy end address
1756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label copy;
1757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&copy);
1758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ lw(t0, MemOperand(a0));  // Adjusted above for return addr and receiver.
17593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Subu(sp, sp, kPointerSize);
1760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Subu(a0, a0, kPointerSize);
17613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(USE_DELAY_SLOT, &copy, ne, a0, Operand(t3));
17623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(t0, MemOperand(sp));  // In the delay slot.
1763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Fill the remaining expected arguments with undefined.
1765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a1: function
1766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a2: expected number of arguments
1767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // a3: code entry to call
1768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ LoadRoot(t0, Heap::kUndefinedValueRootIndex);
1769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ sll(t2, a2, kPointerSizeLog2);
1770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Subu(a2, fp, Operand(t2));
1771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Addu(a2, a2, Operand(-4 * kPointerSize));  // Adjust for frame.
1772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label fill;
1774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ bind(&fill);
17753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Subu(sp, sp, kPointerSize);
17763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(USE_DELAY_SLOT, &fill, ne, sp, Operand(a2));
17773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(t0, MemOperand(sp));
1778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Call the entry point.
1781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&invoke);
1782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Call(a3);
1784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
17853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Store offset of return address for deoptimizer.
17863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
17873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Exit frame and return.
1789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  LeaveArgumentsAdaptorFrame(masm);
1790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Ret();
1791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -------------------------------------------
1794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Don't adapt arguments.
1795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // -------------------------------------------
1796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&dont_adapt_arguments);
1797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Jump(a3);
17983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
17993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
18003100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
18013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#undef __
18023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
18033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} }  // namespace v8::internal
18043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_MIPS
1806