1f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Copyright 2013 the V8 project authors. All rights reserved. 23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be 33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file. 4f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 5196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h" 6f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 7fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org#if V8_TARGET_ARCH_ARM64 8f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 9196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/codegen.h" 10196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/debug.h" 11196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/deoptimizer.h" 12196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/full-codegen.h" 13196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/runtime.h" 14196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/stub-cache.h" 15f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 16f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgnamespace v8 { 17f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgnamespace internal { 18f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 19f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 20f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define __ ACCESS_MASM(masm) 21f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 22f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 23f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Load the built-in Array function from the current context. 24f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) { 25f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Load the native context. 26f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(result, GlobalObjectMemOperand()); 27f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(result, 28f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FieldMemOperand(result, GlobalObject::kNativeContextOffset)); 29f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Load the InternalArray function from the native context. 30f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(result, 31f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org MemOperand(result, 32f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); 33f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 34f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 35f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 36f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Load the built-in InternalArray function from the current context. 37f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic void GenerateLoadInternalArrayFunction(MacroAssembler* masm, 38f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register result) { 39f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Load the native context. 40f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(result, GlobalObjectMemOperand()); 41f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(result, 42f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FieldMemOperand(result, GlobalObject::kNativeContextOffset)); 43f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Load the InternalArray function from the native context. 44f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(result, ContextMemOperand(result, 45f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Context::INTERNAL_ARRAY_FUNCTION_INDEX)); 46f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 47f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 48f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 49f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_Adaptor(MacroAssembler* masm, 50f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CFunctionId id, 51f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org BuiltinExtraArguments extra_args) { 52f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // ----------- S t a t e ------------- 53f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- x0 : number of arguments excluding receiver 54f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- x1 : called function (only guaranteed when 55f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // extra_args requires it) 56f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- cp : context 57f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- sp[0] : last argument 58f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- ... 59f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- sp[4 * (argc - 1)] : first argument (argc == x0) 60f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- sp[4 * argc] : receiver 61f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // ----------------------------------- 62f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 63f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Insert extra arguments. 64f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int num_extra_args = 0; 65f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (extra_args == NEEDS_CALLED_FUNCTION) { 66f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org num_extra_args = 1; 67f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(x1); 68f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 69f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(extra_args == NO_EXTRA_ARGUMENTS); 70f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 71f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 72f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // JumpToExternalReference expects x0 to contain the number of arguments 73f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // including the receiver and the extra arguments. 74f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Add(x0, x0, num_extra_args + 1); 75f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ JumpToExternalReference(ExternalReference(id, masm->isolate())); 76f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 77f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 78f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 79f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { 80f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // ----------- S t a t e ------------- 81f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- x0 : number of arguments 82f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- lr : return address 83f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- sp[...]: constructor arguments 84f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // ----------------------------------- 85f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASM_LOCATION("Builtins::Generate_InternalArrayCode"); 86f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label generic_array_code; 87f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 88f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Get the InternalArray function. 89f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org GenerateLoadInternalArrayFunction(masm, x1); 90f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 91f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (FLAG_debug_code) { 92f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Initial map for the builtin InternalArray functions should be maps. 93f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(x10, FieldMemOperand(x1, JSFunction::kPrototypeOrInitialMapOffset)); 94f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Tst(x10, kSmiTagMask); 95f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Assert(ne, kUnexpectedInitialMapForInternalArrayFunction); 96f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ CompareObjectType(x10, x11, x12, MAP_TYPE); 97f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Assert(eq, kUnexpectedInitialMapForInternalArrayFunction); 98f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 99f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 100f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Run the native code for the InternalArray function called as a normal 101f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // function. 102f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org InternalArrayConstructorStub stub(masm->isolate()); 103f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ TailCallStub(&stub); 104f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 105f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 106f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 107f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_ArrayCode(MacroAssembler* masm) { 108f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // ----------- S t a t e ------------- 109f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- x0 : number of arguments 110f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- lr : return address 111f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- sp[...]: constructor arguments 112f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // ----------------------------------- 113f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASM_LOCATION("Builtins::Generate_ArrayCode"); 114f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label generic_array_code, one_or_more_arguments, two_or_more_arguments; 115f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 116f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Get the Array function. 117f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org GenerateLoadArrayFunction(masm, x1); 118f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 119f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (FLAG_debug_code) { 120f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Initial map for the builtin Array functions should be maps. 121f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(x10, FieldMemOperand(x1, JSFunction::kPrototypeOrInitialMapOffset)); 122f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Tst(x10, kSmiTagMask); 123f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Assert(ne, kUnexpectedInitialMapForArrayFunction); 124f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ CompareObjectType(x10, x11, x12, MAP_TYPE); 125f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Assert(eq, kUnexpectedInitialMapForArrayFunction); 126f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 127f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 128f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Run the native code for the Array function called as a normal function. 1295697144afb43181fed170b81c194fe1cc0fce3b6machenbach@chromium.org __ LoadRoot(x2, Heap::kUndefinedValueRootIndex); 130f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ArrayConstructorStub stub(masm->isolate()); 131f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ TailCallStub(&stub); 132f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 133f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 134f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 135f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_StringConstructCode(MacroAssembler* masm) { 136f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // ----------- S t a t e ------------- 137f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- x0 : number of arguments 138f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- x1 : constructor function 139f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- lr : return address 140f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- sp[(argc - n - 1) * 8] : arg[n] (zero based) 141f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- sp[argc * 8] : receiver 142f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // ----------------------------------- 143f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASM_LOCATION("Builtins::Generate_StringConstructCode"); 144f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Counters* counters = masm->isolate()->counters(); 145f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ IncrementCounter(counters->string_ctor_calls(), 1, x10, x11); 146f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 147f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register argc = x0; 148f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register function = x1; 149f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (FLAG_debug_code) { 150f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, x10); 151f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Cmp(function, x10); 152f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Assert(eq, kUnexpectedStringFunction); 153f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 154f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 155f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Load the first arguments in x0 and get rid of the rest. 156f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label no_arguments; 157f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Cbz(argc, &no_arguments); 158f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // First args = sp[(argc - 1) * 8]. 159f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Sub(argc, argc, 1); 16097b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org __ Claim(argc, kXRegSize); 161f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // jssp now point to args[0], load and drop args[0] + receiver. 162ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org Register arg = argc; 163ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Ldr(arg, MemOperand(jssp, 2 * kPointerSize, PostIndex)); 164ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org argc = NoReg; 165f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 166f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register argument = x2; 167f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label not_cached, argument_is_string; 168ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ LookupNumberStringCache(arg, // Input. 169f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org argument, // Result. 170f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org x10, // Scratch. 171f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org x11, // Scratch. 172f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org x12, // Scratch. 173f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ¬_cached); 174f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ IncrementCounter(counters->string_ctor_cached_number(), 1, x10, x11); 175f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&argument_is_string); 176f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 177f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // ----------- S t a t e ------------- 178f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- x2 : argument converted to string 179f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- x1 : constructor function 180f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- lr : return address 181f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // ----------------------------------- 182f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 183f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label gc_required; 184f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register new_obj = x0; 185f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Allocate(JSValue::kSize, new_obj, x10, x11, &gc_required, TAG_OBJECT); 186f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 187f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Initialize the String object. 188f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register map = x3; 189f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ LoadGlobalFunctionInitialMap(function, map, x10); 190f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (FLAG_debug_code) { 191f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldrb(x4, FieldMemOperand(map, Map::kInstanceSizeOffset)); 192f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Cmp(x4, JSValue::kSize >> kPointerSizeLog2); 193f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Assert(eq, kUnexpectedStringWrapperInstanceSize); 194f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldrb(x4, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset)); 195f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Cmp(x4, 0); 196f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Assert(eq, kUnexpectedUnusedPropertiesOfStringWrapper); 197f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 198f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Str(map, FieldMemOperand(new_obj, HeapObject::kMapOffset)); 199f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 200f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register empty = x3; 201f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ LoadRoot(empty, Heap::kEmptyFixedArrayRootIndex); 202f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Str(empty, FieldMemOperand(new_obj, JSObject::kPropertiesOffset)); 203f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Str(empty, FieldMemOperand(new_obj, JSObject::kElementsOffset)); 204f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 205f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Str(argument, FieldMemOperand(new_obj, JSValue::kValueOffset)); 206f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 207f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Ensure the object is fully initialized. 208f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org STATIC_ASSERT(JSValue::kSize == (4 * kPointerSize)); 209f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 210f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ret(); 211f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 212f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // The argument was not found in the number to string cache. Check 213f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // if it's a string already before calling the conversion builtin. 214f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label convert_argument; 215f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(¬_cached); 216ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ JumpIfSmi(arg, &convert_argument); 217f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 218f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Is it a String? 219f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(x10, FieldMemOperand(x0, HeapObject::kMapOffset)); 220f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldrb(x11, FieldMemOperand(x10, Map::kInstanceTypeOffset)); 221f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Tbnz(x11, MaskToBit(kIsNotStringMask), &convert_argument); 222ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Mov(argument, arg); 223f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ IncrementCounter(counters->string_ctor_string_value(), 1, x10, x11); 224f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(&argument_is_string); 225f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 226f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Invoke the conversion builtin and put the result into x2. 227f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&convert_argument); 228f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(function); // Preserve the function. 229f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ IncrementCounter(counters->string_ctor_conversions(), 1, x10, x11); 230f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org { 231f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 232ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Push(arg); 233f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION); 234f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 235f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Pop(function); 236f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(argument, x0); 237f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(&argument_is_string); 238f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 239f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Load the empty string into x2, remove the receiver from the 240f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // stack, and jump back to the case where the argument is a string. 241f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&no_arguments); 242f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ LoadRoot(argument, Heap::kempty_stringRootIndex); 243f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Drop(1); 244f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(&argument_is_string); 245f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 246f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // At this point the argument is already a string. Call runtime to create a 247f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // string wrapper. 248f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&gc_required); 249f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ IncrementCounter(counters->string_ctor_gc_required(), 1, x10, x11); 250f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org { 251f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 252f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(argument); 253f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ CallRuntime(Runtime::kNewStringWrapper, 1); 254f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 255f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ret(); 256f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 257f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 258f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 259f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic void CallRuntimePassFunction(MacroAssembler* masm, 260f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Runtime::FunctionId function_id) { 261f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 262f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // - Push a copy of the function onto the stack. 263f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // - Push another copy as a parameter to the runtime call. 264f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(x1, x1); 265f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 266f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ CallRuntime(function_id, 1); 267f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 268f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // - Restore receiver. 269f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Pop(x1); 270f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 271f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 272f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 273f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic void GenerateTailCallToSharedCode(MacroAssembler* masm) { 274f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(x2, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); 275f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(x2, FieldMemOperand(x2, SharedFunctionInfo::kCodeOffset)); 276f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Add(x2, x2, Code::kHeaderSize - kHeapObjectTag); 277f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Br(x2); 278f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 279f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 280f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 281f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic void GenerateTailCallToReturnedCode(MacroAssembler* masm) { 282f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Add(x0, x0, Code::kHeaderSize - kHeapObjectTag); 283f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Br(x0); 284f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 285f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 286f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 287f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) { 288f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Checking whether the queued function is ready for install is optional, 289f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // since we come across interrupts and stack checks elsewhere. However, not 290f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // checking may delay installing ready functions, and always checking would be 291f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // quite expensive. A good compromise is to first check against stack limit as 292f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // a cue for an interrupt signal. 293f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label ok; 294f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ CompareRoot(masm->StackPointer(), Heap::kStackLimitRootIndex); 295f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(hs, &ok); 296f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 297895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org CallRuntimePassFunction(masm, Runtime::kHiddenTryInstallOptimizedCode); 298f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org GenerateTailCallToReturnedCode(masm); 299f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 300f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&ok); 301f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org GenerateTailCallToSharedCode(masm); 302f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 303f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 304f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 305f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic void Generate_JSConstructStubHelper(MacroAssembler* masm, 306f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool is_api_function, 30769f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org bool create_memento) { 308f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // ----------- S t a t e ------------- 309f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- x0 : number of arguments 310f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- x1 : constructor function 31169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // -- x2 : allocation site or undefined 312f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- lr : return address 313f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- sp[...]: constructor arguments 314f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // ----------------------------------- 315f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 316f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASM_LOCATION("Builtins::Generate_JSConstructStubHelper"); 31769f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // Should never create mementos for api functions. 31869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org ASSERT(!is_api_function || !create_memento); 319f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 320f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Isolate* isolate = masm->isolate(); 321f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 322f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Enter a construct frame. 323f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org { 324f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FrameScope scope(masm, StackFrame::CONSTRUCT); 325f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 32669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // Preserve the three incoming parameters on the stack. 32769f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org if (create_memento) { 32869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ AssertUndefinedOrAllocationSite(x2, x10); 32969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ Push(x2); 33069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org } 33169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org 332f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register argc = x0; 333f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register constructor = x1; 334f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x1: constructor function 335f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ SmiTag(argc); 336f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(argc, constructor); 337f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // sp[0] : Constructor function. 338f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // sp[1]: number of arguments (smi-tagged) 339f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 340f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Try to allocate the object without transitioning into C code. If any of 341f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the preconditions is not met, the code bails out to the runtime call. 342f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label rt_call, allocated; 343f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (FLAG_inline_new) { 344f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label undo_allocation; 345f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ExternalReference debug_step_in_fp = 346f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ExternalReference::debug_step_in_fp_address(isolate); 347f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(x2, Operand(debug_step_in_fp)); 348f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(x2, MemOperand(x2)); 349f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Cbnz(x2, &rt_call); 350f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Load the initial map and verify that it is in fact a map. 351f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register init_map = x2; 352f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(init_map, 353f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FieldMemOperand(constructor, 354f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org JSFunction::kPrototypeOrInitialMapOffset)); 355f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ JumpIfSmi(init_map, &rt_call); 356f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ JumpIfNotObjectType(init_map, x10, x11, MAP_TYPE, &rt_call); 357f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 358f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Check that the constructor is not constructing a JSFunction (see 359f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // comments in Runtime_NewObject in runtime.cc). In which case the initial 360f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // map's instance type would be JS_FUNCTION_TYPE. 361f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ CompareInstanceType(init_map, x10, JS_FUNCTION_TYPE); 362f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(eq, &rt_call); 363f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 364011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org Register constructon_count = x14; 365011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org if (!is_api_function) { 366f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label allocate; 367011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org MemOperand bit_field3 = 368011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org FieldMemOperand(init_map, Map::kBitField3Offset); 369011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org // Check if slack tracking is enabled. 370011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ Ldr(x4, bit_field3); 371011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ DecodeField<Map::ConstructionCount>(constructon_count, x4); 372011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ Cmp(constructon_count, Operand(JSFunction::kNoSlackTracking)); 373011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ B(eq, &allocate); 374f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Decrease generous allocation count. 375011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ Subs(x4, x4, Operand(1 << Map::ConstructionCount::kShift)); 376011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ Str(x4, bit_field3); 377011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ Cmp(constructon_count, Operand(JSFunction::kFinishSlackTracking)); 378f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(ne, &allocate); 379f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 380f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Push the constructor and map to the stack, and the constructor again 381f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // as argument to the runtime call. 382f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(constructor, init_map, constructor); 383895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org __ CallRuntime(Runtime::kHiddenFinalizeInstanceSize, 1); 384f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Pop(init_map, constructor); 385011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ Mov(constructon_count, Operand(JSFunction::kNoSlackTracking)); 386f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&allocate); 387f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 388f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 389f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Now allocate the JSObject on the heap. 390f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register obj_size = x3; 391f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register new_obj = x4; 392f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldrb(obj_size, FieldMemOperand(init_map, Map::kInstanceSizeOffset)); 39369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org if (create_memento) { 39469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ Add(x7, obj_size, 39569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org Operand(AllocationMemento::kSize / kPointerSize)); 39669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ Allocate(x7, new_obj, x10, x11, &rt_call, SIZE_IN_WORDS); 39769f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org } else { 39869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ Allocate(obj_size, new_obj, x10, x11, &rt_call, SIZE_IN_WORDS); 39969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org } 400f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 401f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Allocated the JSObject, now initialize the fields. Map is set to 402f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // initial map and properties and elements are set to empty fixed array. 403f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // NB. the object pointer is not tagged, so MemOperand is used. 404f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register empty = x5; 405f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ LoadRoot(empty, Heap::kEmptyFixedArrayRootIndex); 406f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Str(init_map, MemOperand(new_obj, JSObject::kMapOffset)); 407381adef828187e237e8758ab730dee1c2834a0b3machenbach@chromium.org STATIC_ASSERT(JSObject::kElementsOffset == 408381adef828187e237e8758ab730dee1c2834a0b3machenbach@chromium.org (JSObject::kPropertiesOffset + kPointerSize)); 409381adef828187e237e8758ab730dee1c2834a0b3machenbach@chromium.org __ Stp(empty, empty, MemOperand(new_obj, JSObject::kPropertiesOffset)); 410f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 411f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register first_prop = x5; 412f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Add(first_prop, new_obj, JSObject::kHeaderSize); 413f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 414f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Fill all of the in-object properties with the appropriate filler. 415011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org Register filler = x7; 416011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ LoadRoot(filler, Heap::kUndefinedValueRootIndex); 417f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 418f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Obtain number of pre-allocated property fields and in-object 419f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // properties. 420f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register prealloc_fields = x10; 421f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register inobject_props = x11; 422f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register inst_sizes = x11; 423f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(inst_sizes, FieldMemOperand(init_map, Map::kInstanceSizesOffset)); 424f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ubfx(prealloc_fields, inst_sizes, 425f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte, 426f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org kBitsPerByte); 427f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ubfx(inobject_props, inst_sizes, 428f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Map::kInObjectPropertiesByte * kBitsPerByte, kBitsPerByte); 429f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 430381adef828187e237e8758ab730dee1c2834a0b3machenbach@chromium.org // Calculate number of property fields in the object. 431381adef828187e237e8758ab730dee1c2834a0b3machenbach@chromium.org Register prop_fields = x6; 432381adef828187e237e8758ab730dee1c2834a0b3machenbach@chromium.org __ Sub(prop_fields, obj_size, JSObject::kHeaderSize / kPointerSize); 433381adef828187e237e8758ab730dee1c2834a0b3machenbach@chromium.org 434011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org if (!is_api_function) { 435011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org Label no_inobject_slack_tracking; 436011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org 437011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org // Check if slack tracking is enabled. 438011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ Cmp(constructon_count, Operand(JSFunction::kNoSlackTracking)); 439011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ B(eq, &no_inobject_slack_tracking); 440011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org constructon_count = NoReg; 441011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org 442381adef828187e237e8758ab730dee1c2834a0b3machenbach@chromium.org // Fill the pre-allocated fields with undef. 443011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ FillFields(first_prop, prealloc_fields, filler); 444381adef828187e237e8758ab730dee1c2834a0b3machenbach@chromium.org 445011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org // Update first_prop register to be the offset of the first field after 446f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // pre-allocated fields. 447011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ Add(first_prop, first_prop, 448f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Operand(prealloc_fields, LSL, kPointerSizeLog2)); 449f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 450f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (FLAG_debug_code) { 451011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org Register obj_end = x14; 452381adef828187e237e8758ab730dee1c2834a0b3machenbach@chromium.org __ Add(obj_end, new_obj, Operand(obj_size, LSL, kPointerSizeLog2)); 453011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ Cmp(first_prop, obj_end); 454f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields); 455f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 456381adef828187e237e8758ab730dee1c2834a0b3machenbach@chromium.org 457381adef828187e237e8758ab730dee1c2834a0b3machenbach@chromium.org // Fill the remaining fields with one pointer filler map. 458011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ LoadRoot(filler, Heap::kOnePointerFillerMapRootIndex); 459011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ Sub(prop_fields, prop_fields, prealloc_fields); 460011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org 461011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ bind(&no_inobject_slack_tracking); 462011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org } 463011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org if (create_memento) { 46469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // Fill the pre-allocated fields with undef. 465011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ FillFields(first_prop, prop_fields, filler); 46669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ Add(first_prop, new_obj, Operand(obj_size, LSL, kPointerSizeLog2)); 46769f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ LoadRoot(x14, Heap::kAllocationMementoMapRootIndex); 46869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org ASSERT_EQ(0 * kPointerSize, AllocationMemento::kMapOffset); 46969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ Str(x14, MemOperand(first_prop, kPointerSize, PostIndex)); 47069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // Load the AllocationSite 47169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ Peek(x14, 2 * kXRegSize); 47269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org ASSERT_EQ(1 * kPointerSize, AllocationMemento::kAllocationSiteOffset); 47369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ Str(x14, MemOperand(first_prop, kPointerSize, PostIndex)); 47469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org first_prop = NoReg; 475f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 476381adef828187e237e8758ab730dee1c2834a0b3machenbach@chromium.org // Fill all of the property fields with undef. 477011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ FillFields(first_prop, prop_fields, filler); 478381adef828187e237e8758ab730dee1c2834a0b3machenbach@chromium.org first_prop = NoReg; 479381adef828187e237e8758ab730dee1c2834a0b3machenbach@chromium.org prop_fields = NoReg; 480f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 481f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 482f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Add the object tag to make the JSObject real, so that we can continue 483f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // and jump into the continuation code at any time from now on. Any 484f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // failures need to undo the allocation, so that the heap is in a 485f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // consistent state and verifiable. 486f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Add(new_obj, new_obj, kHeapObjectTag); 487f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 488f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Check if a non-empty properties array is needed. Continue with 489f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // allocated object if not, or fall through to runtime call if it is. 490f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register element_count = x3; 491381adef828187e237e8758ab730dee1c2834a0b3machenbach@chromium.org __ Ldrb(element_count, 492381adef828187e237e8758ab730dee1c2834a0b3machenbach@chromium.org FieldMemOperand(init_map, Map::kUnusedPropertyFieldsOffset)); 493f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // The field instance sizes contains both pre-allocated property fields 494f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // and in-object properties. 495381adef828187e237e8758ab730dee1c2834a0b3machenbach@chromium.org __ Add(element_count, element_count, prealloc_fields); 496381adef828187e237e8758ab730dee1c2834a0b3machenbach@chromium.org __ Subs(element_count, element_count, inobject_props); 497f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 498f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Done if no extra properties are to be allocated. 499f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(eq, &allocated); 500f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Assert(pl, kPropertyAllocationCountFailed); 501f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 502f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Scale the number of elements by pointer size and add the header for 503f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // FixedArrays to the start of the next object calculation from above. 504f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register new_array = x5; 505f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register array_size = x6; 506f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Add(array_size, element_count, FixedArray::kHeaderSize / kPointerSize); 507f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Allocate(array_size, new_array, x11, x12, &undo_allocation, 508f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | 509f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org SIZE_IN_WORDS)); 510f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 511f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register array_map = x10; 512f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ LoadRoot(array_map, Heap::kFixedArrayMapRootIndex); 513f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Str(array_map, MemOperand(new_array, FixedArray::kMapOffset)); 514f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ SmiTag(x0, element_count); 515f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Str(x0, MemOperand(new_array, FixedArray::kLengthOffset)); 516f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 517f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Initialize the fields to undefined. 518f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register elements = x10; 519f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Add(elements, new_array, FixedArray::kHeaderSize); 520011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ FillFields(elements, element_count, filler); 521f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 522f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Store the initialized FixedArray into the properties field of the 523f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // JSObject. 524f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Add(new_array, new_array, kHeapObjectTag); 525f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Str(new_array, FieldMemOperand(new_obj, JSObject::kPropertiesOffset)); 526f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 527f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Continue with JSObject being successfully allocated. 528f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(&allocated); 529f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 530f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Undo the setting of the new top so that the heap is verifiable. For 531f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // example, the map's unused properties potentially do not match the 532f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // allocated objects unused properties. 533f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&undo_allocation); 534f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ UndoAllocationInNewSpace(new_obj, x14); 535f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 536f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 537f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Allocate the new receiver object using the runtime call. 538f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&rt_call); 53969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org Label count_incremented; 54069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org if (create_memento) { 54169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // Get the cell or allocation site. 54269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ Peek(x4, 2 * kXRegSize); 54369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ Push(x4); 54469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ Push(constructor); // Argument for Runtime_NewObject. 545895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org __ CallRuntime(Runtime::kHiddenNewObjectWithAllocationSite, 2); 54669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ Mov(x4, x0); 54769f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // If we ended up using the runtime, and we want a memento, then the 54869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // runtime call made it for us, and we shouldn't do create count 54969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // increment. 55069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ jmp(&count_incremented); 55169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org } else { 55269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ Push(constructor); // Argument for Runtime_NewObject. 553895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org __ CallRuntime(Runtime::kHiddenNewObject, 1); 55469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ Mov(x4, x0); 55569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org } 556f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 557f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Receiver for constructor call allocated. 558f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x4: JSObject 559f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&allocated); 56069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org 56169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org if (create_memento) { 56269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ Peek(x10, 2 * kXRegSize); 56369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ JumpIfRoot(x10, Heap::kUndefinedValueRootIndex, &count_incremented); 56469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // r2 is an AllocationSite. We are creating a memento from it, so we 56569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // need to increment the memento create count. 56669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ Ldr(x5, FieldMemOperand(x10, 56769f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org AllocationSite::kPretenureCreateCountOffset)); 56869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ Add(x5, x5, Operand(Smi::FromInt(1))); 56969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ Str(x5, FieldMemOperand(x10, 57069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org AllocationSite::kPretenureCreateCountOffset)); 57169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ bind(&count_incremented); 57269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org } 57369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org 574f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(x4, x4); 575f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 576f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Reload the number of arguments from the stack. 577f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Set it up in x0 for the function call below. 578f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // jssp[0]: receiver 579f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // jssp[1]: receiver 580f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // jssp[2]: constructor function 581f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // jssp[3]: number of arguments (smi-tagged) 58297b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org __ Peek(constructor, 2 * kXRegSize); // Load constructor. 58397b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org __ Peek(argc, 3 * kXRegSize); // Load number of arguments. 584f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ SmiUntag(argc); 585f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 586f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Set up pointer to last argument. 587f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Add(x2, fp, StandardFrameConstants::kCallerSPOffset); 588f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 589f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Copy arguments and receiver to the expression stack. 590f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Copy 2 values every loop to use ldp/stp. 591f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x0: number of arguments 592f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x1: constructor function 593f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x2: address of last argument (caller sp) 594f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // jssp[0]: receiver 595f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // jssp[1]: receiver 596f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // jssp[2]: constructor function 597f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // jssp[3]: number of arguments (smi-tagged) 598f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Compute the start address of the copy in x3. 599f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Add(x3, x2, Operand(argc, LSL, kPointerSizeLog2)); 600f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label loop, entry, done_copying_arguments; 601f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(&entry); 602f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&loop); 603f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldp(x10, x11, MemOperand(x3, -2 * kPointerSize, PreIndex)); 604f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(x11, x10); 605f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&entry); 606f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Cmp(x3, x2); 607f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(gt, &loop); 608f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Because we copied values 2 by 2 we may have copied one extra value. 609f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Drop it if that is the case. 610f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(eq, &done_copying_arguments); 611f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Drop(1); 612f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&done_copying_arguments); 613f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 614f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Call the function. 615f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x0: number of arguments 616f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x1: constructor function 617f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (is_api_function) { 618f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(cp, FieldMemOperand(constructor, JSFunction::kContextOffset)); 619f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Handle<Code> code = 620f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org masm->isolate()->builtins()->HandleApiCallConstruct(); 621f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Call(code, RelocInfo::CODE_TARGET); 622f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 623f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ParameterCount actual(argc); 624f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ InvokeFunction(constructor, actual, CALL_FUNCTION, NullCallWrapper()); 625f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 626f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 627f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Store offset of return address for deoptimizer. 628011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org if (!is_api_function) { 629f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); 630f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 631f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 632f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Restore the context from the frame. 633f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x0: result 634f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // jssp[0]: receiver 635f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // jssp[1]: constructor function 636f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // jssp[2]: number of arguments (smi-tagged) 637f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 638f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 639f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If the result is an object (in the ECMA sense), we should get rid 640f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // of the receiver and use the result; see ECMA-262 section 13.2.2-7 641f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // on page 74. 642f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label use_receiver, exit; 643f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 644f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If the result is a smi, it is *not* an object in the ECMA sense. 645f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x0: result 646f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // jssp[0]: receiver (newly allocated object) 647f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // jssp[1]: constructor function 648f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // jssp[2]: number of arguments (smi-tagged) 649f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ JumpIfSmi(x0, &use_receiver); 650f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 651f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If the type of the result (stored in its map) is less than 652f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. 653f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ JumpIfObjectType(x0, x1, x3, FIRST_SPEC_OBJECT_TYPE, &exit, ge); 654f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 655f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Throw away the result of the constructor invocation and use the 656f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // on-stack receiver as the result. 657f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&use_receiver); 658f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Peek(x0, 0); 659f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 660f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Remove the receiver from the stack, remove caller arguments, and 661f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // return. 662f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&exit); 663f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x0: result 664f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // jssp[0]: receiver (newly allocated object) 665f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // jssp[1]: constructor function 666f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // jssp[2]: number of arguments (smi-tagged) 66797b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org __ Peek(x1, 2 * kXRegSize); 668f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 669f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Leave construct frame. 670f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 671f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 672f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ DropBySMI(x1); 673f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Drop(1); 674f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ IncrementCounter(isolate->counters()->constructed_objects(), 1, x1, x2); 675f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ret(); 676f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 677f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 678f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 679f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 680011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); 681f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 682f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 683f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 684f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 685011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org Generate_JSConstructStubHelper(masm, true, false); 686f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 687f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 688f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 689f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Input: 690f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// x0: code entry. 691f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// x1: function. 692f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// x2: receiver. 693f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// x3: argc. 694f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// x4: argv. 695f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Output: 696f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// x0: result. 697f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, 698f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool is_construct) { 699f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Called from JSEntryStub::GenerateBody(). 700f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register function = x1; 701f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register receiver = x2; 702f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register argc = x3; 703f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register argv = x4; 704f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 705f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ProfileEntryHookStub::MaybeCallEntryHook(masm); 706f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 707f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Clear the context before we push it when entering the internal frame. 708f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(cp, 0); 709f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 710f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org { 711f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Enter an internal frame. 712f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 713f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 714f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Set up the context from the function argument. 715f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset)); 716f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 717f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ InitializeRootRegister(); 718f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 719f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Push the function and the receiver onto the stack. 720f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(function, receiver); 721f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 722f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Copy arguments to the stack in a loop, in reverse order. 723f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x3: argc. 724f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x4: argv. 725f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label loop, entry; 726f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Compute the copy end address. 727f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Add(x10, argv, Operand(argc, LSL, kPointerSizeLog2)); 728f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 729f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(&entry); 730f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&loop); 731f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(x11, MemOperand(argv, kPointerSize, PostIndex)); 732f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(x12, MemOperand(x11)); // Dereference the handle. 733f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(x12); // Push the argument. 734f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&entry); 735f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Cmp(x10, argv); 736f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(ne, &loop); 737f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 738f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Initialize all JavaScript callee-saved registers, since they will be seen 739f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // by the garbage collector as part of handlers. 740f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // The original values have been saved in JSEntryStub::GenerateBody(). 741f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ LoadRoot(x19, Heap::kUndefinedValueRootIndex); 742f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(x20, x19); 743f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(x21, x19); 744f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(x22, x19); 745f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(x23, x19); 746f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(x24, x19); 747f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(x25, x19); 748f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Don't initialize the reserved registers. 749f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x26 : root register (root). 750f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x27 : context pointer (cp). 751f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x28 : JS stack pointer (jssp). 752f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x29 : frame pointer (fp). 753f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 754f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(x0, argc); 755f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (is_construct) { 756f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // No type feedback cell is available. 7575697144afb43181fed170b81c194fe1cc0fce3b6machenbach@chromium.org __ LoadRoot(x2, Heap::kUndefinedValueRootIndex); 758f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 759a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS); 760f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ CallStub(&stub); 761f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 762f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ParameterCount actual(x0); 763f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ InvokeFunction(function, actual, CALL_FUNCTION, NullCallWrapper()); 764f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 765f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Exit the JS internal frame and remove the parameters (except function), 766f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // and return. 767f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 768f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 769f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Result is in x0. Return. 770f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ret(); 771f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 772f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 773f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 774f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { 775f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Generate_JSEntryTrampolineHelper(masm, false); 776f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 777f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 778f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 779f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { 780f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Generate_JSEntryTrampolineHelper(masm, true); 781f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 782f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 783f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 784f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_CompileUnoptimized(MacroAssembler* masm) { 785895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org CallRuntimePassFunction(masm, Runtime::kHiddenCompileUnoptimized); 786f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org GenerateTailCallToReturnedCode(masm); 787f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 788f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 789f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 790f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic void CallCompileOptimized(MacroAssembler* masm, bool concurrent) { 791f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 792f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register function = x1; 793f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 794f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Preserve function. At the same time, push arguments for 795895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org // kHiddenCompileOptimized. 796f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ LoadObject(x10, masm->isolate()->factory()->ToBoolean(concurrent)); 797f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(function, function, x10); 798f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 799895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org __ CallRuntime(Runtime::kHiddenCompileOptimized, 2); 800f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 801f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Restore receiver. 802f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Pop(function); 803f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 804f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 805f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 806f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_CompileOptimized(MacroAssembler* masm) { 807f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallCompileOptimized(masm, false); 808f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org GenerateTailCallToReturnedCode(masm); 809f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 810f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 811f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 812f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_CompileOptimizedConcurrent(MacroAssembler* masm) { 813f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallCompileOptimized(masm, true); 814f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org GenerateTailCallToReturnedCode(masm); 815f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 816f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 817f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 818f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) { 819f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // For now, we are relying on the fact that make_code_young doesn't do any 820f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // garbage collection which allows us to save/restore the registers without 821f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // worrying about which of them contain pointers. We also don't build an 822f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // internal frame to make the code fast, since we shouldn't have to do stack 823f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // crawls in MakeCodeYoung. This seems a bit fragile. 824f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 825f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // The following caller-saved registers must be saved and restored when 826f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // calling through to the runtime: 827f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x0 - The address from which to resume execution. 828f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x1 - isolate 829f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // lr - The return address for the JSFunction itself. It has not yet been 830f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // preserved on the stack because the frame setup code was replaced 831f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // with a call to this stub, to handle code ageing. 832f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org { 833f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FrameScope scope(masm, StackFrame::MANUAL); 834f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(x0, x1, fp, lr); 8357010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org __ Mov(x1, ExternalReference::isolate_address(masm->isolate())); 836f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ CallCFunction( 837f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ExternalReference::get_make_code_young_function(masm->isolate()), 2); 838f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Pop(lr, fp, x1, x0); 839f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 840f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 841f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // The calling function has been made young again, so return to execute the 842f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // real frame set-up code. 843f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Br(x0); 844f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 845f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 846f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define DEFINE_CODE_AGE_BUILTIN_GENERATOR(C) \ 847f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_Make##C##CodeYoungAgainEvenMarking( \ 848f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org MacroAssembler* masm) { \ 849f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org GenerateMakeCodeYoungAgainCommon(masm); \ 850f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} \ 851f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_Make##C##CodeYoungAgainOddMarking( \ 852f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org MacroAssembler* masm) { \ 853f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org GenerateMakeCodeYoungAgainCommon(masm); \ 854f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 855f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgCODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR) 856f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#undef DEFINE_CODE_AGE_BUILTIN_GENERATOR 857f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 858f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 859f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) { 860f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // For now, as in GenerateMakeCodeYoungAgainCommon, we are relying on the fact 861f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // that make_code_young doesn't do any garbage collection which allows us to 862f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // save/restore the registers without worrying about which of them contain 863f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // pointers. 864f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 865f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // The following caller-saved registers must be saved and restored when 866f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // calling through to the runtime: 867f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x0 - The address from which to resume execution. 868f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x1 - isolate 869f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // lr - The return address for the JSFunction itself. It has not yet been 870f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // preserved on the stack because the frame setup code was replaced 871f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // with a call to this stub, to handle code ageing. 872f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org { 873f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FrameScope scope(masm, StackFrame::MANUAL); 874f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(x0, x1, fp, lr); 8757010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org __ Mov(x1, ExternalReference::isolate_address(masm->isolate())); 876f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ CallCFunction( 877f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ExternalReference::get_mark_code_as_executed_function( 878f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org masm->isolate()), 2); 879f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Pop(lr, fp, x1, x0); 880f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 881f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Perform prologue operations usually performed by the young code stub. 882f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ EmitFrameSetupForCodeAgePatching(masm); 883f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 884f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 885f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Jump to point after the code-age stub. 8865924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org __ Add(x0, x0, kNoCodeAgeSequenceLength); 887f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Br(x0); 888f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 889f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 890f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 891f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) { 892f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org GenerateMakeCodeYoungAgainCommon(masm); 893f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 894f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 895f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 896f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic void Generate_NotifyStubFailureHelper(MacroAssembler* masm, 897f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org SaveFPRegsMode save_doubles) { 898f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org { 899f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 900f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 901f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Preserve registers across notification, this is important for compiled 902f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // stubs that tail call the runtime on deopts passing their parameters in 903f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // registers. 904f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // TODO(jbramley): Is it correct (and appropriate) to use safepoint 905f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // registers here? According to the comment above, we should only need to 906f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // preserve the registers with parameters. 907f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ PushXRegList(kSafepointSavedRegisters); 908f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Pass the function and deoptimization type to the runtime system. 909895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org __ CallRuntime(Runtime::kHiddenNotifyStubFailure, 0, save_doubles); 910f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ PopXRegList(kSafepointSavedRegisters); 911f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 912f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 913f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Ignore state (pushed by Deoptimizer::EntryGenerator::Generate). 914f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Drop(1); 915f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 916f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Jump to the miss handler. Deoptimizer::EntryGenerator::Generate loads this 917f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // into lr before it jumps here. 918f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Br(lr); 919f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 920f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 921f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 922f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) { 923f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Generate_NotifyStubFailureHelper(masm, kDontSaveFPRegs); 924f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 925f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 926f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 927f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) { 928f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Generate_NotifyStubFailureHelper(masm, kSaveFPRegs); 929f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 930f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 931f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 932f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm, 933f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Deoptimizer::BailoutType type) { 934f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org { 935f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 936f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Pass the deoptimization type to the runtime system. 9377010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org __ Mov(x0, Smi::FromInt(static_cast<int>(type))); 938f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(x0); 939895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org __ CallRuntime(Runtime::kHiddenNotifyDeoptimized, 1); 940f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 941f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 942f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Get the full codegen state from the stack and untag it. 943f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register state = x6; 944f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Peek(state, 0); 945f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ SmiUntag(state); 946f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 947f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Switch on the state. 948f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label with_tos_register, unknown_state; 949f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ CompareAndBranch( 950f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org state, FullCodeGenerator::NO_REGISTERS, ne, &with_tos_register); 951f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Drop(1); // Remove state. 952f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ret(); 953f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 954f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&with_tos_register); 955f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Reload TOS register. 956f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Peek(x0, kPointerSize); 957f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ CompareAndBranch(state, FullCodeGenerator::TOS_REG, ne, &unknown_state); 958f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Drop(2); // Remove state and TOS. 959f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ret(); 960f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 961f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&unknown_state); 962f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Abort(kInvalidFullCodegenState); 963f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 964f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 965f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 966f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) { 967f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); 968f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 969f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 970f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 971f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) { 972f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); 973f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 974f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 975f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 976f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) { 977f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT); 978f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 979f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 980f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 981f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { 982f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Lookup the function in the JavaScript frame. 983f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(x0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 984f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org { 985f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 986f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Pass function as argument. 987f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(x0); 988f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1); 989f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 990f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 991f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If the code object is null, just return to the unoptimized code. 992f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label skip; 9937010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org __ CompareAndBranch(x0, Smi::FromInt(0), ne, &skip); 994f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ret(); 995f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 996f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&skip); 997f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 998f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Load deoptimization data from the code object. 999f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // <deopt_data> = <code>[#deoptimization_data_offset] 1000f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(x1, MemOperand(x0, Code::kDeoptimizationDataOffset - kHeapObjectTag)); 1001f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1002f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Load the OSR entrypoint offset from the deoptimization data. 1003f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // <osr_offset> = <deopt_data>[#header_size + #osr_pc_offset] 1004f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldrsw(w1, UntagSmiFieldMemOperand(x1, FixedArray::OffsetOfElementAt( 1005f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org DeoptimizationInputData::kOsrPcOffsetIndex))); 1006f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1007f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Compute the target address = code_obj + header_size + osr_offset 1008f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // <entry_addr> = <code_obj> + #header_size + <osr_offset> 1009f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Add(x0, x0, x1); 1010f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Add(lr, x0, Code::kHeaderSize - kHeapObjectTag); 1011f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1012f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // And "return" to the OSR entry point of the function. 1013f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ret(); 1014f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1015f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1016f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1017f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) { 1018f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // We check the stack limit as indicator that recompilation might be done. 1019f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label ok; 1020f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ CompareRoot(jssp, Heap::kStackLimitRootIndex); 1021f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(hs, &ok); 1022f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org { 1023f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 1024895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org __ CallRuntime(Runtime::kHiddenStackGuard, 0); 1025f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1026f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Jump(masm->isolate()->builtins()->OnStackReplacement(), 1027f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org RelocInfo::CODE_TARGET); 1028f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1029f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&ok); 1030f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ret(); 1031f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1032f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1033f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1034f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_FunctionCall(MacroAssembler* masm) { 1035f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org enum { 1036f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org call_type_JS_func = 0, 1037f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org call_type_func_proxy = 1, 1038f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org call_type_non_func = 2 1039f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org }; 1040f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register argc = x0; 1041f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register function = x1; 1042f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register call_type = x4; 1043f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register scratch1 = x10; 1044f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register scratch2 = x11; 1045f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register receiver_type = x13; 1046f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1047f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASM_LOCATION("Builtins::Generate_FunctionCall"); 1048f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 1. Make sure we have at least one argument. 1049f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org { Label done; 1050f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Cbnz(argc, &done); 1051f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex); 1052f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(scratch1); 1053f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(argc, 1); 1054f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&done); 1055f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1056f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1057f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 2. Get the function to call (passed as receiver) from the stack, check 1058f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // if it is a function. 1059f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label slow, non_function; 106097b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org __ Peek(function, Operand(argc, LSL, kXRegSizeLog2)); 1061f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ JumpIfSmi(function, &non_function); 1062f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ JumpIfNotObjectType(function, scratch1, receiver_type, 1063f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org JS_FUNCTION_TYPE, &slow); 1064f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1065f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 3a. Patch the first argument if necessary when calling a function. 1066f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label shift_arguments; 1067f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(call_type, static_cast<int>(call_type_JS_func)); 1068f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org { Label convert_to_object, use_global_receiver, patch_receiver; 1069f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Change context eagerly in case we need the global receiver. 1070f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset)); 1071f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1072f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Do not transform the receiver for strict mode functions. 1073f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Also do not transform the receiver for native (Compilerhints already in 1074f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x3). 1075f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(scratch1, 1076f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); 1077f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(scratch2.W(), 1078f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FieldMemOperand(scratch1, SharedFunctionInfo::kCompilerHintsOffset)); 1079f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ TestAndBranchIfAnySet( 1080f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org scratch2.W(), 1081f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (1 << SharedFunctionInfo::kStrictModeFunction) | 1082f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (1 << SharedFunctionInfo::kNative), 1083f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org &shift_arguments); 1084f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1085486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org // Compute the receiver in sloppy mode. 1086f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register receiver = x2; 1087f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Sub(scratch1, argc, 1); 108897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org __ Peek(receiver, Operand(scratch1, LSL, kXRegSizeLog2)); 1089f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ JumpIfSmi(receiver, &convert_to_object); 1090f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1091f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ JumpIfRoot(receiver, Heap::kUndefinedValueRootIndex, 1092f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org &use_global_receiver); 1093f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ JumpIfRoot(receiver, Heap::kNullValueRootIndex, &use_global_receiver); 1094f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1095f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 1096f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ JumpIfObjectType(receiver, scratch1, scratch2, 1097f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FIRST_SPEC_OBJECT_TYPE, &shift_arguments, ge); 1098f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1099f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&convert_to_object); 1100f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1101f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org { 1102f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Enter an internal frame in order to preserve argument count. 1103f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 1104f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ SmiTag(argc); 1105f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1106f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(argc, receiver); 1107f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 1108f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(receiver, x0); 1109f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1110f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Pop(argc); 1111f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ SmiUntag(argc); 1112f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1113f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Exit the internal frame. 1114f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1115f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1116f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Restore the function and flag in the registers. 111797b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org __ Peek(function, Operand(argc, LSL, kXRegSizeLog2)); 1118f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(call_type, static_cast<int>(call_type_JS_func)); 1119f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(&patch_receiver); 1120f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1121f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&use_global_receiver); 1122f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(receiver, GlobalObjectMemOperand()); 1123f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(receiver, 1124f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FieldMemOperand(receiver, GlobalObject::kGlobalReceiverOffset)); 1125f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1126f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1127f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&patch_receiver); 1128f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Sub(scratch1, argc, 1); 112997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org __ Poke(receiver, Operand(scratch1, LSL, kXRegSizeLog2)); 1130f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1131f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(&shift_arguments); 1132f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1133f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1134f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 3b. Check for function proxy. 1135f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&slow); 1136f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(call_type, static_cast<int>(call_type_func_proxy)); 1137f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Cmp(receiver_type, JS_FUNCTION_PROXY_TYPE); 1138f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(eq, &shift_arguments); 1139f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&non_function); 1140f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(call_type, static_cast<int>(call_type_non_func)); 1141f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1142f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 3c. Patch the first argument when calling a non-function. The 1143f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // CALL_NON_FUNCTION builtin expects the non-function callee as 1144f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // receiver, so overwrite the first argument which will ultimately 1145f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // become the receiver. 1146f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // call type (0: JS function, 1: function proxy, 2: non-function) 1147f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Sub(scratch1, argc, 1); 114897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org __ Poke(function, Operand(scratch1, LSL, kXRegSizeLog2)); 1149f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1150f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 4. Shift arguments and return address one slot down on the stack 1151f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // (overwriting the original receiver). Adjust argument count to make 1152f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the original first argument the new receiver. 1153f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // call type (0: JS function, 1: function proxy, 2: non-function) 1154f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&shift_arguments); 1155f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org { Label loop; 1156f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Calculate the copy start address (destination). Copy end address is jssp. 1157f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Add(scratch2, jssp, Operand(argc, LSL, kPointerSizeLog2)); 1158f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Sub(scratch1, scratch2, kPointerSize); 1159f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1160f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&loop); 1161f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(x12, MemOperand(scratch1, -kPointerSize, PostIndex)); 1162f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Str(x12, MemOperand(scratch2, -kPointerSize, PostIndex)); 1163f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Cmp(scratch1, jssp); 1164f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(ge, &loop); 1165f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Adjust the actual number of arguments and remove the top element 1166f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // (which is a copy of the last argument). 1167f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Sub(argc, argc, 1); 1168f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Drop(1); 1169f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1170f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1171f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin, 1172f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // or a function proxy via CALL_FUNCTION_PROXY. 1173f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // call type (0: JS function, 1: function proxy, 2: non-function) 1174f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org { Label js_function, non_proxy; 1175f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Cbz(call_type, &js_function); 1176f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Expected number of arguments is 0 for CALL_NON_FUNCTION. 1177f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(x2, 0); 1178f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Cmp(call_type, static_cast<int>(call_type_func_proxy)); 1179f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(ne, &non_proxy); 1180f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1181f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(function); // Re-add proxy object as additional argument. 1182f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Add(argc, argc, 1); 1183f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ GetBuiltinFunction(function, Builtins::CALL_FUNCTION_PROXY); 1184f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 1185f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org RelocInfo::CODE_TARGET); 1186f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1187f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&non_proxy); 1188f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ GetBuiltinFunction(function, Builtins::CALL_NON_FUNCTION); 1189f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 1190f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org RelocInfo::CODE_TARGET); 1191f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&js_function); 1192f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1193f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1194f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 5b. Get the code to call from the function and check that the number of 1195f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // expected arguments matches what we're providing. If so, jump 1196f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // (tail-call) to the code in register edx without checking arguments. 1197f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(x3, FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); 1198f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldrsw(x2, 1199f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FieldMemOperand(x3, 1200f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org SharedFunctionInfo::kFormalParameterCountOffset)); 1201f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label dont_adapt_args; 1202f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Cmp(x2, argc); // Check formal and actual parameter counts. 1203f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(eq, &dont_adapt_args); 1204f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 1205f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org RelocInfo::CODE_TARGET); 1206f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&dont_adapt_args); 1207f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1208f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(x3, FieldMemOperand(function, JSFunction::kCodeEntryOffset)); 1209f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ParameterCount expected(0); 1210f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ InvokeCode(x3, expected, expected, JUMP_FUNCTION, NullCallWrapper()); 1211f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1212f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1213f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1214f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_FunctionApply(MacroAssembler* masm) { 1215f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASM_LOCATION("Builtins::Generate_FunctionApply"); 1216f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const int kIndexOffset = 1217f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); 1218f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const int kLimitOffset = 1219f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); 1220f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const int kArgsOffset = 2 * kPointerSize; 1221f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const int kReceiverOffset = 3 * kPointerSize; 1222f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const int kFunctionOffset = 4 * kPointerSize; 1223f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1224f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org { 1225f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FrameScope frame_scope(masm, StackFrame::INTERNAL); 1226f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1227f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register args = x12; 1228f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register receiver = x14; 1229f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register function = x15; 1230f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1231f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Get the length of the arguments via a builtin call. 1232f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(function, MemOperand(fp, kFunctionOffset)); 1233f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(args, MemOperand(fp, kArgsOffset)); 1234f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(function, args); 1235f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); 1236f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register argc = x0; 1237f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1238f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Check the stack for overflow. 1239f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // We are not trying to catch interruptions (e.g. debug break and 1240f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // preemption) here, so the "real stack limit" is checked. 1241f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label enough_stack_space; 1242f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ LoadRoot(x10, Heap::kRealStackLimitRootIndex); 1243f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(function, MemOperand(fp, kFunctionOffset)); 1244f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Make x10 the space we have left. The stack might already be overflowed 1245f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // here which will cause x10 to become negative. 1246f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // TODO(jbramley): Check that the stack usage here is safe. 1247f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Sub(x10, jssp, x10); 1248f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Check if the arguments will overflow the stack. 1249f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Cmp(x10, Operand(argc, LSR, kSmiShift - kPointerSizeLog2)); 1250f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(gt, &enough_stack_space); 1251f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // There is not enough stack space, so use a builtin to throw an appropriate 1252f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // error. 1253f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(function, argc); 1254e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); 1255f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // We should never return from the APPLY_OVERFLOW builtin. 1256f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (__ emit_debug_code()) { 1257f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Unreachable(); 1258f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1259f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1260f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&enough_stack_space); 1261f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Push current limit and index. 1262f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(x1, 0); // Initial index. 1263f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(argc, x1); 1264f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1265f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label push_receiver; 1266f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(receiver, MemOperand(fp, kReceiverOffset)); 1267f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1268f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Check that the function is a JS function. Otherwise it must be a proxy. 1269f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // When it is not the function proxy will be invoked later. 1270f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ JumpIfNotObjectType(function, x10, x11, JS_FUNCTION_TYPE, 1271f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org &push_receiver); 1272f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1273f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Change context eagerly to get the right global object if necessary. 1274f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset)); 1275f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Load the shared function info. 1276f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(x2, FieldMemOperand(function, 1277f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org JSFunction::kSharedFunctionInfoOffset)); 1278f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1279f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Compute and push the receiver. 1280f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Do not transform the receiver for strict mode functions. 1281f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label convert_receiver_to_object, use_global_receiver; 1282f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(w10, FieldMemOperand(x2, SharedFunctionInfo::kCompilerHintsOffset)); 1283f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Tbnz(x10, SharedFunctionInfo::kStrictModeFunction, &push_receiver); 1284f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Do not transform the receiver for native functions. 1285f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Tbnz(x10, SharedFunctionInfo::kNative, &push_receiver); 1286f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1287486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org // Compute the receiver in sloppy mode. 1288f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ JumpIfSmi(receiver, &convert_receiver_to_object); 1289f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ JumpIfRoot(receiver, Heap::kNullValueRootIndex, &use_global_receiver); 1290f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ JumpIfRoot(receiver, Heap::kUndefinedValueRootIndex, 1291f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org &use_global_receiver); 1292f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1293f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Check if the receiver is already a JavaScript object. 1294f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 1295f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ JumpIfObjectType(receiver, x10, x11, FIRST_SPEC_OBJECT_TYPE, 1296f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org &push_receiver, ge); 1297f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1298f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Call a builtin to convert the receiver to a regular object. 1299f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&convert_receiver_to_object); 1300f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(receiver); 1301f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 1302f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(receiver, x0); 1303f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(&push_receiver); 1304f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1305f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&use_global_receiver); 1306f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(x10, GlobalObjectMemOperand()); 1307f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(receiver, FieldMemOperand(x10, GlobalObject::kGlobalReceiverOffset)); 1308f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1309f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Push the receiver 1310f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&push_receiver); 1311f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(receiver); 1312f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1313f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Copy all arguments from the array to the stack. 1314f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label entry, loop; 1315f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register current = x0; 1316f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(current, MemOperand(fp, kIndexOffset)); 1317f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(&entry); 1318f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1319f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&loop); 1320f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Load the current argument from the arguments array and push it. 1321f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // TODO(all): Couldn't we optimize this for JS arrays? 1322f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1323f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(x1, MemOperand(fp, kArgsOffset)); 1324f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(x1, current); 1325f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1326f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Call the runtime to access the property in the arguments array. 1327f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ CallRuntime(Runtime::kGetProperty, 2); 1328f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(x0); 1329f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1330f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Use inline caching to access the arguments. 1331f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(current, MemOperand(fp, kIndexOffset)); 13327010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org __ Add(current, current, Smi::FromInt(1)); 1333f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Str(current, MemOperand(fp, kIndexOffset)); 1334f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1335f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Test if the copy loop has finished copying all the elements from the 1336f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // arguments object. 1337f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&entry); 1338f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(x1, MemOperand(fp, kLimitOffset)); 1339f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Cmp(current, x1); 1340f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(ne, &loop); 1341f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1342f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // At the end of the loop, the number of arguments is stored in 'current', 1343f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // represented as a smi. 1344f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1345f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org function = x1; // From now on we want the function to be kept in x1; 1346f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(function, MemOperand(fp, kFunctionOffset)); 1347f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1348f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Call the function. 1349f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label call_proxy; 1350f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ParameterCount actual(current); 1351f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ SmiUntag(current); 1352f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ JumpIfNotObjectType(function, x10, x11, JS_FUNCTION_TYPE, &call_proxy); 1353f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ InvokeFunction(function, actual, CALL_FUNCTION, NullCallWrapper()); 1354f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org frame_scope.GenerateLeaveFrame(); 1355f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Drop(3); 1356f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ret(); 1357f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1358f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Call the function proxy. 1359f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&call_proxy); 1360f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x0 : argc 1361f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x1 : function 1362f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(function); // Add function proxy as last argument. 1363f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Add(x0, x0, 1); 1364f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(x2, 0); 1365f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ GetBuiltinFunction(x1, Builtins::CALL_FUNCTION_PROXY); 1366f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 1367f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org RelocInfo::CODE_TARGET); 1368f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1369f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Drop(3); 1370f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ret(); 1371f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1372f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1373f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1374e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.orgstatic void ArgumentAdaptorStackCheck(MacroAssembler* masm, 1375e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org Label* stack_overflow) { 1376e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // ----------- S t a t e ------------- 1377e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // -- x0 : actual number of arguments 1378e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // -- x1 : function (passed through to callee) 1379e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // -- x2 : expected number of arguments 1380e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // ----------------------------------- 1381e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // Check the stack for overflow. 1382e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // We are not trying to catch interruptions (e.g. debug break and 1383e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // preemption) here, so the "real stack limit" is checked. 1384e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org Label enough_stack_space; 1385e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org __ LoadRoot(x10, Heap::kRealStackLimitRootIndex); 1386e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // Make x10 the space we have left. The stack might already be overflowed 1387e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // here which will cause x10 to become negative. 1388e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org __ Sub(x10, jssp, x10); 1389e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // Check if the arguments will overflow the stack. 1390e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org __ Cmp(x10, Operand(x2, LSL, kPointerSizeLog2)); 1391e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org __ B(le, stack_overflow); 1392e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org} 1393e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org 1394e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org 1395f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { 1396f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ SmiTag(x10, x0); 13977010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org __ Mov(x11, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 1398f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(lr, fp); 1399f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(x11, x1, x10); 1400f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Add(fp, jssp, 1401f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize); 1402f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1403f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1404f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1405f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { 1406f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // ----------- S t a t e ------------- 1407f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- x0 : result being passed through 1408f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // ----------------------------------- 1409f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Get the number of arguments passed (as a smi), tear down the frame and 1410f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // then drop the parameters and the receiver. 1411f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(x10, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp + 1412f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org kPointerSize))); 1413f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(jssp, fp); 1414f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Pop(fp, lr); 141597b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org __ DropBySMI(x10, kXRegSize); 1416f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Drop(1); 1417f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1418f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1419f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1420f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { 1421f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASM_LOCATION("Builtins::Generate_ArgumentsAdaptorTrampoline"); 1422f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // ----------- S t a t e ------------- 1423f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- x0 : actual number of arguments 1424f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- x1 : function (passed through to callee) 1425f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // -- x2 : expected number of arguments 1426f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // ----------------------------------- 1427f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1428e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org Label stack_overflow; 1429e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org ArgumentAdaptorStackCheck(masm, &stack_overflow); 1430e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org 1431ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org Register argc_actual = x0; // Excluding the receiver. 1432ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org Register argc_expected = x2; // Excluding the receiver. 1433ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org Register function = x1; 1434ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org Register code_entry = x3; 1435ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org 1436f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label invoke, dont_adapt_arguments; 1437f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1438f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label enough, too_few; 1439ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Ldr(code_entry, FieldMemOperand(function, JSFunction::kCodeEntryOffset)); 1440ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Cmp(argc_actual, argc_expected); 1441f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(lt, &too_few); 1442ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Cmp(argc_expected, SharedFunctionInfo::kDontAdaptArgumentsSentinel); 1443f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(eq, &dont_adapt_arguments); 1444f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1445f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org { // Enough parameters: actual >= expected 1446f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org EnterArgumentsAdaptorFrame(masm); 1447f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1448ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org Register copy_start = x10; 1449ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org Register copy_end = x11; 1450ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org Register copy_to = x12; 1451ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org Register scratch1 = x13, scratch2 = x14; 1452ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org 1453ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Lsl(argc_expected, argc_expected, kPointerSizeLog2); 1454ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org 1455ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org // Adjust for fp, lr, and the receiver. 1456ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Add(copy_start, fp, 3 * kPointerSize); 1457ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Add(copy_start, copy_start, Operand(argc_actual, LSL, kPointerSizeLog2)); 1458ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Sub(copy_end, copy_start, argc_expected); 1459ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Sub(copy_end, copy_end, kPointerSize); 1460ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Mov(copy_to, jssp); 1461ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org 1462ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org // Claim space for the arguments, the receiver, and one extra slot. 1463ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org // The extra slot ensures we do not write under jssp. It will be popped 1464ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org // later. 1465ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Add(scratch1, argc_expected, 2 * kPointerSize); 1466ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Claim(scratch1, 1); 1467f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1468f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Copy the arguments (including the receiver) to the new stack frame. 1469ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org Label copy_2_by_2; 1470ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Bind(©_2_by_2); 1471ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Ldp(scratch1, scratch2, 1472ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org MemOperand(copy_start, - 2 * kPointerSize, PreIndex)); 1473ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Stp(scratch1, scratch2, 1474ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org MemOperand(copy_to, - 2 * kPointerSize, PreIndex)); 1475ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Cmp(copy_start, copy_end); 1476ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ B(hi, ©_2_by_2); 1477ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org 1478ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org // Correct the space allocated for the extra slot. 1479ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Drop(1); 1480f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1481f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ B(&invoke); 1482f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1483f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1484f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org { // Too few parameters: Actual < expected 1485f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&too_few); 1486f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org EnterArgumentsAdaptorFrame(masm); 1487f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1488ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org Register copy_from = x10; 1489ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org Register copy_end = x11; 1490ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org Register copy_to = x12; 1491ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org Register scratch1 = x13, scratch2 = x14; 1492ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org 1493ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Lsl(argc_expected, argc_expected, kPointerSizeLog2); 1494ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Lsl(argc_actual, argc_actual, kPointerSizeLog2); 1495ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org 1496ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org // Adjust for fp, lr, and the receiver. 1497ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Add(copy_from, fp, 3 * kPointerSize); 1498ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Add(copy_from, copy_from, argc_actual); 1499ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Mov(copy_to, jssp); 1500ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Sub(copy_end, copy_to, 1 * kPointerSize); // Adjust for the receiver. 1501ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Sub(copy_end, copy_end, argc_actual); 1502ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org 1503ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org // Claim space for the arguments, the receiver, and one extra slot. 1504ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org // The extra slot ensures we do not write under jssp. It will be popped 1505ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org // later. 1506ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Add(scratch1, argc_expected, 2 * kPointerSize); 1507ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Claim(scratch1, 1); 1508f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1509f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Copy the arguments (including the receiver) to the new stack frame. 1510ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org Label copy_2_by_2; 1511ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Bind(©_2_by_2); 1512ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Ldp(scratch1, scratch2, 1513ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org MemOperand(copy_from, - 2 * kPointerSize, PreIndex)); 1514ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Stp(scratch1, scratch2, 1515ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org MemOperand(copy_to, - 2 * kPointerSize, PreIndex)); 1516ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Cmp(copy_to, copy_end); 1517ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ B(hi, ©_2_by_2); 1518ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org 1519ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Mov(copy_to, copy_end); 1520f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1521f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Fill the remaining expected arguments with undefined. 1522ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex); 1523ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Add(copy_end, jssp, kPointerSize); 1524ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org 1525f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label fill; 1526f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&fill); 1527ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Stp(scratch1, scratch1, 1528ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org MemOperand(copy_to, - 2 * kPointerSize, PreIndex)); 1529ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Cmp(copy_to, copy_end); 1530ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ B(hi, &fill); 1531ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org 1532ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org // Correct the space allocated for the extra slot. 1533ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Drop(1); 1534f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1535f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1536f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Arguments have been adapted. Now call the entry point. 1537f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&invoke); 1538ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Call(code_entry); 1539f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1540f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Store offset of return address for deoptimizer. 1541f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset()); 1542f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1543f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Exit frame and return. 1544f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LeaveArgumentsAdaptorFrame(masm); 1545f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ret(); 1546f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1547f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Call the entry point without adapting the arguments. 1548f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Bind(&dont_adapt_arguments); 1549ca2f2040e0e1a10df95bec18e69499f85f4c1316machenbach@chromium.org __ Jump(code_entry); 1550e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org 1551e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org __ Bind(&stack_overflow); 1552e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org { 1553e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org FrameScope frame(masm, StackFrame::MANUAL); 1554e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org EnterArgumentsAdaptorFrame(masm); 1555e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); 1556f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org __ Unreachable(); 1557e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org } 1558f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1559f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1560f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1561f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#undef __ 1562f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1563f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} } // namespace v8::internal 1564f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1565f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#endif // V8_TARGET_ARCH_ARM 1566