builtins-arm.cc revision e46be819fca9468a0cd4e74859ce0f778eb8ca60
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2009 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 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "codegen-inl.h" 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "debug.h" 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "runtime.h" 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm) 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 41e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_Adaptor(MacroAssembler* masm, 42e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke CFunctionId id, 43e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BuiltinExtraArguments extra_args) { 44e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------- S t a t e ------------- 45e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- r0 : number of arguments excluding receiver 46e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- r1 : called function (only guaranteed when 47e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // extra_args requires it) 48e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- cp : context 49e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- sp[0] : last argument 50e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 51e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- sp[4 * (argc - 1)] : first argument (argc == r0) 52e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- sp[4 * argc] : receiver 53e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------------------------------- 54e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 55e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Insert extra arguments. 56e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int num_extra_args = 0; 57e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (extra_args == NEEDS_CALLED_FUNCTION) { 58e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke num_extra_args = 1; 59e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(r1); 60e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 61e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(extra_args == NO_EXTRA_ARGUMENTS); 62e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 63e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 64e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // JumpToRuntime expects r0 to contain the number of arguments 65e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // including the receiver and the extra arguments. 66e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(r0, r0, Operand(num_extra_args + 1)); 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ JumpToRuntime(ExternalReference(id)); 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load the built-in Array function from the current context. 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) { 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the global context. 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(result, 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldMemOperand(result, GlobalObject::kGlobalContextOffset)); 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the Array function from the global context. 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(result, 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MemOperand(result, 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This constant has the same value as JSArray::kPreallocatedArrayElements and 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// if JSArray::kPreallocatedArrayElements is changed handling of loop unfolding 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// below should be reconsidered. 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kLoopUnfoldLimit = 4; 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Allocate an empty JSArray. The allocated array is put into the result 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register. An elements backing store is allocated with size initial_capacity 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and filled with the hole values. 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void AllocateEmptyJSArray(MacroAssembler* masm, 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register array_function, 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch3, 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int initial_capacity, 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required) { 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(initial_capacity > 0); 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the initial map from the array function. 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(scratch1, FieldMemOperand(array_function, 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSFunction::kPrototypeOrInitialMapOffset)); 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate the JSArray object together with space for a fixed array with the 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // requested elements. 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size = JSArray::kSize + FixedArray::SizeFor(initial_capacity); 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ AllocateInNewSpace(size / kPointerSize, 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result, 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scratch2, 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scratch3, 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block gc_required, 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TAG_OBJECT); 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocated the JSArray. Now initialize the fields except for the elements 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array. 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch1: initial map 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch2: start of next object 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch1, FieldMemOperand(result, JSObject::kMapOffset)); 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex); 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch1, FieldMemOperand(result, JSArray::kPropertiesOffset)); 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Field JSArray::kElementsOffset is initialized later. 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(scratch3, Operand(0)); 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch3, FieldMemOperand(result, JSArray::kLengthOffset)); 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the location of the elements array and set elements array member 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of the JSArray. 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch2: start of next object 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(scratch1, MemOperand(result, JSArray::kSize)); 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch1, FieldMemOperand(result, JSArray::kElementsOffset)); 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Clear the heap tag on the elements array. 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(scratch1, scratch1, Operand(~kHeapObjectTagMask)); 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize the FixedArray and fill it with holes. FixedArray length is not 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // stored as a smi. 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch1: elements array (untagged) 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch2: start of next object 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(scratch3, Heap::kFixedArrayMapRootIndex); 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset); 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(scratch3, Operand(initial_capacity)); 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the FixedArray with the hole value. 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize); 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(initial_capacity <= kLoopUnfoldLimit); 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex); 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < initial_capacity; i++) { 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Allocate a JSArray with the number of elements stored in a register. The 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register array_function holds the built-in Array function and the register 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// array_size holds the size of the array as a smi. The allocated array is put 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// into the result register and beginning and end of the FixedArray elements 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// storage is put into registers elements_array_storage and elements_array_end 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (see below for when that is not the case). If the parameter fill_with_holes 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// is true the allocated elements backing store is filled with the hole values 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// otherwise it is left uninitialized. When the backing store is filled the 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// register elements_array_storage is scratched. 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void AllocateJSArray(MacroAssembler* masm, 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register array_function, // Array function. 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register array_size, // As a smi. 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register result, 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register elements_array_storage, 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register elements_array_end, 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch1, 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch2, 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool fill_with_hole, 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* gc_required) { 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label not_empty, allocated; 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the initial map from the array function. 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(elements_array_storage, 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldMemOperand(array_function, 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSFunction::kPrototypeOrInitialMapOffset)); 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check whether an empty sized array is requested. 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(array_size, array_size); 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(nz, ¬_empty); 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If an empty array is requested allocate a small elements array anyway. This 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // keeps the code below free of special casing for the empty array. 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size = JSArray::kSize + 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FixedArray::SizeFor(JSArray::kPreallocatedArrayElements); 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ AllocateInNewSpace(size / kPointerSize, 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result, 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block elements_array_end, 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scratch1, 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block gc_required, 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TAG_OBJECT); 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&allocated); 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate the JSArray object together with space for a FixedArray with the 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // requested number of elements. 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(¬_empty); 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(elements_array_end, 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand((JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize)); 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(elements_array_end, 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block elements_array_end, 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(array_size, ASR, kSmiTagSize)); 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ AllocateInNewSpace(elements_array_end, 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result, 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scratch1, 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scratch2, 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block gc_required, 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TAG_OBJECT); 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocated the JSArray. Now initialize the fields except for the elements 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array. 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // elements_array_storage: initial map 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array_size: size of array (smi) 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&allocated); 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(elements_array_storage, FieldMemOperand(result, JSObject::kMapOffset)); 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(elements_array_storage, Heap::kEmptyFixedArrayRootIndex); 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(elements_array_storage, 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldMemOperand(result, JSArray::kPropertiesOffset)); 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Field JSArray::kElementsOffset is initialized later. 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(array_size, FieldMemOperand(result, JSArray::kLengthOffset)); 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the location of the elements array and set elements array member 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of the JSArray. 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array_size: size of array (smi) 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(elements_array_storage, result, Operand(JSArray::kSize)); 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(elements_array_storage, 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldMemOperand(result, JSArray::kElementsOffset)); 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Clear the heap tag on the elements array. 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(elements_array_storage, 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block elements_array_storage, 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(~kHeapObjectTagMask)); 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize the fixed array and fill it with holes. FixedArray length is not 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // stored as a smi. 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // elements_array_storage: elements array (untagged) 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array_size: size of array (smi) 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(kSmiTag == 0); 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(scratch1, Heap::kFixedArrayMapRootIndex); 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset); 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch1, MemOperand(elements_array_storage, kPointerSize, PostIndex)); 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convert array_size from smi to value. 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(array_size, 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(array_size, ASR, kSmiTagSize)); 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(array_size, array_size); 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Length of the FixedArray is the number of pre-allocated elements if 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the actual JSArray has length 0 and the size of the JSArray for non-empty 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // JSArrays. The length of a FixedArray is not stored as a smi. 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(array_size, Operand(JSArray::kPreallocatedArrayElements), LeaveCC, eq); 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(array_size, 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MemOperand(elements_array_storage, kPointerSize, PostIndex)); 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate elements array and elements array end. 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // elements_array_storage: elements array element storage 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // array_size: size of elements array 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(elements_array_end, 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block elements_array_storage, 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(array_size, LSL, kPointerSizeLog2)); 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the allocated FixedArray with the hole value if requested. 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result: JSObject 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // elements_array_storage: elements array element storage 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // elements_array_end: start of next object 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (fill_with_hole) { 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop, entry; 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(scratch1, Heap::kTheHoleValueRootIndex); 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&entry); 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(scratch1, 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MemOperand(elements_array_storage, kPointerSize, PostIndex)); 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry); 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(elements_array_storage, elements_array_end); 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(lt, &loop); 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Create a new array for the built-in Array function. This function allocates 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the JSArray object and the FixedArray elements array and initializes these. 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// If the Array cannot be constructed in native code the runtime is called. This 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// function assumes the following state: 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// r0: argc 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// r1: constructor (built-in Array function) 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// lr: return address 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// sp[0]: last argument 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This function is used for both construct and normal calls of Array. The only 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// difference between handling a construct call and a normal call is that for a 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// construct call the constructor function in r1 needs to be preserved for 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// entering the generic code. In both cases argc in r0 needs to be preserved. 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Both registers are preserved by this code so no need to differentiate between 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// construct call and normal call. 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ArrayNativeCode(MacroAssembler* masm, 304d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label* call_generic_code) { 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label argc_one_or_more, argc_two_or_more; 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for array construction with zero arguments or one. 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand(0)); 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &argc_one_or_more); 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle construction of an empty array. 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocateEmptyJSArray(masm, 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r1, 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r2, 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r3, 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r4, 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r5, 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSArray::kPreallocatedArrayElements, 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call_generic_code); 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::array_function_native, 1, r3, r4); 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Setup return value, remove receiver from stack and return. 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, r2); 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(kPointerSize)); 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for one argument. Bail out if argument is not smi or if it is 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // negative. 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&argc_one_or_more); 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand(1)); 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &argc_two_or_more); 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(kSmiTag == 0); 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(sp)); // Get the argument from the stack. 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(r3, r2, Operand(kIntptrSignBit | kSmiTagMask), SetCC); 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, call_generic_code); 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle construction of an empty array of a certain size. Bail out if size 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is too large to actually allocate an elements array. 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(kSmiTag == 0); 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, Operand(JSObject::kInitialMaxFastElementArray << kSmiTagSize)); 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ge, call_generic_code); 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: array_size (smi) 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: argument 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocateJSArray(masm, 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r1, 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r2, 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r3, 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r4, 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r5, 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r6, 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r7, 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block true, 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call_generic_code); 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::array_function_native, 1, r2, r4); 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Setup return value, remove receiver and argument from stack and return. 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, r3); 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(2 * kPointerSize)); 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle construction of an array from a list of arguments. 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&argc_two_or_more); 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(r0, LSL, kSmiTagSize)); // Convet argc to a smi. 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: array_size (smi) 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: last argument 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AllocateJSArray(masm, 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r1, 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r2, 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r3, 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r4, 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r5, 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r6, 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r7, 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block false, 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call_generic_code); 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::array_function_native, 1, r2, r6); 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill arguments as array elements. Copy from the top of the stack (last 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // element) to the array backing store filling it backwards. Note: 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // elements_array_end points after the backing store therefore PreIndex is 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // used when filling the backing store. 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: JSArray 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: elements_array storage start (untagged) 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5: elements_array_end (untagged) 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: last argument 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop, entry; 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&entry); 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(sp, kPointerSize, PostIndex)); 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r5, -kPointerSize, PreIndex)); 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry); 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r4, r5); 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(lt, &loop); 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Remove caller arguments and receiver from the stack, setup return value and 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // return. 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: argc 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: JSArray 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: receiver 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(kPointerSize)); 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, r3); 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArrayCode(MacroAssembler* masm) { 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : number of arguments 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[...]: constructor arguments 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label generic_array_code, one_or_more_arguments, two_or_more_arguments; 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the Array function. 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadArrayFunction(masm, r1); 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initial map for the builtin Array function shoud be a map. 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r2, Operand(kSmiTagMask)); 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(ne, "Unexpected initial map for Array function"); 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r2, r3, r4, MAP_TYPE); 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(eq, "Unexpected initial map for Array function"); 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Run the native code for the Array function called as a normal function. 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ArrayNativeCode(masm, &generic_array_code); 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the generic array code if the specialized code cannot handle 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the construction. 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&generic_array_code); 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* code = Builtins::builtin(Builtins::ArrayCodeGeneric); 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> array_code(code); 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(array_code, RelocInfo::CODE_TARGET); 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) { 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : number of arguments 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r1 : constructor function 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[...]: constructor arguments 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label generic_constructor; 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The array construct code is only set for the builtin Array function which 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // always have a map. 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadArrayFunction(masm, r2); 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r1, r2); 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(eq, "Unexpected Array function"); 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initial map for the builtin Array function should be a map. 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r2, Operand(kSmiTagMask)); 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(ne, "Unexpected initial map for Array function"); 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r2, r3, r4, MAP_TYPE); 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(eq, "Unexpected initial map for Array function"); 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Run the native code for the Array function called as a constructor. 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ArrayNativeCode(masm, &generic_constructor); 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the generic construct code in case the specialized code cannot 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // handle the construction. 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&generic_constructor); 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric); 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> generic_construct_stub(code); 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSConstructCall(MacroAssembler* masm) { 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : number of arguments 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r1 : constructor function 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[...]: constructor arguments 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label non_function_call; 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the function is not a smi. 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r1, Operand(kSmiTagMask)); 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &non_function_call); 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the function is a JSFunction. 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &non_function_call); 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the function-specific construct stub. 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kConstructStubOffset)); 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(pc, r2, Operand(Code::kHeaderSize - kHeapObjectTag)); 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: number of arguments 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: called object 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&non_function_call); 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set expected number of arguments to zero (not changing r0). 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(0)); 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::CODE_TARGET); 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkestatic void Generate_JSConstructStubHelper(MacroAssembler* masm, 512e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke bool is_api_function) { 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Enter a construct frame. 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ EnterConstructFrame(); 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Preserve the two incoming parameters on the stack. 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(r0, LSL, kSmiTagSize)); 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); // Smi-tagged arguments count. 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r1); // Constructor function. 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use r7 for holding undefined which is used in several places below. 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Try to allocate the object without transitioning into C code. If any of the 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // preconditions is not met, the code bails out to the runtime call. 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label rt_call, allocated; 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_inline_new) { 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label undo_allocation; 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference debug_step_in_fp = 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::debug_step_in_fp_address(); 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(debug_step_in_fp)); 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(r2)); 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r2, r2); 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(nz, &rt_call); 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the initial map and verify that it is in fact a map. 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r2, Operand(kSmiTagMask)); 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &rt_call); 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r2, r3, r4, MAP_TYPE); 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &rt_call); 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the constructor is not constructing a JSFunction (see comments 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // in Runtime_NewObject in runtime.cc). In which case the initial map's 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // instance type would be JS_FUNCTION_TYPE. 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: initial map 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &rt_call); 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Now allocate the JSObject on the heap. 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: initial map 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset)); 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, NO_ALLOCATION_FLAGS); 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocated the JSObject, now initialize the fields. Map is set to initial 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // map and properties and elements are set to empty fixed array. 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: initial map 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: object size 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject (not tagged) 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r5, r4); 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset); 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset); 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill all the in-object properties with undefined. 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: initial map 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: object size (in words) 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject (not tagged) 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5: First in-object property of JSObject (not tagged) 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object. 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize); 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { Label loop, entry; 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&entry); 590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r7, MemOperand(r5, kPointerSize, PostIndex)); 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry); 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r5, Operand(r6)); 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(lt, &loop); 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Add the object tag to make the JSObject real, so that we can continue and 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // jump into the continuation code at any time from now on. Any failures 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // need to undo the allocation, so that the heap is in a consistent state 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // and verifiable. 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r4, r4, Operand(kHeapObjectTag)); 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if a non-empty properties array is needed. Continue with allocated 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // object if not fall through to runtime call if it is. 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5: start of next object (not tagged) 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset)); 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The field instance sizes contains both pre-allocated property fields and 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // in-object properties. 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset)); 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(r6, 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r0, 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(0x000000FF << Map::kPreAllocatedPropertyFieldsByte * 8)); 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r3, r3, Operand(r6, LSR, Map::kPreAllocatedPropertyFieldsByte * 8)); 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(r6, r0, Operand(0x000000FF << Map::kInObjectPropertiesByte * 8)); 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r3, r3, Operand(r6, LSR, Map::kInObjectPropertiesByte * 8), SetCC); 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Done if no extra properties are to be allocated. 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &allocated); 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(pl, "Property allocation count failed."); 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Scale the number of elements by pointer size and add the header for 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // FixedArrays to the start of the next object calculation from above. 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: number of elements in properties array 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5: start of next object 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize)); 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ AllocateInNewSpace(r0, 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r5, 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r6, 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r2, 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &undo_allocation, 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RESULT_CONTAINS_TOP); 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize the FixedArray. 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: number of elements in properties array 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5: FixedArray (not tagged) 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex); 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, r5); 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r6, MemOperand(r2, kPointerSize, PostIndex)); 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(1 * kPointerSize, Array::kLengthOffset); 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r3, MemOperand(r2, kPointerSize, PostIndex)); 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize the fields to undefined. 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: First element of FixedArray (not tagged) 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: number of elements in properties array 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5: FixedArray (not tagged) 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r7: undefined 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2)); // End of object. 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize); 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { Label loop, entry; 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&entry); 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r7, MemOperand(r2, kPointerSize, PostIndex)); 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry); 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, Operand(r6)); 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(lt, &loop); 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store the initialized FixedArray into the properties field of 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the JSObject 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5: FixedArray (not tagged) 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r5, r5, Operand(kHeapObjectTag)); // Add the heap tag. 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r5, FieldMemOperand(r4, JSObject::kPropertiesOffset)); 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Continue with JSObject being successfully allocated 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&allocated); 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Undo the setting of the new top so that the heap is verifiable. For 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // example, the map's unused properties potentially do not match the 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // allocated objects unused properties. 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject (previous new top) 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&undo_allocation); 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ UndoAllocationInNewSpace(r4, r5); 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate the new receiver object using the runtime call. 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&rt_call); 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r1); // argument for Runtime_NewObject 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CallRuntime(Runtime::kNewObject, 1); 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r4, r0); 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Receiver for constructor call allocated. 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: JSObject 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&allocated); 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r4); 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the function and the allocated receiver from the stack. 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: receiver (newly allocated object) 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[1]: constructor function 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[2]: number of arguments (smi-tagged) 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(sp, kPointerSize)); 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r1); // Constructor function. 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r4); // Receiver. 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reload the number of arguments from the stack. 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: receiver 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[1]: constructor function 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[2]: receiver 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[3]: constructor function 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[4]: number of arguments (smi-tagged) 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, MemOperand(sp, 4 * kPointerSize)); 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Setup pointer to last argument. 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Setup number of arguments for function call below 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(r3, LSR, kSmiTagSize)); 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy arguments and receiver to the expression stack. 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: number of arguments 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: address of last argument (caller sp) 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: number of arguments (smi-tagged) 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: receiver 732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[1]: constructor function 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[2]: receiver 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[3]: constructor function 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[4]: number of arguments (smi-tagged) 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop, entry; 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&entry); 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1)); 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ip); 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry); 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r3, r3, Operand(2), SetCC); 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ge, &loop); 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call the function. 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: number of arguments 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 748e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (is_api_function) { 749e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 750e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Code> code = Handle<Code>( 751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Builtins::builtin(Builtins::HandleApiCallConstruct)); 752e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ParameterCount expected(0); 753e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ InvokeCode(code, expected, expected, 754e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke RelocInfo::CODE_TARGET, CALL_FUNCTION); 755e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 756e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ParameterCount actual(r0); 757e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ InvokeFunction(r1, actual, CALL_FUNCTION); 758e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop the function from the stack. 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: constructor function 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[2]: receiver 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[3]: constructor function 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[4]: number of arguments (smi-tagged) 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(); 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore context from the frame. 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: result 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: receiver 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[1]: constructor function 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[2]: number of arguments (smi-tagged) 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the result is an object (in the ECMA sense), we should get rid 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // of the receiver and use the result; see ECMA-262 section 13.2.2-7 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // on page 74. 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label use_receiver, exit; 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the result is a smi, it is *not* an object in the ECMA sense. 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: result 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: receiver (newly allocated object) 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[1]: constructor function 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[2]: number of arguments (smi-tagged) 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r0, Operand(kSmiTagMask)); 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &use_receiver); 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the type of the result (stored in its map) is less than 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // FIRST_JS_OBJECT_TYPE, it is not an object in the ECMA sense. 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r0, r3, r3, FIRST_JS_OBJECT_TYPE); 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ge, &exit); 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Throw away the result of the constructor invocation and use the 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // on-stack receiver as the result. 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&use_receiver); 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(sp)); 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Remove receiver from the stack, remove caller arguments, and 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // return. 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&exit); 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: result 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[0]: receiver (newly allocated object) 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[1]: constructor function 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // sp[2]: number of arguments (smi-tagged) 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LeaveConstructFrame(); 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(kPointerSize)); 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ IncrementCounter(&Counters::constructed_objects, 1, r1, r2); 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 813e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 814e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Generate_JSConstructStubHelper(masm, false); 815e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 816e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 817e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 818e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 819e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Generate_JSConstructStubHelper(masm, true); 820e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 821e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 822e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_construct) { 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Called from Generate_JS_Entry 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: code entry 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: receiver 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: argc 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: argv 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r5-r7, cp may be clobbered 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Clear the context before we push it when entering the JS frame. 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(cp, Operand(0)); 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Enter an internal frame. 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ EnterInternalFrame(); 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set up the context from the function argument. 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set up the roots register. 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference roots_address = ExternalReference::roots_address(); 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r10, Operand(roots_address)); 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the function and the receiver onto the stack. 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r1); 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r2); 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy arguments to the stack in a loop. 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: argc 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: argv, i.e. points to first arg 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop, entry; 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2)); 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2 points past last arg. 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&entry); 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex)); // read next parameter 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(r0)); // dereference handle 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); // push parameter 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry); 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r4, Operand(r2)); 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &loop); 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize all JavaScript callee-saved registers, since they will be seen 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // by the garbage collector as part of handlers. 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r5, Operand(r4)); 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r6, Operand(r4)); 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r7, Operand(r4)); 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (kR9Available == 1) { 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r9, Operand(r4)); 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the code and pass argc as r0. 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(r3)); 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (is_construct) { 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::CODE_TARGET); 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount actual(r0); 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeFunction(r1, actual, CALL_FUNCTION); 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit the JS frame and remove the parameters (except function), and return. 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Respect ABI stack constraint. 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LeaveInternalFrame(); 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: result 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Generate_JSEntryTrampolineHelper(masm, false); 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Generate_JSEntryTrampolineHelper(masm, true); 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_FunctionCall(MacroAssembler* masm) { 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 1. Make sure we have at least one argument. 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of argument 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { Label done; 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r0, Operand(r0)); 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &done); 911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r2); 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, r0, Operand(1)); 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&done); 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 2. Get the function to call from the stack. 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of argument 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { Label done, non_function, function; 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r1, Operand(kSmiTagMask)); 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &non_function); 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &function); 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Non-function called: Clear the function to force exception. 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&non_function); 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r1, Operand(0)); 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&done); 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Change the context eagerly because it will be used below to get the 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // right global object. 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&function); 934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&done); 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 3. Make sure first argument is an object; convert if necessary. 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { Label call_to_object, use_global_receiver, patch_receiver, done; 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(r2, -kPointerSize)); 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: first argument 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r2, Operand(kSmiTagMask)); 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &call_to_object); 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r3, Heap::kNullValueRootIndex); 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, r3); 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &use_global_receiver); 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, r3); 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &use_global_receiver); 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r2, r3, r3, FIRST_JS_OBJECT_TYPE); 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(lt, &call_to_object); 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r3, Operand(LAST_JS_OBJECT_TYPE)); 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(le, &done); 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&call_to_object); 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ EnterInternalFrame(); 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store number of arguments and function across the call into the runtime. 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(r0, LSL, kSmiTagSize)); 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r1); 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r2); 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS); 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, r0); 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore number of arguments and function. 977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(r1); 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(r0); 979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(r0, ASR, kSmiTagSize)); 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LeaveInternalFrame(); 982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&patch_receiver); 983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use the global receiver object from the called function as the receiver. 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&use_global_receiver); 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kGlobalIndex = 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(cp, kGlobalIndex)); 989d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalContextOffset)); 990d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r2, FieldMemOperand(r2, kGlobalIndex)); 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset)); 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&patch_receiver); 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2)); 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r3, -kPointerSize)); 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&done); 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 4. Shift stuff one slot down the stack 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments (including call() receiver) 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { Label loop; 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the copy start address (destination). Copy end address is sp. 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r2, r2, Operand(kPointerSize)); // copy receiver too 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(ip, MemOperand(r2, -kPointerSize)); 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(ip, MemOperand(r2)); 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r2, r2, Operand(kPointerSize)); 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, sp); 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &loop); 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 5. Adjust the actual number of arguments and remove the top element. 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments (including call() receiver) 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r0, r0, Operand(1)); 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(kPointerSize)); 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 6. Get the code for the function or the non-function builtin. 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If number of expected arguments matches, then call. Otherwise restart 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the arguments adaptor stub. 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { Label invoke; 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r1, r1); 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &invoke); 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(0)); // expected arguments is 0 for CALL_NON_FUNCTION 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::CODE_TARGET); 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&invoke); 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FieldMemOperand(r3, 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SharedFunctionInfo::kFormalParameterCountOffset)); 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MemOperand(r3, SharedFunctionInfo::kCodeOffset - kHeapObjectTag)); 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag)); 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, r0); // Check formal and actual parameter counts. 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RelocInfo::CODE_TARGET, ne); 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 7. Jump to the code in r3 without checking arguments. 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount expected(0); 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeCode(r3, expected, expected, JUMP_FUNCTION); 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_FunctionApply(MacroAssembler* masm) { 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kIndexOffset = -5 * kPointerSize; 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kLimitOffset = -4 * kPointerSize; 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kArgsOffset = 2 * kPointerSize; 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kRecvOffset = 3 * kPointerSize; 1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kFunctionOffset = 4 * kPointerSize; 1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ EnterInternalFrame(); 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function 1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(fp, kArgsOffset)); // get the args array 1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_JS); 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1069d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check the stack for overflow. We are not trying need to catch 1070d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // interruptions (e.g. debug break and preemption) here, so the "real stack 1071d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // limit" is checked. 1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label okay; 1073d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); 1074d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Make r2 the space we have left. The stack might already be overflowed 1075d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // here which will cause r2 to become negative. 1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r2, sp, r2); 1077d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Check if the arguments will overflow the stack. 1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 1079d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ b(gt, &okay); // Signed comparison. 1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Out of stack space. 1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(fp, kFunctionOffset)); 1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r1); 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_JS); 1086d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // End of stack check. 1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push current limit and index. 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&okay); 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); // limit 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r1, Operand(0)); // initial index 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r1); 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Change context eagerly to get the right global object if necessary. 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(fp, kFunctionOffset)); 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(cp, FieldMemOperand(r0, JSFunction::kContextOffset)); 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the receiver. 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label call_to_object, use_global_receiver, push_receiver; 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(fp, kRecvOffset)); 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ tst(r0, Operand(kSmiTagMask)); 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &call_to_object); 1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r1, Heap::kNullValueRootIndex); 1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, r1); 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &use_global_receiver); 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); 1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, r1); 1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &use_global_receiver); 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the receiver is already a JavaScript object. 1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: receiver 1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(lt, &call_to_object); 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE)); 1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(le, &push_receiver); 1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convert the receiver to a regular object. 1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: receiver 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&call_to_object); 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); 1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS); 1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&push_receiver); 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use the current global receiver object as the receiver. 1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&use_global_receiver); 1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kGlobalOffset = 1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; 1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, FieldMemOperand(cp, kGlobalOffset)); 1129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset)); 1130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r0, FieldMemOperand(r0, kGlobalOffset)); 1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); 1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the receiver. 1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: receiver 1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&push_receiver); 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy all arguments from the array to the stack. 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label entry, loop; 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(fp, kIndexOffset)); 1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&entry); 1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the current argument from the arguments array and push it to the 1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // stack. 1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: current argument index 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(fp, kArgsOffset)); 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r1); 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call the runtime to access the property in the arguments array. 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CallRuntime(Runtime::kGetProperty, 2); 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use inline caching to access the arguments. 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(fp, kIndexOffset)); 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, r0, Operand(1 << kSmiTagSize)); 1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r0, MemOperand(fp, kIndexOffset)); 1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Test if the copy loop has finished copying all the elements from the 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arguments object. 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry); 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(fp, kLimitOffset)); 1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, r1); 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &loop); 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Invoke the function. 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ParameterCount actual(r0); 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(r0, ASR, kSmiTagSize)); 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(fp, kFunctionOffset)); 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ InvokeFunction(r1, actual, CALL_FUNCTION); 1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Tear down the internal frame and remove function, receiver and args. 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LeaveInternalFrame(); 1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(3 * kPointerSize)); 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { 1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(r0, LSL, kSmiTagSize)); 1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() | fp.bit() | lr.bit()); 1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(fp, sp, Operand(3 * kPointerSize)); 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { 1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : result being passed through 1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the number of arguments passed (as a smi), tear down the frame and 1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // then tear down the parameters. 1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(fp, -3 * kPointerSize)); 1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(sp, fp); 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldm(ia_w, sp, fp.bit() | lr.bit()); 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize)); 1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(kPointerSize)); // adjust for receiver 1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { 1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : actual number of arguments 1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r1 : function (passed through to callee) 1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : expected number of arguments 1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r3 : code entry to call 1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label invoke, dont_adapt_arguments; 1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label enough, too_few; 1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand(r2)); 1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(lt, &too_few); 1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel)); 1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &dont_adapt_arguments); 1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { // Enough parameters: actual >= expected 1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&enough); 1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EnterArgumentsAdaptorFrame(masm); 1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate copy start address into r0 and copy end address into r2. 1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments as a smi 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: expected number of arguments 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: code entry to call 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // adjust for return address and receiver 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, r0, Operand(2 * kPointerSize)); 1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r2, r0, Operand(r2, LSL, kPointerSizeLog2)); 1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy the arguments (including the receiver) to the new stack frame. 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: copy start address 1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: copy end address 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: code entry to call 1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label copy; 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(©); 1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(ip, MemOperand(r0, 0)); 1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ip); 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, r2); // Compare before moving to next argument. 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r0, r0, Operand(kPointerSize)); 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, ©); 1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&invoke); 1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { // Too few parameters: Actual < expected 1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&too_few); 1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EnterArgumentsAdaptorFrame(masm); 1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate copy start address into r0 and copy end address is fp. 1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments as a smi 1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: expected number of arguments 1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: code entry to call 1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy the arguments (including the receiver) to the new stack frame. 1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: copy start address 1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: expected number of arguments 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: code entry to call 1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label copy; 1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(©); 1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust load for return address and receiver. 1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(ip, MemOperand(r0, 2 * kPointerSize)); 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ip); 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, fp); // Compare before moving to next argument. 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r0, r0, Operand(kPointerSize)); 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, ©); 1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the remaining expected arguments with undefined. 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: expected number of arguments 1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: code entry to call 1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r2, fp, Operand(r2, LSL, kPointerSizeLog2)); 1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r2, r2, Operand(4 * kPointerSize)); // Adjust for frame. 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fill; 1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fill); 1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ip); 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(sp, r2); 1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &fill); 1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call the entry point. 1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&invoke); 1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Call(r3); 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit frame and return. 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LeaveArgumentsAdaptorFrame(masm); 1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ------------------------------------------- 1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Dont adapt arguments. 1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ------------------------------------------- 1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&dont_adapt_arguments); 1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(r3); 1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 1309