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(¬_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(¬_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, ¬_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(¬_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 ¬_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(¬_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(©); 1726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t0, MemOperand(a0)); 1727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(t0); 1728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(USE_DELAY_SLOT, ©, 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(©); 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, ©, 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