| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 __ Ldr(result, GlobalObjectMemOperand()); | 48 __ Ldr(result, GlobalObjectMemOperand()); |
| 49 __ Ldr(result, | 49 __ Ldr(result, |
| 50 FieldMemOperand(result, GlobalObject::kNativeContextOffset)); | 50 FieldMemOperand(result, GlobalObject::kNativeContextOffset)); |
| 51 // Load the InternalArray function from the native context. | 51 // Load the InternalArray function from the native context. |
| 52 __ Ldr(result, | 52 __ Ldr(result, |
| 53 MemOperand(result, | 53 MemOperand(result, |
| 54 Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); | 54 Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); |
| 55 } | 55 } |
| 56 | 56 |
| 57 | 57 |
| 58 // Allocate an empty JSArray. The allocated array is put into the result | |
| 59 // register. An elements backing store is allocated with size initial_capacity | |
| 60 // and filled with the hole values. | |
| 61 static void AllocateEmptyJSArray(MacroAssembler* masm, | |
| 62 Register array_function, | |
| 63 Register result, | |
| 64 Register scratch1, | |
| 65 Register scratch2, | |
| 66 Register scratch3, | |
| 67 Label* gc_required) { | |
| 68 ASSERT(!AreAliased(array_function, result, scratch1, scratch2, scratch3)); | |
| 69 const int initial_capacity = JSArray::kPreallocatedArrayElements; | |
| 70 STATIC_ASSERT(initial_capacity >= 0); | |
| 71 Register map = scratch1; | |
| 72 __ LoadInitialArrayMap(array_function, scratch2, map, kArrayCantHaveHoles); | |
| 73 | |
| 74 // Allocate the JSArray object together with space for a fixed array with the | |
| 75 // requested elements. | |
| 76 int size = JSArray::kSize; | |
| 77 if (initial_capacity > 0) { | |
| 78 size += FixedArray::SizeFor(initial_capacity); | |
| 79 } | |
| 80 __ Allocate(size, result, scratch2, scratch3, gc_required, TAG_OBJECT); | |
| 81 | |
| 82 // Allocated the JSArray. Now initialize the fields except for the elements | |
| 83 // array. | |
| 84 __ Str(map, FieldMemOperand(result, JSObject::kMapOffset)); | |
| 85 | |
| 86 Register empty_prop = scratch1; | |
| 87 __ LoadRoot(empty_prop, Heap::kEmptyFixedArrayRootIndex); | |
| 88 __ Str(empty_prop, FieldMemOperand(result, JSArray::kPropertiesOffset)); | |
| 89 | |
| 90 // Field JSArray::kElementsOffset is initialized later. | |
| 91 __ Mov(scratch3, Operand(Smi::FromInt(0))); | |
| 92 __ Str(scratch3, FieldMemOperand(result, JSArray::kLengthOffset)); | |
| 93 | |
| 94 if (initial_capacity == 0) { | |
| 95 __ Str(empty_prop, FieldMemOperand(result, JSArray::kElementsOffset)); | |
| 96 return; | |
| 97 } | |
| 98 | |
| 99 // Calculate the location of the elements array and set elements array member | |
| 100 // of the JSArray. | |
| 101 Register elements_offset = scratch1; | |
| 102 __ Add(elements_offset, result, JSArray::kSize); | |
| 103 __ Str(elements_offset, FieldMemOperand(result, JSArray::kElementsOffset)); | |
| 104 | |
| 105 // Set up fixed array map. | |
| 106 __ LoadRoot(scratch3, Heap::kFixedArrayMapRootIndex); | |
| 107 __ Str(scratch3, FieldMemOperand(elements_offset, FixedArray::kMapOffset)); | |
| 108 | |
| 109 // Set up fixed array length. | |
| 110 __ Mov(scratch3, Operand(Smi::FromInt(initial_capacity))); | |
| 111 __ Str(scratch3, FieldMemOperand(elements_offset, FixedArray::kLengthOffset)); | |
| 112 | |
| 113 // Set elements_offset to point to first element of fixed array. | |
| 114 __ Add(elements_offset, elements_offset, | |
| 115 FixedArray::kHeaderSize - kHeapObjectTag); | |
| 116 | |
| 117 // Set elements_end to the element after the last in the fixed array. | |
| 118 Register elements_end = scratch2; | |
| 119 STATIC_ASSERT(initial_capacity > 0); | |
| 120 __ Add(elements_end, elements_offset, initial_capacity * kPointerSize); | |
| 121 | |
| 122 // Fill the FixedArray with the hole value. Inline the code if short. | |
| 123 Register the_hole = scratch3; | |
| 124 __ LoadRoot(the_hole, Heap::kTheHoleValueRootIndex); | |
| 125 __ InitializeFieldsWithFiller(elements_offset, elements_end, the_hole); | |
| 126 } | |
| 127 | |
| 128 enum JSArrayFillMode { kDontFillWithHoles, kFillWithHoles }; | |
| 129 | |
| 130 // Allocate a JSArray with the number of elements stored in a register. The | |
| 131 // register array_function holds the built-in Array function and the register | |
| 132 // array_size holds the size of the array as a smi. The allocated array is put | |
| 133 // into the result register and beginning and end of the FixedArray elements | |
| 134 // storage is put into registers elements_array_storage and elements_array_end | |
| 135 // (see below for when that is not the case.) If the parameter fill_mode is | |
| 136 // kFillWithHoles, the allocated elements backing store is filled with the hole | |
| 137 // values otherwise it is left uninitialized. When the backing store is filled, | |
| 138 // the register elements_array_storage is scratched. | |
| 139 static void AllocateJSArray(MacroAssembler* masm, | |
| 140 Register array_function, | |
| 141 Register array_size, | |
| 142 Register result, | |
| 143 Register elements_array_storage, | |
| 144 Register elements_array_end, | |
| 145 Register scratch1, | |
| 146 Register scratch2, | |
| 147 JSArrayFillMode fill_mode, | |
| 148 Label* gc_required) { | |
| 149 ASSERT(!AreAliased(array_function, array_size, result, elements_array_storage, | |
| 150 elements_array_end, scratch1, scratch2)); | |
| 151 // Load the initial map from the array function. | |
| 152 Register map = elements_array_storage; | |
| 153 __ LoadInitialArrayMap(array_function, scratch2, map, | |
| 154 (fill_mode == kFillWithHoles) ? kArrayCanHaveHoles | |
| 155 : kArrayCantHaveHoles); | |
| 156 if (FLAG_debug_code) { | |
| 157 __ Cmp(array_size, Operand(Smi::FromInt(0))); | |
| 158 __ Assert(ne, "Array size is unexpectedly 0"); | |
| 159 } | |
| 160 | |
| 161 // Allocate the JSArray object together with space for a FixedArray with the | |
| 162 // requested number of elements. | |
| 163 __ Mov(elements_array_end, | |
| 164 (JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize); | |
| 165 __ Add(elements_array_end, elements_array_end, Operand::UntagSmi(array_size)); | |
| 166 __ Allocate(elements_array_end, result, scratch1, scratch2, gc_required, | |
| 167 static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); | |
| 168 | |
| 169 // Allocated the JSArray. Now initialize the fields except for the elements | |
| 170 // array. | |
| 171 __ Str(map, FieldMemOperand(result, JSObject::kMapOffset)); | |
| 172 Register empty_prop = elements_array_storage; | |
| 173 __ LoadRoot(empty_prop, Heap::kEmptyFixedArrayRootIndex); | |
| 174 __ Str(empty_prop, FieldMemOperand(result, JSArray::kPropertiesOffset)); | |
| 175 // Field JSArray::kElementsOffset is initialized later. | |
| 176 __ Str(array_size, FieldMemOperand(result, JSArray::kLengthOffset)); | |
| 177 | |
| 178 // Calculate the location of the elements array and set elements array member | |
| 179 // of the JSArray. | |
| 180 Register elements = elements_array_storage; | |
| 181 __ Add(elements, result, JSArray::kSize); | |
| 182 __ Str(elements, FieldMemOperand(result, JSArray::kElementsOffset)); | |
| 183 | |
| 184 // Set up fixed array map. | |
| 185 __ LoadRoot(scratch1, Heap::kFixedArrayMapRootIndex); | |
| 186 __ Str(scratch1, FieldMemOperand(elements, FixedArray::kMapOffset)); | |
| 187 | |
| 188 // Set up fixed array length. | |
| 189 __ Str(array_size, FieldMemOperand(elements, FixedArray::kLengthOffset)); | |
| 190 | |
| 191 // Set elements to point to first element of fixed array. | |
| 192 __ Add(elements, elements, FixedArray::kHeaderSize - kHeapObjectTag); | |
| 193 | |
| 194 // Calculate elements array and elements array end. | |
| 195 __ Add(elements_array_end, elements, | |
| 196 Operand::UntagSmiAndScale(array_size, kPointerSizeLog2)); | |
| 197 | |
| 198 // Fill the allocated FixedArray with the hole value if requested. | |
| 199 if (fill_mode == kFillWithHoles) { | |
| 200 Register the_hole = scratch1; | |
| 201 __ LoadRoot(the_hole, Heap::kTheHoleValueRootIndex); | |
| 202 __ InitializeFieldsWithFiller(elements, elements_array_end, the_hole); | |
| 203 } | |
| 204 } | |
| 205 | |
| 206 | |
| 207 // Load the built-in InternalArray function from the current context. | 58 // Load the built-in InternalArray function from the current context. |
| 208 static void GenerateLoadInternalArrayFunction(MacroAssembler* masm, | 59 static void GenerateLoadInternalArrayFunction(MacroAssembler* masm, |
| 209 Register result) { | 60 Register result) { |
| 210 // Load the native context. | 61 // Load the native context. |
| 211 __ Ldr(result, GlobalObjectMemOperand()); | 62 __ Ldr(result, GlobalObjectMemOperand()); |
| 212 __ Ldr(result, | 63 __ Ldr(result, |
| 213 FieldMemOperand(result, GlobalObject::kNativeContextOffset)); | 64 FieldMemOperand(result, GlobalObject::kNativeContextOffset)); |
| 214 // Load the InternalArray function from the native context. | 65 // Load the InternalArray function from the native context. |
| 215 __ Ldr(result, ContextMemOperand(result, | 66 __ Ldr(result, ContextMemOperand(result, |
| 216 Context::INTERNAL_ARRAY_FUNCTION_INDEX)); | 67 Context::INTERNAL_ARRAY_FUNCTION_INDEX)); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 240 ASSERT(extra_args == NO_EXTRA_ARGUMENTS); | 91 ASSERT(extra_args == NO_EXTRA_ARGUMENTS); |
| 241 } | 92 } |
| 242 | 93 |
| 243 // JumpToExternalReference expects x0 to contain the number of arguments | 94 // JumpToExternalReference expects x0 to contain the number of arguments |
| 244 // including the receiver and the extra arguments. | 95 // including the receiver and the extra arguments. |
| 245 __ Add(x0, x0, num_extra_args + 1); | 96 __ Add(x0, x0, num_extra_args + 1); |
| 246 __ JumpToExternalReference(ExternalReference(id, masm->isolate())); | 97 __ JumpToExternalReference(ExternalReference(id, masm->isolate())); |
| 247 } | 98 } |
| 248 | 99 |
| 249 | 100 |
| 250 // Create a new array for the built-in Array function. This function allocates | |
| 251 // the JSArray object and the FixedArray elements array and initializes these. | |
| 252 // If the Array cannot be constructed in native code the runtime is called. This | |
| 253 // function assumes the following state: | |
| 254 // x0: argc | |
| 255 // x1: constructor (built-in Array function) | |
| 256 // lr: return address | |
| 257 // sp[0]: last argument | |
| 258 // This function is used for both construct and normal calls of Array. The only | |
| 259 // difference between handling a construct call and a normal call is that for a | |
| 260 // construct call the constructor function in x1 needs to be preserved for | |
| 261 // entering the generic code. In both cases argc in x0 needs to be preserved. | |
| 262 // Both registers are preserved by this code so no need to differentiate between | |
| 263 // construct call and normal call. | |
| 264 void ArrayNativeCode(MacroAssembler* masm, Label* call_generic_code) { | |
| 265 Counters* counters = masm->isolate()->counters(); | |
| 266 Label argc_one_or_more, argc_two_or_more, not_empty_array, empty_array, | |
| 267 has_non_smi_element, finish, cant_transition_map, not_double; | |
| 268 Register result = x0; | |
| 269 Register argc = x0; | |
| 270 Register constructor = x1; | |
| 271 Register last_arg = x2; | |
| 272 Register jsarray = x3; | |
| 273 | |
| 274 __ Peek(last_arg, 0 * kPointerSize); | |
| 275 | |
| 276 // Check for array construction with zero arguments or one. | |
| 277 __ Cbnz(argc, &argc_one_or_more); | |
| 278 | |
| 279 // Handle construction of an empty array. | |
| 280 __ Bind(&empty_array); | |
| 281 AllocateEmptyJSArray(masm, constructor, jsarray, x10, x11, x12, | |
| 282 call_generic_code); | |
| 283 __ IncrementCounter(counters->array_function_native(), 1, x10, x11); | |
| 284 // Set up return value, remove receiver from stack and return. | |
| 285 __ Mov(result, jsarray); | |
| 286 __ Drop(1); | |
| 287 __ Ret(); | |
| 288 | |
| 289 // Check for one argument. Bail out if argument is not smi or if it is | |
| 290 // negative. | |
| 291 __ Bind(&argc_one_or_more); | |
| 292 __ Cmp(argc, 1); | |
| 293 __ B(ne, &argc_two_or_more); | |
| 294 __ Cbnz(last_arg, ¬_empty_array); | |
| 295 __ Drop(1); | |
| 296 __ Mov(argc, 0); // Treat this as a call with argc of zero. | |
| 297 __ B(&empty_array); | |
| 298 | |
| 299 __ Bind(¬_empty_array); | |
| 300 // Call generic code for non-smi and negative smi values. | |
| 301 __ JumpIfNotSmi(last_arg, call_generic_code); | |
| 302 __ Tbnz(last_arg, MaskToBit(kIntptrSignBit), call_generic_code); | |
| 303 | |
| 304 // Handle construction of an empty array of a certain size. Bail out if size | |
| 305 // is too large to actually allocate an elements array. | |
| 306 __ Cmp(last_arg, | |
| 307 Operand(Smi::FromInt(JSObject::kInitialMaxFastElementArray))); | |
| 308 __ B(ge, call_generic_code); | |
| 309 | |
| 310 AllocateJSArray(masm, constructor, last_arg, jsarray, x4, x5, x6, x7, | |
| 311 kFillWithHoles, call_generic_code); | |
| 312 __ IncrementCounter(counters->array_function_native(), 1, x10, x11); | |
| 313 __ Mov(result, jsarray); | |
| 314 __ Drop(2); | |
| 315 __ Ret(); | |
| 316 | |
| 317 // Handle construction of an array from a list of arguments. | |
| 318 Register array_size = x10; | |
| 319 Register elements_array = x4; | |
| 320 Register elements_array_end = x5; | |
| 321 __ Bind(&argc_two_or_more); | |
| 322 __ SmiTag(array_size, argc); | |
| 323 AllocateJSArray(masm, constructor, array_size, jsarray, elements_array, | |
| 324 elements_array_end, x6, x7, kDontFillWithHoles, | |
| 325 call_generic_code); | |
| 326 __ IncrementCounter(counters->array_function_native(), 1, x10, x11); | |
| 327 | |
| 328 // Fill arguments as array elements. Copy from the top of the stack (last | |
| 329 // element) to the array backing store filling it backwards. | |
| 330 // Note: elements_array_end points after the backing store, therefore PreIndex | |
| 331 // is used when filling the backing store. | |
| 332 Label loop, entry; | |
| 333 Register index = x6; | |
| 334 Register element = x7; | |
| 335 __ Mov(index, 0); | |
| 336 __ B(&entry); | |
| 337 __ Bind(&loop); | |
| 338 __ Peek(element, Operand(index, LSL, kPointerSizeLog2)); | |
| 339 __ Add(index, index, 1); | |
| 340 if (FLAG_smi_only_arrays) { | |
| 341 __ JumpIfNotSmi(element, &has_non_smi_element); | |
| 342 } | |
| 343 __ Str(element, MemOperand(elements_array_end, -kPointerSize, PreIndex)); | |
| 344 __ Bind(&entry); | |
| 345 __ Cmp(elements_array, elements_array_end); | |
| 346 __ B(lt, &loop); | |
| 347 | |
| 348 __ Bind(&finish); | |
| 349 | |
| 350 // Remove caller arguments and receiver from the stack, set up return value | |
| 351 // and return. | |
| 352 __ Drop(index); | |
| 353 __ Drop(1); | |
| 354 __ Mov(result, jsarray); | |
| 355 __ Ret(); | |
| 356 | |
| 357 __ Bind(&has_non_smi_element); | |
| 358 // Double values are handled by the runtime. | |
| 359 __ CheckMap(element, x10, Heap::kHeapNumberMapRootIndex, ¬_double, | |
| 360 DONT_DO_SMI_CHECK); | |
| 361 __ Bind(&cant_transition_map); | |
| 362 __ UndoAllocationInNewSpace(jsarray, x4); | |
| 363 __ B(call_generic_code); | |
| 364 | |
| 365 __ Bind(¬_double); | |
| 366 // Transition FAST_SMI_ELEMENTS to FAST_ELEMENTS. | |
| 367 __ Ldr(element, FieldMemOperand(jsarray, HeapObject::kMapOffset)); | |
| 368 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, FAST_ELEMENTS, | |
| 369 element, x10, &cant_transition_map); | |
| 370 __ Str(element, FieldMemOperand(jsarray, HeapObject::kMapOffset)); | |
| 371 __ RecordWriteField(jsarray, HeapObject::kMapOffset, element, x10, | |
| 372 kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET, | |
| 373 OMIT_SMI_CHECK); | |
| 374 | |
| 375 Label loop2; | |
| 376 __ Sub(index, index, 1); | |
| 377 __ Bind(&loop2); | |
| 378 __ Peek(element, Operand(index, LSL, kPointerSizeLog2)); | |
| 379 __ Add(index, index, 1); | |
| 380 __ Str(element, MemOperand(elements_array_end, -kPointerSize, PreIndex)); | |
| 381 __ Cmp(elements_array, elements_array_end); | |
| 382 __ B(lt, &loop2); | |
| 383 __ B(&finish); | |
| 384 } | |
| 385 | |
| 386 | |
| 387 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { | 101 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { |
| 388 // ----------- S t a t e ------------- | 102 // ----------- S t a t e ------------- |
| 389 // -- x0 : number of arguments | 103 // -- x0 : number of arguments |
| 390 // -- lr : return address | 104 // -- lr : return address |
| 391 // -- sp[...]: constructor arguments | 105 // -- sp[...]: constructor arguments |
| 392 // ----------------------------------- | 106 // ----------------------------------- |
| 393 ASM_LOCATION("Builtins::Generate_InternalArrayCode"); | 107 ASM_LOCATION("Builtins::Generate_InternalArrayCode"); |
| 394 Label generic_array_code; | 108 Label generic_array_code; |
| 395 | 109 |
| 396 // Get the InternalArray function. | 110 // Get the InternalArray function. |
| 397 GenerateLoadInternalArrayFunction(masm, x1); | 111 GenerateLoadInternalArrayFunction(masm, x1); |
| 398 | 112 |
| 399 if (FLAG_debug_code) { | 113 if (FLAG_debug_code) { |
| 400 // Initial map for the builtin InternalArray functions should be maps. | 114 // Initial map for the builtin InternalArray functions should be maps. |
| 401 __ Ldr(x10, FieldMemOperand(x1, JSFunction::kPrototypeOrInitialMapOffset)); | 115 __ Ldr(x10, FieldMemOperand(x1, JSFunction::kPrototypeOrInitialMapOffset)); |
| 402 __ Tst(x10, kSmiTagMask); | 116 __ Tst(x10, kSmiTagMask); |
| 403 __ Assert(ne, "Unexpected initial map for InternalArray function"); | 117 __ Assert(ne, "Unexpected initial map for InternalArray function"); |
| 404 __ CompareObjectType(x10, x11, x12, MAP_TYPE); | 118 __ CompareObjectType(x10, x11, x12, MAP_TYPE); |
| 405 __ Assert(eq, "Unexpected initial map for InternalArray function"); | 119 __ Assert(eq, "Unexpected initial map for InternalArray function"); |
| 406 } | 120 } |
| 407 | 121 |
| 408 // Run the native code for the InternalArray function called as a normal | 122 // Run the native code for the InternalArray function called as a normal |
| 409 // function. | 123 // function. |
| 410 if (FLAG_optimize_constructed_arrays) { | 124 InternalArrayConstructorStub stub(masm->isolate()); |
| 411 // tail call a stub | 125 __ TailCallStub(&stub); |
| 412 InternalArrayConstructorStub stub(masm->isolate()); | |
| 413 __ TailCallStub(&stub); | |
| 414 } else { | |
| 415 ArrayNativeCode(masm, &generic_array_code); | |
| 416 | |
| 417 // Jump to the generic array code if the specialized code cannot handle the | |
| 418 // construction. | |
| 419 __ Bind(&generic_array_code); | |
| 420 Handle<Code> array_code = | |
| 421 masm->isolate()->builtins()->InternalArrayCodeGeneric(); | |
| 422 __ Jump(array_code, RelocInfo::CODE_TARGET); | |
| 423 } | |
| 424 } | 126 } |
| 425 | 127 |
| 426 | 128 |
| 427 void Builtins::Generate_ArrayCode(MacroAssembler* masm) { | 129 void Builtins::Generate_ArrayCode(MacroAssembler* masm) { |
| 428 // ----------- S t a t e ------------- | 130 // ----------- S t a t e ------------- |
| 429 // -- x0 : number of arguments | 131 // -- x0 : number of arguments |
| 430 // -- lr : return address | 132 // -- lr : return address |
| 431 // -- sp[...]: constructor arguments | 133 // -- sp[...]: constructor arguments |
| 432 // ----------------------------------- | 134 // ----------------------------------- |
| 433 ASM_LOCATION("Builtins::Generate_ArrayCode"); | 135 ASM_LOCATION("Builtins::Generate_ArrayCode"); |
| 434 Label generic_array_code, one_or_more_arguments, two_or_more_arguments; | 136 Label generic_array_code, one_or_more_arguments, two_or_more_arguments; |
| 435 | 137 |
| 436 // Get the Array function. | 138 // Get the Array function. |
| 437 GenerateLoadArrayFunction(masm, x1); | 139 GenerateLoadArrayFunction(masm, x1); |
| 438 | 140 |
| 439 if (FLAG_debug_code) { | 141 if (FLAG_debug_code) { |
| 440 // Initial map for the builtin Array functions should be maps. | 142 // Initial map for the builtin Array functions should be maps. |
| 441 __ Ldr(x10, FieldMemOperand(x1, JSFunction::kPrototypeOrInitialMapOffset)); | 143 __ Ldr(x10, FieldMemOperand(x1, JSFunction::kPrototypeOrInitialMapOffset)); |
| 442 __ Tst(x10, kSmiTagMask); | 144 __ Tst(x10, kSmiTagMask); |
| 443 __ Assert(ne, "Unexpected initial map for Array function"); | 145 __ Assert(ne, "Unexpected initial map for Array function"); |
| 444 __ CompareObjectType(x10, x11, x12, MAP_TYPE); | 146 __ CompareObjectType(x10, x11, x12, MAP_TYPE); |
| 445 __ Assert(eq, "Unexpected initial map for Array function"); | 147 __ Assert(eq, "Unexpected initial map for Array function"); |
| 446 } | 148 } |
| 447 | 149 |
| 448 // Run the native code for the Array function called as a normal function. | 150 // Run the native code for the Array function called as a normal function. |
| 449 if (FLAG_optimize_constructed_arrays) { | 151 Handle<Object> undefined_sentinel( |
| 450 // tail call a stub | 152 masm->isolate()->heap()->undefined_value(), |
| 451 Handle<Object> undefined_sentinel( | 153 masm->isolate()); |
| 452 masm->isolate()->heap()->undefined_value(), | 154 __ Mov(x2, Operand(undefined_sentinel)); |
| 453 masm->isolate()); | 155 ArrayConstructorStub stub(masm->isolate()); |
| 454 __ Mov(x2, Operand(undefined_sentinel)); | 156 __ TailCallStub(&stub); |
| 455 ArrayConstructorStub stub(masm->isolate()); | |
| 456 __ TailCallStub(&stub); | |
| 457 } else { | |
| 458 ArrayNativeCode(masm, &generic_array_code); | |
| 459 | |
| 460 // Jump to the generic array code if the specialized code cannot handle | |
| 461 // the construction. | |
| 462 __ Bind(&generic_array_code); | |
| 463 Handle<Code> array_code = | |
| 464 masm->isolate()->builtins()->ArrayCodeGeneric(); | |
| 465 __ Jump(array_code, RelocInfo::CODE_TARGET); | |
| 466 } | |
| 467 } | 157 } |
| 468 | 158 |
| 469 | 159 |
| 470 void Builtins::Generate_CommonArrayConstructCode(MacroAssembler* masm) { | |
| 471 // ----------- S t a t e ------------- | |
| 472 // -- x0 : number of arguments | |
| 473 // -- x1 : constructor function | |
| 474 // -- x2 : type info cell | |
| 475 // -- lr : return address | |
| 476 // -- sp[...]: constructor arguments | |
| 477 // ----------------------------------- | |
| 478 ASM_LOCATION("Builtins::Generate_CommonArrayConstructCode"); | |
| 479 | |
| 480 if (FLAG_debug_code) { | |
| 481 Register constructor = x1; | |
| 482 // The array construct code is only set for the builtin and internal | |
| 483 // Array functions which always have a map. | |
| 484 // Initial map for the builtin Array function should be a map. | |
| 485 __ Ldr(x3, FieldMemOperand(constructor, | |
| 486 JSFunction::kPrototypeOrInitialMapOffset)); | |
| 487 __ Tst(x3, kSmiTagMask); | |
| 488 __ Assert(ne, "Unexpected initial map for Array function"); | |
| 489 __ CompareObjectType(x3, x10, x11, MAP_TYPE); | |
| 490 __ Assert(eq, "Unexpected initial map for Array function"); | |
| 491 } | |
| 492 Label generic_constructor; | |
| 493 // Run the native code for the Array function called as a constructor. | |
| 494 ArrayNativeCode(masm, &generic_constructor); | |
| 495 | |
| 496 // Jump to the generic construct code in case the specialized code cannot | |
| 497 // handle the construction. | |
| 498 __ Bind(&generic_constructor); | |
| 499 Handle<Code> generic_construct_stub = | |
| 500 masm->isolate()->builtins()->JSConstructStubGeneric(); | |
| 501 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); | |
| 502 } | |
| 503 | |
| 504 | |
| 505 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { | 160 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { |
| 506 // ----------- S t a t e ------------- | 161 // ----------- S t a t e ------------- |
| 507 // -- x0 : number of arguments | 162 // -- x0 : number of arguments |
| 508 // -- x1 : constructor function | 163 // -- x1 : constructor function |
| 509 // -- lr : return address | 164 // -- lr : return address |
| 510 // -- sp[(argc - n - 1) * 8] : arg[n] (zero based) | 165 // -- sp[(argc - n - 1) * 8] : arg[n] (zero based) |
| 511 // -- sp[argc * 8] : receiver | 166 // -- sp[argc * 8] : receiver |
| 512 // ----------------------------------- | 167 // ----------------------------------- |
| 513 ASM_LOCATION("Builtins::Generate_StringConstructCode"); | 168 ASM_LOCATION("Builtins::Generate_StringConstructCode"); |
| 514 Counters* counters = masm->isolate()->counters(); | 169 Counters* counters = masm->isolate()->counters(); |
| (...skipping 1249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1764 __ Bind(&dont_adapt_arguments); | 1419 __ Bind(&dont_adapt_arguments); |
| 1765 __ Jump(x3); | 1420 __ Jump(x3); |
| 1766 } | 1421 } |
| 1767 | 1422 |
| 1768 | 1423 |
| 1769 #undef __ | 1424 #undef __ |
| 1770 | 1425 |
| 1771 } } // namespace v8::internal | 1426 } } // namespace v8::internal |
| 1772 | 1427 |
| 1773 #endif // V8_TARGET_ARCH_ARM | 1428 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |