OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
480 | 480 |
481 // Check bit field. | 481 // Check bit field. |
482 __ testb(FieldOperand(map, Map::kBitFieldOffset), | 482 __ testb(FieldOperand(map, Map::kBitFieldOffset), |
483 Immediate((1 << Map::kIsAccessCheckNeeded) | | 483 Immediate((1 << Map::kIsAccessCheckNeeded) | |
484 (1 << interceptor_bit))); | 484 (1 << interceptor_bit))); |
485 __ j(not_zero, slow); | 485 __ j(not_zero, slow); |
486 } | 486 } |
487 | 487 |
488 | 488 |
489 // Loads an indexed element from a fast case array. | 489 // Loads an indexed element from a fast case array. |
| 490 // If not_fast_array is NULL, doesn't perform the elements map check. |
490 static void GenerateFastArrayLoad(MacroAssembler* masm, | 491 static void GenerateFastArrayLoad(MacroAssembler* masm, |
491 Register receiver, | 492 Register receiver, |
492 Register key, | 493 Register key, |
493 Register elements, | 494 Register elements, |
494 Register scratch, | 495 Register scratch, |
495 Register result, | 496 Register result, |
496 Label* not_fast_array, | 497 Label* not_fast_array, |
497 Label* out_of_range) { | 498 Label* out_of_range) { |
498 // Register use: | 499 // Register use: |
499 // | 500 // |
500 // receiver - holds the receiver on entry. | 501 // receiver - holds the receiver on entry. |
501 // Unchanged unless 'result' is the same register. | 502 // Unchanged unless 'result' is the same register. |
502 // | 503 // |
503 // key - holds the smi key on entry. | 504 // key - holds the smi key on entry. |
504 // Unchanged unless 'result' is the same register. | 505 // Unchanged unless 'result' is the same register. |
505 // | 506 // |
506 // elements - holds the elements of the receiver on exit. | 507 // elements - holds the elements of the receiver on exit. |
507 // | 508 // |
508 // result - holds the result on exit if the load succeeded. | 509 // result - holds the result on exit if the load succeeded. |
509 // Allowed to be the the same as 'receiver' or 'key'. | 510 // Allowed to be the the same as 'receiver' or 'key'. |
510 // Unchanged on bailout so 'receiver' and 'key' can be safely | 511 // Unchanged on bailout so 'receiver' and 'key' can be safely |
511 // used by further computation. | 512 // used by further computation. |
512 // | 513 // |
513 // Scratch registers: | 514 // Scratch registers: |
514 // | 515 // |
515 // scratch - used to hold elements of the receiver and the loaded value. | 516 // scratch - used to hold elements of the receiver and the loaded value. |
516 | 517 |
517 __ movq(elements, FieldOperand(receiver, JSObject::kElementsOffset)); | 518 __ movq(elements, FieldOperand(receiver, JSObject::kElementsOffset)); |
518 // Check that the object is in fast mode (not dictionary). | 519 if (not_fast_array != NULL) { |
519 __ CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), | 520 // Check that the object is in fast mode and writable. |
520 Heap::kFixedArrayMapRootIndex); | 521 __ CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), |
521 __ j(not_equal, not_fast_array); | 522 Heap::kFixedArrayMapRootIndex); |
| 523 __ j(not_equal, not_fast_array); |
| 524 } else { |
| 525 __ AssertFastElements(elements); |
| 526 } |
522 // Check that the key (index) is within bounds. | 527 // Check that the key (index) is within bounds. |
523 __ SmiCompare(key, FieldOperand(elements, FixedArray::kLengthOffset)); | 528 __ SmiCompare(key, FieldOperand(elements, FixedArray::kLengthOffset)); |
524 // Unsigned comparison rejects negative indices. | 529 // Unsigned comparison rejects negative indices. |
525 __ j(above_equal, out_of_range); | 530 __ j(above_equal, out_of_range); |
526 // Fast case: Do the load. | 531 // Fast case: Do the load. |
527 SmiIndex index = masm->SmiToIndex(scratch, key, kPointerSizeLog2); | 532 SmiIndex index = masm->SmiToIndex(scratch, key, kPointerSizeLog2); |
528 __ movq(scratch, FieldOperand(elements, | 533 __ movq(scratch, FieldOperand(elements, |
529 index.reg, | 534 index.reg, |
530 index.scale, | 535 index.scale, |
531 FixedArray::kHeaderSize)); | 536 FixedArray::kHeaderSize)); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 | 609 |
605 // Check that the key is a smi. | 610 // Check that the key is a smi. |
606 __ JumpIfNotSmi(rax, &check_string); | 611 __ JumpIfNotSmi(rax, &check_string); |
607 __ bind(&index_smi); | 612 __ bind(&index_smi); |
608 // Now the key is known to be a smi. This place is also jumped to from below | 613 // Now the key is known to be a smi. This place is also jumped to from below |
609 // where a numeric string is converted to a smi. | 614 // where a numeric string is converted to a smi. |
610 | 615 |
611 GenerateKeyedLoadReceiverCheck( | 616 GenerateKeyedLoadReceiverCheck( |
612 masm, rdx, rcx, Map::kHasIndexedInterceptor, &slow); | 617 masm, rdx, rcx, Map::kHasIndexedInterceptor, &slow); |
613 | 618 |
| 619 // Check the "has fast elements" bit in the receiver's map which is |
| 620 // now in rcx. |
| 621 __ testb(FieldOperand(rcx, Map::kBitField2Offset), |
| 622 Immediate(1 << Map::kHasFastElements)); |
| 623 __ j(zero, &check_pixel_array); |
| 624 |
614 GenerateFastArrayLoad(masm, | 625 GenerateFastArrayLoad(masm, |
615 rdx, | 626 rdx, |
616 rax, | 627 rax, |
617 rcx, | 628 rcx, |
618 rbx, | 629 rbx, |
619 rax, | 630 rax, |
620 &check_pixel_array, | 631 NULL, |
621 &slow); | 632 &slow); |
622 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); | 633 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); |
623 __ ret(0); | 634 __ ret(0); |
624 | 635 |
625 __ bind(&check_pixel_array); | 636 __ bind(&check_pixel_array); |
626 // Check whether the elements object is a pixel array. | 637 // Check whether the elements object is a pixel array. |
627 // rdx: receiver | 638 // rdx: receiver |
628 // rax: key | 639 // rax: key |
629 // rcx: elements array | 640 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); |
630 __ SmiToInteger32(rbx, rax); // Used on both directions of next branch. | 641 __ SmiToInteger32(rbx, rax); // Used on both directions of next branch. |
631 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), | 642 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), |
632 Heap::kPixelArrayMapRootIndex); | 643 Heap::kPixelArrayMapRootIndex); |
633 __ j(not_equal, &check_number_dictionary); | 644 __ j(not_equal, &check_number_dictionary); |
634 __ cmpl(rbx, FieldOperand(rcx, PixelArray::kLengthOffset)); | 645 __ cmpl(rbx, FieldOperand(rcx, PixelArray::kLengthOffset)); |
635 __ j(above_equal, &slow); | 646 __ j(above_equal, &slow); |
636 __ movq(rax, FieldOperand(rcx, PixelArray::kExternalPointerOffset)); | 647 __ movq(rax, FieldOperand(rcx, PixelArray::kExternalPointerOffset)); |
637 __ movzxbq(rax, Operand(rax, rbx, times_1, 0)); | 648 __ movzxbq(rax, Operand(rax, rbx, times_1, 0)); |
638 __ Integer32ToSmi(rax, rax); | 649 __ Integer32ToSmi(rax, rax); |
639 __ ret(0); | 650 __ ret(0); |
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1005 __ j(equal, &array); | 1016 __ j(equal, &array); |
1006 // Check that the object is some kind of JS object. | 1017 // Check that the object is some kind of JS object. |
1007 __ CmpInstanceType(rbx, FIRST_JS_OBJECT_TYPE); | 1018 __ CmpInstanceType(rbx, FIRST_JS_OBJECT_TYPE); |
1008 __ j(below, &slow); | 1019 __ j(below, &slow); |
1009 | 1020 |
1010 // Object case: Check key against length in the elements array. | 1021 // Object case: Check key against length in the elements array. |
1011 // rax: value | 1022 // rax: value |
1012 // rdx: JSObject | 1023 // rdx: JSObject |
1013 // rcx: index | 1024 // rcx: index |
1014 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); | 1025 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); |
1015 // Check that the object is in fast mode (not dictionary). | 1026 // Check that the object is in fast mode and writable. |
1016 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), | 1027 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), |
1017 Heap::kFixedArrayMapRootIndex); | 1028 Heap::kFixedArrayMapRootIndex); |
1018 __ j(not_equal, &check_pixel_array); | 1029 __ j(not_equal, &check_pixel_array); |
1019 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx); | 1030 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx); |
1020 // rax: value | 1031 // rax: value |
1021 // rbx: FixedArray | 1032 // rbx: FixedArray |
1022 // rcx: index | 1033 // rcx: index |
1023 __ j(above, &fast); | 1034 __ j(above, &fast); |
1024 | 1035 |
1025 // Slow case: call runtime. | 1036 // Slow case: call runtime. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1068 // flags: smicompare (rdx.length(), rbx) | 1079 // flags: smicompare (rdx.length(), rbx) |
1069 __ j(not_equal, &slow); // do not leave holes in the array | 1080 __ j(not_equal, &slow); // do not leave holes in the array |
1070 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx); | 1081 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx); |
1071 __ j(below_equal, &slow); | 1082 __ j(below_equal, &slow); |
1072 // Increment index to get new length. | 1083 // Increment index to get new length. |
1073 __ leal(rdi, Operand(rcx, 1)); | 1084 __ leal(rdi, Operand(rcx, 1)); |
1074 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rdi); | 1085 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rdi); |
1075 __ jmp(&fast); | 1086 __ jmp(&fast); |
1076 | 1087 |
1077 // Array case: Get the length and the elements array from the JS | 1088 // Array case: Get the length and the elements array from the JS |
1078 // array. Check that the array is in fast mode; if it is the | 1089 // array. Check that the array is in fast mode (and writable); if it |
1079 // length is always a smi. | 1090 // is the length is always a smi. |
1080 __ bind(&array); | 1091 __ bind(&array); |
1081 // rax: value | 1092 // rax: value |
1082 // rdx: receiver (a JSArray) | 1093 // rdx: receiver (a JSArray) |
1083 // rcx: index | 1094 // rcx: index |
1084 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); | 1095 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); |
1085 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), | 1096 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), |
1086 Heap::kFixedArrayMapRootIndex); | 1097 Heap::kFixedArrayMapRootIndex); |
1087 __ j(not_equal, &slow); | 1098 __ j(not_equal, &slow); |
1088 | 1099 |
1089 // Check the key against the length in the array, compute the | 1100 // Check the key against the length in the array, compute the |
(...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1855 Register scratch = rbx; | 1866 Register scratch = rbx; |
1856 | 1867 |
1857 // Check that the receiver isn't a smi. | 1868 // Check that the receiver isn't a smi. |
1858 __ JumpIfSmi(receiver, &miss); | 1869 __ JumpIfSmi(receiver, &miss); |
1859 | 1870 |
1860 // Check that the object is a JS array. | 1871 // Check that the object is a JS array. |
1861 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); | 1872 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); |
1862 __ j(not_equal, &miss); | 1873 __ j(not_equal, &miss); |
1863 | 1874 |
1864 // Check that elements are FixedArray. | 1875 // Check that elements are FixedArray. |
| 1876 // We rely on StoreIC_ArrayLength below to deal with all types of |
| 1877 // fast elements (including COW). |
1865 __ movq(scratch, FieldOperand(receiver, JSArray::kElementsOffset)); | 1878 __ movq(scratch, FieldOperand(receiver, JSArray::kElementsOffset)); |
1866 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch); | 1879 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch); |
1867 __ j(not_equal, &miss); | 1880 __ j(not_equal, &miss); |
1868 | 1881 |
1869 // Check that value is a smi. | 1882 // Check that value is a smi. |
1870 __ JumpIfNotSmi(value, &miss); | 1883 __ JumpIfNotSmi(value, &miss); |
1871 | 1884 |
1872 // Prepare tail call to StoreIC_ArrayLength. | 1885 // Prepare tail call to StoreIC_ArrayLength. |
1873 __ pop(scratch); | 1886 __ pop(scratch); |
1874 __ push(receiver); | 1887 __ push(receiver); |
(...skipping 30 matching lines...) Expand all Loading... |
1905 GenerateMiss(masm); | 1918 GenerateMiss(masm); |
1906 } | 1919 } |
1907 | 1920 |
1908 | 1921 |
1909 #undef __ | 1922 #undef __ |
1910 | 1923 |
1911 | 1924 |
1912 } } // namespace v8::internal | 1925 } } // namespace v8::internal |
1913 | 1926 |
1914 #endif // V8_TARGET_ARCH_X64 | 1927 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |