OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 197 matching lines...) Loading... |
208 __ LoadInitialArrayMap(array_function, scratch2, | 208 __ LoadInitialArrayMap(array_function, scratch2, |
209 elements_array_storage, fill_with_hole); | 209 elements_array_storage, fill_with_hole); |
210 | 210 |
211 if (FLAG_debug_code) { // Assert that array size is not zero. | 211 if (FLAG_debug_code) { // Assert that array size is not zero. |
212 __ tst(array_size, array_size); | 212 __ tst(array_size, array_size); |
213 __ Assert(ne, "array size is unexpectedly 0"); | 213 __ Assert(ne, "array size is unexpectedly 0"); |
214 } | 214 } |
215 | 215 |
216 // Allocate the JSArray object together with space for a FixedArray with the | 216 // Allocate the JSArray object together with space for a FixedArray with the |
217 // requested number of elements. | 217 // requested number of elements. |
218 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | |
219 __ mov(elements_array_end, | 218 __ mov(elements_array_end, |
220 Operand((JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize)); | 219 Operand((JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize)); |
221 __ add(elements_array_end, | 220 __ add(elements_array_end, elements_array_end, Operand::SmiUntag(array_size)); |
222 elements_array_end, | |
223 Operand(array_size, ASR, kSmiTagSize)); | |
224 __ Allocate(elements_array_end, | 221 __ Allocate(elements_array_end, |
225 result, | 222 result, |
226 scratch1, | 223 scratch1, |
227 scratch2, | 224 scratch2, |
228 gc_required, | 225 gc_required, |
229 static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); | 226 static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); |
230 | 227 |
231 // Allocated the JSArray. Now initialize the fields except for the elements | 228 // Allocated the JSArray. Now initialize the fields except for the elements |
232 // array. | 229 // array. |
233 // result: JSObject | 230 // result: JSObject |
234 // elements_array_storage: initial map | 231 // elements_array_storage: initial map |
235 // array_size: size of array (smi) | 232 // array_size: size of array (smi) |
236 __ str(elements_array_storage, FieldMemOperand(result, JSObject::kMapOffset)); | 233 __ str(elements_array_storage, FieldMemOperand(result, JSObject::kMapOffset)); |
237 __ LoadRoot(elements_array_storage, Heap::kEmptyFixedArrayRootIndex); | 234 __ LoadRoot(elements_array_storage, Heap::kEmptyFixedArrayRootIndex); |
238 __ str(elements_array_storage, | 235 __ str(elements_array_storage, |
239 FieldMemOperand(result, JSArray::kPropertiesOffset)); | 236 FieldMemOperand(result, JSArray::kPropertiesOffset)); |
240 // Field JSArray::kElementsOffset is initialized later. | 237 // Field JSArray::kElementsOffset is initialized later. |
241 __ str(array_size, FieldMemOperand(result, JSArray::kLengthOffset)); | 238 __ str(array_size, FieldMemOperand(result, JSArray::kLengthOffset)); |
242 | 239 |
243 // Calculate the location of the elements array and set elements array member | 240 // Calculate the location of the elements array and set elements array member |
244 // of the JSArray. | 241 // of the JSArray. |
245 // result: JSObject | 242 // result: JSObject |
246 // array_size: size of array (smi) | 243 // array_size: size of array (smi) |
247 __ add(elements_array_storage, result, Operand(JSArray::kSize)); | 244 __ add(elements_array_storage, result, Operand(JSArray::kSize)); |
248 __ str(elements_array_storage, | 245 __ str(elements_array_storage, |
249 FieldMemOperand(result, JSArray::kElementsOffset)); | 246 FieldMemOperand(result, JSArray::kElementsOffset)); |
250 | 247 |
251 // Clear the heap tag on the elements array. | 248 // Clear the heap tag on the elements array. |
252 STATIC_ASSERT(kSmiTag == 0); | |
253 __ sub(elements_array_storage, | 249 __ sub(elements_array_storage, |
254 elements_array_storage, | 250 elements_array_storage, |
255 Operand(kHeapObjectTag)); | 251 Operand(kHeapObjectTag)); |
256 // Initialize the fixed array and fill it with holes. FixedArray length is | 252 // Initialize the fixed array and fill it with holes. FixedArray length is |
257 // stored as a smi. | 253 // stored as a smi. |
258 // result: JSObject | 254 // result: JSObject |
259 // elements_array_storage: elements array (untagged) | 255 // elements_array_storage: elements array (untagged) |
260 // array_size: size of array (smi) | 256 // array_size: size of array (smi) |
261 __ LoadRoot(scratch1, Heap::kFixedArrayMapRootIndex); | 257 __ LoadRoot(scratch1, Heap::kFixedArrayMapRootIndex); |
262 ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset); | 258 ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset); |
263 __ str(scratch1, MemOperand(elements_array_storage, kPointerSize, PostIndex)); | 259 __ str(scratch1, MemOperand(elements_array_storage, kPointerSize, PostIndex)); |
264 STATIC_ASSERT(kSmiTag == 0); | |
265 ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); | 260 ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); |
266 __ str(array_size, | 261 __ str(array_size, |
267 MemOperand(elements_array_storage, kPointerSize, PostIndex)); | 262 MemOperand(elements_array_storage, kPointerSize, PostIndex)); |
268 | 263 |
269 // Calculate elements array and elements array end. | 264 // Calculate elements array and elements array end. |
270 // result: JSObject | 265 // result: JSObject |
271 // elements_array_storage: elements array element storage | 266 // elements_array_storage: elements array element storage |
272 // array_size: smi-tagged size of elements array | 267 // array_size: smi-tagged size of elements array |
273 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); | |
274 __ add(elements_array_end, | 268 __ add(elements_array_end, |
275 elements_array_storage, | 269 elements_array_storage, |
276 Operand(array_size, LSL, kPointerSizeLog2 - kSmiTagSize)); | 270 Operand::PointerOffsetFromSmiKey(array_size)); |
277 | 271 |
278 // Fill the allocated FixedArray with the hole value if requested. | 272 // Fill the allocated FixedArray with the hole value if requested. |
279 // result: JSObject | 273 // result: JSObject |
280 // elements_array_storage: elements array element storage | 274 // elements_array_storage: elements array element storage |
281 // elements_array_end: start of next object | 275 // elements_array_end: start of next object |
282 if (fill_with_hole) { | 276 if (fill_with_hole) { |
283 Label loop, entry; | 277 Label loop, entry; |
284 __ LoadRoot(scratch1, Heap::kTheHoleValueRootIndex); | 278 __ LoadRoot(scratch1, Heap::kTheHoleValueRootIndex); |
285 __ jmp(&entry); | 279 __ jmp(&entry); |
286 __ bind(&loop); | 280 __ bind(&loop); |
(...skipping 41 matching lines...) Loading... |
328 // Set up return value, remove receiver from stack and return. | 322 // Set up return value, remove receiver from stack and return. |
329 __ mov(r0, r2); | 323 __ mov(r0, r2); |
330 __ add(sp, sp, Operand(kPointerSize)); | 324 __ add(sp, sp, Operand(kPointerSize)); |
331 __ Jump(lr); | 325 __ Jump(lr); |
332 | 326 |
333 // Check for one argument. Bail out if argument is not smi or if it is | 327 // Check for one argument. Bail out if argument is not smi or if it is |
334 // negative. | 328 // negative. |
335 __ bind(&argc_one_or_more); | 329 __ bind(&argc_one_or_more); |
336 __ cmp(r0, Operand(1)); | 330 __ cmp(r0, Operand(1)); |
337 __ b(ne, &argc_two_or_more); | 331 __ b(ne, &argc_two_or_more); |
338 STATIC_ASSERT(kSmiTag == 0); | |
339 __ ldr(r2, MemOperand(sp)); // Get the argument from the stack. | 332 __ ldr(r2, MemOperand(sp)); // Get the argument from the stack. |
340 __ tst(r2, r2); | 333 __ tst(r2, r2); |
341 __ b(ne, ¬_empty_array); | 334 __ b(ne, ¬_empty_array); |
342 __ Drop(1); // Adjust stack. | 335 __ Drop(1); // Adjust stack. |
343 __ mov(r0, Operand::Zero()); // Treat this as a call with argc of zero. | 336 __ mov(r0, Operand::Zero()); // Treat this as a call with argc of zero. |
344 __ b(&empty_array); | 337 __ b(&empty_array); |
345 | 338 |
346 __ bind(¬_empty_array); | 339 __ bind(¬_empty_array); |
| 340 STATIC_ASSERT(kSmiTag == 0); |
347 __ and_(r3, r2, Operand(kIntptrSignBit | kSmiTagMask), SetCC); | 341 __ and_(r3, r2, Operand(kIntptrSignBit | kSmiTagMask), SetCC); |
348 __ b(ne, call_generic_code); | 342 __ b(ne, call_generic_code); |
349 | 343 |
350 // Handle construction of an empty array of a certain size. Bail out if size | 344 // Handle construction of an empty array of a certain size. Bail out if size |
351 // is too large to actually allocate an elements array. | 345 // is too large to actually allocate an elements array. |
352 STATIC_ASSERT(kSmiTag == 0); | 346 STATIC_ASSERT(kSmiTag == 0); |
353 __ cmp(r2, Operand(JSObject::kInitialMaxFastElementArray << kSmiTagSize)); | 347 __ cmp(r2, Operand(JSObject::kInitialMaxFastElementArray << kSmiTagSize)); |
354 __ b(ge, call_generic_code); | 348 __ b(ge, call_generic_code); |
355 | 349 |
356 // r0: argc | 350 // r0: argc |
(...skipping 11 matching lines...) Loading... |
368 true, | 362 true, |
369 call_generic_code); | 363 call_generic_code); |
370 __ IncrementCounter(counters->array_function_native(), 1, r2, r4); | 364 __ IncrementCounter(counters->array_function_native(), 1, r2, r4); |
371 // Set up return value, remove receiver and argument from stack and return. | 365 // Set up return value, remove receiver and argument from stack and return. |
372 __ mov(r0, r3); | 366 __ mov(r0, r3); |
373 __ add(sp, sp, Operand(2 * kPointerSize)); | 367 __ add(sp, sp, Operand(2 * kPointerSize)); |
374 __ Jump(lr); | 368 __ Jump(lr); |
375 | 369 |
376 // Handle construction of an array from a list of arguments. | 370 // Handle construction of an array from a list of arguments. |
377 __ bind(&argc_two_or_more); | 371 __ bind(&argc_two_or_more); |
378 __ mov(r2, Operand(r0, LSL, kSmiTagSize)); // Convet argc to a smi. | 372 __ SmiTag(r2, r0); |
379 | 373 |
380 // r0: argc | 374 // r0: argc |
381 // r1: constructor | 375 // r1: constructor |
382 // r2: array_size (smi) | 376 // r2: array_size (smi) |
383 // sp[0]: last argument | 377 // sp[0]: last argument |
384 AllocateJSArray(masm, | 378 AllocateJSArray(masm, |
385 r1, | 379 r1, |
386 r2, | 380 r2, |
387 r3, | 381 r3, |
388 r4, | 382 r4, |
(...skipping 82 matching lines...) Loading... |
471 // -- sp[...]: constructor arguments | 465 // -- sp[...]: constructor arguments |
472 // ----------------------------------- | 466 // ----------------------------------- |
473 Label generic_array_code, one_or_more_arguments, two_or_more_arguments; | 467 Label generic_array_code, one_or_more_arguments, two_or_more_arguments; |
474 | 468 |
475 // Get the InternalArray function. | 469 // Get the InternalArray function. |
476 GenerateLoadInternalArrayFunction(masm, r1); | 470 GenerateLoadInternalArrayFunction(masm, r1); |
477 | 471 |
478 if (FLAG_debug_code) { | 472 if (FLAG_debug_code) { |
479 // Initial map for the builtin InternalArray functions should be maps. | 473 // Initial map for the builtin InternalArray functions should be maps. |
480 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); | 474 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); |
481 __ tst(r2, Operand(kSmiTagMask)); | 475 __ SmiTst(r2); |
482 __ Assert(ne, "Unexpected initial map for InternalArray function"); | 476 __ Assert(ne, "Unexpected initial map for InternalArray function"); |
483 __ CompareObjectType(r2, r3, r4, MAP_TYPE); | 477 __ CompareObjectType(r2, r3, r4, MAP_TYPE); |
484 __ Assert(eq, "Unexpected initial map for InternalArray function"); | 478 __ Assert(eq, "Unexpected initial map for InternalArray function"); |
485 } | 479 } |
486 | 480 |
487 // Run the native code for the InternalArray function called as a normal | 481 // Run the native code for the InternalArray function called as a normal |
488 // function. | 482 // function. |
489 ArrayNativeCode(masm, &generic_array_code); | 483 ArrayNativeCode(masm, &generic_array_code); |
490 | 484 |
491 // Jump to the generic array code if the specialized code cannot handle the | 485 // Jump to the generic array code if the specialized code cannot handle the |
(...skipping 13 matching lines...) Loading... |
505 // -- sp[...]: constructor arguments | 499 // -- sp[...]: constructor arguments |
506 // ----------------------------------- | 500 // ----------------------------------- |
507 Label generic_array_code, one_or_more_arguments, two_or_more_arguments; | 501 Label generic_array_code, one_or_more_arguments, two_or_more_arguments; |
508 | 502 |
509 // Get the Array function. | 503 // Get the Array function. |
510 GenerateLoadArrayFunction(masm, r1); | 504 GenerateLoadArrayFunction(masm, r1); |
511 | 505 |
512 if (FLAG_debug_code) { | 506 if (FLAG_debug_code) { |
513 // Initial map for the builtin Array functions should be maps. | 507 // Initial map for the builtin Array functions should be maps. |
514 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); | 508 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); |
515 __ tst(r2, Operand(kSmiTagMask)); | 509 __ SmiTst(r2); |
516 __ Assert(ne, "Unexpected initial map for Array function"); | 510 __ Assert(ne, "Unexpected initial map for Array function"); |
517 __ CompareObjectType(r2, r3, r4, MAP_TYPE); | 511 __ CompareObjectType(r2, r3, r4, MAP_TYPE); |
518 __ Assert(eq, "Unexpected initial map for Array function"); | 512 __ Assert(eq, "Unexpected initial map for Array function"); |
519 } | 513 } |
520 | 514 |
521 // Run the native code for the Array function called as a normal function. | 515 // Run the native code for the Array function called as a normal function. |
522 ArrayNativeCode(masm, &generic_array_code); | 516 ArrayNativeCode(masm, &generic_array_code); |
523 | 517 |
524 // Jump to the generic array code if the specialized code cannot handle | 518 // Jump to the generic array code if the specialized code cannot handle |
525 // the construction. | 519 // the construction. |
(...skipping 12 matching lines...) Loading... |
538 // -- r2 : type info cell | 532 // -- r2 : type info cell |
539 // -- lr : return address | 533 // -- lr : return address |
540 // -- sp[...]: constructor arguments | 534 // -- sp[...]: constructor arguments |
541 // ----------------------------------- | 535 // ----------------------------------- |
542 | 536 |
543 if (FLAG_debug_code) { | 537 if (FLAG_debug_code) { |
544 // The array construct code is only set for the builtin and internal | 538 // The array construct code is only set for the builtin and internal |
545 // Array functions which always have a map. | 539 // Array functions which always have a map. |
546 // Initial map for the builtin Array function should be a map. | 540 // Initial map for the builtin Array function should be a map. |
547 __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); | 541 __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); |
548 __ tst(r3, Operand(kSmiTagMask)); | 542 __ SmiTst(r3); |
549 __ Assert(ne, "Unexpected initial map for Array function"); | 543 __ Assert(ne, "Unexpected initial map for Array function"); |
550 __ CompareObjectType(r3, r3, r4, MAP_TYPE); | 544 __ CompareObjectType(r3, r3, r4, MAP_TYPE); |
551 __ Assert(eq, "Unexpected initial map for Array function"); | 545 __ Assert(eq, "Unexpected initial map for Array function"); |
552 } | 546 } |
553 Label generic_constructor; | 547 Label generic_constructor; |
554 // Run the native code for the Array function called as a constructor. | 548 // Run the native code for the Array function called as a constructor. |
555 ArrayNativeCode(masm, &generic_constructor); | 549 ArrayNativeCode(masm, &generic_constructor); |
556 | 550 |
557 // Jump to the generic construct code in case the specialized code cannot | 551 // Jump to the generic construct code in case the specialized code cannot |
558 // handle the construction. | 552 // handle the construction. |
(...skipping 212 matching lines...) Loading... |
771 // Should never count constructions for api objects. | 765 // Should never count constructions for api objects. |
772 ASSERT(!is_api_function || !count_constructions); | 766 ASSERT(!is_api_function || !count_constructions); |
773 | 767 |
774 Isolate* isolate = masm->isolate(); | 768 Isolate* isolate = masm->isolate(); |
775 | 769 |
776 // Enter a construct frame. | 770 // Enter a construct frame. |
777 { | 771 { |
778 FrameScope scope(masm, StackFrame::CONSTRUCT); | 772 FrameScope scope(masm, StackFrame::CONSTRUCT); |
779 | 773 |
780 // Preserve the two incoming parameters on the stack. | 774 // Preserve the two incoming parameters on the stack. |
781 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); | 775 __ SmiTag(r0); |
782 __ push(r0); // Smi-tagged arguments count. | 776 __ push(r0); // Smi-tagged arguments count. |
783 __ push(r1); // Constructor function. | 777 __ push(r1); // Constructor function. |
784 | 778 |
785 // Try to allocate the object without transitioning into C code. If any of | 779 // Try to allocate the object without transitioning into C code. If any of |
786 // the preconditions is not met, the code bails out to the runtime call. | 780 // the preconditions is not met, the code bails out to the runtime call. |
787 Label rt_call, allocated; | 781 Label rt_call, allocated; |
788 if (FLAG_inline_new) { | 782 if (FLAG_inline_new) { |
789 Label undo_allocation; | 783 Label undo_allocation; |
790 #ifdef ENABLE_DEBUGGER_SUPPORT | 784 #ifdef ENABLE_DEBUGGER_SUPPORT |
791 ExternalReference debug_step_in_fp = | 785 ExternalReference debug_step_in_fp = |
(...skipping 132 matching lines...) Loading... |
924 // Initialize the FixedArray. | 918 // Initialize the FixedArray. |
925 // r1: constructor | 919 // r1: constructor |
926 // r3: number of elements in properties array | 920 // r3: number of elements in properties array |
927 // r4: JSObject | 921 // r4: JSObject |
928 // r5: FixedArray (not tagged) | 922 // r5: FixedArray (not tagged) |
929 __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex); | 923 __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex); |
930 __ mov(r2, r5); | 924 __ mov(r2, r5); |
931 ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); | 925 ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); |
932 __ str(r6, MemOperand(r2, kPointerSize, PostIndex)); | 926 __ str(r6, MemOperand(r2, kPointerSize, PostIndex)); |
933 ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); | 927 ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); |
934 __ mov(r0, Operand(r3, LSL, kSmiTagSize)); | 928 __ SmiTag(r0, r3); |
935 __ str(r0, MemOperand(r2, kPointerSize, PostIndex)); | 929 __ str(r0, MemOperand(r2, kPointerSize, PostIndex)); |
936 | 930 |
937 // Initialize the fields to undefined. | 931 // Initialize the fields to undefined. |
938 // r1: constructor function | 932 // r1: constructor function |
939 // r2: First element of FixedArray (not tagged) | 933 // r2: First element of FixedArray (not tagged) |
940 // r3: number of elements in properties array | 934 // r3: number of elements in properties array |
941 // r4: JSObject | 935 // r4: JSObject |
942 // r5: FixedArray (not tagged) | 936 // r5: FixedArray (not tagged) |
943 __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2)); // End of object. | 937 __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2)); // End of object. |
944 ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize); | 938 ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize); |
(...skipping 52 matching lines...) Loading... |
997 // sp[1]: receiver | 991 // sp[1]: receiver |
998 // sp[2]: constructor function | 992 // sp[2]: constructor function |
999 // sp[3]: number of arguments (smi-tagged) | 993 // sp[3]: number of arguments (smi-tagged) |
1000 __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); | 994 __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); |
1001 __ ldr(r3, MemOperand(sp, 3 * kPointerSize)); | 995 __ ldr(r3, MemOperand(sp, 3 * kPointerSize)); |
1002 | 996 |
1003 // Set up pointer to last argument. | 997 // Set up pointer to last argument. |
1004 __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); | 998 __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); |
1005 | 999 |
1006 // Set up number of arguments for function call below | 1000 // Set up number of arguments for function call below |
1007 __ mov(r0, Operand(r3, LSR, kSmiTagSize)); | 1001 __ SmiUntag(r0, r3); |
1008 | 1002 |
1009 // Copy arguments and receiver to the expression stack. | 1003 // Copy arguments and receiver to the expression stack. |
1010 // r0: number of arguments | 1004 // r0: number of arguments |
1011 // r1: constructor function | 1005 // r1: constructor function |
1012 // r2: address of last argument (caller sp) | 1006 // r2: address of last argument (caller sp) |
1013 // r3: number of arguments (smi-tagged) | 1007 // r3: number of arguments (smi-tagged) |
1014 // sp[0]: receiver | 1008 // sp[0]: receiver |
1015 // sp[1]: receiver | 1009 // sp[1]: receiver |
1016 // sp[2]: constructor function | 1010 // sp[2]: constructor function |
1017 // sp[3]: number of arguments (smi-tagged) | 1011 // sp[3]: number of arguments (smi-tagged) |
(...skipping 434 matching lines...) Loading... |
1452 | 1446 |
1453 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | 1447 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); |
1454 __ CompareObjectType(r2, r3, r3, FIRST_SPEC_OBJECT_TYPE); | 1448 __ CompareObjectType(r2, r3, r3, FIRST_SPEC_OBJECT_TYPE); |
1455 __ b(ge, &shift_arguments); | 1449 __ b(ge, &shift_arguments); |
1456 | 1450 |
1457 __ bind(&convert_to_object); | 1451 __ bind(&convert_to_object); |
1458 | 1452 |
1459 { | 1453 { |
1460 // Enter an internal frame in order to preserve argument count. | 1454 // Enter an internal frame in order to preserve argument count. |
1461 FrameScope scope(masm, StackFrame::INTERNAL); | 1455 FrameScope scope(masm, StackFrame::INTERNAL); |
1462 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); // Smi-tagged. | 1456 __ SmiTag(r0); |
1463 __ push(r0); | 1457 __ push(r0); |
1464 | 1458 |
1465 __ push(r2); | 1459 __ push(r2); |
1466 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 1460 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
1467 __ mov(r2, r0); | 1461 __ mov(r2, r0); |
1468 | 1462 |
1469 __ pop(r0); | 1463 __ pop(r0); |
1470 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); | 1464 __ SmiUntag(r0); |
1471 | 1465 |
1472 // Exit the internal frame. | 1466 // Exit the internal frame. |
1473 } | 1467 } |
1474 | 1468 |
1475 // Restore the function to r1, and the flag to r4. | 1469 // Restore the function to r1, and the flag to r4. |
1476 __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); | 1470 __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); |
1477 __ mov(r4, Operand::Zero()); | 1471 __ mov(r4, Operand::Zero()); |
1478 __ jmp(&patch_receiver); | 1472 __ jmp(&patch_receiver); |
1479 | 1473 |
1480 // Use the global receiver object from the called function as the | 1474 // Use the global receiver object from the called function as the |
(...skipping 82 matching lines...) Loading... |
1563 } | 1557 } |
1564 | 1558 |
1565 // 5b. Get the code to call from the function and check that the number of | 1559 // 5b. Get the code to call from the function and check that the number of |
1566 // expected arguments matches what we're providing. If so, jump | 1560 // expected arguments matches what we're providing. If so, jump |
1567 // (tail-call) to the code in register edx without checking arguments. | 1561 // (tail-call) to the code in register edx without checking arguments. |
1568 // r0: actual number of arguments | 1562 // r0: actual number of arguments |
1569 // r1: function | 1563 // r1: function |
1570 __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 1564 __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
1571 __ ldr(r2, | 1565 __ ldr(r2, |
1572 FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset)); | 1566 FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset)); |
1573 __ mov(r2, Operand(r2, ASR, kSmiTagSize)); | 1567 __ SmiUntag(r2); |
1574 __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); | 1568 __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); |
1575 __ SetCallKind(r5, CALL_AS_METHOD); | 1569 __ SetCallKind(r5, CALL_AS_METHOD); |
1576 __ cmp(r2, r0); // Check formal and actual parameter counts. | 1570 __ cmp(r2, r0); // Check formal and actual parameter counts. |
1577 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 1571 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
1578 RelocInfo::CODE_TARGET, | 1572 RelocInfo::CODE_TARGET, |
1579 ne); | 1573 ne); |
1580 | 1574 |
1581 ParameterCount expected(0); | 1575 ParameterCount expected(0); |
1582 __ InvokeCode(r3, expected, expected, JUMP_FUNCTION, | 1576 __ InvokeCode(r3, expected, expected, JUMP_FUNCTION, |
1583 NullCallWrapper(), CALL_AS_METHOD); | 1577 NullCallWrapper(), CALL_AS_METHOD); |
(...skipping 18 matching lines...) Loading... |
1602 | 1596 |
1603 // Check the stack for overflow. We are not trying to catch | 1597 // Check the stack for overflow. We are not trying to catch |
1604 // interruptions (e.g. debug break and preemption) here, so the "real stack | 1598 // interruptions (e.g. debug break and preemption) here, so the "real stack |
1605 // limit" is checked. | 1599 // limit" is checked. |
1606 Label okay; | 1600 Label okay; |
1607 __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); | 1601 __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); |
1608 // Make r2 the space we have left. The stack might already be overflowed | 1602 // Make r2 the space we have left. The stack might already be overflowed |
1609 // here which will cause r2 to become negative. | 1603 // here which will cause r2 to become negative. |
1610 __ sub(r2, sp, r2); | 1604 __ sub(r2, sp, r2); |
1611 // Check if the arguments will overflow the stack. | 1605 // Check if the arguments will overflow the stack. |
1612 __ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); | 1606 __ cmp(r2, Operand::PointerOffsetFromSmiKey(r0)); |
1613 __ b(gt, &okay); // Signed comparison. | 1607 __ b(gt, &okay); // Signed comparison. |
1614 | 1608 |
1615 // Out of stack space. | 1609 // Out of stack space. |
1616 __ ldr(r1, MemOperand(fp, kFunctionOffset)); | 1610 __ ldr(r1, MemOperand(fp, kFunctionOffset)); |
1617 __ push(r1); | 1611 __ push(r1); |
1618 __ push(r0); | 1612 __ push(r0); |
1619 __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION); | 1613 __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION); |
1620 // End of stack check. | 1614 // End of stack check. |
1621 | 1615 |
1622 // Push current limit and index. | 1616 // Push current limit and index. |
(...skipping 89 matching lines...) Loading... |
1712 // Test if the copy loop has finished copying all the elements from the | 1706 // Test if the copy loop has finished copying all the elements from the |
1713 // arguments object. | 1707 // arguments object. |
1714 __ bind(&entry); | 1708 __ bind(&entry); |
1715 __ ldr(r1, MemOperand(fp, kLimitOffset)); | 1709 __ ldr(r1, MemOperand(fp, kLimitOffset)); |
1716 __ cmp(r0, r1); | 1710 __ cmp(r0, r1); |
1717 __ b(ne, &loop); | 1711 __ b(ne, &loop); |
1718 | 1712 |
1719 // Invoke the function. | 1713 // Invoke the function. |
1720 Label call_proxy; | 1714 Label call_proxy; |
1721 ParameterCount actual(r0); | 1715 ParameterCount actual(r0); |
1722 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); | 1716 __ SmiUntag(r0); |
1723 __ ldr(r1, MemOperand(fp, kFunctionOffset)); | 1717 __ ldr(r1, MemOperand(fp, kFunctionOffset)); |
1724 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); | 1718 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); |
1725 __ b(ne, &call_proxy); | 1719 __ b(ne, &call_proxy); |
1726 __ InvokeFunction(r1, actual, CALL_FUNCTION, | 1720 __ InvokeFunction(r1, actual, CALL_FUNCTION, |
1727 NullCallWrapper(), CALL_AS_METHOD); | 1721 NullCallWrapper(), CALL_AS_METHOD); |
1728 | 1722 |
1729 frame_scope.GenerateLeaveFrame(); | 1723 frame_scope.GenerateLeaveFrame(); |
1730 __ add(sp, sp, Operand(3 * kPointerSize)); | 1724 __ add(sp, sp, Operand(3 * kPointerSize)); |
1731 __ Jump(lr); | 1725 __ Jump(lr); |
1732 | 1726 |
1733 // Invoke the function proxy. | 1727 // Invoke the function proxy. |
1734 __ bind(&call_proxy); | 1728 __ bind(&call_proxy); |
1735 __ push(r1); // add function proxy as last argument | 1729 __ push(r1); // add function proxy as last argument |
1736 __ add(r0, r0, Operand(1)); | 1730 __ add(r0, r0, Operand(1)); |
1737 __ mov(r2, Operand::Zero()); | 1731 __ mov(r2, Operand::Zero()); |
1738 __ SetCallKind(r5, CALL_AS_METHOD); | 1732 __ SetCallKind(r5, CALL_AS_METHOD); |
1739 __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY); | 1733 __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY); |
1740 __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 1734 __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
1741 RelocInfo::CODE_TARGET); | 1735 RelocInfo::CODE_TARGET); |
1742 | 1736 |
1743 // Tear down the internal frame and remove function, receiver and args. | 1737 // Tear down the internal frame and remove function, receiver and args. |
1744 } | 1738 } |
1745 __ add(sp, sp, Operand(3 * kPointerSize)); | 1739 __ add(sp, sp, Operand(3 * kPointerSize)); |
1746 __ Jump(lr); | 1740 __ Jump(lr); |
1747 } | 1741 } |
1748 | 1742 |
1749 | 1743 |
1750 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { | 1744 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { |
1751 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); | 1745 __ SmiTag(r0); |
1752 __ mov(r4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 1746 __ mov(r4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
1753 __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() | fp.bit() | lr.bit()); | 1747 __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() | fp.bit() | lr.bit()); |
1754 __ add(fp, sp, Operand(3 * kPointerSize)); | 1748 __ add(fp, sp, Operand(3 * kPointerSize)); |
1755 } | 1749 } |
1756 | 1750 |
1757 | 1751 |
1758 static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { | 1752 static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { |
1759 // ----------- S t a t e ------------- | 1753 // ----------- S t a t e ------------- |
1760 // -- r0 : result being passed through | 1754 // -- r0 : result being passed through |
1761 // ----------------------------------- | 1755 // ----------------------------------- |
1762 // Get the number of arguments passed (as a smi), tear down the frame and | 1756 // Get the number of arguments passed (as a smi), tear down the frame and |
1763 // then tear down the parameters. | 1757 // then tear down the parameters. |
1764 __ ldr(r1, MemOperand(fp, -3 * kPointerSize)); | 1758 __ ldr(r1, MemOperand(fp, -3 * kPointerSize)); |
1765 __ mov(sp, fp); | 1759 __ mov(sp, fp); |
1766 __ ldm(ia_w, sp, fp.bit() | lr.bit()); | 1760 __ ldm(ia_w, sp, fp.bit() | lr.bit()); |
1767 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize)); | 1761 __ add(sp, sp, Operand::PointerOffsetFromSmiKey(r1)); |
1768 __ add(sp, sp, Operand(kPointerSize)); // adjust for receiver | 1762 __ add(sp, sp, Operand(kPointerSize)); // adjust for receiver |
1769 } | 1763 } |
1770 | 1764 |
1771 | 1765 |
1772 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { | 1766 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { |
1773 // ----------- S t a t e ------------- | 1767 // ----------- S t a t e ------------- |
1774 // -- r0 : actual number of arguments | 1768 // -- r0 : actual number of arguments |
1775 // -- r1 : function (passed through to callee) | 1769 // -- r1 : function (passed through to callee) |
1776 // -- r2 : expected number of arguments | 1770 // -- r2 : expected number of arguments |
1777 // -- r3 : code entry to call | 1771 // -- r3 : code entry to call |
(...skipping 10 matching lines...) Loading... |
1788 | 1782 |
1789 { // Enough parameters: actual >= expected | 1783 { // Enough parameters: actual >= expected |
1790 __ bind(&enough); | 1784 __ bind(&enough); |
1791 EnterArgumentsAdaptorFrame(masm); | 1785 EnterArgumentsAdaptorFrame(masm); |
1792 | 1786 |
1793 // Calculate copy start address into r0 and copy end address into r2. | 1787 // Calculate copy start address into r0 and copy end address into r2. |
1794 // r0: actual number of arguments as a smi | 1788 // r0: actual number of arguments as a smi |
1795 // r1: function | 1789 // r1: function |
1796 // r2: expected number of arguments | 1790 // r2: expected number of arguments |
1797 // r3: code entry to call | 1791 // r3: code entry to call |
1798 __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); | 1792 __ add(r0, fp, Operand::PointerOffsetFromSmiKey(r0)); |
1799 // adjust for return address and receiver | 1793 // adjust for return address and receiver |
1800 __ add(r0, r0, Operand(2 * kPointerSize)); | 1794 __ add(r0, r0, Operand(2 * kPointerSize)); |
1801 __ sub(r2, r0, Operand(r2, LSL, kPointerSizeLog2)); | 1795 __ sub(r2, r0, Operand(r2, LSL, kPointerSizeLog2)); |
1802 | 1796 |
1803 // Copy the arguments (including the receiver) to the new stack frame. | 1797 // Copy the arguments (including the receiver) to the new stack frame. |
1804 // r0: copy start address | 1798 // r0: copy start address |
1805 // r1: function | 1799 // r1: function |
1806 // r2: copy end address | 1800 // r2: copy end address |
1807 // r3: code entry to call | 1801 // r3: code entry to call |
1808 | 1802 |
(...skipping 10 matching lines...) Loading... |
1819 | 1813 |
1820 { // Too few parameters: Actual < expected | 1814 { // Too few parameters: Actual < expected |
1821 __ bind(&too_few); | 1815 __ bind(&too_few); |
1822 EnterArgumentsAdaptorFrame(masm); | 1816 EnterArgumentsAdaptorFrame(masm); |
1823 | 1817 |
1824 // Calculate copy start address into r0 and copy end address is fp. | 1818 // Calculate copy start address into r0 and copy end address is fp. |
1825 // r0: actual number of arguments as a smi | 1819 // r0: actual number of arguments as a smi |
1826 // r1: function | 1820 // r1: function |
1827 // r2: expected number of arguments | 1821 // r2: expected number of arguments |
1828 // r3: code entry to call | 1822 // r3: code entry to call |
1829 __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); | 1823 __ add(r0, fp, Operand::PointerOffsetFromSmiKey(r0)); |
1830 | 1824 |
1831 // Copy the arguments (including the receiver) to the new stack frame. | 1825 // Copy the arguments (including the receiver) to the new stack frame. |
1832 // r0: copy start address | 1826 // r0: copy start address |
1833 // r1: function | 1827 // r1: function |
1834 // r2: expected number of arguments | 1828 // r2: expected number of arguments |
1835 // r3: code entry to call | 1829 // r3: code entry to call |
1836 Label copy; | 1830 Label copy; |
1837 __ bind(©); | 1831 __ bind(©); |
1838 // Adjust load for return address and receiver. | 1832 // Adjust load for return address and receiver. |
1839 __ ldr(ip, MemOperand(r0, 2 * kPointerSize)); | 1833 __ ldr(ip, MemOperand(r0, 2 * kPointerSize)); |
(...skipping 35 matching lines...) Loading... |
1875 __ bind(&dont_adapt_arguments); | 1869 __ bind(&dont_adapt_arguments); |
1876 __ Jump(r3); | 1870 __ Jump(r3); |
1877 } | 1871 } |
1878 | 1872 |
1879 | 1873 |
1880 #undef __ | 1874 #undef __ |
1881 | 1875 |
1882 } } // namespace v8::internal | 1876 } } // namespace v8::internal |
1883 | 1877 |
1884 #endif // V8_TARGET_ARCH_ARM | 1878 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |