builtins-arm.cc revision 5d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0b
1c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_ARM) 31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "codegen.h" 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "debug.h" 34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "deoptimizer.h" 35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "full-codegen.h" 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "runtime.h" 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm) 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 45e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_Adaptor(MacroAssembler* masm, 46e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke CFunctionId id, 47e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BuiltinExtraArguments extra_args) { 48e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------- S t a t e ------------- 49e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- r0 : number of arguments excluding receiver 50e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- r1 : called function (only guaranteed when 51e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // extra_args requires it) 52e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- cp : context 53e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- sp[0] : last argument 54e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 55e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- sp[4 * (argc - 1)] : first argument (argc == r0) 56e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- sp[4 * argc] : receiver 57e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------------------------------- 58e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 59e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Insert extra arguments. 60e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int num_extra_args = 0; 61e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (extra_args == NEEDS_CALLED_FUNCTION) { 62e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke num_extra_args = 1; 63e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(r1); 64e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 65e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(extra_args == NO_EXTRA_ARGUMENTS); 66e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 67e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // JumpToExternalReference expects r0 to contain the number of arguments 69e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // including the receiver and the extra arguments. 70e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(r0, r0, Operand(num_extra_args + 1)); 7144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ JumpToExternalReference(ExternalReference(id, masm->isolate())); 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 75c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch// Load the built-in InternalArray function from the current context. 76c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochstatic void GenerateLoadInternalArrayFunction(MacroAssembler* masm, 77c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Register result) { 78c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Load the global context. 79c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 80c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ ldr(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 81c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ ldr(result, 82c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch FieldMemOperand(result, GlobalObject::kGlobalContextOffset)); 83c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Load the InternalArray function from the global context. 84c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ ldr(result, 85c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch MemOperand(result, 86c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Context::SlotOffset( 87c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Context::INTERNAL_ARRAY_FUNCTION_INDEX))); 88c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch} 89c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 90c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load the built-in Array function from the current context. 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) { 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the global context. 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(result, 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldMemOperand(result, GlobalObject::kGlobalContextOffset)); 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the Array function from the global context. 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(result, 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MemOperand(result, 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Allocate an empty JSArray. The allocated array is put into the result 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register. An elements backing store is allocated with size initial_capacity 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and filled with the hole values. 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void AllocateEmptyJSArray(MacroAssembler* masm, 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register array_function, 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch3, 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required) { 115592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch const int initial_capacity = JSArray::kPreallocatedArrayElements; 116592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch STATIC_ASSERT(initial_capacity >= 0); 1175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ LoadInitialArrayMap(array_function, scratch2, scratch1); 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate the JSArray object together with space for a fixed array with the 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // requested elements. 121592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch int size = JSArray::kSize; 122592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (initial_capacity > 0) { 123592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch size += FixedArray::SizeFor(initial_capacity); 124592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 12525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ AllocateInNewSpace(size, 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result, 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scratch2, 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scratch3, 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block gc_required, 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TAG_OBJECT); 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocated the JSArray. Now initialize the fields except for the elements 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array. 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch1: initial map 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch2: start of next object 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch1, FieldMemOperand(result, JSObject::kMapOffset)); 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex); 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch1, FieldMemOperand(result, JSArray::kPropertiesOffset)); 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Field JSArray::kElementsOffset is initialized later. 1419ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ mov(scratch3, Operand(0, RelocInfo::NONE)); 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch3, FieldMemOperand(result, JSArray::kLengthOffset)); 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 144592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (initial_capacity == 0) { 145592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ str(scratch1, FieldMemOperand(result, JSArray::kElementsOffset)); 146592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return; 147592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 148592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the location of the elements array and set elements array member 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of the JSArray. 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch2: start of next object 153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(scratch1, result, Operand(JSArray::kSize)); 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch1, FieldMemOperand(result, JSArray::kElementsOffset)); 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Clear the heap tag on the elements array. 1579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ sub(scratch1, scratch1, Operand(kHeapObjectTag)); 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Initialize the FixedArray and fill it with holes. FixedArray length is 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // stored as a smi. 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch1: elements array (untagged) 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch2: start of next object 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(scratch3, Heap::kFixedArrayMapRootIndex); 165592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch STATIC_ASSERT(0 * kPointerSize == FixedArray::kMapOffset); 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); 1677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(scratch3, Operand(Smi::FromInt(initial_capacity))); 168592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch STATIC_ASSERT(1 * kPointerSize == FixedArray::kLengthOffset); 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 171592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Fill the FixedArray with the hole value. Inline the code if short. 172592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch STATIC_ASSERT(2 * kPointerSize == FixedArray::kHeaderSize); 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex); 174592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch static const int kLoopUnfoldLimit = 4; 175592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (initial_capacity <= kLoopUnfoldLimit) { 176592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch for (int i = 0; i < initial_capacity; i++) { 177592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); 178592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 179592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else { 180592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label loop, entry; 181592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(scratch2, scratch1, Operand(initial_capacity * kPointerSize)); 182592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(&entry); 183592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&loop); 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); 185592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&entry); 186592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(scratch1, scratch2); 187592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(lt, &loop); 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Allocate a JSArray with the number of elements stored in a register. The 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register array_function holds the built-in Array function and the register 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// array_size holds the size of the array as a smi. The allocated array is put 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// into the result register and beginning and end of the FixedArray elements 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// storage is put into registers elements_array_storage and elements_array_end 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (see below for when that is not the case). If the parameter fill_with_holes 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// is true the allocated elements backing store is filled with the hole values 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// otherwise it is left uninitialized. When the backing store is filled the 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register elements_array_storage is scratched. 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void AllocateJSArray(MacroAssembler* masm, 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register array_function, // Array function. 202592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Register array_size, // As a smi, cannot be 0. 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register elements_array_storage, 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register elements_array_end, 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool fill_with_hole, 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required) { 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the initial map from the array function. 2115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ LoadInitialArrayMap(array_function, scratch2, elements_array_storage); 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 213592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (FLAG_debug_code) { // Assert that array size is not zero. 214592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ tst(array_size, array_size); 215592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ Assert(ne, "array size is unexpectedly 0"); 216592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate the JSArray object together with space for a FixedArray with the 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // requested number of elements. 22069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(elements_array_end, 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand((JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize)); 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(elements_array_end, 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block elements_array_end, 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(array_size, ASR, kSmiTagSize)); 22625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ AllocateInNewSpace( 22725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen elements_array_end, 22825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen result, 22925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen scratch1, 23025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen scratch2, 23125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen gc_required, 23225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocated the JSArray. Now initialize the fields except for the elements 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array. 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // elements_array_storage: initial map 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array_size: size of array (smi) 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(elements_array_storage, FieldMemOperand(result, JSObject::kMapOffset)); 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(elements_array_storage, Heap::kEmptyFixedArrayRootIndex); 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(elements_array_storage, 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldMemOperand(result, JSArray::kPropertiesOffset)); 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Field JSArray::kElementsOffset is initialized later. 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(array_size, FieldMemOperand(result, JSArray::kLengthOffset)); 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the location of the elements array and set elements array member 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of the JSArray. 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array_size: size of array (smi) 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(elements_array_storage, result, Operand(JSArray::kSize)); 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(elements_array_storage, 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldMemOperand(result, JSArray::kElementsOffset)); 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Clear the heap tag on the elements array. 25569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 2569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ sub(elements_array_storage, 2579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen elements_array_storage, 2589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Operand(kHeapObjectTag)); 2597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Initialize the fixed array and fill it with holes. FixedArray length is 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // stored as a smi. 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // elements_array_storage: elements array (untagged) 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array_size: size of array (smi) 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(scratch1, Heap::kFixedArrayMapRootIndex); 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset); 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch1, MemOperand(elements_array_storage, kPointerSize, PostIndex)); 26769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(array_size, 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MemOperand(elements_array_storage, kPointerSize, PostIndex)); 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate elements array and elements array end. 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // elements_array_storage: elements array element storage 2757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // array_size: smi-tagged size of elements array 27669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(elements_array_end, 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block elements_array_storage, 2797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Operand(array_size, LSL, kPointerSizeLog2 - kSmiTagSize)); 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the allocated FixedArray with the hole value if requested. 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // elements_array_storage: elements array element storage 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // elements_array_end: start of next object 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (fill_with_hole) { 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop, entry; 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(scratch1, Heap::kTheHoleValueRootIndex); 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&entry); 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch1, 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MemOperand(elements_array_storage, kPointerSize, PostIndex)); 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry); 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(elements_array_storage, elements_array_end); 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(lt, &loop); 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Create a new array for the built-in Array function. This function allocates 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the JSArray object and the FixedArray elements array and initializes these. 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// If the Array cannot be constructed in native code the runtime is called. This 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// function assumes the following state: 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// r0: argc 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// r1: constructor (built-in Array function) 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// lr: return address 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// sp[0]: last argument 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This function is used for both construct and normal calls of Array. The only 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// difference between handling a construct call and a normal call is that for a 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// construct call the constructor function in r1 needs to be preserved for 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// entering the generic code. In both cases argc in r0 needs to be preserved. 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Both registers are preserved by this code so no need to differentiate between 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// construct call and normal call. 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ArrayNativeCode(MacroAssembler* masm, 313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* call_generic_code) { 31444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm->isolate()->counters(); 315c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Label argc_one_or_more, argc_two_or_more, not_empty_array, empty_array, 3165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch has_non_smi_element, finish, cant_transition_map, not_double; 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for array construction with zero arguments or one. 3199ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ cmp(r0, Operand(0, RelocInfo::NONE)); 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &argc_one_or_more); 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle construction of an empty array. 323592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&empty_array); 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocateEmptyJSArray(masm, 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r1, 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r2, 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r3, 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r4, 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r5, 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call_generic_code); 33144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->array_function_native(), 1, r3, r4); 332c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Set up return value, remove receiver from stack and return. 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, r2); 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(kPointerSize)); 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for one argument. Bail out if argument is not smi or if it is 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // negative. 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&argc_one_or_more); 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand(1)); 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &argc_two_or_more); 34269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(sp)); // Get the argument from the stack. 344592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ tst(r2, r2); 345592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(ne, ¬_empty_array); 346592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ Drop(1); // Adjust stack. 347592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(r0, Operand(0)); // Treat this as a call with argc of zero. 348592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(&empty_array); 349592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 350592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(¬_empty_array); 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(r3, r2, Operand(kIntptrSignBit | kSmiTagMask), SetCC); 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, call_generic_code); 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle construction of an empty array of a certain size. Bail out if size 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is too large to actually allocate an elements array. 35669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, Operand(JSObject::kInitialMaxFastElementArray << kSmiTagSize)); 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ge, call_generic_code); 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: array_size (smi) 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: argument 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocateJSArray(masm, 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r1, 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r2, 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r3, 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r4, 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r5, 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r6, 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r7, 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block true, 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call_generic_code); 37444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->array_function_native(), 1, r2, r4); 375c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Set up return value, remove receiver and argument from stack and return. 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, r3); 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(2 * kPointerSize)); 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle construction of an array from a list of arguments. 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&argc_two_or_more); 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(r0, LSL, kSmiTagSize)); // Convet argc to a smi. 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: array_size (smi) 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: last argument 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocateJSArray(masm, 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r1, 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r2, 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r3, 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r4, 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r5, 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r6, 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r7, 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block false, 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call_generic_code); 39844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->array_function_native(), 1, r2, r6); 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill arguments as array elements. Copy from the top of the stack (last 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // element) to the array backing store filling it backwards. Note: 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // elements_array_end points after the backing store therefore PreIndex is 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // used when filling the backing store. 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: JSArray 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: elements_array storage start (untagged) 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5: elements_array_end (untagged) 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: last argument 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop, entry; 410c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ mov(r7, sp); 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&entry); 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 413c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ ldr(r2, MemOperand(r7, kPointerSize, PostIndex)); 414c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (FLAG_smi_only_arrays) { 415c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ JumpIfNotSmi(r2, &has_non_smi_element); 416c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r5, -kPointerSize, PreIndex)); 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry); 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r4, r5); 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(lt, &loop); 4215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 4225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ bind(&finish); 423c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ mov(sp, r7); 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Remove caller arguments and receiver from the stack, setup return value and 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // return. 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: JSArray 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: receiver 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(kPointerSize)); 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, r3); 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 433c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 434c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ bind(&has_non_smi_element); 4355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Double values are handled by the runtime. 4365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ CheckMap( 4375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch r2, r9, Heap::kHeapNumberMapRootIndex, ¬_double, DONT_DO_SMI_CHECK); 4385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ bind(&cant_transition_map); 439c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ UndoAllocationInNewSpace(r3, r4); 440c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ b(call_generic_code); 4415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 4425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ bind(¬_double); 4435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Transition FAST_SMI_ONLY_ELEMENTS to FAST_ELEMENTS. 4445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // r3: JSArray 4455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset)); 4465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS, 4475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch FAST_ELEMENTS, 4485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch r2, 4495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch r9, 4505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch &cant_transition_map); 4515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ str(r2, FieldMemOperand(r3, HeapObject::kMapOffset)); 4525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ RecordWriteField(r3, 4535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HeapObject::kMapOffset, 4545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch r2, 4555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch r9, 4565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch kLRHasNotBeenSaved, 4575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch kDontSaveFPRegs, 4585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch EMIT_REMEMBERED_SET, 4595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch OMIT_SMI_CHECK); 4605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Label loop2; 4615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ sub(r7, r7, Operand(kPointerSize)); 4625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ bind(&loop2); 4635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ ldr(r2, MemOperand(r7, kPointerSize, PostIndex)); 4645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ str(r2, MemOperand(r5, -kPointerSize, PreIndex)); 4655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ cmp(r4, r5); 4665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ b(lt, &loop2); 4675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ b(&finish); 468c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch} 469c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 470c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 471c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochvoid Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { 472c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // ----------- S t a t e ------------- 473c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // -- r0 : number of arguments 474c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // -- lr : return address 475c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // -- sp[...]: constructor arguments 476c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // ----------------------------------- 477c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Label generic_array_code, one_or_more_arguments, two_or_more_arguments; 478c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 479c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Get the InternalArray function. 480c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch GenerateLoadInternalArrayFunction(masm, r1); 481c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 482c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (FLAG_debug_code) { 483c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Initial map for the builtin InternalArray functions should be maps. 484c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 485c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ tst(r2, Operand(kSmiTagMask)); 486c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ Assert(ne, "Unexpected initial map for InternalArray function"); 487c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ CompareObjectType(r2, r3, r4, MAP_TYPE); 488c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ Assert(eq, "Unexpected initial map for InternalArray function"); 489c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 490c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 491c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Run the native code for the InternalArray function called as a normal 492c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // function. 493c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch ArrayNativeCode(masm, &generic_array_code); 494c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 495c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Jump to the generic array code if the specialized code cannot handle the 496c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // construction. 497c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ bind(&generic_array_code); 498c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 499c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Handle<Code> array_code = 500c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch masm->isolate()->builtins()->InternalArrayCodeGeneric(); 501c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ Jump(array_code, RelocInfo::CODE_TARGET); 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArrayCode(MacroAssembler* masm) { 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : number of arguments 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[...]: constructor arguments 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label generic_array_code, one_or_more_arguments, two_or_more_arguments; 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the Array function. 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadArrayFunction(masm, r1); 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 517e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Initial map for the builtin Array functions should be maps. 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r2, Operand(kSmiTagMask)); 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(ne, "Unexpected initial map for Array function"); 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r2, r3, r4, MAP_TYPE); 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(eq, "Unexpected initial map for Array function"); 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Run the native code for the Array function called as a normal function. 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ArrayNativeCode(masm, &generic_array_code); 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the generic array code if the specialized code cannot handle 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the construction. 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&generic_array_code); 53144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 53244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> array_code = 53344f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->isolate()->builtins()->ArrayCodeGeneric(); 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(array_code, RelocInfo::CODE_TARGET); 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) { 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : number of arguments 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r1 : constructor function 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[...]: constructor arguments 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label generic_constructor; 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 548e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The array construct code is only set for the builtin and internal 549e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Array functions which always have a map. 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initial map for the builtin Array function should be a map. 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r2, Operand(kSmiTagMask)); 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(ne, "Unexpected initial map for Array function"); 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r2, r3, r4, MAP_TYPE); 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(eq, "Unexpected initial map for Array function"); 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Run the native code for the Array function called as a constructor. 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ArrayNativeCode(masm, &generic_constructor); 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the generic construct code in case the specialized code cannot 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // handle the construction. 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&generic_constructor); 56444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> generic_construct_stub = 56544f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->isolate()->builtins()->JSConstructStubGeneric(); 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 57080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid Builtins::Generate_StringConstructCode(MacroAssembler* masm) { 5718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // ----------- S t a t e ------------- 5728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- r0 : number of arguments 5738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- r1 : constructor function 5748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- lr : return address 5758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[(argc - n - 1) * 4] : arg[n] (zero based) 5768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[argc * 4] : receiver 5778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // ----------------------------------- 57844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm->isolate()->counters(); 57944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->string_ctor_calls(), 1, r2, r3); 5808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register function = r1; 5828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (FLAG_debug_code) { 5838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, r2); 5848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(function, Operand(r2)); 5858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Assert(eq, "Unexpected String function"); 5868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 5878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the first arguments in r0 and get rid of the rest. 5898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label no_arguments; 590b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ cmp(r0, Operand(0, RelocInfo::NONE)); 5918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(eq, &no_arguments); 5928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // First args = sp[(argc - 1) * 4]. 5938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ sub(r0, r0, Operand(1)); 5948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, MemOperand(sp, r0, LSL, kPointerSizeLog2, PreIndex)); 5958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // sp now point to args[0], drop args[0] + receiver. 5968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(2); 5978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register argument = r2; 5998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label not_cached, argument_is_string; 6008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang NumberToStringStub::GenerateLookupNumberStringCache( 6018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang masm, 6028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang r0, // Input. 6038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang argument, // Result. 6048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang r3, // Scratch. 6058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang r4, // Scratch. 6068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang r5, // Scratch. 6078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang false, // Is it a Smi? 6088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ¬_cached); 60944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->string_ctor_cached_number(), 1, r3, r4); 6108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&argument_is_string); 6118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 6128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // ----------- S t a t e ------------- 6138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- r2 : argument converted to string 6148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- r1 : constructor function 6158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- lr : return address 6168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // ----------------------------------- 6178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 6188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label gc_required; 6198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ AllocateInNewSpace(JSValue::kSize, 6208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang r0, // Result. 6218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang r3, // Scratch. 6228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang r4, // Scratch. 6238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang &gc_required, 6248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang TAG_OBJECT); 6258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 6268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Initialising the String Object. 6278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register map = r3; 6288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadGlobalFunctionInitialMap(function, map, r4); 6298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (FLAG_debug_code) { 6308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldrb(r4, FieldMemOperand(map, Map::kInstanceSizeOffset)); 6318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(r4, Operand(JSValue::kSize >> kPointerSizeLog2)); 6328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Assert(eq, "Unexpected string wrapper instance size"); 6338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldrb(r4, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset)); 634b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ cmp(r4, Operand(0, RelocInfo::NONE)); 6358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Assert(eq, "Unexpected unused properties of string wrapper"); 6368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 6378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(map, FieldMemOperand(r0, HeapObject::kMapOffset)); 6388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 6398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex); 6408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset)); 6418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset)); 6428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 6438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(argument, FieldMemOperand(r0, JSValue::kValueOffset)); 6448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 6458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Ensure the object is fully initialized. 6468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); 6478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 6488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 6498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 6508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // The argument was not found in the number to string cache. Check 6518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // if it's a string already before calling the conversion builtin. 6528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label convert_argument; 6538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(¬_cached); 6541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, &convert_argument); 6558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 6568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Is it a String? 6578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 6588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceTypeOffset)); 65969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kNotStringTag != 0); 6608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ tst(r3, Operand(kIsNotStringMask)); 6618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(ne, &convert_argument); 6628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(argument, r0); 66344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4); 6648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&argument_is_string); 6658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 6668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Invoke the conversion builtin and put the result into r2. 6678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&convert_argument); 6688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(function); // Preserve the function. 66944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4); 670592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch { 671592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 672592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r0); 673592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION); 674592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 6758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ pop(function); 6768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(argument, r0); 6778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&argument_is_string); 6788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 6798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the empty string into r2, remove the receiver from the 6808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // stack, and jump back to the case where the argument is a string. 6818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&no_arguments); 6828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadRoot(argument, Heap::kEmptyStringRootIndex); 6838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(1); 6848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&argument_is_string); 6858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 6868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // At this point the argument is already a string. Call runtime to 6878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // create a string wrapper. 6888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&gc_required); 68944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->string_ctor_gc_required(), 1, r3, r4); 690592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch { 691592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 692592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(argument); 693592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ CallRuntime(Runtime::kNewStringWrapper, 1); 694592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 6958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 69680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 69780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 69880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 6995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochstatic void Generate_JSConstructStubHelper(MacroAssembler* masm, 7005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch bool is_api_function, 7015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch bool count_constructions) { 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : number of arguments 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r1 : constructor function 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[...]: constructor arguments 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Should never count constructions for api objects. 7100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(!is_api_function || !count_constructions); 7110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 71244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate = masm->isolate(); 71344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Enter a construct frame. 715592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch { 716592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch FrameScope scope(masm, StackFrame::CONSTRUCT); 717592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 718592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Preserve the two incoming parameters on the stack. 719592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(r0, Operand(r0, LSL, kSmiTagSize)); 720592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r0); // Smi-tagged arguments count. 721592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r1); // Constructor function. 722592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 723592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Try to allocate the object without transitioning into C code. If any of 724592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // the preconditions is not met, the code bails out to the runtime call. 725592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label rt_call, allocated; 726592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (FLAG_inline_new) { 727592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label undo_allocation; 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 729592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ExternalReference debug_step_in_fp = 730592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ExternalReference::debug_step_in_fp_address(isolate); 731592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(r2, Operand(debug_step_in_fp)); 732592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r2, MemOperand(r2)); 733592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ tst(r2, r2); 734592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(ne, &rt_call); 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 737592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Load the initial map and verify that it is in fact a map. 738592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r1: constructor function 739592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 740592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ JumpIfSmi(r2, &rt_call); 741592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ CompareObjectType(r2, r3, r4, MAP_TYPE); 742592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(ne, &rt_call); 743592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 744592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Check that the constructor is not constructing a JSFunction (see 745592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // comments in Runtime_NewObject in runtime.cc). In which case the 746592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // initial map's instance type would be JS_FUNCTION_TYPE. 747592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r1: constructor function 748592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r2: initial map 749592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); 750592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(eq, &rt_call); 7510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 752592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (count_constructions) { 753592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label allocate; 754592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Decrease generous allocation count. 755592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 756592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch MemOperand constructor_count = 757592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch FieldMemOperand(r3, SharedFunctionInfo::kConstructionCountOffset); 758592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldrb(r4, constructor_count); 759592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ sub(r4, r4, Operand(1), SetCC); 760592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ strb(r4, constructor_count); 761592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(ne, &allocate); 762592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 763592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ Push(r1, r2); 764592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 765592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r1); // constructor 766592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // The call will replace the stub, so the countdown is only done once. 767592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); 768592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 769592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ pop(r2); 770592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ pop(r1); 771592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 772592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&allocate); 773592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 775592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Now allocate the JSObject on the heap. 776592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r1: constructor function 777592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r2: initial map 778592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset)); 779592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS); 780592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 781592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Allocated the JSObject, now initialize the fields. Map is set to 782592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // initial map and properties and elements are set to empty fixed array. 783592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r1: constructor function 784592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r2: initial map 785592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r3: object size 786592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r4: JSObject (not tagged) 787592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); 788592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(r5, r4); 789592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); 790592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); 791592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset); 792592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 793592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset); 794592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 795592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 796592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Fill all the in-object properties with the appropriate filler. 797592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r1: constructor function 798592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r2: initial map 799592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r3: object size (in words) 800592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r4: JSObject (not tagged) 801592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r5: First in-object property of JSObject (not tagged) 802592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object. 803592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize); 804592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); 8050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (count_constructions) { 806592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset)); 807592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ Ubfx(r0, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte, 808592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch kBitsPerByte); 809592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(r0, r5, Operand(r0, LSL, kPointerSizeLog2)); 810592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r0: offset of first field after pre-allocated fields 811592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (FLAG_debug_code) { 812592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(r0, r6); 813592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ Assert(le, "Unexpected number of pre-allocated property fields."); 814592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 815592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ InitializeFieldsWithFiller(r5, r0, r7); 8160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // To allow for truncation. 8170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(r7, Heap::kOnePointerFillerMapRootIndex); 8180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 819592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ InitializeFieldsWithFiller(r5, r6, r7); 820592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 821592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Add the object tag to make the JSObject real, so that we can continue 822592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // and jump into the continuation code at any time from now on. Any 823592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // failures need to undo the allocation, so that the heap is in a 824592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // consistent state and verifiable. 825592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(r4, r4, Operand(kHeapObjectTag)); 826592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 827592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Check if a non-empty properties array is needed. Continue with 828592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // allocated object if not fall through to runtime call if it is. 829592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r1: constructor function 830592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r4: JSObject 831592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r5: start of next object (not tagged) 832592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset)); 833592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // The field instance sizes contains both pre-allocated property fields 834592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // and in-object properties. 835592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset)); 836592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ Ubfx(r6, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte, 837592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch kBitsPerByte); 838592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(r3, r3, Operand(r6)); 839592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ Ubfx(r6, r0, Map::kInObjectPropertiesByte * kBitsPerByte, 840592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch kBitsPerByte); 841592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ sub(r3, r3, Operand(r6), SetCC); 842592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 843592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Done if no extra properties are to be allocated. 844592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(eq, &allocated); 845592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ Assert(pl, "Property allocation count failed."); 846592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 847592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Scale the number of elements by pointer size and add the header for 848592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // FixedArrays to the start of the next object calculation from above. 849592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r1: constructor 850592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r3: number of elements in properties array 851592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r4: JSObject 852592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r5: start of next object 853592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize)); 854592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ AllocateInNewSpace( 855592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch r0, 856592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch r5, 857592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch r6, 858592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch r2, 859592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch &undo_allocation, 860592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS)); 861592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 862592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Initialize the FixedArray. 863592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r1: constructor 864592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r3: number of elements in properties array 865592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r4: JSObject 866592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r5: FixedArray (not tagged) 867592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex); 868592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(r2, r5); 869592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); 870592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ str(r6, MemOperand(r2, kPointerSize, PostIndex)); 871592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); 872592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(r0, Operand(r3, LSL, kSmiTagSize)); 873592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ str(r0, MemOperand(r2, kPointerSize, PostIndex)); 874592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 875592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Initialize the fields to undefined. 876592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r1: constructor function 877592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r2: First element of FixedArray (not tagged) 878592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r3: number of elements in properties array 879592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r4: JSObject 880592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r5: FixedArray (not tagged) 881592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2)); // End of object. 882592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize); 883592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch { Label loop, entry; 884592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (count_constructions) { 885592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); 886592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else if (FLAG_debug_code) { 887592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); 888592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(r7, r8); 889592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ Assert(eq, "Undefined value not loaded."); 890592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 891592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(&entry); 892592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&loop); 893592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ str(r7, MemOperand(r2, kPointerSize, PostIndex)); 894592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&entry); 895592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(r2, r6); 896592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(lt, &loop); 897592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 899592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Store the initialized FixedArray into the properties field of 900592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // the JSObject 901592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r1: constructor function 902592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r4: JSObject 903592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r5: FixedArray (not tagged) 904592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(r5, r5, Operand(kHeapObjectTag)); // Add the heap tag. 905592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ str(r5, FieldMemOperand(r4, JSObject::kPropertiesOffset)); 906592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 907592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Continue with JSObject being successfully allocated 908592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r1: constructor function 909592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r4: JSObject 910592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ jmp(&allocated); 911592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 912592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Undo the setting of the new top so that the heap is verifiable. For 913592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // example, the map's unused properties potentially do not match the 914592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // allocated objects unused properties. 915592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r4: JSObject (previous new top) 916592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&undo_allocation); 917592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ UndoAllocationInNewSpace(r4, r5); 918592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 920592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Allocate the new receiver object using the runtime call. 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 922592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&rt_call); 923592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r1); // argument for Runtime_NewObject 924592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ CallRuntime(Runtime::kNewObject, 1); 925592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(r4, r0); 926592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 927592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Receiver for constructor call allocated. 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject 929592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&allocated); 930592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r4); 9315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ push(r4); 932592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 9335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Reload the number of arguments and the constructor from the stack. 934592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // sp[0]: receiver 9355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // sp[1]: receiver 9365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // sp[2]: constructor function 9375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // sp[3]: number of arguments (smi-tagged) 9385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); 9395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ ldr(r3, MemOperand(sp, 3 * kPointerSize)); 940592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 941c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Set up pointer to last argument. 942592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); 943592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 944c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Set up number of arguments for function call below 945592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(r0, Operand(r3, LSR, kSmiTagSize)); 946592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 947592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Copy arguments and receiver to the expression stack. 948592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r0: number of arguments 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 9505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // r2: address of last argument (caller sp) 951592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r3: number of arguments (smi-tagged) 952592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // sp[0]: receiver 9535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // sp[1]: receiver 9545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // sp[2]: constructor function 9555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // sp[3]: number of arguments (smi-tagged) 956592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label loop, entry; 957592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(&entry); 958592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&loop); 959592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1)); 960592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(ip); 961592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&entry); 962592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ sub(r3, r3, Operand(2), SetCC); 963592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(ge, &loop); 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 965592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Call the function. 966592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r0: number of arguments 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 968592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (is_api_function) { 969592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 970592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Code> code = 971592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch masm->isolate()->builtins()->HandleApiCallConstruct(); 972592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ParameterCount expected(0); 973592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ InvokeCode(code, expected, expected, 974592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch RelocInfo::CODE_TARGET, CALL_FUNCTION, CALL_AS_METHOD); 975592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else { 976592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ParameterCount actual(r0); 977592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ InvokeFunction(r1, actual, CALL_FUNCTION, 978592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch NullCallWrapper(), CALL_AS_METHOD); 979592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Store offset of return address for deoptimizer. 9825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (!is_api_function && !count_constructions) { 9835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); 9845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 986592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Restore context from the frame. 987592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r0: result 988592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // sp[0]: receiver 989592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // sp[1]: constructor function 990592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // sp[2]: number of arguments (smi-tagged) 991592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 992592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 993592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // If the result is an object (in the ECMA sense), we should get rid 994592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // of the receiver and use the result; see ECMA-262 section 13.2.2-7 995592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // on page 74. 996592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label use_receiver, exit; 997592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 998592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // If the result is a smi, it is *not* an object in the ECMA sense. 999592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r0: result 1000592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // sp[0]: receiver (newly allocated object) 1001592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // sp[1]: constructor function 1002592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // sp[2]: number of arguments (smi-tagged) 1003592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ JumpIfSmi(r0, &use_receiver); 1004592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1005592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // If the type of the result (stored in its map) is less than 1006592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. 1007592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ CompareObjectType(r0, r3, r3, FIRST_SPEC_OBJECT_TYPE); 1008592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(ge, &exit); 1009592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1010592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Throw away the result of the constructor invocation and use the 1011592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // on-stack receiver as the result. 1012592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&use_receiver); 1013592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r0, MemOperand(sp)); 1014592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1015592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Remove receiver from the stack, remove caller arguments, and 1016592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // return. 1017592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&exit); 1018592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r0: result 1019592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // sp[0]: receiver (newly allocated object) 1020592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // sp[1]: constructor function 1021592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // sp[2]: number of arguments (smi-tagged) 1022592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); 1023592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1024592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Leave construct frame. 1025e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(kPointerSize)); 102944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2); 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10340d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { 10350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Generate_JSConstructStubHelper(masm, false, true); 10360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 10370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 10380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 1039e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 10400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Generate_JSConstructStubHelper(masm, false, false); 1041e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1042e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1043e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1044e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 10450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Generate_JSConstructStubHelper(masm, true, false); 1046e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1047e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1048e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_construct) { 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Called from Generate_JS_Entry 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: code entry 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: receiver 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: argc 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: argv 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5-r7, cp may be clobbered 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1059592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Clear the context before we push it when entering the internal frame. 10609ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ mov(cp, Operand(0, RelocInfo::NONE)); 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Enter an internal frame. 1063592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch { 1064592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1066592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Set up the context from the function argument. 1067592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1069c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ InitializeRootRegister(); 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1071592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Push the function and the receiver onto the stack. 1072592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r1); 1073592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r2); 1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1075592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Copy arguments to the stack in a loop. 1076592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r1: function 1077592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r3: argc 1078592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r4: argv, i.e. points to first arg 1079592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label loop, entry; 1080592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2)); 1081592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r2 points past last arg. 1082592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(&entry); 1083592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&loop); 1084592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex)); // read next parameter 1085592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r0, MemOperand(r0)); // dereference handle 1086592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r0); // push parameter 1087592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&entry); 1088592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(r4, r2); 1089592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(ne, &loop); 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1091592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Initialize all JavaScript callee-saved registers, since they will be seen 1092592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // by the garbage collector as part of handlers. 1093592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); 1094592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(r5, Operand(r4)); 1095592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(r6, Operand(r4)); 1096592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(r7, Operand(r4)); 1097592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (kR9Available == 1) { 1098592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(r9, Operand(r4)); 1099592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1101592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Invoke the code and pass argc as r0. 1102592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(r0, Operand(r3)); 1103592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (is_construct) { 11045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); 11055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ CallStub(&stub); 1106592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else { 1107592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ParameterCount actual(r0); 1108592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ InvokeFunction(r1, actual, CALL_FUNCTION, 1109592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch NullCallWrapper(), CALL_AS_METHOD); 1110592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 1111592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Exit the JS frame and remove the parameters (except function), and 1112592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // return. 1113592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Respect ABI stack constraint. 1114592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: result 1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { 1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Generate_JSEntryTrampolineHelper(masm, false); 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { 1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Generate_JSEntryTrampolineHelper(masm, true); 1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1131756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid Builtins::Generate_LazyCompile(MacroAssembler* masm) { 1132756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Enter an internal frame. 1133592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch { 1134592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 1135756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 1136592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Preserve the function. 1137592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r1); 1138592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Push call kind information. 1139592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r5); 1140756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 1141592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Push the function on the stack as the argument to the runtime function. 1142592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r1); 1143592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ CallRuntime(Runtime::kLazyCompile, 1); 1144592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Calculate the entry point. 1145592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); 1146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1147592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Restore call kind information. 1148592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ pop(r5); 1149592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Restore saved function. 1150592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ pop(r1); 1151756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 1152592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Tear down internal frame. 1153592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 1154756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 1155756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Do a tail-call of the compiled function. 1156756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ Jump(r2); 1157756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 1158756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 1159756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 1160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_LazyRecompile(MacroAssembler* masm) { 1161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Enter an internal frame. 1162592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch { 1163592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 1164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1165592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Preserve the function. 1166592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r1); 1167592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Push call kind information. 1168592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r5); 1169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1170592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Push the function on the stack as the argument to the runtime function. 1171592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r1); 1172592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ CallRuntime(Runtime::kLazyRecompile, 1); 1173592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Calculate the entry point. 1174592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); 1175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1176592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Restore call kind information. 1177592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ pop(r5); 1178592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Restore saved function. 1179592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ pop(r1); 1180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1181592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Tear down internal frame. 1182592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 1183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Do a tail-call of the compiled function. 1185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ Jump(r2); 1186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm, 1190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Deoptimizer::BailoutType type) { 1191592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch { 1192592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 1193592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Pass the function and deoptimization type to the runtime system. 1194592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(r0, Operand(Smi::FromInt(static_cast<int>(type)))); 1195592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r0); 1196592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ CallRuntime(Runtime::kNotifyDeoptimized, 1); 1197592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 1198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Get the full codegen state from the stack and untag it -> r6. 1200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r6, MemOperand(sp, 0 * kPointerSize)); 1201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ SmiUntag(r6); 1202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Switch on the state. 1203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label with_tos_register, unknown_state; 1204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(r6, Operand(FullCodeGenerator::NO_REGISTERS)); 1205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ b(ne, &with_tos_register); 1206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(sp, sp, Operand(1 * kPointerSize)); // Remove state. 1207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ Ret(); 1208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&with_tos_register); 1210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); 1211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(r6, Operand(FullCodeGenerator::TOS_REG)); 1212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ b(ne, &unknown_state); 1213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(sp, sp, Operand(2 * kPointerSize)); // Remove state. 1214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ Ret(); 1215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&unknown_state); 1217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ stop("no cases left"); 1218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) { 1222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); 1223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) { 1227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); 1228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_NotifyOSR(MacroAssembler* masm) { 12321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For now, we are relying on the fact that Runtime::NotifyOSR 12331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // doesn't do any garbage collection which allows us to save/restore 12341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the registers without worrying about which of them contain 12351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // pointers. This seems a bit fragile. 12361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ stm(db_w, sp, kJSCallerSaved | kCalleeSaved | lr.bit() | fp.bit()); 1237592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch { 1238592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 1239592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ CallRuntime(Runtime::kNotifyOSR, 0); 1240592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 12411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldm(ia_w, sp, kJSCallerSaved | kCalleeSaved | lr.bit() | fp.bit()); 12421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 1243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { 12478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CpuFeatures::TryForceFeatureScope scope(VFP3); 12488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (!CpuFeatures::IsSupported(VFP3)) { 12498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ Abort("Unreachable code: Cannot optimize without VFP3 support."); 12508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return; 12518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 12521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Lookup the function in the JavaScript frame and push it as an 12541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // argument to the on-stack replacement function. 12551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 1256592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch { 1257592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 1258592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r0); 1259592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1); 1260592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 12611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // If the result was -1 it means that we couldn't optimize the 12631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // function. Just return and continue in the unoptimized version. 12641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label skip; 12651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(r0, Operand(Smi::FromInt(-1))); 12661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(ne, &skip); 12671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 12681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&skip); 12701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Untag the AST id and push it on the stack. 12711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiUntag(r0); 12721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(r0); 12731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Generate the code for doing the frame-to-frame translation using 12751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the deoptimizer infrastructure. 12761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); 12771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block generator.Generate(); 1278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_FunctionCall(MacroAssembler* masm) { 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 1. Make sure we have at least one argument. 1283402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r0: actual number of arguments 1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { Label done; 12855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ cmp(r0, Operand(0)); 1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &done); 1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r2); 1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, r0, Operand(1)); 1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&done); 1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1293402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // 2. Get the function to call (passed as receiver) from the stack, check 1294402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // if it is a function. 1295402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r0: actual number of arguments 1296589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label slow, non_function; 1297402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); 12983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r1, &non_function); 1299402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); 1300589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ b(ne, &slow); 1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1302402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // 3a. Patch the first argument if necessary when calling a function. 1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments 1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1305402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label shift_arguments; 1306589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r4, Operand(0, RelocInfo::NONE)); // indicate regular JS_FUNCTION 1307402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu { Label convert_to_object, use_global_receiver, patch_receiver; 1308402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Change context eagerly in case we need the global receiver. 1309402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 1310402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Do not transform the receiver for strict mode functions. 1312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 1313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(r3, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset)); 1314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ tst(r3, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + 1315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kSmiTagSize))); 1316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ b(ne, &shift_arguments); 1317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Do not transform the receiver for native (Compilerhints already in r3). 13193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ tst(r3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); 1320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, &shift_arguments); 1321e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1322e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Compute the receiver in non-strict mode. 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(r2, -kPointerSize)); 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments 1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: first argument 13283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r2, &convert_to_object); 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, r3); 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &use_global_receiver); 1333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(r3, Heap::kNullValueRootIndex); 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, r3); 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &use_global_receiver); 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 13383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CompareObjectType(r2, r3, r3, FIRST_SPEC_OBJECT_TYPE); 1339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ b(ge, &shift_arguments); 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1341402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(&convert_to_object); 1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1343592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch { 1344592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Enter an internal frame in order to preserve argument count. 1345592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 1346592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(r0, Operand(r0, LSL, kSmiTagSize)); // Smi-tagged. 1347592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r0); 1348592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1349592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r2); 1350592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 1351592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(r2, r0); 1352592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1353592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ pop(r0); 1354592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(r0, Operand(r0, ASR, kSmiTagSize)); 1355592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1356592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Exit the internal frame. 1357592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1359589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Restore the function to r1, and the flag to r4. 1360402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); 1361589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r4, Operand(0, RelocInfo::NONE)); 1362402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ jmp(&patch_receiver); 1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1364402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Use the global receiver object from the called function as the 1365402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // receiver. 1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&use_global_receiver); 1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kGlobalIndex = 1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(cp, kGlobalIndex)); 1370d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalContextOffset)); 1371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r2, FieldMemOperand(r2, kGlobalIndex)); 1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset)); 1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&patch_receiver); 1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2)); 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r3, -kPointerSize)); 1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1378402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ jmp(&shift_arguments); 1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1381589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // 3b. Check for function proxy. 1382589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&slow); 1383589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r4, Operand(1, RelocInfo::NONE)); // indicate function proxy 1384589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ cmp(r2, Operand(JS_FUNCTION_PROXY_TYPE)); 1385589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ b(eq, &shift_arguments); 1386589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&non_function); 1387589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ mov(r4, Operand(2, RelocInfo::NONE)); // indicate non-function 1388589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1389589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // 3c. Patch the first argument when calling a non-function. The 1390402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // CALL_NON_FUNCTION builtin expects the non-function callee as 1391402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // receiver, so overwrite the first argument which will ultimately 1392402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // become the receiver. 1393402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r0: actual number of arguments 1394402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r1: function 1395589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // r4: call type (0: JS function, 1: function proxy, 2: non-function) 1396402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); 1397402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ str(r1, MemOperand(r2, -kPointerSize)); 1398402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1399402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // 4. Shift arguments and return address one slot down on the stack 1400402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // (overwriting the original receiver). Adjust argument count to make 1401402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // the original first argument the new receiver. 1402402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r0: actual number of arguments 1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1404589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // r4: call type (0: JS function, 1: function proxy, 2: non-function) 1405402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(&shift_arguments); 1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { Label loop; 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the copy start address (destination). Copy end address is sp. 1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); 1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(ip, MemOperand(r2, -kPointerSize)); 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(ip, MemOperand(r2)); 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r2, r2, Operand(kPointerSize)); 1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, sp); 1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &loop); 1416402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Adjust the actual number of arguments and remove the top element 1417402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // (which is a copy of the last argument). 1418402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ sub(r0, r0, Operand(1)); 1419402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(); 1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1422589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin, 1423589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // or a function proxy via CALL_FUNCTION_PROXY. 1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments 1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1426589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // r4: call type (0: JS function, 1: function proxy, 2: non-function) 1427589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch { Label function, non_proxy; 1428589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ tst(r4, r4); 1429589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ b(eq, &function); 14309ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick // Expected number of arguments is 0 for CALL_NON_FUNCTION. 14319ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ mov(r2, Operand(0, RelocInfo::NONE)); 1432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SetCallKind(r5, CALL_AS_METHOD); 1433589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ cmp(r4, Operand(1)); 1434589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ b(ne, &non_proxy); 1435589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1436589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ push(r1); // re-add proxy object as additional argument 1437589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ add(r0, r0, Operand(1)); 1438589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY); 1439589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 1440589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch RelocInfo::CODE_TARGET); 1441589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1442589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&non_proxy); 1443589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); 144444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 144544f0eee88ff00398ff7f715fab053374d808c90dSteve Block RelocInfo::CODE_TARGET); 1446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(&function); 1447402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // 5b. Get the code to call from the function and check that the number of 1450402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // expected arguments matches what we're providing. If so, jump 1451402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // (tail-call) to the code in register edx without checking arguments. 1452402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r0: actual number of arguments 1453402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r1: function 1454402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 1455402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r2, 1456402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset)); 14577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(r2, Operand(r2, ASR, kSmiTagSize)); 1458791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); 1459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SetCallKind(r5, CALL_AS_METHOD); 1460402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(r2, r0); // Check formal and actual parameter counts. 146144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 146244f0eee88ff00398ff7f715fab053374d808c90dSteve Block RelocInfo::CODE_TARGET, 146344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ne); 1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1465402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ParameterCount expected(0); 1466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeCode(r3, expected, expected, JUMP_FUNCTION, 1467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), CALL_AS_METHOD); 1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_FunctionApply(MacroAssembler* masm) { 1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kIndexOffset = -5 * kPointerSize; 1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kLimitOffset = -4 * kPointerSize; 1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kArgsOffset = 2 * kPointerSize; 1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kRecvOffset = 3 * kPointerSize; 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kFunctionOffset = 4 * kPointerSize; 1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1478592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch { 1479592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch FrameScope frame_scope(masm, StackFrame::INTERNAL); 1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1481592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function 1482592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r0); 1483592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r0, MemOperand(fp, kArgsOffset)); // get the args array 1484592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r0); 1485592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); 1486592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1487592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Check the stack for overflow. We are not trying to catch 1488592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // interruptions (e.g. debug break and preemption) here, so the "real stack 1489592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // limit" is checked. 1490592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label okay; 1491592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); 1492592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Make r2 the space we have left. The stack might already be overflowed 1493592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // here which will cause r2 to become negative. 1494592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ sub(r2, sp, r2); 1495592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Check if the arguments will overflow the stack. 1496592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 1497592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(gt, &okay); // Signed comparison. 1498592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1499592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Out of stack space. 1500592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r1, MemOperand(fp, kFunctionOffset)); 1501592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r1); 1502592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r0); 1503592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION); 1504592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // End of stack check. 1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1506592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Push current limit and index. 1507592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&okay); 1508592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r0); // limit 1509592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(r1, Operand(0, RelocInfo::NONE)); // initial index 1510592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r1); 1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1512592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Get the receiver. 1513592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r0, MemOperand(fp, kRecvOffset)); 1514589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1515592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Check that the function is a JS function (otherwise it must be a proxy). 1516592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label push_receiver; 1517592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r1, MemOperand(fp, kFunctionOffset)); 1518592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); 1519592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(ne, &push_receiver); 1520589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1521592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Change context eagerly to get the right global object if necessary. 1522592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 1523592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Load the shared function info while the function is still in r1. 1524592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1526592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Compute the receiver. 1527592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Do not transform the receiver for strict mode functions. 1528592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label call_to_object, use_global_receiver; 1529592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset)); 1530592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ tst(r2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + 1531592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch kSmiTagSize))); 1532592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(ne, &push_receiver); 1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1534592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Do not transform the receiver for strict mode functions. 1535592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ tst(r2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); 1536592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(ne, &push_receiver); 1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1538592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Compute the receiver in non-strict mode. 1539592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ JumpIfSmi(r0, &call_to_object); 1540592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ LoadRoot(r1, Heap::kNullValueRootIndex); 1541592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(r0, r1); 1542592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(eq, &use_global_receiver); 1543592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); 1544592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(r0, r1); 1545592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(eq, &use_global_receiver); 1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1547592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Check if the receiver is already a JavaScript object. 1548592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r0: receiver 1549592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 1550592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); 1551592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(ge, &push_receiver); 1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1553592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Convert the receiver to a regular object. 1554592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r0: receiver 1555592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&call_to_object); 1556592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r0); 1557592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 1558592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(&push_receiver); 1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1560592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Use the current global receiver object as the receiver. 1561592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&use_global_receiver); 1562592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch const int kGlobalOffset = 1563592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 1564592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r0, FieldMemOperand(cp, kGlobalOffset)); 1565592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset)); 1566592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r0, FieldMemOperand(r0, kGlobalOffset)); 1567592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); 1568592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1569592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Push the receiver. 1570592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r0: receiver 1571592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&push_receiver); 1572592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r0); 1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1574592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Copy all arguments from the array to the stack. 1575592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label entry, loop; 1576592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r0, MemOperand(fp, kIndexOffset)); 1577592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(&entry); 1578589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1579592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Load the current argument from the arguments array and push it to the 1580592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // stack. 1581592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // r0: current argument index 1582592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&loop); 1583592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r1, MemOperand(fp, kArgsOffset)); 1584592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r1); 1585592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r0); 1586592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1587592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Call the runtime to access the property in the arguments array. 1588592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ CallRuntime(Runtime::kGetProperty, 2); 1589592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r0); 1590589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1591592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Use inline caching to access the arguments. 1592592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r0, MemOperand(fp, kIndexOffset)); 1593592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(r0, r0, Operand(1 << kSmiTagSize)); 1594592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ str(r0, MemOperand(fp, kIndexOffset)); 1595592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1596592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Test if the copy loop has finished copying all the elements from the 1597592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // arguments object. 1598592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&entry); 1599592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r1, MemOperand(fp, kLimitOffset)); 1600592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ cmp(r0, r1); 1601592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(ne, &loop); 1602592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1603592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Invoke the function. 1604592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Label call_proxy; 1605592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ParameterCount actual(r0); 1606592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(r0, Operand(r0, ASR, kSmiTagSize)); 1607592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ ldr(r1, MemOperand(fp, kFunctionOffset)); 1608592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); 1609592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ b(ne, &call_proxy); 1610592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ InvokeFunction(r1, actual, CALL_FUNCTION, 1611592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch NullCallWrapper(), CALL_AS_METHOD); 1612592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1613592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch frame_scope.GenerateLeaveFrame(); 1614592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(sp, sp, Operand(3 * kPointerSize)); 1615592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ Jump(lr); 1616592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1617592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Invoke the function proxy. 1618592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ bind(&call_proxy); 1619592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ push(r1); // add function proxy as last argument 1620592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ add(r0, r0, Operand(1)); 1621592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ mov(r2, Operand(0, RelocInfo::NONE)); 1622592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ SetCallKind(r5, CALL_AS_METHOD); 1623592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY); 1624592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 1625592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch RelocInfo::CODE_TARGET); 1626592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1627592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Tear down the internal frame and remove function, receiver and args. 1628592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 1629589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ add(sp, sp, Operand(3 * kPointerSize)); 1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { 1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(r0, LSL, kSmiTagSize)); 1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() | fp.bit() | lr.bit()); 1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(fp, sp, Operand(3 * kPointerSize)); 1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { 1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : result being passed through 1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the number of arguments passed (as a smi), tear down the frame and 1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // then tear down the parameters. 1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(fp, -3 * kPointerSize)); 1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(sp, fp); 1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldm(ia_w, sp, fp.bit() | lr.bit()); 1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize)); 1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(kPointerSize)); // adjust for receiver 1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { 1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : actual number of arguments 1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r1 : function (passed through to callee) 1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : expected number of arguments 1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r3 : code entry to call 1662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- r5 : call kind information 1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label invoke, dont_adapt_arguments; 1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label enough, too_few; 16686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(r0, r2); 1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(lt, &too_few); 1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel)); 1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &dont_adapt_arguments); 1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { // Enough parameters: actual >= expected 1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&enough); 1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EnterArgumentsAdaptorFrame(masm); 1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate copy start address into r0 and copy end address into r2. 1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments as a smi 1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: expected number of arguments 1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: code entry to call 1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // adjust for return address and receiver 1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, r0, Operand(2 * kPointerSize)); 1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r2, r0, Operand(r2, LSL, kPointerSizeLog2)); 1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy the arguments (including the receiver) to the new stack frame. 1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: copy start address 1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: copy end address 1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: code entry to call 1692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label copy; 1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(©); 1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(ip, MemOperand(r0, 0)); 1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ip); 1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, r2); // Compare before moving to next argument. 1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r0, r0, Operand(kPointerSize)); 1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, ©); 1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&invoke); 1702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { // Too few parameters: Actual < expected 1705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&too_few); 1706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EnterArgumentsAdaptorFrame(masm); 1707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate copy start address into r0 and copy end address is fp. 1709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments as a smi 1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: expected number of arguments 1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: code entry to call 1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 1714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy the arguments (including the receiver) to the new stack frame. 1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: copy start address 1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: expected number of arguments 1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: code entry to call 1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label copy; 1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(©); 1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust load for return address and receiver. 1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(ip, MemOperand(r0, 2 * kPointerSize)); 1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ip); 1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, fp); // Compare before moving to next argument. 1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r0, r0, Operand(kPointerSize)); 1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, ©); 1728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the remaining expected arguments with undefined. 1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: expected number of arguments 1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: code entry to call 1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r2, fp, Operand(r2, LSL, kPointerSizeLog2)); 1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r2, r2, Operand(4 * kPointerSize)); // Adjust for frame. 1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fill; 1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fill); 1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ip); 1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(sp, r2); 1741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &fill); 1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call the entry point. 1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&invoke); 1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Call(r3); 1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Store offset of return address for deoptimizer. 1749c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset()); 17505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit frame and return. 1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LeaveArgumentsAdaptorFrame(masm); 1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 1754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ------------------------------------------- 1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Dont adapt arguments. 1758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ------------------------------------------- 1759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&dont_adapt_arguments); 1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(r3); 1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 1767f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_ARM 1769