13ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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 753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Load the built-in InternalArray function from the current context. 763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateLoadInternalArrayFunction(MacroAssembler* masm, 773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register result) { 783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the global context. 793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(result, 823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(result, GlobalObject::kGlobalContextOffset)); 833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the InternalArray function from the global context. 843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(result, 853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MemOperand(result, 863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Context::SlotOffset( 873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Context::INTERNAL_ARRAY_FUNCTION_INDEX))); 883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 903ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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) { 1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const int initial_capacity = JSArray::kPreallocatedArrayElements; 1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(initial_capacity >= 0); 1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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. 1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int size = JSArray::kSize; 1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (initial_capacity > 0) { 1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size += FixedArray::SizeFor(initial_capacity); 1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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 1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (initial_capacity == 0) { 1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(scratch1, FieldMemOperand(result, JSArray::kElementsOffset)); 1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return; 1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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); 1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(0 * kPointerSize == FixedArray::kMapOffset); 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); 1677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(scratch3, Operand(Smi::FromInt(initial_capacity))); 1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(1 * kPointerSize == FixedArray::kLengthOffset); 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Fill the FixedArray with the hole value. Inline the code if short. 1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(2 * kPointerSize == FixedArray::kHeaderSize); 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex); 1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kLoopUnfoldLimit = 4; 1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (initial_capacity <= kLoopUnfoldLimit) { 1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < initial_capacity; i++) { 1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); 1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label loop, entry; 1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(scratch2, scratch1, Operand(initial_capacity * kPointerSize)); 1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(&entry); 1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&loop); 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); 1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&entry); 1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(scratch1, scratch2); 1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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. 2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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) { 21085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Load the initial map from the array function. 2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadInitialArrayMap(array_function, scratch2, elements_array_storage); 2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { // Assert that array size is not zero. 2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ tst(array_size, array_size); 2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(ne, "array size is unexpectedly 0"); 2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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(); 3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label argc_one_or_more, argc_two_or_more, not_empty_array, empty_array, 3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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. 3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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); 3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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. 3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ tst(r2, r2); 3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, ¬_empty_array); 3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Drop(1); // Adjust stack. 3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r0, Operand(0)); // Treat this as a call with argc of zero. 3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(&empty_array); 3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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); 3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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; 4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r7, sp); 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&entry); 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r2, MemOperand(r7, kPointerSize, PostIndex)); 4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_smi_only_arrays) { 4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(r2, &has_non_smi_element); 4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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 4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&finish); 4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(sp, r7); 4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 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); 4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&has_non_smi_element); 4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Double values are handled by the runtime. 4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap( 4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r2, r9, Heap::kHeapNumberMapRootIndex, ¬_double, DONT_DO_SMI_CHECK); 4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&cant_transition_map); 4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ UndoAllocationInNewSpace(r3, r4); 4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(call_generic_code); 4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(¬_double); 4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Transition FAST_SMI_ONLY_ELEMENTS to FAST_ELEMENTS. 4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r3: JSArray 4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset)); 4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS, 4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FAST_ELEMENTS, 4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r2, 4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r9, 4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &cant_transition_map); 4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r2, FieldMemOperand(r3, HeapObject::kMapOffset)); 4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(r3, 4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HeapObject::kMapOffset, 4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r2, 4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r9, 4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kLRHasNotBeenSaved, 4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label loop2; 4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(r7, r7, Operand(kPointerSize)); 4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&loop2); 4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r2, MemOperand(r7, kPointerSize, PostIndex)); 4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r2, MemOperand(r5, -kPointerSize, PreIndex)); 4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r4, r5); 4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(lt, &loop2); 4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(&finish); 4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { 4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ----------- S t a t e ------------- 4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- r0 : number of arguments 4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- lr : return address 4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- sp[...]: constructor arguments 4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ----------------------------------- 4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label generic_array_code, one_or_more_arguments, two_or_more_arguments; 4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the InternalArray function. 4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadInternalArrayFunction(masm, r1); 4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initial map for the builtin InternalArray functions should be maps. 4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ tst(r2, Operand(kSmiTagMask)); 4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(ne, "Unexpected initial map for InternalArray function"); 4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareObjectType(r2, r3, r4, MAP_TYPE); 4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(eq, "Unexpected initial map for InternalArray function"); 4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Run the native code for the InternalArray function called as a normal 4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // function. 4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ArrayNativeCode(masm, &generic_array_code); 4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Jump to the generic array code if the specialized code cannot handle the 4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // construction. 4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&generic_array_code); 4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> array_code = 5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->builtins()->InternalArrayCodeGeneric(); 5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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); 6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 6713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 6723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 6733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION); 6743ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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); 6903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 6913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 6923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(argument); 6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kNewStringWrapper, 1); 6943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 6958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 69680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 69780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 69880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 6993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void Generate_JSConstructStubHelper(MacroAssembler* masm, 7003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_api_function, 7013ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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. 7153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 7163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::CONSTRUCT); 7173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Preserve the two incoming parameters on the stack. 7193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r0, Operand(r0, LSL, kSmiTagSize)); 7203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); // Smi-tagged arguments count. 7213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r1); // Constructor function. 7223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Try to allocate the object without transitioning into C code. If any of 7243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the preconditions is not met, the code bails out to the runtime call. 7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label rt_call, allocated; 7263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_inline_new) { 7273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label undo_allocation; 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 7293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference debug_step_in_fp = 7303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::debug_step_in_fp_address(isolate); 7313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r2, Operand(debug_step_in_fp)); 7323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r2, MemOperand(r2)); 7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ tst(r2, r2); 7343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &rt_call); 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the initial map and verify that it is in fact a map. 7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor function 7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 7403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(r2, &rt_call); 7413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareObjectType(r2, r3, r4, MAP_TYPE); 7423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &rt_call); 7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that the constructor is not constructing a JSFunction (see 7453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // comments in Runtime_NewObject in runtime.cc). In which case the 7463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // initial map's instance type would be JS_FUNCTION_TYPE. 7473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor function 7483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r2: initial map 7493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); 7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, &rt_call); 75185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 7523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (count_constructions) { 7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label allocate; 7543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Decrease generous allocation count. 7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 7563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MemOperand constructor_count = 7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(r3, SharedFunctionInfo::kConstructionCountOffset); 7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldrb(r4, constructor_count); 7593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(r4, r4, Operand(1), SetCC); 7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ strb(r4, constructor_count); 7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &allocate); 7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(r1, r2); 7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r1); // constructor 7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The call will replace the stub, so the countdown is only done once. 7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); 7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(r2); 7703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(r1); 7713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&allocate); 7733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Now allocate the JSObject on the heap. 7763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor function 7773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r2: initial map 7783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset)); 7793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS); 7803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocated the JSObject, now initialize the fields. Map is set to 7823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // initial map and properties and elements are set to empty fixed array. 7833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor function 7843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r2: initial map 7853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r3: object size 7863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r4: JSObject (not tagged) 7873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); 7883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r5, r4); 7893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); 7903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); 7913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset); 7923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset); 7943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 7953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Fill all the in-object properties with the appropriate filler. 7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor function 7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r2: initial map 7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r3: object size (in words) 8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r4: JSObject (not tagged) 8013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r5: First in-object property of JSObject (not tagged) 8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object. 8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize); 8043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); 8050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (count_constructions) { 8063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset)); 8073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ubfx(r0, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte, 8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kBitsPerByte); 8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r0, r5, Operand(r0, LSL, kPointerSizeLog2)); 8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r0: offset of first field after pre-allocated fields 8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, r6); 8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(le, "Unexpected number of pre-allocated property fields."); 8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InitializeFieldsWithFiller(r5, r0, r7); 8160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // To allow for truncation. 8170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(r7, Heap::kOnePointerFillerMapRootIndex); 8180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InitializeFieldsWithFiller(r5, r6, r7); 8203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Add the object tag to make the JSObject real, so that we can continue 8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // and jump into the continuation code at any time from now on. Any 8233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // failures need to undo the allocation, so that the heap is in a 8243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // consistent state and verifiable. 8253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r4, r4, Operand(kHeapObjectTag)); 8263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if a non-empty properties array is needed. Continue with 8283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allocated object if not fall through to runtime call if it is. 8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor function 8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r4: JSObject 8313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r5: start of next object (not tagged) 8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset)); 8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The field instance sizes contains both pre-allocated property fields 8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // and in-object properties. 8353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset)); 8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ubfx(r6, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte, 8373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kBitsPerByte); 8383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r3, r3, Operand(r6)); 8393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ubfx(r6, r0, Map::kInObjectPropertiesByte * kBitsPerByte, 8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kBitsPerByte); 8413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(r3, r3, Operand(r6), SetCC); 8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Done if no extra properties are to be allocated. 8443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, &allocated); 8453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(pl, "Property allocation count failed."); 8463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Scale the number of elements by pointer size and add the header for 8483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // FixedArrays to the start of the next object calculation from above. 8493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor 8503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r3: number of elements in properties array 8513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r4: JSObject 8523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r5: start of next object 8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize)); 8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace( 8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r0, 8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r5, 8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r6, 8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r2, 8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &undo_allocation, 8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS)); 8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initialize the FixedArray. 8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor 8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r3: number of elements in properties array 8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r4: JSObject 8663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r5: FixedArray (not tagged) 8673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex); 8683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r2, r5); 8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); 8703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r6, MemOperand(r2, kPointerSize, PostIndex)); 8713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); 8723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r0, Operand(r3, LSL, kSmiTagSize)); 8733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r0, MemOperand(r2, kPointerSize, PostIndex)); 8743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initialize the fields to undefined. 8763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor function 8773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r2: First element of FixedArray (not tagged) 8783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r3: number of elements in properties array 8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r4: JSObject 8803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r5: FixedArray (not tagged) 8813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2)); // End of object. 8823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize); 8833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { Label loop, entry; 8843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (count_constructions) { 8853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); 8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (FLAG_debug_code) { 8873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); 8883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r7, r8); 8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(eq, "Undefined value not loaded."); 8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(&entry); 8923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&loop); 8933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r7, MemOperand(r2, kPointerSize, PostIndex)); 8943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&entry); 8953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r2, r6); 8963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(lt, &loop); 89785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } 8983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the initialized FixedArray into the properties field of 9003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the JSObject 9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor function 9023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r4: JSObject 9033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r5: FixedArray (not tagged) 9043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r5, r5, Operand(kHeapObjectTag)); // Add the heap tag. 9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r5, FieldMemOperand(r4, JSObject::kPropertiesOffset)); 9063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Continue with JSObject being successfully allocated 9083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor function 9093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r4: JSObject 9103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&allocated); 9113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Undo the setting of the new top so that the heap is verifiable. For 9133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // example, the map's unused properties potentially do not match the 9143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allocated objects unused properties. 9153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r4: JSObject (previous new top) 9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&undo_allocation); 9173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ UndoAllocationInNewSpace(r4, r5); 91885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate the new receiver object using the runtime call. 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 9223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&rt_call); 9233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r1); // argument for Runtime_NewObject 9243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kNewObject, 1); 9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r4, r0); 9263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Receiver for constructor call allocated. 92885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // r4: JSObject 9293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&allocated); 9303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r4); 9313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r4); 9323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Reload the number of arguments and the constructor from the stack. 9343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[0]: receiver 9353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[1]: receiver 9363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[2]: constructor function 9373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[3]: number of arguments (smi-tagged) 9383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); 9393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r3, MemOperand(sp, 3 * kPointerSize)); 9403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up pointer to last argument. 9423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); 9433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up number of arguments for function call below 9453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r0, Operand(r3, LSR, kSmiTagSize)); 9463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Copy arguments and receiver to the expression stack. 9483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r0: number of arguments 9493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor function 9503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r2: address of last argument (caller sp) 9513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r3: number of arguments (smi-tagged) 9523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[0]: receiver 9533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[1]: receiver 9543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[2]: constructor function 9553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[3]: number of arguments (smi-tagged) 9563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label loop, entry; 9573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(&entry); 9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&loop); 9593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1)); 9603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(ip); 9613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&entry); 9623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(r3, r3, Operand(2), SetCC); 9633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ge, &loop); 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Call the function. 9663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r0: number of arguments 96785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // r1: constructor function 9683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_api_function) { 9693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 9703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = 9713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->builtins()->HandleApiCallConstruct(); 9723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ParameterCount expected(0); 9733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeCode(code, expected, expected, 9743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RelocInfo::CODE_TARGET, CALL_FUNCTION, CALL_AS_METHOD); 9753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 9763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ParameterCount actual(r0); 9773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeFunction(r1, actual, CALL_FUNCTION, 9783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NullCallWrapper(), CALL_AS_METHOD); 9793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store offset of return address for deoptimizer. 9823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!is_api_function && !count_constructions) { 9833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); 9843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 98585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 9863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore context from the frame. 9873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r0: result 9883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[0]: receiver 9893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[1]: constructor function 9903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[2]: number of arguments (smi-tagged) 9913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 9923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the result is an object (in the ECMA sense), we should get rid 9943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // of the receiver and use the result; see ECMA-262 section 13.2.2-7 9953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // on page 74. 9963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label use_receiver, exit; 9973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the result is a smi, it is *not* an object in the ECMA sense. 9993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r0: result 10003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[0]: receiver (newly allocated object) 10013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[1]: constructor function 10023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[2]: number of arguments (smi-tagged) 10033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(r0, &use_receiver); 10043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 10053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the type of the result (stored in its map) is less than 10063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. 10073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareObjectType(r0, r3, r3, FIRST_SPEC_OBJECT_TYPE); 10083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ge, &exit); 10093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 10103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Throw away the result of the constructor invocation and use the 10113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // on-stack receiver as the result. 10123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&use_receiver); 10133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, MemOperand(sp)); 10143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 10153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Remove receiver from the stack, remove caller arguments, and 10163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // return. 10173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&exit); 10183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r0: result 10193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[0]: receiver (newly allocated object) 10203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[1]: constructor function 10213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[2]: number of arguments (smi-tagged) 10223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); 10233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 10243ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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 10593ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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. 10633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 10643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the context from the function argument. 10673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InitializeRootRegister(); 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push the function and the receiver onto the stack. 10723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r1); 10733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r2); 1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Copy arguments to the stack in a loop. 10763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: function 10773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r3: argc 10783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r4: argv, i.e. points to first arg 10793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label loop, entry; 10803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2)); 10813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r2 points past last arg. 10823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(&entry); 10833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&loop); 10843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex)); // read next parameter 10853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, MemOperand(r0)); // dereference handle 10863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); // push parameter 10873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&entry); 10883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r4, r2); 10893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &loop); 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initialize all JavaScript callee-saved registers, since they will be seen 10923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // by the garbage collector as part of handlers. 10933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); 10943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r5, Operand(r4)); 10953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r6, Operand(r4)); 10963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r7, Operand(r4)); 10973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (kR9Available == 1) { 10983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r9, Operand(r4)); 10993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 110085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 11013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Invoke the code and pass argc as r0. 11023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r0, Operand(r3)); 11033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_construct) { 11043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); 11053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 11063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 11073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ParameterCount actual(r0); 11083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeFunction(r1, actual, CALL_FUNCTION, 11093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NullCallWrapper(), CALL_AS_METHOD); 11103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 11113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Exit the JS frame and remove the parameters (except function), and 11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // return. 11133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Respect ABI stack constraint. 11143ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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. 11333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 11343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 1135756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 11363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Preserve the function. 11373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r1); 11383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push call kind information. 11393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r5); 1140756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push the function on the stack as the argument to the runtime function. 11423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r1); 11433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kLazyCompile, 1); 11443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calculate the entry point. 11453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); 1146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 11473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore call kind information. 11483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(r5); 11493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore saved function. 11503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(r1); 1151756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 11523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Tear down internal frame. 11533ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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. 11623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 11633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 1164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 11653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Preserve the function. 11663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r1); 11673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push call kind information. 11683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r5); 1169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 11703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push the function on the stack as the argument to the runtime function. 11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r1); 11723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kLazyRecompile, 1); 11733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calculate the entry point. 11743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); 1175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 11763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore call kind information. 11773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(r5); 11783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore saved function. 11793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(r1); 1180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 11813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Tear down internal frame. 11823ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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) { 11913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 11923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 11933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Pass the function and deoptimization type to the runtime system. 11943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r0, Operand(Smi::FromInt(static_cast<int>(type)))); 11953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 11963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kNotifyDeoptimized, 1); 11973ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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()); 12373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 12383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 12393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kNotifyOSR, 0); 12403ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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)); 12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 12573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 12583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1); 12603ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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; 12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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 13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 13443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Enter an internal frame in order to preserve argument count. 13453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 13463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r0, Operand(r0, LSL, kSmiTagSize)); // Smi-tagged. 13473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 13483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r2); 13503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 13513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r2, r0); 13523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(r0); 13543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r0, Operand(r0, ASR, kSmiTagSize)); 13553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Exit the internal frame. 13573ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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 14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope frame_scope(masm, StackFrame::INTERNAL); 1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function 14823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, MemOperand(fp, kArgsOffset)); // get the args array 14843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 14853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); 14863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check the stack for overflow. We are not trying to catch 14883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // interruptions (e.g. debug break and preemption) here, so the "real stack 14893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // limit" is checked. 14903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label okay; 14913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); 14923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make r2 the space we have left. The stack might already be overflowed 14933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // here which will cause r2 to become negative. 14943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(r2, sp, r2); 14953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the arguments will overflow the stack. 14963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 14973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(gt, &okay); // Signed comparison. 14983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Out of stack space. 15003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, MemOperand(fp, kFunctionOffset)); 15013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r1); 15023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 15033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION); 15043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // End of stack check. 1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push current limit and index. 15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&okay); 15083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); // limit 15093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r1, Operand(0, RelocInfo::NONE)); // initial index 15103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r1); 1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the receiver. 15133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, MemOperand(fp, kRecvOffset)); 1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that the function is a JS function (otherwise it must be a proxy). 15163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label push_receiver; 15173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, MemOperand(fp, kFunctionOffset)); 15183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); 15193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &push_receiver); 1520589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 15213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Change context eagerly to get the right global object if necessary. 15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the shared function info while the function is still in r1. 15243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 1525592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Compute the receiver. 15273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Do not transform the receiver for strict mode functions. 15283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label call_to_object, use_global_receiver; 15293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset)); 15303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ tst(r2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + 15313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kSmiTagSize))); 15323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &push_receiver); 1533589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 15343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Do not transform the receiver for strict mode functions. 15353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ tst(r2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); 15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &push_receiver); 1537592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Compute the receiver in non-strict mode. 15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(r0, &call_to_object); 15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r1, Heap::kNullValueRootIndex); 15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, r1); 15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, &use_global_receiver); 15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); 15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, r1); 15453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, &use_global_receiver); 1546592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 15473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the receiver is already a JavaScript object. 15483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r0: receiver 15493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 15503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); 15513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ge, &push_receiver); 1552592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 15533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Convert the receiver to a regular object. 15543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r0: receiver 15553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&call_to_object); 15563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 15573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 15583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(&push_receiver); 1559592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 15603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Use the current global receiver object as the receiver. 15613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&use_global_receiver); 15623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const int kGlobalOffset = 15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, FieldMemOperand(cp, kGlobalOffset)); 15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset)); 15663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, FieldMemOperand(r0, kGlobalOffset)); 15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); 15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push the receiver. 15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r0: receiver 15713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&push_receiver); 15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Copy all arguments from the array to the stack. 15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label entry, loop; 15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, MemOperand(fp, kIndexOffset)); 15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(&entry); 15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the current argument from the arguments array and push it to the 15803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // stack. 15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r0: current argument index 15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&loop); 15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, MemOperand(fp, kArgsOffset)); 15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r1); 15853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Call the runtime to access the property in the arguments array. 15883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kGetProperty, 2); 15893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 15903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Use inline caching to access the arguments. 15923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, MemOperand(fp, kIndexOffset)); 15933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r0, r0, Operand(1 << kSmiTagSize)); 15943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r0, MemOperand(fp, kIndexOffset)); 15953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Test if the copy loop has finished copying all the elements from the 15973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // arguments object. 15983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&entry); 15993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, MemOperand(fp, kLimitOffset)); 16003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, r1); 16013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &loop); 1602592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 16033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Invoke the function. 16043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label call_proxy; 16053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ParameterCount actual(r0); 16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r0, Operand(r0, ASR, kSmiTagSize)); 16073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, MemOperand(fp, kFunctionOffset)); 16083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); 16093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &call_proxy); 16103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeFunction(r1, actual, CALL_FUNCTION, 16113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NullCallWrapper(), CALL_AS_METHOD); 16123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 16133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch frame_scope.GenerateLeaveFrame(); 16143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(sp, sp, Operand(3 * kPointerSize)); 16153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(lr); 16163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 16173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Invoke the function proxy. 16183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&call_proxy); 16193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r1); // add function proxy as last argument 16203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r0, r0, Operand(1)); 16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r2, Operand(0, RelocInfo::NONE)); 16223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SetCallKind(r5, CALL_AS_METHOD); 16233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY); 16243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 16253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RelocInfo::CODE_TARGET); 16263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 16273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Tear down the internal frame and remove function, receiver and args. 16283ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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 17483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store offset of return address for deoptimizer. 17493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset()); 17503ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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