13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_ARM 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/debug.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/deoptimizer.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/full-codegen.h" 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/runtime.h" 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm) 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_Adaptor(MacroAssembler* masm, 23e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke CFunctionId id, 24e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BuiltinExtraArguments extra_args) { 25e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------- S t a t e ------------- 26e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- r0 : number of arguments excluding receiver 27e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- r1 : called function (only guaranteed when 28e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // extra_args requires it) 29e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- cp : context 30e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- sp[0] : last argument 31e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 32e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- sp[4 * (argc - 1)] : first argument (argc == r0) 33e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- sp[4 * argc] : receiver 34e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------------------------------- 35e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 36e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Insert extra arguments. 37e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int num_extra_args = 0; 38e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (extra_args == NEEDS_CALLED_FUNCTION) { 39e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke num_extra_args = 1; 40e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ push(r1); 41e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(extra_args == NO_EXTRA_ARGUMENTS); 43e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 44e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // JumpToExternalReference expects r0 to contain the number of arguments 46e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // including the receiver and the extra arguments. 47e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ add(r0, r0, Operand(num_extra_args + 1)); 4844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ JumpToExternalReference(ExternalReference(id, masm->isolate())); 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Load the built-in InternalArray function from the current context. 533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateLoadInternalArrayFunction(MacroAssembler* masm, 543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register result) { 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the native context. 563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(result, 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(result, 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(result, GlobalObject::kNativeContextOffset)); 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the InternalArray function from the native context. 623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(result, 633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MemOperand(result, 643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Context::SlotOffset( 653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Context::INTERNAL_ARRAY_FUNCTION_INDEX))); 663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load the built-in Array function from the current context. 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) { 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the native context. 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(result, 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(result, 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(result, GlobalObject::kNativeContextOffset)); 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the Array function from the native context. 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(result, 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MemOperand(result, 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { 853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ----------- S t a t e ------------- 863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- r0 : number of arguments 873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- lr : return address 883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- sp[...]: constructor arguments 893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ----------------------------------- 903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label generic_array_code, one_or_more_arguments, two_or_more_arguments; 913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the InternalArray function. 933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadInternalArrayFunction(masm, r1); 943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initial map for the builtin InternalArray functions should be maps. 973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTst(r2); 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(ne, kUnexpectedInitialMapForInternalArrayFunction); 1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareObjectType(r2, r3, r4, MAP_TYPE); 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(eq, kUnexpectedInitialMapForInternalArrayFunction); 1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Run the native code for the InternalArray function called as a normal 1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // function. 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // tail call a stub 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InternalArrayConstructorStub stub(masm->isolate()); 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub); 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArrayCode(MacroAssembler* masm) { 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : number of arguments 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[...]: constructor arguments 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label generic_array_code, one_or_more_arguments, two_or_more_arguments; 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the Array function. 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GenerateLoadArrayFunction(masm, r1); 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 124e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Initial map for the builtin Array functions should be maps. 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTst(r2); 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(ne, kUnexpectedInitialMapForArrayFunction); 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CompareObjectType(r2, r3, r4, MAP_TYPE); 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(eq, kUnexpectedInitialMapForArrayFunction); 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Run the native code for the Array function called as a normal function. 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // tail call a stub 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArrayConstructorStub stub(masm->isolate()); 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub); 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid Builtins::Generate_StringConstructCode(MacroAssembler* masm) { 1418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // ----------- S t a t e ------------- 1428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- r0 : number of arguments 1438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- r1 : constructor function 1448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- lr : return address 1458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[(argc - n - 1) * 4] : arg[n] (zero based) 1468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- sp[argc * 4] : receiver 1478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // ----------------------------------- 14844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm->isolate()->counters(); 14944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->string_ctor_calls(), 1, r2, r3); 1508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register function = r1; 1528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (FLAG_debug_code) { 1538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, r2); 1548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(function, Operand(r2)); 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(eq, kUnexpectedStringFunction); 1568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 1578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the first arguments in r0 and get rid of the rest. 1598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label no_arguments; 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r0, Operand::Zero()); 1618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(eq, &no_arguments); 1628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // First args = sp[(argc - 1) * 4]. 1638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ sub(r0, r0, Operand(1)); 1648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r0, MemOperand(sp, r0, LSL, kPointerSizeLog2, PreIndex)); 1658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // sp now point to args[0], drop args[0] + receiver. 1668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(2); 1678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register argument = r2; 1698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label not_cached, argument_is_string; 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LookupNumberStringCache(r0, // Input. 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch argument, // Result. 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch r3, // Scratch. 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch r4, // Scratch. 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch r5, // Scratch. 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ¬_cached); 17644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->string_ctor_cached_number(), 1, r3, r4); 1778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&argument_is_string); 1788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // ----------- S t a t e ------------- 1808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- r2 : argument converted to string 1818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- r1 : constructor function 1828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- lr : return address 1838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // ----------------------------------- 1848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label gc_required; 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Allocate(JSValue::kSize, 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch r0, // Result. 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch r3, // Scratch. 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch r4, // Scratch. 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &gc_required, 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TAG_OBJECT); 1928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Initialising the String Object. 1948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register map = r3; 1958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadGlobalFunctionInitialMap(function, map, r4); 1968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (FLAG_debug_code) { 1978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldrb(r4, FieldMemOperand(map, Map::kInstanceSizeOffset)); 1988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ cmp(r4, Operand(JSValue::kSize >> kPointerSizeLog2)); 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(eq, kUnexpectedStringWrapperInstanceSize); 2008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldrb(r4, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset)); 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r4, Operand::Zero()); 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(eq, kUnexpectedUnusedPropertiesOfStringWrapper); 2038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 2048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(map, FieldMemOperand(r0, HeapObject::kMapOffset)); 2058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex); 2078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset)); 2088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset)); 2098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ str(argument, FieldMemOperand(r0, JSValue::kValueOffset)); 2118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Ensure the object is fully initialized. 2138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); 2148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 2168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // The argument was not found in the number to string cache. Check 2188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // if it's a string already before calling the conversion builtin. 2198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Label convert_argument; 2208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(¬_cached); 2211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(r0, &convert_argument); 2228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Is it a String? 2248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 2258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceTypeOffset)); 22669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kNotStringTag != 0); 2278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ tst(r3, Operand(kIsNotStringMask)); 2288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(ne, &convert_argument); 2298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(argument, r0); 23044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4); 2318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&argument_is_string); 2328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Invoke the conversion builtin and put the result into r2. 2348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&convert_argument); 2358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ push(function); // Preserve the function. 23644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4); 2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION); 2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ pop(function); 2438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ mov(argument, r0); 2448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&argument_is_string); 2458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the empty string into r2, remove the receiver from the 2478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // stack, and jump back to the case where the argument is a string. 2488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&no_arguments); 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(argument, Heap::kempty_stringRootIndex); 2508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Drop(1); 2518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ b(&argument_is_string); 2528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // At this point the argument is already a string. Call runtime to 2548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // create a string wrapper. 2558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ bind(&gc_required); 25644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->string_ctor_gc_required(), 1, r3, r4); 2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(argument); 2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kNewStringWrapper, 1); 2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Ret(); 26380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 26480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 26580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CallRuntimePassFunction( 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Runtime::FunctionId function_id) { 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push a copy of the function onto the stack. 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r1); 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push function as parameter to the runtime call. 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(r1); 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(function_id, 1); 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore receiver. 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(r1); 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GenerateTailCallToSharedCode(MacroAssembler* masm) { 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCodeOffset)); 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(r2, r2, Operand(Code::kHeaderSize - kHeapObjectTag)); 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Jump(r2); 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GenerateTailCallToReturnedCode(MacroAssembler* masm) { 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(r0, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Jump(r0); 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) { 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Checking whether the queued function is ready for install is optional, 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // since we come across interrupts and stack checks elsewhere. However, 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // not checking may delay installing ready functions, and always checking 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // would be quite expensive. A good compromise is to first check against 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // stack limit as a cue for an interrupt signal. 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(ip, Heap::kStackLimitRootIndex); 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(sp, Operand(ip)); 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(hs, &ok); 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateTailCallToReturnedCode(masm); 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&ok); 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateTailCallToSharedCode(masm); 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void Generate_JSConstructStubHelper(MacroAssembler* masm, 3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_api_function, 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool create_memento) { 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : number of arguments 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r1 : constructor function 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- r2 : allocation site or undefined 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- lr : return address 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- sp[...]: constructor arguments 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Should never create mementos for api functions. 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!is_api_function || !create_memento); 3260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 32744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate = masm->isolate(); 32844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Enter a construct frame. 3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (create_memento) { 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertUndefinedOrAllocationSite(r2, r3); 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r2); 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Preserve the two incoming parameters on the stack. 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(r0); 3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); // Smi-tagged arguments count. 3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r1); // Constructor function. 3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Try to allocate the object without transitioning into C code. If any of 3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the preconditions is not met, the code bails out to the runtime call. 3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label rt_call, allocated; 3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_inline_new) { 3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label undo_allocation; 3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference debug_step_in_fp = 3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::debug_step_in_fp_address(isolate); 3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r2, Operand(debug_step_in_fp)); 3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r2, MemOperand(r2)); 3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ tst(r2, r2); 3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &rt_call); 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the initial map and verify that it is in fact a map. 3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor function 3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(r2, &rt_call); 3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareObjectType(r2, r3, r4, MAP_TYPE); 3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &rt_call); 3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that the constructor is not constructing a JSFunction (see 3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // comments in Runtime_NewObject in runtime.cc). In which case the 3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // initial map's instance type would be JS_FUNCTION_TYPE. 3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor function 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r2: initial map 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); 3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, &rt_call); 36985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!is_api_function) { 3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label allocate; 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand bit_field3 = FieldMemOperand(r2, Map::kBitField3Offset); 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if slack tracking is enabled. 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r4, bit_field3); 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ DecodeField<Map::ConstructionCount>(r3, r4); 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r3, Operand(JSFunction::kNoSlackTracking)); 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, &allocate); 3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Decrease generous allocation count. 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(r4, r4, Operand(1 << Map::ConstructionCount::kShift)); 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r4, bit_field3); 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r3, Operand(JSFunction::kFinishSlackTracking)); 3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &allocate); 3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r1); 3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(r2, r1); // r1 = constructor 3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); 3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(r2); 3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(r1); 3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&allocate); 3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Now allocate the JSObject on the heap. 3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor function 3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r2: initial map 3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset)); 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (create_memento) { 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(r3, r3, Operand(AllocationMemento::kSize / kPointerSize)); 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Allocate(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS); 4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocated the JSObject, now initialize the fields. Map is set to 4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // initial map and properties and elements are set to empty fixed array. 4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor function 4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r2: initial map 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r3: object size (not including memento if create_memento) 4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r4: JSObject (not tagged) 4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); 4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r5, r4); 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0 * kPointerSize, JSObject::kMapOffset); 4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(1 * kPointerSize, JSObject::kPropertiesOffset); 4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(2 * kPointerSize, JSObject::kElementsOffset); 4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Fill all the in-object properties with the appropriate filler. 4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor function 4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r2: initial map 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r3: object size (in words, including memento if create_memento) 4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r4: JSObject (not tagged) 4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r5: First in-object property of JSObject (not tagged) 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(3 * kPointerSize, JSObject::kHeaderSize); 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r6, Heap::kUndefinedValueRootIndex); 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!is_api_function) { 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label no_inobject_slack_tracking; 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if slack tracking is enabled. 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(ip, FieldMemOperand(r2, Map::kBitField3Offset)); 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ DecodeField<Map::ConstructionCount>(ip); 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ip, Operand(JSFunction::kNoSlackTracking)); 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, &no_inobject_slack_tracking); 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Allocate object with a slack. 4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset)); 4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ubfx(r0, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte, 4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kBitsPerByte); 4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r0, r5, Operand(r0, LSL, kPointerSizeLog2)); 4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r0: offset of first field after pre-allocated fields 4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(ip, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object. 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r0, ip); 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields); 4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InitializeFieldsWithFiller(r5, r0, r6); 4500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // To allow for truncation. 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r6, Heap::kOnePointerFillerMapRootIndex); 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fill the remaining fields with one pointer filler map. 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&no_inobject_slack_tracking); 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (create_memento) { 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(ip, r3, Operand(AllocationMemento::kSize / kPointerSize)); 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(r0, r4, Operand(ip, LSL, kPointerSizeLog2)); // End of object. 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InitializeFieldsWithFiller(r5, r0, r6); 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fill in memento fields. 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r5: points to the allocated but uninitialized memento. 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r6, Heap::kAllocationMementoMapRootIndex); 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0 * kPointerSize, AllocationMemento::kMapOffset); 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the AllocationSite 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r6, MemOperand(sp, 2 * kPointerSize)); 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(1 * kPointerSize, AllocationMemento::kAllocationSiteOffset); 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(r0, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object. 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InitializeFieldsWithFiller(r5, r0, r6); 4740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Add the object tag to make the JSObject real, so that we can continue 4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // and jump into the continuation code at any time from now on. Any 4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // failures need to undo the allocation, so that the heap is in a 4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // consistent state and verifiable. 4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r4, r4, Operand(kHeapObjectTag)); 4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if a non-empty properties array is needed. Continue with 4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allocated object if not fall through to runtime call if it is. 4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor function 4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r4: JSObject 4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r5: start of next object (not tagged) 4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset)); 4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The field instance sizes contains both pre-allocated property fields 4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // and in-object properties. 4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset)); 4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ubfx(r6, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte, 4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kBitsPerByte); 4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r3, r3, Operand(r6)); 4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ubfx(r6, r0, Map::kInObjectPropertiesByte * kBitsPerByte, 4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kBitsPerByte); 4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(r3, r3, Operand(r6), SetCC); 4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Done if no extra properties are to be allocated. 4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(eq, &allocated); 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(pl, kPropertyAllocationCountFailed); 5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Scale the number of elements by pointer size and add the header for 5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // FixedArrays to the start of the next object calculation from above. 5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor 5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r3: number of elements in properties array 5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r4: JSObject 5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r5: start of next object 5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize)); 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Allocate( 5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r0, 5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r5, 5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r6, 5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r2, 5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &undo_allocation, 5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS)); 5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initialize the FixedArray. 5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor 5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r3: number of elements in properties array 5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r4: JSObject 5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r5: FixedArray (not tagged) 5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex); 5233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r2, r5); 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0 * kPointerSize, JSObject::kMapOffset); 5253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r6, MemOperand(r2, kPointerSize, PostIndex)); 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(1 * kPointerSize, FixedArray::kLengthOffset); 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(r0, r3); 5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r0, MemOperand(r2, kPointerSize, PostIndex)); 5293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initialize the fields to undefined. 5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor function 5323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r2: First element of FixedArray (not tagged) 5333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r3: number of elements in properties array 5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r4: JSObject 5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r5: FixedArray (not tagged) 5363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2)); // End of object. 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(2 * kPointerSize, FixedArray::kHeaderSize); 5383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { Label loop, entry; 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 5403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(&entry); 5413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&loop); 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r0, MemOperand(r2, kPointerSize, PostIndex)); 5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&entry); 5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r2, r6); 5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(lt, &loop); 54685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } 5473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the initialized FixedArray into the properties field of 5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the JSObject 5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor function 5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r4: JSObject 5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r5: FixedArray (not tagged) 5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r5, r5, Operand(kHeapObjectTag)); // Add the heap tag. 5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r5, FieldMemOperand(r4, JSObject::kPropertiesOffset)); 5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Continue with JSObject being successfully allocated 5573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor function 5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r4: JSObject 5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&allocated); 5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Undo the setting of the new top so that the heap is verifiable. For 5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // example, the map's unused properties potentially do not match the 5633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allocated objects unused properties. 5643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r4: JSObject (previous new top) 5653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&undo_allocation); 5663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ UndoAllocationInNewSpace(r4, r5); 56785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate the new receiver object using the runtime call. 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: constructor function 5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&rt_call); 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (create_memento) { 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the cell or allocation site. 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, MemOperand(sp, 2 * kPointerSize)); 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r2); 576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r1); // argument for Runtime_NewObject 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (create_memento) { 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 2); 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kNewObject, 1); 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r4, r0); 5853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we ended up using the runtime, and we want a memento, then the 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // runtime call made it for us, and we shouldn't do create count 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // increment. 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label count_incremented; 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (create_memento) { 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&count_incremented); 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Receiver for constructor call allocated. 59585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // r4: JSObject 5963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&allocated); 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (create_memento) { 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, MemOperand(sp, kPointerSize * 2)); 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r2, r5); 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, &count_incremented); 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r2 is an AllocationSite. We are creating a memento from it, so we 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // need to increment the memento create count. 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, FieldMemOperand(r2, 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSite::kPretenureCreateCountOffset)); 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(r3, r3, Operand(Smi::FromInt(1))); 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(r3, FieldMemOperand(r2, 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSite::kPretenureCreateCountOffset)); 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&count_incremented); 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r4); 6143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r4); 6153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Reload the number of arguments and the constructor from the stack. 6173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[0]: receiver 6183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[1]: receiver 6193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[2]: constructor function 6203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[3]: number of arguments (smi-tagged) 6213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); 6223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r3, MemOperand(sp, 3 * kPointerSize)); 6233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up pointer to last argument. 6253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); 6263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up number of arguments for function call below 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(r0, r3); 6293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Copy arguments and receiver to the expression stack. 6313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r0: number of arguments 6323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: constructor function 6333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r2: address of last argument (caller sp) 6343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r3: number of arguments (smi-tagged) 6353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[0]: receiver 6363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[1]: receiver 6373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[2]: constructor function 6383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[3]: number of arguments (smi-tagged) 6393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label loop, entry; 6403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(&entry); 6413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&loop); 6423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1)); 6433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(ip); 6443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&entry); 6453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(r3, r3, Operand(2), SetCC); 6463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ge, &loop); 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Call the function. 6493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r0: number of arguments 65085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // r1: constructor function 6513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_api_function) { 6523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 6533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = 6543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->builtins()->HandleApiCallConstruct(); 655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Call(code, RelocInfo::CODE_TARGET); 6563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 6573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ParameterCount actual(r0); 658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeFunction(r1, actual, CALL_FUNCTION, NullCallWrapper()); 6593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store offset of return address for deoptimizer. 662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!is_api_function) { 6633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); 6643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 66585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 6663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore context from the frame. 6673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r0: result 6683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[0]: receiver 6693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[1]: constructor function 6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[2]: number of arguments (smi-tagged) 6713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 6723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the result is an object (in the ECMA sense), we should get rid 6743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // of the receiver and use the result; see ECMA-262 section 13.2.2-7 6753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // on page 74. 6763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label use_receiver, exit; 6773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the result is a smi, it is *not* an object in the ECMA sense. 6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r0: result 6803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[0]: receiver (newly allocated object) 6813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[1]: constructor function 6823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[2]: number of arguments (smi-tagged) 6833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(r0, &use_receiver); 6843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the type of the result (stored in its map) is less than 6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. 687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareObjectType(r0, r1, r3, FIRST_SPEC_OBJECT_TYPE); 6883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ge, &exit); 6893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Throw away the result of the constructor invocation and use the 6913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // on-stack receiver as the result. 6923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&use_receiver); 6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, MemOperand(sp)); 6943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Remove receiver from the stack, remove caller arguments, and 6963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // return. 6973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&exit); 6983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r0: result 6993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[0]: receiver (newly allocated object) 7003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[1]: constructor function 7013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // sp[2]: number of arguments (smi-tagged) 7023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); 7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Leave construct frame. 705e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(kPointerSize)); 70944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2); 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 714e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); 716e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 719e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 7200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Generate_JSConstructStubHelper(masm, true, false); 721e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 722e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 723e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_construct) { 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Called from Generate_JS_Entry 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: code entry 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: receiver 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: argc 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r4: argv 732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r5-r6, r8 (if not FLAG_enable_ool_constant_pool) and cp may be clobbered 733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ProfileEntryHookStub::MaybeCallEntryHook(masm); 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Clear the context before we push it when entering the internal frame. 736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(cp, Operand::Zero()); 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Enter an internal frame. 7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 7403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the context from the function argument. 7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InitializeRootRegister(); 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push the function and the receiver onto the stack. 7483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r1); 7493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r2); 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Copy arguments to the stack in a loop. 7523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r1: function 7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r3: argc 7543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r4: argv, i.e. points to first arg 7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label loop, entry; 7563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2)); 7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r2 points past last arg. 7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(&entry); 7593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&loop); 7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex)); // read next parameter 7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, MemOperand(r0)); // dereference handle 7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); // push parameter 7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&entry); 7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r4, r2); 7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &loop); 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initialize all JavaScript callee-saved registers, since they will be seen 7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // by the garbage collector as part of handlers. 7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); 7703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r5, Operand(r4)); 7713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r6, Operand(r4)); 772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!FLAG_enable_ool_constant_pool) { 773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r8, Operand(r4)); 774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 7753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (kR9Available == 1) { 7763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r9, Operand(r4)); 7773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 77885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 7793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Invoke the code and pass argc as r0. 7803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r0, Operand(r3)); 7813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_construct) { 782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // No type feedback cell is available 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS); 7853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 7863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 7873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ParameterCount actual(r0); 788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeFunction(r1, actual, CALL_FUNCTION, NullCallWrapper()); 7893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 7903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Exit the JS frame and remove the parameters (except function), and 7913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // return. 7923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Respect ABI stack constraint. 7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: result 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Generate_JSEntryTrampolineHelper(masm, false); 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Generate_JSEntryTrampolineHelper(masm, true); 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_CompileLazy(MacroAssembler* masm) { 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallRuntimePassFunction(masm, Runtime::kCompileLazy); 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateTailCallToReturnedCode(masm); 813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 814756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 815756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CallCompileOptimized(MacroAssembler* masm, bool concurrent) { 817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push a copy of the function onto the stack. 819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(r1); 820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push function as parameter to the runtime call. 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(r1); 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Whether to compile in a background thread. 823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(masm->isolate()->factory()->ToBoolean(concurrent)); 824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kCompileOptimized, 2); 826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore receiver. 827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(r1); 828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 829756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 830756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_CompileOptimized(MacroAssembler* masm) { 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCompileOptimized(masm, false); 833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateTailCallToReturnedCode(masm); 834756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 835756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 836756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_CompileOptimizedConcurrent(MacroAssembler* masm) { 838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCompileOptimized(masm, true); 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateTailCallToReturnedCode(masm); 840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) { 844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For now, we are relying on the fact that make_code_young doesn't do any 845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // garbage collection which allows us to save/restore the registers without 846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // worrying about which of them contain pointers. We also don't build an 847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // internal frame to make the code faster, since we shouldn't have to do stack 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // crawls in MakeCodeYoung. This seems a bit fragile. 849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The following registers must be saved and restored when calling through to 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the runtime: 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r0 - contains return address (beginning of patch sequence) 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r1 - isolate 854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ stm(db_w, sp, r0.bit() | r1.bit() | fp.bit() | lr.bit()); 856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PrepareCallCFunction(2, 0, r2); 857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r1, Operand(ExternalReference::isolate_address(masm->isolate()))); 858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallCFunction( 859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::get_make_code_young_function(masm->isolate()), 2); 860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldm(ia_w, sp, r0.bit() | r1.bit() | fp.bit() | lr.bit()); 861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(pc, r0); 862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DEFINE_CODE_AGE_BUILTIN_GENERATOR(C) \ 865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_Make##C##CodeYoungAgainEvenMarking( \ 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm) { \ 867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateMakeCodeYoungAgainCommon(masm); \ 868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} \ 869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_Make##C##CodeYoungAgainOddMarking( \ 870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm) { \ 871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateMakeCodeYoungAgainCommon(masm); \ 872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR) 874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef DEFINE_CODE_AGE_BUILTIN_GENERATOR 875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) { 878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For now, as in GenerateMakeCodeYoungAgainCommon, we are relying on the fact 879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // that make_code_young doesn't do any garbage collection which allows us to 880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // save/restore the registers without worrying about which of them contain 881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // pointers. 882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The following registers must be saved and restored when calling through to 884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the runtime: 885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r0 - contains return address (beginning of patch sequence) 886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r1 - isolate 887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ stm(db_w, sp, r0.bit() | r1.bit() | fp.bit() | lr.bit()); 889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PrepareCallCFunction(2, 0, r2); 890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r1, Operand(ExternalReference::isolate_address(masm->isolate()))); 891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallCFunction(ExternalReference::get_mark_code_as_executed_function( 892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()), 2); 893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldm(ia_w, sp, r0.bit() | r1.bit() | fp.bit() | lr.bit()); 894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform prologue operations usually performed by the young code stub. 896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushFixedFrame(r1); 897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); 898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Jump to point after the code-age stub. 900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(r0, r0, Operand(kNoCodeAgeSequenceLength)); 901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(pc, r0); 902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) { 906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateMakeCodeYoungAgainCommon(masm); 907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void Generate_NotifyStubFailureHelper(MacroAssembler* masm, 911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SaveFPRegsMode save_doubles) { 912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve registers across notification, this is important for compiled 916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // stubs that tail call the runtime on deopts passing their parameters in 917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // registers. 918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ stm(db_w, sp, kJSCallerSaved | kCalleeSaved); 919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pass the function and deoptimization type to the runtime system. 920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kNotifyStubFailure, 0, save_doubles); 921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldm(ia_w, sp, kJSCallerSaved | kCalleeSaved); 9223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(sp, sp, Operand(kPointerSize)); // Ignore state 925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(pc, lr); // Jump to miss handler 926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) { 930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Generate_NotifyStubFailureHelper(masm, kDontSaveFPRegs); 931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) { 935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Generate_NotifyStubFailureHelper(masm, kSaveFPRegs); 936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm, 940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Deoptimizer::BailoutType type) { 9413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 9433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Pass the function and deoptimization type to the runtime system. 9443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r0, Operand(Smi::FromInt(static_cast<int>(type)))); 9453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 9463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kNotifyDeoptimized, 1); 9473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Get the full codegen state from the stack and untag it -> r6. 950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r6, MemOperand(sp, 0 * kPointerSize)); 951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ SmiUntag(r6); 952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Switch on the state. 953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label with_tos_register, unknown_state; 954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(r6, Operand(FullCodeGenerator::NO_REGISTERS)); 955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ b(ne, &with_tos_register); 956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(sp, sp, Operand(1 * kPointerSize)); // Remove state. 957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ Ret(); 958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&with_tos_register); 960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); 961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(r6, Operand(FullCodeGenerator::TOS_REG)); 962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ b(ne, &unknown_state); 963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(sp, sp, Operand(2 * kPointerSize)); // Remove state. 964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ Ret(); 965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&unknown_state); 967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ stop("no cases left"); 968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) { 972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); 973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) { 977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT); 978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) { 982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); 983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { 987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Lookup the function in the JavaScript frame. 9881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 9893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pass function as argument. 9923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 9933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1); 9943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 9951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the code object is null, just return to the unoptimized code. 9971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label skip; 998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r0, Operand(Smi::FromInt(0))); 9991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ b(ne, &skip); 10001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(); 10011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 10021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&skip); 1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load deoptimization data from the code object. 1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // <deopt_data> = <code>[#deoptimization_data_offset] 1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r1, FieldMemOperand(r0, Code::kDeoptimizationDataOffset)); 1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { ConstantPoolUnavailableScope constant_pool_unavailable(masm); 1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_enable_ool_constant_pool) { 1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(pp, FieldMemOperand(r0, Code::kConstantPoolOffset)); 1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the OSR entrypoint offset from the deoptimization data. 1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // <osr_offset> = <deopt_data>[#header_size + #osr_pc_offset] 1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r1, FieldMemOperand(r1, FixedArray::OffsetOfElementAt( 1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizationInputData::kOsrPcOffsetIndex))); 1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compute the target address = code_obj + header_size + osr_offset 1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // <entry_addr> = <code_obj> + #header_size + <osr_offset> 1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(r0, r0, Operand::SmiUntag(r1)); 1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(lr, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); 1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // And "return" to the OSR entry point of the function. 1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) { 1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We check the stack limit as indicator that recompilation might be done. 1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(ip, Heap::kStackLimitRootIndex); 1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(sp, Operand(ip)); 1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(hs, &ok); 1035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 1036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kStackGuard, 0); 1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Jump(masm->isolate()->builtins()->OnStackReplacement(), 1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfo::CODE_TARGET); 1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&ok); 1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 1044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_FunctionCall(MacroAssembler* masm) { 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 1. Make sure we have at least one argument. 1049402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r0: actual number of arguments 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { Label done; 1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r0, Operand::Zero()); 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &done); 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r2); 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, r0, Operand(1)); 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&done); 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1059402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // 2. Get the function to call (passed as receiver) from the stack, check 1060402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // if it is a function. 1061402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r0: actual number of arguments 1062589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label slow, non_function; 1063402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); 10643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r1, &non_function); 1065402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); 1066589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ b(ne, &slow); 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1068402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // 3a. Patch the first argument if necessary when calling a function. 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1071402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label shift_arguments; 1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r4, Operand::Zero()); // indicate regular JS_FUNCTION 1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { Label convert_to_object, use_global_proxy, patch_receiver; 1074402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Change context eagerly in case we need the global receiver. 1075402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 1076402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1077e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Do not transform the receiver for strict mode functions. 1078e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 1079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldr(r3, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset)); 1080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ tst(r3, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + 1081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kSmiTagSize))); 1082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ b(ne, &shift_arguments); 1083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Do not transform the receiver for native (Compilerhints already in r3). 10853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ tst(r3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); 1086e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ b(ne, &shift_arguments); 1087e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compute the receiver in sloppy mode. 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, MemOperand(r2, -kPointerSize)); 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: first argument 10943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(r2, &convert_to_object); 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, r3); 1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, &use_global_proxy); 1099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(r3, Heap::kNullValueRootIndex); 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, r3); 1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, &use_global_proxy); 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 11043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CompareObjectType(r2, r3, r3, FIRST_SPEC_OBJECT_TYPE); 1105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ b(ge, &shift_arguments); 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1107402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(&convert_to_object); 1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 11103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Enter an internal frame in order to preserve argument count. 1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(r0); 11133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 11143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 11153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r2); 11163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 11173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(r2, r0); 11183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 11193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(r0); 1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(r0); 11213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 11223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Exit the internal frame. 11233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1125589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Restore the function to r1, and the flag to r4. 1126402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); 1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r4, Operand::Zero()); 1128402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ jmp(&patch_receiver); 1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&use_global_proxy); 1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); 1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalProxyOffset)); 1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&patch_receiver); 1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2)); 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r3, -kPointerSize)); 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1138402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ jmp(&shift_arguments); 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1141589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // 3b. Check for function proxy. 1142589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&slow); 1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r4, Operand(1, RelocInfo::NONE32)); // indicate function proxy 1144589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ cmp(r2, Operand(JS_FUNCTION_PROXY_TYPE)); 1145589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ b(eq, &shift_arguments); 1146589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&non_function); 1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r4, Operand(2, RelocInfo::NONE32)); // indicate non-function 1148589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1149589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // 3c. Patch the first argument when calling a non-function. The 1150402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // CALL_NON_FUNCTION builtin expects the non-function callee as 1151402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // receiver, so overwrite the first argument which will ultimately 1152402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // become the receiver. 1153402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r0: actual number of arguments 1154402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r1: function 1155589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // r4: call type (0: JS function, 1: function proxy, 2: non-function) 1156402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); 1157402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ str(r1, MemOperand(r2, -kPointerSize)); 1158402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1159402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // 4. Shift arguments and return address one slot down on the stack 1160402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // (overwriting the original receiver). Adjust argument count to make 1161402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // the original first argument the new receiver. 1162402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r0: actual number of arguments 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1164589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // r4: call type (0: JS function, 1: function proxy, 2: non-function) 1165402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(&shift_arguments); 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { Label loop; 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the copy start address (destination). Copy end address is sp. 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2)); 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(ip, MemOperand(r2, -kPointerSize)); 1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(ip, MemOperand(r2)); 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r2, r2, Operand(kPointerSize)); 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, sp); 1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &loop); 1176402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Adjust the actual number of arguments and remove the top element 1177402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // (which is a copy of the last argument). 1178402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ sub(r0, r0, Operand(1)); 1179402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(); 1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1182589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin, 1183589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // or a function proxy via CALL_FUNCTION_PROXY. 1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1186589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // r4: call type (0: JS function, 1: function proxy, 2: non-function) 1187589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch { Label function, non_proxy; 1188589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ tst(r4, r4); 1189589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ b(eq, &function); 11909ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick // Expected number of arguments is 0 for CALL_NON_FUNCTION. 1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r2, Operand::Zero()); 1192589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ cmp(r4, Operand(1)); 1193589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ b(ne, &non_proxy); 1194589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1195589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ push(r1); // re-add proxy object as additional argument 1196589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ add(r0, r0, Operand(1)); 1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ GetBuiltinFunction(r1, Builtins::CALL_FUNCTION_PROXY); 1198589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 1199589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch RelocInfo::CODE_TARGET); 1200589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1201589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&non_proxy); 1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ GetBuiltinFunction(r1, Builtins::CALL_NON_FUNCTION); 120344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 120444f0eee88ff00398ff7f715fab053374d808c90dSteve Block RelocInfo::CODE_TARGET); 1205402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ bind(&function); 1206402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1208402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // 5b. Get the code to call from the function and check that the number of 1209402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // expected arguments matches what we're providing. If so, jump 1210402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // (tail-call) to the code in register edx without checking arguments. 1211402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r0: actual number of arguments 1212402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // r1: function 1213402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 1214402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ ldr(r2, 1215402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset)); 1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(r2); 1217402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ cmp(r2, r0); // Check formal and actual parameter counts. 121844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 121944f0eee88ff00398ff7f715fab053374d808c90dSteve Block RelocInfo::CODE_TARGET, 122044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ne); 1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); 1223402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ParameterCount expected(0); 1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeCode(r3, expected, expected, JUMP_FUNCTION, NullCallWrapper()); 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_FunctionApply(MacroAssembler* masm) { 1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kIndexOffset = 1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); 1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kLimitOffset = 1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); 1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kArgsOffset = 2 * kPointerSize; 1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kRecvOffset = 3 * kPointerSize; 1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kFunctionOffset = 4 * kPointerSize; 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL); 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function 12413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 12423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, MemOperand(fp, kArgsOffset)); // get the args array 12433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 12443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); 12453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 12463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check the stack for overflow. We are not trying to catch 12473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // interruptions (e.g. debug break and preemption) here, so the "real stack 12483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // limit" is checked. 12493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label okay; 12503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); 12513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make r2 the space we have left. The stack might already be overflowed 12523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // here which will cause r2 to become negative. 12533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(r2, sp, r2); 12543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the arguments will overflow the stack. 1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r2, Operand::PointerOffsetFromSmiKey(r0)); 12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(gt, &okay); // Signed comparison. 12573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 12583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Out of stack space. 12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, MemOperand(fp, kFunctionOffset)); 1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(r1, r0); 1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); 12623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // End of stack check. 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push current limit and index. 12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&okay); 12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); // limit 1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r1, Operand::Zero()); // initial index 12683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r1); 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the receiver. 12713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, MemOperand(fp, kRecvOffset)); 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that the function is a JS function (otherwise it must be a proxy). 12743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label push_receiver; 12753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, MemOperand(fp, kFunctionOffset)); 12763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); 12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &push_receiver); 1278589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Change context eagerly to get the right global object if necessary. 12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the shared function info while the function is still in r1. 12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 1283592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Compute the receiver. 12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Do not transform the receiver for strict mode functions. 1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label call_to_object, use_global_proxy; 12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset)); 12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ tst(r2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + 12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kSmiTagSize))); 12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &push_receiver); 1291589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Do not transform the receiver for strict mode functions. 12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ tst(r2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); 12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &push_receiver); 1295592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compute the receiver in sloppy mode. 12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(r0, &call_to_object); 12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r1, Heap::kNullValueRootIndex); 12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, r1); 1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, &use_global_proxy); 13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); 13023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, r1); 1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, &use_global_proxy); 1304592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the receiver is already a JavaScript object. 13063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r0: receiver 13073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 13083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); 13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ge, &push_receiver); 1310592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 13113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Convert the receiver to a regular object. 13123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r0: receiver 13133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&call_to_object); 13143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 13153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 13163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(&push_receiver); 1317592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&use_global_proxy); 1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r0, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); 1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalProxyOffset)); 13213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push the receiver. 13233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r0: receiver 13243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&push_receiver); 13253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 13263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Copy all arguments from the array to the stack. 13283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label entry, loop; 13293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, MemOperand(fp, kIndexOffset)); 13303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(&entry); 13313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the current argument from the arguments array and push it to the 13333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // stack. 13343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r0: current argument index 13353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&loop); 13363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, MemOperand(fp, kArgsOffset)); 1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(r1, r0); 13383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Call the runtime to access the property in the arguments array. 13403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kGetProperty, 2); 13413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r0); 13423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Use inline caching to access the arguments. 13443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r0, MemOperand(fp, kIndexOffset)); 13453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r0, r0, Operand(1 << kSmiTagSize)); 13463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ str(r0, MemOperand(fp, kIndexOffset)); 13473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Test if the copy loop has finished copying all the elements from the 13493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // arguments object. 13503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&entry); 13513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, MemOperand(fp, kLimitOffset)); 13523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, r1); 13533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &loop); 1354592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the function. 13563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label call_proxy; 13573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ParameterCount actual(r0); 1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(r0); 13593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ldr(r1, MemOperand(fp, kFunctionOffset)); 13603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); 13613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ b(ne, &call_proxy); 1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeFunction(r1, actual, CALL_FUNCTION, NullCallWrapper()); 13633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch frame_scope.GenerateLeaveFrame(); 13653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(sp, sp, Operand(3 * kPointerSize)); 13663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(lr); 13673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the function proxy. 13693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&call_proxy); 13703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(r1); // add function proxy as last argument 13713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(r0, r0, Operand(1)); 1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(r2, Operand::Zero()); 1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ GetBuiltinFunction(r1, Builtins::CALL_FUNCTION_PROXY); 13743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 13753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RelocInfo::CODE_TARGET); 13763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Tear down the internal frame and remove function, receiver and args. 13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1379589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ add(sp, sp, Operand(3 * kPointerSize)); 1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ArgumentAdaptorStackCheck(MacroAssembler* masm, 1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* stack_overflow) { 1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- r0 : actual number of arguments 1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- r1 : function (passed through to callee) 1389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- r2 : expected number of arguments 1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check the stack for overflow. We are not trying to catch 1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // interruptions (e.g. debug break and preemption) here, so the "real stack 1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // limit" is checked. 1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(r5, Heap::kRealStackLimitRootIndex); 1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make r5 the space we have left. The stack might already be overflowed 1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // here which will cause r5 to become negative. 1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(r5, sp, r5); 1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if the arguments will overflow the stack. 1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r5, Operand(r2, LSL, kPointerSizeLog2)); 1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(le, stack_overflow); // Signed comparison. 1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { 1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(r0); 1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() | 1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (FLAG_enable_ool_constant_pool ? pp.bit() : 0) | 1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch fp.bit() | lr.bit()); 1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(fp, sp, 1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize)); 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { 1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : result being passed through 1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the number of arguments passed (as a smi), tear down the frame and 1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // then tear down the parameters. 1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r1, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp + 1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kPointerSize))); 1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LeaveFrame(StackFrame::ARGUMENTS_ADAPTOR); 1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(sp, sp, Operand::PointerOffsetFromSmiKey(r1)); 1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(sp, sp, Operand(kPointerSize)); // adjust for receiver 1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { 1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r0 : actual number of arguments 1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r1 : function (passed through to callee) 1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- r2 : expected number of arguments 1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label stack_overflow; 1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArgumentAdaptorStackCheck(masm, &stack_overflow); 1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label invoke, dont_adapt_arguments; 1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label enough, too_few; 1442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); 14436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ cmp(r0, r2); 1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(lt, &too_few); 1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel)); 1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &dont_adapt_arguments); 1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { // Enough parameters: actual >= expected 1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&enough); 1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EnterArgumentsAdaptorFrame(masm); 1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate copy start address into r0 and copy end address into r2. 1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments as a smi 1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: expected number of arguments 1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: code entry to call 1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(r0, fp, Operand::PointerOffsetFromSmiKey(r0)); 1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // adjust for return address and receiver 1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, r0, Operand(2 * kPointerSize)); 1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r2, r0, Operand(r2, LSL, kPointerSizeLog2)); 1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy the arguments (including the receiver) to the new stack frame. 1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: copy start address 1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: copy end address 1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: code entry to call 1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label copy; 1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(©); 1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(ip, MemOperand(r0, 0)); 1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ip); 1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, r2); // Compare before moving to next argument. 1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r0, r0, Operand(kPointerSize)); 1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, ©); 1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(&invoke); 1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { // Too few parameters: Actual < expected 1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&too_few); 1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EnterArgumentsAdaptorFrame(masm); 1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate copy start address into r0 and copy end address is fp. 1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: actual number of arguments as a smi 1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: expected number of arguments 1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: code entry to call 1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(r0, fp, Operand::PointerOffsetFromSmiKey(r0)); 1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy the arguments (including the receiver) to the new stack frame. 1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: copy start address 1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: expected number of arguments 1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: code entry to call 1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label copy; 1496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(©); 1497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust load for return address and receiver. 1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(ip, MemOperand(r0, 2 * kPointerSize)); 1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ip); 1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, fp); // Compare before moving to next argument. 1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r0, r0, Operand(kPointerSize)); 1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, ©); 1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the remaining expected arguments with undefined. 1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: function 1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: expected number of arguments 1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r3: code entry to call 1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r2, fp, Operand(r2, LSL, kPointerSizeLog2)); 1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Adjust for frame. 1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(r2, r2, Operand(StandardFrameConstants::kFixedFrameSizeFromFp + 1512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2 * kPointerSize)); 1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fill; 1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fill); 1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ip); 1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(sp, r2); 1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &fill); 1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call the entry point. 1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&invoke); 1523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Call(r3); 1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store offset of return address for deoptimizer. 15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset()); 15273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit frame and return. 1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LeaveArgumentsAdaptorFrame(masm); 1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(lr); 1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ------------------------------------------- 1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Dont adapt arguments. 1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ------------------------------------------- 1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&dont_adapt_arguments); 1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(r3); 1538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&stack_overflow); 1540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 1541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope frame(masm, StackFrame::MANUAL); 1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EnterArgumentsAdaptorFrame(masm); 1543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); 1544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bkpt(0); 1545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 1552f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1553f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_ARM 1554