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                             &not_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(&not_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(&copy);
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, &copy);
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(&copy);
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, &copy);
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