builtins-arm.cc revision b0fe1620dcb4135ac3ab2d66ff93072373911299
1b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Copyright 2010 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 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "codegen-inl.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)); 716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ JumpToExternalReference(ExternalReference(id)); 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load the built-in Array function from the current context. 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) { 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the global context. 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(result, 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldMemOperand(result, GlobalObject::kGlobalContextOffset)); 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the Array function from the global context. 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(result, 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MemOperand(result, 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This constant has the same value as JSArray::kPreallocatedArrayElements and 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// if JSArray::kPreallocatedArrayElements is changed handling of loop unfolding 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// below should be reconsidered. 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kLoopUnfoldLimit = 4; 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Allocate an empty JSArray. The allocated array is put into the result 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register. An elements backing store is allocated with size initial_capacity 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and filled with the hole values. 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void AllocateEmptyJSArray(MacroAssembler* masm, 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register array_function, 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch3, 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int initial_capacity, 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required) { 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(initial_capacity > 0); 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the initial map from the array function. 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(scratch1, FieldMemOperand(array_function, 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSFunction::kPrototypeOrInitialMapOffset)); 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate the JSArray object together with space for a fixed array with the 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // requested elements. 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size = JSArray::kSize + FixedArray::SizeFor(initial_capacity); 11425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ AllocateInNewSpace(size, 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result, 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scratch2, 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scratch3, 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block gc_required, 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TAG_OBJECT); 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocated the JSArray. Now initialize the fields except for the elements 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array. 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch1: initial map 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch2: start of next object 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch1, FieldMemOperand(result, JSObject::kMapOffset)); 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex); 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch1, FieldMemOperand(result, JSArray::kPropertiesOffset)); 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Field JSArray::kElementsOffset is initialized later. 1309ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ mov(scratch3, Operand(0, RelocInfo::NONE)); 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch3, FieldMemOperand(result, JSArray::kLengthOffset)); 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the location of the elements array and set elements array member 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of the JSArray. 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch2: start of next object 137f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ add(scratch1, result, Operand(JSArray::kSize)); 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch1, FieldMemOperand(result, JSArray::kElementsOffset)); 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Clear the heap tag on the elements array. 1419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen ASSERT(kSmiTag == 0); 1429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ sub(scratch1, scratch1, Operand(kHeapObjectTag)); 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Initialize the FixedArray and fill it with holes. FixedArray length is 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // stored as a smi. 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch1: elements array (untagged) 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch2: start of next object 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(scratch3, Heap::kFixedArrayMapRootIndex); 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset); 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); 1527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(scratch3, Operand(Smi::FromInt(initial_capacity))); 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the FixedArray with the hole value. 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize); 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(initial_capacity <= kLoopUnfoldLimit); 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex); 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < initial_capacity; i++) { 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Allocate a JSArray with the number of elements stored in a register. The 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register array_function holds the built-in Array function and the register 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// array_size holds the size of the array as a smi. The allocated array is put 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// into the result register and beginning and end of the FixedArray elements 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// storage is put into registers elements_array_storage and elements_array_end 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (see below for when that is not the case). If the parameter fill_with_holes 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// is true the allocated elements backing store is filled with the hole values 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// otherwise it is left uninitialized. When the backing store is filled the 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register elements_array_storage is scratched. 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void AllocateJSArray(MacroAssembler* masm, 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register array_function, // Array function. 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register array_size, // As a smi. 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register elements_array_storage, 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register elements_array_end, 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool fill_with_hole, 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required) { 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label not_empty, allocated; 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the initial map from the array function. 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(elements_array_storage, 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldMemOperand(array_function, 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSFunction::kPrototypeOrInitialMapOffset)); 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check whether an empty sized array is requested. 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(array_size, array_size); 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(nz, ¬_empty); 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If an empty array is requested allocate a small elements array anyway. This 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // keeps the code below free of special casing for the empty array. 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size = JSArray::kSize + 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FixedArray::SizeFor(JSArray::kPreallocatedArrayElements); 19925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ AllocateInNewSpace(size, 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result, 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block elements_array_end, 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scratch1, 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block gc_required, 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TAG_OBJECT); 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&allocated); 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate the JSArray object together with space for a FixedArray with the 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // requested number of elements. 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(¬_empty); 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(elements_array_end, 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand((JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize)); 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(elements_array_end, 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block elements_array_end, 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(array_size, ASR, kSmiTagSize)); 21625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ AllocateInNewSpace( 21725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen elements_array_end, 21825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen result, 21925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen scratch1, 22025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen scratch2, 22125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen gc_required, 22225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocated the JSArray. Now initialize the fields except for the elements 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array. 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // elements_array_storage: initial map 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array_size: size of array (smi) 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&allocated); 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(elements_array_storage, FieldMemOperand(result, JSObject::kMapOffset)); 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(elements_array_storage, Heap::kEmptyFixedArrayRootIndex); 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(elements_array_storage, 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldMemOperand(result, JSArray::kPropertiesOffset)); 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Field JSArray::kElementsOffset is initialized later. 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(array_size, FieldMemOperand(result, JSArray::kLengthOffset)); 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the location of the elements array and set elements array member 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of the JSArray. 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array_size: size of array (smi) 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(elements_array_storage, result, Operand(JSArray::kSize)); 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(elements_array_storage, 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldMemOperand(result, JSArray::kElementsOffset)); 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Clear the heap tag on the elements array. 2469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen ASSERT(kSmiTag == 0); 2479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ sub(elements_array_storage, 2489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen elements_array_storage, 2499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen Operand(kHeapObjectTag)); 2507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Initialize the fixed array and fill it with holes. FixedArray length is 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // stored as a smi. 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // elements_array_storage: elements array (untagged) 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array_size: size of array (smi) 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(scratch1, Heap::kFixedArrayMapRootIndex); 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset); 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch1, MemOperand(elements_array_storage, kPointerSize, PostIndex)); 2587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(kSmiTag == 0); 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(array_size, array_size); 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Length of the FixedArray is the number of pre-allocated elements if 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the actual JSArray has length 0 and the size of the JSArray for non-empty 2627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // JSArrays. The length of a FixedArray is stored as a smi. 2637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(array_size, 2647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements)), 2657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch LeaveCC, 2667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch eq); 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(array_size, 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MemOperand(elements_array_storage, kPointerSize, PostIndex)); 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate elements array and elements array end. 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // elements_array_storage: elements array element storage 2747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // array_size: smi-tagged size of elements array 2757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(elements_array_end, 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block elements_array_storage, 2787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Operand(array_size, LSL, kPointerSizeLog2 - kSmiTagSize)); 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the allocated FixedArray with the hole value if requested. 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // elements_array_storage: elements array element storage 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // elements_array_end: start of next object 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (fill_with_hole) { 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop, entry; 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(scratch1, Heap::kTheHoleValueRootIndex); 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&entry); 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch1, 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MemOperand(elements_array_storage, kPointerSize, PostIndex)); 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry); 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(elements_array_storage, elements_array_end); 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(lt, &loop); 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Create a new array for the built-in Array function. This function allocates 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the JSArray object and the FixedArray elements array and initializes these. 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// If the Array cannot be constructed in native code the runtime is called. This 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// function assumes the following state: 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// r0: argc 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// r1: constructor (built-in Array function) 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// lr: return address 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// sp[0]: last argument 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This function is used for both construct and normal calls of Array. The only 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// difference between handling a construct call and a normal call is that for a 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// construct call the constructor function in r1 needs to be preserved for 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// entering the generic code. In both cases argc in r0 needs to be preserved. 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Both registers are preserved by this code so no need to differentiate between 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// construct call and normal call. 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ArrayNativeCode(MacroAssembler* masm, 312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* call_generic_code) { 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label argc_one_or_more, argc_two_or_more; 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for array construction with zero arguments or one. 3169ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ cmp(r0, Operand(0, RelocInfo::NONE)); 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &argc_one_or_more); 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle construction of an empty array. 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocateEmptyJSArray(masm, 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r1, 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r2, 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r3, 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r4, 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r5, 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSArray::kPreallocatedArrayElements, 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call_generic_code); 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::array_function_native, 1, r3, r4); 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Setup return value, remove receiver from stack and return. 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, r2); 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(kPointerSize)); 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for one argument. Bail out if argument is not smi or if it is 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // negative. 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&argc_one_or_more); 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand(1)); 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &argc_two_or_more); 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(kSmiTag == 0); 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(sp)); // Get the argument from the stack. 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(r3, r2, Operand(kIntptrSignBit | kSmiTagMask), SetCC); 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, call_generic_code); 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle construction of an empty array of a certain size. Bail out if size 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is too large to actually allocate an elements array. 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(kSmiTag == 0); 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, Operand(JSObject::kInitialMaxFastElementArray << kSmiTagSize)); 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ge, call_generic_code); 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: array_size (smi) 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: argument 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocateJSArray(masm, 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r1, 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r2, 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r3, 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r4, 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r5, 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r6, 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r7, 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block true, 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call_generic_code); 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::array_function_native, 1, r2, r4); 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Setup return value, remove receiver and argument from stack and return. 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, r3); 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(2 * kPointerSize)); 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle construction of an array from a list of arguments. 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&argc_two_or_more); 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(r0, LSL, kSmiTagSize)); // Convet argc to a smi. 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: array_size (smi) 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: last argument 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocateJSArray(masm, 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r1, 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r2, 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r3, 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r4, 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r5, 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r6, 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r7, 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block false, 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call_generic_code); 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::array_function_native, 1, r2, r6); 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill arguments as array elements. Copy from the top of the stack (last 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // element) to the array backing store filling it backwards. Note: 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // elements_array_end points after the backing store therefore PreIndex is 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // used when filling the backing store. 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: JSArray 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: elements_array storage start (untagged) 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5: elements_array_end (untagged) 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: last argument 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop, entry; 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&entry); 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(sp, kPointerSize, PostIndex)); 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r5, -kPointerSize, PreIndex)); 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry); 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r4, r5); 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(lt, &loop); 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Remove caller arguments and receiver from the stack, setup return value and 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // return. 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: JSArray 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: receiver 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(kPointerSize)); 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, r3); 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArrayCode(MacroAssembler* masm) { 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : number of arguments 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[...]: constructor arguments 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label generic_array_code, one_or_more_arguments, two_or_more_arguments; 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the Array function. 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadArrayFunction(masm, r1); 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initial map for the builtin Array function shoud be a map. 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r2, Operand(kSmiTagMask)); 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(ne, "Unexpected initial map for Array function"); 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r2, r3, r4, MAP_TYPE); 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(eq, "Unexpected initial map for Array function"); 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Run the native code for the Array function called as a normal function. 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ArrayNativeCode(masm, &generic_array_code); 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the generic array code if the specialized code cannot handle 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the construction. 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&generic_array_code); 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* code = Builtins::builtin(Builtins::ArrayCodeGeneric); 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> array_code(code); 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(array_code, RelocInfo::CODE_TARGET); 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) { 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : number of arguments 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r1 : constructor function 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[...]: constructor arguments 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label generic_constructor; 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The array construct code is only set for the builtin Array function which 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // always have a map. 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadArrayFunction(masm, r2); 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r1, r2); 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(eq, "Unexpected Array function"); 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initial map for the builtin Array function should be a map. 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r2, Operand(kSmiTagMask)); 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(ne, "Unexpected initial map for Array function"); 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r2, r3, r4, MAP_TYPE); 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(eq, "Unexpected initial map for Array function"); 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Run the native code for the Array function called as a constructor. 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ArrayNativeCode(masm, &generic_constructor); 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the generic construct code in case the specialized code cannot 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // handle the construction. 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&generic_constructor); 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric); 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> generic_construct_stub(code); 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 48680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid Builtins::Generate_StringConstructCode(MacroAssembler* masm) { 4878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // ----------- S t a t e ------------- 4888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- r0 : number of arguments 4898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- r1 : constructor function 4908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- lr : return address 4918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[(argc - n - 1) * 4] : arg[n] (zero based) 4928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[argc * 4] : receiver 4938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // ----------------------------------- 4948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ IncrementCounter(&Counters::string_ctor_calls, 1, r2, r3); 4958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 4968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register function = r1; 4978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (FLAG_debug_code) { 4988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, r2); 4998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(function, Operand(r2)); 5008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Assert(eq, "Unexpected String function"); 5018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 5028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the first arguments in r0 and get rid of the rest. 5048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label no_arguments; 5058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(r0, Operand(0)); 5068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(eq, &no_arguments); 5078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // First args = sp[(argc - 1) * 4]. 5088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ sub(r0, r0, Operand(1)); 5098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, MemOperand(sp, r0, LSL, kPointerSizeLog2, PreIndex)); 5108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // sp now point to args[0], drop args[0] + receiver. 5118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(2); 5128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register argument = r2; 5148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label not_cached, argument_is_string; 5158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang NumberToStringStub::GenerateLookupNumberStringCache( 5168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang masm, 5178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang r0, // Input. 5188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang argument, // Result. 5198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang r3, // Scratch. 5208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang r4, // Scratch. 5218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang r5, // Scratch. 5228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang false, // Is it a Smi? 5238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ¬_cached); 5248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ IncrementCounter(&Counters::string_ctor_cached_number, 1, r3, r4); 5258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&argument_is_string); 5268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // ----------- S t a t e ------------- 5288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- r2 : argument converted to string 5298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- r1 : constructor function 5308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- lr : return address 5318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // ----------------------------------- 5328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label gc_required; 5348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ AllocateInNewSpace(JSValue::kSize, 5358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang r0, // Result. 5368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang r3, // Scratch. 5378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang r4, // Scratch. 5388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang &gc_required, 5398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang TAG_OBJECT); 5408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Initialising the String Object. 5428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register map = r3; 5438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadGlobalFunctionInitialMap(function, map, r4); 5448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (FLAG_debug_code) { 5458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldrb(r4, FieldMemOperand(map, Map::kInstanceSizeOffset)); 5468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(r4, Operand(JSValue::kSize >> kPointerSizeLog2)); 5478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Assert(eq, "Unexpected string wrapper instance size"); 5488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldrb(r4, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset)); 5498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(r4, Operand(0)); 5508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Assert(eq, "Unexpected unused properties of string wrapper"); 5518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 5528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(map, FieldMemOperand(r0, HeapObject::kMapOffset)); 5538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex); 5558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset)); 5568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset)); 5578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(argument, FieldMemOperand(r0, JSValue::kValueOffset)); 5598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Ensure the object is fully initialized. 5618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); 5628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 5648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // The argument was not found in the number to string cache. Check 5668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // if it's a string already before calling the conversion builtin. 5678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label convert_argument; 5688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(¬_cached); 5698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ BranchOnSmi(r0, &convert_argument); 5708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Is it a String? 5728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 5738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceTypeOffset)); 5748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ASSERT(kNotStringTag != 0); 5758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ tst(r3, Operand(kIsNotStringMask)); 5768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(ne, &convert_argument); 5778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(argument, r0); 5788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ IncrementCounter(&Counters::string_ctor_conversions, 1, r3, r4); 5798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&argument_is_string); 5808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Invoke the conversion builtin and put the result into r2. 5828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&convert_argument); 5838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(function); // Preserve the function. 5848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ IncrementCounter(&Counters::string_ctor_conversions, 1, r3, r4); 5858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ EnterInternalFrame(); 5868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(r0); 5878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ InvokeBuiltin(Builtins::TO_STRING, CALL_JS); 5888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LeaveInternalFrame(); 5898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ pop(function); 5908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(argument, r0); 5918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&argument_is_string); 5928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the empty string into r2, remove the receiver from the 5948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // stack, and jump back to the case where the argument is a string. 5958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&no_arguments); 5968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadRoot(argument, Heap::kEmptyStringRootIndex); 5978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(1); 5988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&argument_is_string); 5998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 6008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // At this point the argument is already a string. Call runtime to 6018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // create a string wrapper. 6028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&gc_required); 6038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ IncrementCounter(&Counters::string_ctor_gc_required, 1, r3, r4); 6048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ EnterInternalFrame(); 6058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(argument); 6068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ CallRuntime(Runtime::kNewStringWrapper, 1); 6078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LeaveInternalFrame(); 6088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 60980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 61080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 61180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSConstructCall(MacroAssembler* masm) { 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : number of arguments 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r1 : constructor function 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[...]: constructor arguments 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label non_function_call; 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the function is not a smi. 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r1, Operand(kSmiTagMask)); 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &non_function_call); 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the function is a JSFunction. 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &non_function_call); 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the function-specific construct stub. 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kConstructStubOffset)); 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(pc, r2, Operand(Code::kHeaderSize - kHeapObjectTag)); 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: number of arguments 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: called object 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&non_function_call); 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set expected number of arguments to zero (not changing r0). 6379ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ mov(r2, Operand(0, RelocInfo::NONE)); 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::CODE_TARGET); 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkestatic void Generate_JSConstructStubHelper(MacroAssembler* masm, 6450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool is_api_function, 6460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool count_constructions) { 6470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Should never count constructions for api objects. 6480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen ASSERT(!is_api_function || !count_constructions); 6490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Enter a construct frame. 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ EnterConstructFrame(); 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Preserve the two incoming parameters on the stack. 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(r0, LSL, kSmiTagSize)); 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); // Smi-tagged arguments count. 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r1); // Constructor function. 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Try to allocate the object without transitioning into C code. If any of the 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // preconditions is not met, the code bails out to the runtime call. 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label rt_call, allocated; 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_inline_new) { 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label undo_allocation; 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference debug_step_in_fp = 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::debug_step_in_fp_address(); 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(debug_step_in_fp)); 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(r2)); 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r2, r2); 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(nz, &rt_call); 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the initial map and verify that it is in fact a map. 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r2, Operand(kSmiTagMask)); 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &rt_call); 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r2, r3, r4, MAP_TYPE); 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &rt_call); 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the constructor is not constructing a JSFunction (see comments 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // in Runtime_NewObject in runtime.cc). In which case the initial map's 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // instance type would be JS_FUNCTION_TYPE. 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: initial map 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &rt_call); 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (count_constructions) { 6890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label allocate; 6900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Decrease generous allocation count. 6910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 6920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen MemOperand constructor_count = 6930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen FieldMemOperand(r3, SharedFunctionInfo::kConstructionCountOffset); 6940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ ldrb(r4, constructor_count); 6950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ sub(r4, r4, Operand(1), SetCC); 6960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ strb(r4, constructor_count); 6970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ b(ne, &allocate); 6980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Push(r1, r2); 7000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 7010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ push(r1); // constructor 7020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // The call will replace the stub, so the countdown is only done once. 7030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); 7040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 7050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ pop(r2); 7060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ pop(r1); 7070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 7080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&allocate); 7090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 7100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Now allocate the JSObject on the heap. 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: initial map 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset)); 71525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS); 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocated the JSObject, now initialize the fields. Map is set to initial 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // map and properties and elements are set to empty fixed array. 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: initial map 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: object size 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject (not tagged) 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r5, r4); 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset); 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset); 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Fill all the in-object properties with the appropriate filler. 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: initial map 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: object size (in words) 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject (not tagged) 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5: First in-object property of JSObject (not tagged) 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object. 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize); 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { Label loop, entry; 7410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (count_constructions) { 7420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // To allow for truncation. 7430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(r7, Heap::kOnePointerFillerMapRootIndex); 7440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 7450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); 7460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&entry); 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r7, MemOperand(r5, kPointerSize, PostIndex)); 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry); 7516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(r5, r6); 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(lt, &loop); 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Add the object tag to make the JSObject real, so that we can continue and 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // jump into the continuation code at any time from now on. Any failures 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // need to undo the allocation, so that the heap is in a consistent state 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // and verifiable. 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r4, r4, Operand(kHeapObjectTag)); 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if a non-empty properties array is needed. Continue with allocated 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object if not fall through to runtime call if it is. 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5: start of next object (not tagged) 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset)); 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The field instance sizes contains both pre-allocated property fields and 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // in-object properties. 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset)); 7709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ Ubfx(r6, r0, Map::kPreAllocatedPropertyFieldsByte * 8, 8); 7719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ add(r3, r3, Operand(r6)); 7729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ Ubfx(r6, r0, Map::kInObjectPropertiesByte * 8, 8); 7739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen __ sub(r3, r3, Operand(r6), SetCC); 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Done if no extra properties are to be allocated. 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &allocated); 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(pl, "Property allocation count failed."); 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Scale the number of elements by pointer size and add the header for 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // FixedArrays to the start of the next object calculation from above. 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: number of elements in properties array 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5: start of next object 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize)); 78625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ AllocateInNewSpace( 78725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen r0, 78825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen r5, 78925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen r6, 79025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen r2, 79125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen &undo_allocation, 79225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS)); 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize the FixedArray. 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: number of elements in properties array 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5: FixedArray (not tagged) 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex); 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, r5); 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r6, MemOperand(r2, kPointerSize, PostIndex)); 8037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); 8047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(r0, Operand(r3, LSL, kSmiTagSize)); 8057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ str(r0, MemOperand(r2, kPointerSize, PostIndex)); 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize the fields to undefined. 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: First element of FixedArray (not tagged) 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: number of elements in properties array 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5: FixedArray (not tagged) 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2)); // End of object. 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize); 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { Label loop, entry; 8160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (count_constructions) { 8170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); 8180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (FLAG_debug_code) { 8190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); 8200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ cmp(r7, r8); 8210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Assert(eq, "Undefined value not loaded."); 8220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&entry); 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r7, MemOperand(r2, kPointerSize, PostIndex)); 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry); 8276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(r2, r6); 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(lt, &loop); 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store the initialized FixedArray into the properties field of 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the JSObject 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5: FixedArray (not tagged) 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r5, r5, Operand(kHeapObjectTag)); // Add the heap tag. 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r5, FieldMemOperand(r4, JSObject::kPropertiesOffset)); 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Continue with JSObject being successfully allocated 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&allocated); 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Undo the setting of the new top so that the heap is verifiable. For 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // example, the map's unused properties potentially do not match the 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // allocated objects unused properties. 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject (previous new top) 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&undo_allocation); 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ UndoAllocationInNewSpace(r4, r5); 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate the new receiver object using the runtime call. 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&rt_call); 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r1); // argument for Runtime_NewObject 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CallRuntime(Runtime::kNewObject, 1); 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r4, r0); 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Receiver for constructor call allocated. 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&allocated); 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r4); 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the function and the allocated receiver from the stack. 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: receiver (newly allocated object) 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[1]: constructor function 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[2]: number of arguments (smi-tagged) 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(sp, kPointerSize)); 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r1); // Constructor function. 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r4); // Receiver. 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reload the number of arguments from the stack. 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: receiver 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[1]: constructor function 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[2]: receiver 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[3]: constructor function 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[4]: number of arguments (smi-tagged) 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, MemOperand(sp, 4 * kPointerSize)); 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Setup pointer to last argument. 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Setup number of arguments for function call below 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(r3, LSR, kSmiTagSize)); 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy arguments and receiver to the expression stack. 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: number of arguments 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: address of last argument (caller sp) 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: number of arguments (smi-tagged) 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: receiver 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[1]: constructor function 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[2]: receiver 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[3]: constructor function 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[4]: number of arguments (smi-tagged) 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop, entry; 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&entry); 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1)); 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ip); 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry); 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r3, r3, Operand(2), SetCC); 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ge, &loop); 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call the function. 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: number of arguments 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 909e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (is_api_function) { 910e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 911e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> code = Handle<Code>( 912e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Builtins::builtin(Builtins::HandleApiCallConstruct)); 913e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ParameterCount expected(0); 914e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ InvokeCode(code, expected, expected, 915e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke RelocInfo::CODE_TARGET, CALL_FUNCTION); 916e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 917e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ParameterCount actual(r0); 918e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ InvokeFunction(r1, actual, CALL_FUNCTION); 919e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop the function from the stack. 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: constructor function 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[2]: receiver 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[3]: constructor function 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[4]: number of arguments (smi-tagged) 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(); 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore context from the frame. 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: result 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: receiver 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[1]: constructor function 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[2]: number of arguments (smi-tagged) 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the result is an object (in the ECMA sense), we should get rid 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of the receiver and use the result; see ECMA-262 section 13.2.2-7 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // on page 74. 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label use_receiver, exit; 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the result is a smi, it is *not* an object in the ECMA sense. 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: result 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: receiver (newly allocated object) 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[1]: constructor function 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[2]: number of arguments (smi-tagged) 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r0, Operand(kSmiTagMask)); 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &use_receiver); 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the type of the result (stored in its map) is less than 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // FIRST_JS_OBJECT_TYPE, it is not an object in the ECMA sense. 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r0, r3, r3, FIRST_JS_OBJECT_TYPE); 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ge, &exit); 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Throw away the result of the constructor invocation and use the 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // on-stack receiver as the result. 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&use_receiver); 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(sp)); 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Remove receiver from the stack, remove caller arguments, and 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // return. 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&exit); 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: result 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: receiver (newly allocated object) 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[1]: constructor function 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[2]: number of arguments (smi-tagged) 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LeaveConstructFrame(); 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(kPointerSize)); 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::constructed_objects, 1, r1, r2); 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9740d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { 9750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Generate_JSConstructStubHelper(masm, false, true); 9760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 9770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 9780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 979e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 9800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Generate_JSConstructStubHelper(masm, false, false); 981e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 982e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 983e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 984e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 9850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Generate_JSConstructStubHelper(masm, true, false); 986e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 987e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 988e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_construct) { 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Called from Generate_JS_Entry 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: code entry 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: receiver 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: argc 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: argv 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5-r7, cp may be clobbered 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Clear the context before we push it when entering the JS frame. 10009ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ mov(cp, Operand(0, RelocInfo::NONE)); 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Enter an internal frame. 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ EnterInternalFrame(); 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set up the context from the function argument. 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set up the roots register. 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference roots_address = ExternalReference::roots_address(); 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r10, Operand(roots_address)); 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the function and the receiver onto the stack. 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r1); 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r2); 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy arguments to the stack in a loop. 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: argc 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: argv, i.e. points to first arg 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop, entry; 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2)); 1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2 points past last arg. 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&entry); 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex)); // read next parameter 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(r0)); // dereference handle 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); // push parameter 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry); 10296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(r4, r2); 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &loop); 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize all JavaScript callee-saved registers, since they will be seen 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // by the garbage collector as part of handlers. 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r5, Operand(r4)); 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r6, Operand(r4)); 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r7, Operand(r4)); 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (kR9Available == 1) { 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r9, Operand(r4)); 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the code and pass argc as r0. 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(r3)); 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (is_construct) { 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::CODE_TARGET); 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount actual(r0); 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeFunction(r1, actual, CALL_FUNCTION); 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit the JS frame and remove the parameters (except function), and return. 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Respect ABI stack constraint. 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LeaveInternalFrame(); 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: result 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Generate_JSEntryTrampolineHelper(masm, false); 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Generate_JSEntryTrampolineHelper(masm, true); 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1071756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid Builtins::Generate_LazyCompile(MacroAssembler* masm) { 1072756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Enter an internal frame. 1073756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ EnterInternalFrame(); 1074756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 1075756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Preserve the function. 1076756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(r1); 1077756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 1078756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Push the function on the stack as the argument to the runtime function. 1079756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ push(r1); 1080756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallRuntime(Runtime::kLazyCompile, 1); 1081756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Calculate the entry point. 1082756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); 1083756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Restore saved function. 1084756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ pop(r1); 1085756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 1086756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Tear down temporary frame. 1087756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ LeaveInternalFrame(); 1088756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 1089756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Do a tail-call of the compiled function. 1090756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ Jump(r2); 1091756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 1092756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 1093756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 1094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_LazyRecompile(MacroAssembler* masm) { 1095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Enter an internal frame. 1096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ EnterInternalFrame(); 1097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Preserve the function. 1099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(r1); 1100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Push the function on the stack as the argument to the runtime function. 1102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(r1); 1103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ CallRuntime(Runtime::kLazyRecompile, 1); 1104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Calculate the entry point. 1105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); 1106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Restore saved function. 1107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ pop(r1); 1108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Tear down temporary frame. 1110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ LeaveInternalFrame(); 1111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Do a tail-call of the compiled function. 1113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ Jump(r2); 1114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm, 1118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Deoptimizer::BailoutType type) { 1119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ EnterInternalFrame(); 1120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Pass the function and deoptimization type to the runtime system. 1121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(r0, Operand(Smi::FromInt(static_cast<int>(type)))); 1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(r0); 1123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ CallRuntime(Runtime::kNotifyDeoptimized, 1); 1124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ LeaveInternalFrame(); 1125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Get the full codegen state from the stack and untag it -> r6. 1127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r6, MemOperand(sp, 0 * kPointerSize)); 1128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ SmiUntag(r6); 1129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Switch on the state. 1130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label with_tos_register, unknown_state; 1131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(r6, Operand(FullCodeGenerator::NO_REGISTERS)); 1132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ b(ne, &with_tos_register); 1133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(sp, sp, Operand(1 * kPointerSize)); // Remove state. 1134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ Ret(); 1135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&with_tos_register); 1137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); 1138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(r6, Operand(FullCodeGenerator::TOS_REG)); 1139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ b(ne, &unknown_state); 1140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(sp, sp, Operand(2 * kPointerSize)); // Remove state. 1141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ Ret(); 1142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&unknown_state); 1144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ stop("no cases left"); 1145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) { 1149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); 1150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) { 1154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); 1155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_NotifyOSR(MacroAssembler* masm) { 1159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ stop("builtins-arm.cc: NotifyOSR"); 1160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { 1164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ stop("builtins-arm.cc: OnStackReplacement"); 1165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_FunctionCall(MacroAssembler* masm) { 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 1. Make sure we have at least one argument. 1170402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r0: actual number of arguments 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { Label done; 1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r0, Operand(r0)); 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &done); 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r2); 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, r0, Operand(1)); 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&done); 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1180402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // 2. Get the function to call (passed as receiver) from the stack, check 1181402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // if it is a function. 1182402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r0: actual number of arguments 1183402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label non_function; 1184402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); 1185402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ tst(r1, Operand(kSmiTagMask)); 1186402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ b(eq, &non_function); 1187402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); 1188402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ b(ne, &non_function); 1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1190402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // 3a. Patch the first argument if necessary when calling a function. 1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments 1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1193402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label shift_arguments; 1194402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu { Label convert_to_object, use_global_receiver, patch_receiver; 1195402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Change context eagerly in case we need the global receiver. 1196402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 1197402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); 1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(r2, -kPointerSize)); 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments 1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: first argument 1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r2, Operand(kSmiTagMask)); 1204402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ b(eq, &convert_to_object); 1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r3, Heap::kNullValueRootIndex); 1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, r3); 1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &use_global_receiver); 1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); 1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, r3); 1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &use_global_receiver); 1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r2, r3, r3, FIRST_JS_OBJECT_TYPE); 1214402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ b(lt, &convert_to_object); 1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r3, Operand(LAST_JS_OBJECT_TYPE)); 1216402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ b(le, &shift_arguments); 1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1218402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(&convert_to_object); 1219402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ EnterInternalFrame(); // In order to preserve argument count. 1220402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ mov(r0, Operand(r0, LSL, kSmiTagSize)); // Smi-tagged. 1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); 1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r2); 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS); 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, r0); 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(r0); 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(r0, ASR, kSmiTagSize)); 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LeaveInternalFrame(); 1230402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Restore the function to r1. 1231402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); 1232402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ jmp(&patch_receiver); 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1234402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Use the global receiver object from the called function as the 1235402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // receiver. 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&use_global_receiver); 1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kGlobalIndex = 1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(cp, kGlobalIndex)); 1240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalContextOffset)); 1241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r2, FieldMemOperand(r2, kGlobalIndex)); 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset)); 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&patch_receiver); 1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2)); 1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r3, -kPointerSize)); 1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1248402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ jmp(&shift_arguments); 1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1251402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // 3b. Patch the first argument when calling a non-function. The 1252402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // CALL_NON_FUNCTION builtin expects the non-function callee as 1253402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // receiver, so overwrite the first argument which will ultimately 1254402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // become the receiver. 1255402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r0: actual number of arguments 1256402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r1: function 1257402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(&non_function); 1258402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); 1259402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ str(r1, MemOperand(r2, -kPointerSize)); 1260402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Clear r1 to indicate a non-function being called. 12619ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ mov(r1, Operand(0, RelocInfo::NONE)); 1262402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1263402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // 4. Shift arguments and return address one slot down on the stack 1264402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // (overwriting the original receiver). Adjust argument count to make 1265402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // the original first argument the new receiver. 1266402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r0: actual number of arguments 1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1268402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(&shift_arguments); 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { Label loop; 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the copy start address (destination). Copy end address is sp. 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(ip, MemOperand(r2, -kPointerSize)); 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(ip, MemOperand(r2)); 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r2, r2, Operand(kPointerSize)); 1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, sp); 1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &loop); 1279402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Adjust the actual number of arguments and remove the top element 1280402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // (which is a copy of the last argument). 1281402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ sub(r0, r0, Operand(1)); 1282402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(); 1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1285402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin. 1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments 1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1288402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu { Label function; 1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r1, r1); 1290402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ b(ne, &function); 12919ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick // Expected number of arguments is 0 for CALL_NON_FUNCTION. 12929ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ mov(r2, Operand(0, RelocInfo::NONE)); 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), 1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::CODE_TARGET); 1296402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(&function); 1297402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1299402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // 5b. Get the code to call from the function and check that the number of 1300402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // expected arguments matches what we're providing. If so, jump 1301402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // (tail-call) to the code in register edx without checking arguments. 1302402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r0: actual number of arguments 1303402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r1: function 1304402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 1305402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r2, 1306402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset)); 13077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ mov(r2, Operand(r2, ASR, kSmiTagSize)); 1308791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); 1309402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(r2, r0); // Check formal and actual parameter counts. 1310402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), 1311402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu RelocInfo::CODE_TARGET, ne); 1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1313402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ParameterCount expected(0); 1314402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ InvokeCode(r3, expected, expected, JUMP_FUNCTION); 1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_FunctionApply(MacroAssembler* masm) { 1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kIndexOffset = -5 * kPointerSize; 1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kLimitOffset = -4 * kPointerSize; 1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kArgsOffset = 2 * kPointerSize; 1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kRecvOffset = 3 * kPointerSize; 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kFunctionOffset = 4 * kPointerSize; 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ EnterInternalFrame(); 1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(fp, kArgsOffset)); // get the args array 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_JS); 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check the stack for overflow. We are not trying need to catch 1334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // interruptions (e.g. debug break and preemption) here, so the "real stack 1335d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // limit" is checked. 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label okay; 1337d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); 1338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Make r2 the space we have left. The stack might already be overflowed 1339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // here which will cause r2 to become negative. 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r2, sp, r2); 1341d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check if the arguments will overflow the stack. 1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 1343d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ b(gt, &okay); // Signed comparison. 1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Out of stack space. 1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(fp, kFunctionOffset)); 1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r1); 1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_JS); 1350d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // End of stack check. 1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push current limit and index. 1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&okay); 1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); // limit 13559ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ mov(r1, Operand(0, RelocInfo::NONE)); // initial index 1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r1); 1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Change context eagerly to get the right global object if necessary. 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(fp, kFunctionOffset)); 1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(cp, FieldMemOperand(r0, JSFunction::kContextOffset)); 1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the receiver. 1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label call_to_object, use_global_receiver, push_receiver; 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(fp, kRecvOffset)); 1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r0, Operand(kSmiTagMask)); 1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &call_to_object); 1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r1, Heap::kNullValueRootIndex); 1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, r1); 1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &use_global_receiver); 1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); 1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, r1); 1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &use_global_receiver); 1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the receiver is already a JavaScript object. 1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: receiver 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); 1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(lt, &call_to_object); 1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE)); 1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(le, &push_receiver); 1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convert the receiver to a regular object. 1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: receiver 1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&call_to_object); 1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); 1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS); 1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&push_receiver); 1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use the current global receiver object as the receiver. 1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&use_global_receiver); 1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kGlobalOffset = 1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, FieldMemOperand(cp, kGlobalOffset)); 1393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset)); 1394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r0, FieldMemOperand(r0, kGlobalOffset)); 1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); 1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the receiver. 1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: receiver 1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&push_receiver); 1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); 1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy all arguments from the array to the stack. 1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label entry, loop; 1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(fp, kIndexOffset)); 1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&entry); 1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the current argument from the arguments array and push it to the 1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // stack. 1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: current argument index 1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(fp, kArgsOffset)); 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r1); 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); 1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call the runtime to access the property in the arguments array. 1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CallRuntime(Runtime::kGetProperty, 2); 1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); 1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use inline caching to access the arguments. 1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(fp, kIndexOffset)); 1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, r0, Operand(1 << kSmiTagSize)); 1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r0, MemOperand(fp, kIndexOffset)); 1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Test if the copy loop has finished copying all the elements from the 1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arguments object. 1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry); 1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(fp, kLimitOffset)); 1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, r1); 1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &loop); 1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount actual(r0); 1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(r0, ASR, kSmiTagSize)); 1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(fp, kFunctionOffset)); 1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeFunction(r1, actual, CALL_FUNCTION); 1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tear down the internal frame and remove function, receiver and args. 1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LeaveInternalFrame(); 1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(3 * kPointerSize)); 1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { 1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(r0, LSL, kSmiTagSize)); 1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() | fp.bit() | lr.bit()); 1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(fp, sp, Operand(3 * kPointerSize)); 1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { 1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : result being passed through 1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the number of arguments passed (as a smi), tear down the frame and 1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // then tear down the parameters. 1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(fp, -3 * kPointerSize)); 1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(sp, fp); 1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldm(ia_w, sp, fp.bit() | lr.bit()); 1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize)); 1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(kPointerSize)); // adjust for receiver 1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { 1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : actual number of arguments 1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r1 : function (passed through to callee) 1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : expected number of arguments 1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r3 : code entry to call 1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label invoke, dont_adapt_arguments; 1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label enough, too_few; 14776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(r0, r2); 1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(lt, &too_few); 1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel)); 1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &dont_adapt_arguments); 1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { // Enough parameters: actual >= expected 1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&enough); 1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EnterArgumentsAdaptorFrame(masm); 1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate copy start address into r0 and copy end address into r2. 1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments as a smi 1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: expected number of arguments 1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: code entry to call 1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // adjust for return address and receiver 1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, r0, Operand(2 * kPointerSize)); 1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r2, r0, Operand(r2, LSL, kPointerSizeLog2)); 1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy the arguments (including the receiver) to the new stack frame. 1497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: copy start address 1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: copy end address 1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: code entry to call 1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label copy; 1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(©); 1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(ip, MemOperand(r0, 0)); 1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ip); 1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, r2); // Compare before moving to next argument. 1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r0, r0, Operand(kPointerSize)); 1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, ©); 1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&invoke); 1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { // Too few parameters: Actual < expected 1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&too_few); 1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EnterArgumentsAdaptorFrame(masm); 1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate copy start address into r0 and copy end address is fp. 1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments as a smi 1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: expected number of arguments 1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: code entry to call 1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 1523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy the arguments (including the receiver) to the new stack frame. 1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: copy start address 1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: expected number of arguments 1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: code entry to call 1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label copy; 1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(©); 1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust load for return address and receiver. 1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(ip, MemOperand(r0, 2 * kPointerSize)); 1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ip); 1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, fp); // Compare before moving to next argument. 1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r0, r0, Operand(kPointerSize)); 1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, ©); 1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the remaining expected arguments with undefined. 1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: expected number of arguments 1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: code entry to call 1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r2, fp, Operand(r2, LSL, kPointerSizeLog2)); 1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r2, r2, Operand(4 * kPointerSize)); // Adjust for frame. 1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fill; 1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fill); 1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ip); 1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(sp, r2); 1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &fill); 1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call the entry point. 1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&invoke); 1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Call(r3); 1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit frame and return. 1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LeaveArgumentsAdaptorFrame(masm); 1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ------------------------------------------- 1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Dont adapt arguments. 1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ------------------------------------------- 1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&dont_adapt_arguments); 1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(r3); 1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 1573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_ARM 1575