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