OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
615 __ TailCallExternalReference(ref, 2, 1); | 615 __ TailCallExternalReference(ref, 2, 1); |
616 | 616 |
617 __ bind(&slow); | 617 __ bind(&slow); |
618 GenerateMiss(masm); | 618 GenerateMiss(masm); |
619 } | 619 } |
620 | 620 |
621 | 621 |
622 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { | 622 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { |
623 // ----------- S t a t e ------------- | 623 // ----------- S t a t e ------------- |
624 // -- eax : value | 624 // -- eax : value |
| 625 // -- ecx : key |
| 626 // -- edx : receiver |
625 // -- esp[0] : return address | 627 // -- esp[0] : return address |
626 // -- esp[4] : key | |
627 // -- esp[8] : receiver | |
628 // ----------------------------------- | 628 // ----------------------------------- |
629 Label slow, fast, array, extra, check_pixel_array; | 629 Label slow, fast, array, extra, check_pixel_array; |
630 | 630 |
631 // Get the receiver from the stack. | |
632 __ mov(edx, Operand(esp, 2 * kPointerSize)); // 2 ~ return address, key | |
633 // Check that the object isn't a smi. | 631 // Check that the object isn't a smi. |
634 __ test(edx, Immediate(kSmiTagMask)); | 632 __ test(edx, Immediate(kSmiTagMask)); |
635 __ j(zero, &slow, not_taken); | 633 __ j(zero, &slow, not_taken); |
636 // Get the map from the receiver. | 634 // Get the map from the receiver. |
637 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 635 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); |
638 // Check that the receiver does not require access checks. We need | 636 // Check that the receiver does not require access checks. We need |
639 // to do this because this generic stub does not perform map checks. | 637 // to do this because this generic stub does not perform map checks. |
640 __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset)); | 638 __ movzx_b(ebx, FieldOperand(edi, Map::kBitFieldOffset)); |
641 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); | 639 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); |
642 __ j(not_zero, &slow, not_taken); | 640 __ j(not_zero, &slow, not_taken); |
643 // Get the key from the stack. | |
644 __ mov(ebx, Operand(esp, 1 * kPointerSize)); // 1 ~ return address | |
645 // Check that the key is a smi. | 641 // Check that the key is a smi. |
646 __ test(ebx, Immediate(kSmiTagMask)); | 642 __ test(ecx, Immediate(kSmiTagMask)); |
647 __ j(not_zero, &slow, not_taken); | 643 __ j(not_zero, &slow, not_taken); |
648 // Get the instance type from the map of the receiver. | 644 __ CmpInstanceType(edi, JS_ARRAY_TYPE); |
649 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | |
650 // Check if the object is a JS array or not. | |
651 __ cmp(ecx, JS_ARRAY_TYPE); | |
652 __ j(equal, &array); | 645 __ j(equal, &array); |
653 // Check that the object is some kind of JS object. | 646 // Check that the object is some kind of JS object. |
654 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); | 647 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); |
655 __ j(less, &slow, not_taken); | 648 __ j(below, &slow, not_taken); |
656 | 649 |
657 // Object case: Check key against length in the elements array. | 650 // Object case: Check key against length in the elements array. |
658 // eax: value | 651 // eax: value |
659 // edx: JSObject | 652 // edx: JSObject |
660 // ebx: index (as a smi) | 653 // ecx: key (a smi) |
661 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 654 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
662 // Check that the object is in fast mode (not dictionary). | 655 // Check that the object is in fast mode (not dictionary). |
663 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 656 __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); |
664 Immediate(Factory::fixed_array_map())); | 657 __ mov(ebx, Operand(ecx)); |
665 __ j(not_equal, &check_pixel_array, not_taken); | 658 __ SmiUntag(ebx); |
666 // Untag the key (for checking against untagged length in the fixed array). | 659 __ cmp(ebx, FieldOperand(edi, Array::kLengthOffset)); |
667 __ mov(edx, Operand(ebx)); | |
668 __ sar(edx, kSmiTagSize); // untag the index and use it for the comparison | |
669 __ cmp(edx, FieldOperand(ecx, Array::kLengthOffset)); | |
670 // eax: value | |
671 // ecx: FixedArray | |
672 // ebx: index (as a smi) | |
673 __ j(below, &fast, taken); | 660 __ j(below, &fast, taken); |
674 | 661 |
675 // Slow case: call runtime. | 662 // Slow case: call runtime. |
676 __ bind(&slow); | 663 __ bind(&slow); |
677 GenerateRuntimeSetProperty(masm); | 664 GenerateRuntimeSetProperty(masm); |
678 | 665 |
679 // Check whether the elements is a pixel array. | 666 // Check whether the elements is a pixel array. |
| 667 __ bind(&check_pixel_array); |
680 // eax: value | 668 // eax: value |
681 // ecx: elements array | 669 // ecx: key |
682 // ebx: index (as a smi) | 670 // edx: receiver |
683 __ bind(&check_pixel_array); | 671 // edi: elements array |
684 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 672 __ CheckMap(edi, Factory::pixel_array_map(), &slow, true); |
685 Immediate(Factory::pixel_array_map())); | |
686 __ j(not_equal, &slow); | |
687 // Check that the value is a smi. If a conversion is needed call into the | 673 // Check that the value is a smi. If a conversion is needed call into the |
688 // runtime to convert and clamp. | 674 // runtime to convert and clamp. |
689 __ test(eax, Immediate(kSmiTagMask)); | 675 __ test(eax, Immediate(kSmiTagMask)); |
690 __ j(not_zero, &slow); | 676 __ j(not_zero, &slow); |
691 __ sar(ebx, kSmiTagSize); // Untag the index. | 677 __ mov(ebx, ecx); |
692 __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset)); | 678 __ SmiUntag(ebx); |
| 679 __ cmp(ebx, FieldOperand(edi, PixelArray::kLengthOffset)); |
693 __ j(above_equal, &slow); | 680 __ j(above_equal, &slow); |
694 __ mov(edx, eax); // Save the value. | 681 __ mov(ecx, eax); // Save the value. Key is not longer needed. |
695 __ sar(eax, kSmiTagSize); // Untag the value. | 682 __ SmiUntag(ecx); |
696 { // Clamp the value to [0..255]. | 683 { // Clamp the value to [0..255]. |
697 Label done; | 684 Label done; |
698 __ test(eax, Immediate(0xFFFFFF00)); | 685 __ test(ecx, Immediate(0xFFFFFF00)); |
699 __ j(zero, &done); | 686 __ j(zero, &done); |
700 __ setcc(negative, eax); // 1 if negative, 0 if positive. | 687 __ setcc(negative, ecx); // 1 if negative, 0 if positive. |
701 __ dec_b(eax); // 0 if negative, 255 if positive. | 688 __ dec_b(ecx); // 0 if negative, 255 if positive. |
702 __ bind(&done); | 689 __ bind(&done); |
703 } | 690 } |
704 __ mov(ecx, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); | 691 __ mov(edi, FieldOperand(edi, PixelArray::kExternalPointerOffset)); |
705 __ mov_b(Operand(ecx, ebx, times_1, 0), eax); | 692 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
706 __ mov(eax, edx); // Return the original value. | 693 __ ret(0); // Return value in eax. |
707 __ ret(0); | |
708 | 694 |
709 // Extra capacity case: Check if there is extra capacity to | 695 // Extra capacity case: Check if there is extra capacity to |
710 // perform the store and update the length. Used for adding one | 696 // perform the store and update the length. Used for adding one |
711 // element to the array by writing to array[array.length]. | 697 // element to the array by writing to array[array.length]. |
712 __ bind(&extra); | 698 __ bind(&extra); |
713 // eax: value | 699 // eax: value |
714 // edx: JSArray | 700 // edx: receiver, a JSArray |
715 // ecx: FixedArray | 701 // ecx: key, a smi. |
716 // ebx: index (as a smi) | 702 // edi: receiver->elements, a FixedArray |
717 // flags: compare (ebx, edx.length()) | 703 // flags: compare (ecx, edx.length()) |
718 __ j(not_equal, &slow, not_taken); // do not leave holes in the array | 704 __ j(not_equal, &slow, not_taken); // do not leave holes in the array |
719 __ sar(ebx, kSmiTagSize); // untag | 705 __ mov(ebx, ecx); |
720 __ cmp(ebx, FieldOperand(ecx, Array::kLengthOffset)); | 706 __ SmiUntag(ebx); // untag |
| 707 __ cmp(ebx, FieldOperand(edi, Array::kLengthOffset)); |
721 __ j(above_equal, &slow, not_taken); | 708 __ j(above_equal, &slow, not_taken); |
722 // Restore tag and increment. | 709 // Add 1 to receiver->length, and go to fast array write. |
723 __ lea(ebx, Operand(ebx, times_2, 1 << kSmiTagSize)); | 710 __ add(FieldOperand(edx, JSArray::kLengthOffset), |
724 __ mov(FieldOperand(edx, JSArray::kLengthOffset), ebx); | 711 Immediate(1 << kSmiTagSize)); |
725 __ sub(Operand(ebx), Immediate(1 << kSmiTagSize)); // decrement ebx again | |
726 __ jmp(&fast); | 712 __ jmp(&fast); |
727 | 713 |
728 // Array case: Get the length and the elements array from the JS | 714 // Array case: Get the length and the elements array from the JS |
729 // array. Check that the array is in fast mode; if it is the | 715 // array. Check that the array is in fast mode; if it is the |
730 // length is always a smi. | 716 // length is always a smi. |
731 __ bind(&array); | 717 __ bind(&array); |
732 // eax: value | 718 // eax: value |
733 // edx: JSArray | 719 // edx: receiver, a JSArray |
734 // ebx: index (as a smi) | 720 // ecx: key, a smi. |
735 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 721 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
736 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 722 __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); |
737 Immediate(Factory::fixed_array_map())); | |
738 __ j(not_equal, &check_pixel_array); | |
739 | 723 |
740 // Check the key against the length in the array, compute the | 724 // Check the key against the length in the array, compute the |
741 // address to store into and fall through to fast case. | 725 // address to store into and fall through to fast case. |
742 __ cmp(ebx, FieldOperand(edx, JSArray::kLengthOffset)); | 726 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. |
743 __ j(above_equal, &extra, not_taken); | 727 __ j(above_equal, &extra, not_taken); |
744 | 728 |
745 // Fast case: Do the store. | 729 // Fast case: Do the store. |
746 __ bind(&fast); | 730 __ bind(&fast); |
747 // eax: value | 731 // eax: value |
748 // ecx: FixedArray | 732 // ecx: key (a smi) |
749 // ebx: index (as a smi) | 733 // edx: receiver |
750 __ mov(Operand(ecx, ebx, times_2, FixedArray::kHeaderSize - kHeapObjectTag), | 734 // edi: FixedArray receiver->elements |
751 eax); | 735 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax); |
752 // Update write barrier for the elements array address. | 736 // Update write barrier for the elements array address. |
753 __ mov(edx, Operand(eax)); | 737 __ mov(edx, Operand(eax)); |
754 __ RecordWrite(ecx, 0, edx, ebx); | 738 __ RecordWrite(edi, 0, edx, ecx); |
755 __ ret(0); | 739 __ ret(0); |
756 } | 740 } |
757 | 741 |
758 | 742 |
759 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, | 743 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, |
760 ExternalArrayType array_type) { | 744 ExternalArrayType array_type) { |
761 // ----------- S t a t e ------------- | 745 // ----------- S t a t e ------------- |
762 // -- eax : value | 746 // -- eax : value |
| 747 // -- ecx : key |
| 748 // -- edx : receiver |
763 // -- esp[0] : return address | 749 // -- esp[0] : return address |
764 // -- esp[4] : key | |
765 // -- esp[8] : receiver | |
766 // ----------------------------------- | 750 // ----------------------------------- |
767 Label slow, check_heap_number; | 751 Label slow, check_heap_number; |
768 | 752 |
769 // Get the receiver from the stack. | |
770 __ mov(edx, Operand(esp, 2 * kPointerSize)); | |
771 // Check that the object isn't a smi. | 753 // Check that the object isn't a smi. |
772 __ test(edx, Immediate(kSmiTagMask)); | 754 __ test(edx, Immediate(kSmiTagMask)); |
773 __ j(zero, &slow); | 755 __ j(zero, &slow); |
774 // Get the map from the receiver. | 756 // Get the map from the receiver. |
775 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 757 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); |
776 // Check that the receiver does not require access checks. We need | 758 // Check that the receiver does not require access checks. We need |
777 // to do this because this generic stub does not perform map checks. | 759 // to do this because this generic stub does not perform map checks. |
778 __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset)); | 760 __ movzx_b(ebx, FieldOperand(edi, Map::kBitFieldOffset)); |
779 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); | 761 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); |
780 __ j(not_zero, &slow); | 762 __ j(not_zero, &slow); |
781 // Get the key from the stack. | |
782 __ mov(ebx, Operand(esp, 1 * kPointerSize)); // 1 ~ return address | |
783 // Check that the key is a smi. | 763 // Check that the key is a smi. |
784 __ test(ebx, Immediate(kSmiTagMask)); | 764 __ test(ecx, Immediate(kSmiTagMask)); |
785 __ j(not_zero, &slow); | 765 __ j(not_zero, &slow); |
786 // Get the instance type from the map of the receiver. | 766 // Get the instance type from the map of the receiver. |
787 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 767 __ CmpInstanceType(edi, JS_OBJECT_TYPE); |
788 // Check that the object is a JS object. | |
789 __ cmp(ecx, JS_OBJECT_TYPE); | |
790 __ j(not_equal, &slow); | 768 __ j(not_equal, &slow); |
791 | 769 |
792 // Check that the elements array is the appropriate type of | 770 // Check that the elements array is the appropriate type of |
793 // ExternalArray. | 771 // ExternalArray. |
794 // eax: value | 772 // eax: value |
795 // edx: JSObject | 773 // edx: receiver, a JSObject |
796 // ebx: index (as a smi) | 774 // ecx: key, a smi |
797 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 775 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
798 Handle<Map> map(Heap::MapForExternalArrayType(array_type)); | 776 __ CheckMap(edi, Handle<Map>(Heap::MapForExternalArrayType(array_type)), |
799 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 777 &slow, true); |
800 Immediate(map)); | |
801 __ j(not_equal, &slow); | |
802 | 778 |
803 // Check that the index is in range. | 779 // Check that the index is in range. |
804 __ sar(ebx, kSmiTagSize); // Untag the index. | 780 __ mov(ebx, ecx); |
805 __ cmp(ebx, FieldOperand(ecx, ExternalArray::kLengthOffset)); | 781 __ SmiUntag(ebx); |
| 782 __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset)); |
806 // Unsigned comparison catches both negative and too-large values. | 783 // Unsigned comparison catches both negative and too-large values. |
807 __ j(above_equal, &slow); | 784 __ j(above_equal, &slow); |
808 | 785 |
809 // Handle both smis and HeapNumbers in the fast path. Go to the | 786 // Handle both smis and HeapNumbers in the fast path. Go to the |
810 // runtime for all other kinds of values. | 787 // runtime for all other kinds of values. |
811 // eax: value | 788 // eax: value |
812 // ecx: elements array | 789 // edx: receiver |
| 790 // ecx: key |
| 791 // edi: elements array |
813 // ebx: untagged index | 792 // ebx: untagged index |
814 __ test(eax, Immediate(kSmiTagMask)); | 793 __ test(eax, Immediate(kSmiTagMask)); |
815 __ j(not_equal, &check_heap_number); | 794 __ j(not_equal, &check_heap_number); |
816 // smi case | 795 // smi case |
817 __ mov(edx, eax); // Save the value. | 796 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed. |
818 __ sar(eax, kSmiTagSize); // Untag the value. | 797 __ SmiUntag(ecx); |
819 __ mov(ecx, FieldOperand(ecx, ExternalArray::kExternalPointerOffset)); | 798 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); |
820 // ecx: base pointer of external storage | 799 // ecx: base pointer of external storage |
821 switch (array_type) { | 800 switch (array_type) { |
822 case kExternalByteArray: | 801 case kExternalByteArray: |
823 case kExternalUnsignedByteArray: | 802 case kExternalUnsignedByteArray: |
824 __ mov_b(Operand(ecx, ebx, times_1, 0), eax); | 803 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
825 break; | 804 break; |
826 case kExternalShortArray: | 805 case kExternalShortArray: |
827 case kExternalUnsignedShortArray: | 806 case kExternalUnsignedShortArray: |
828 __ mov_w(Operand(ecx, ebx, times_2, 0), eax); | 807 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); |
829 break; | 808 break; |
830 case kExternalIntArray: | 809 case kExternalIntArray: |
831 case kExternalUnsignedIntArray: | 810 case kExternalUnsignedIntArray: |
832 __ mov(Operand(ecx, ebx, times_4, 0), eax); | 811 __ mov(Operand(edi, ebx, times_4, 0), ecx); |
833 break; | 812 break; |
834 case kExternalFloatArray: | 813 case kExternalFloatArray: |
835 // Need to perform int-to-float conversion. | 814 // Need to perform int-to-float conversion. |
836 __ push(eax); | 815 __ push(ecx); |
837 __ fild_s(Operand(esp, 0)); | 816 __ fild_s(Operand(esp, 0)); |
838 __ pop(eax); | 817 __ pop(ecx); |
839 __ fstp_s(Operand(ecx, ebx, times_4, 0)); | 818 __ fstp_s(Operand(edi, ebx, times_4, 0)); |
840 break; | 819 break; |
841 default: | 820 default: |
842 UNREACHABLE(); | 821 UNREACHABLE(); |
843 break; | 822 break; |
844 } | 823 } |
845 __ mov(eax, edx); // Return the original value. | 824 __ ret(0); // Return the original value. |
846 __ ret(0); | |
847 | 825 |
848 __ bind(&check_heap_number); | 826 __ bind(&check_heap_number); |
| 827 // eax: value |
| 828 // edx: receiver |
| 829 // ecx: key |
| 830 // edi: elements array |
| 831 // ebx: untagged index |
849 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 832 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
850 Immediate(Factory::heap_number_map())); | 833 Immediate(Factory::heap_number_map())); |
851 __ j(not_equal, &slow); | 834 __ j(not_equal, &slow); |
852 | 835 |
853 // The WebGL specification leaves the behavior of storing NaN and | 836 // The WebGL specification leaves the behavior of storing NaN and |
854 // +/-Infinity into integer arrays basically undefined. For more | 837 // +/-Infinity into integer arrays basically undefined. For more |
855 // reproducible behavior, convert these to zero. | 838 // reproducible behavior, convert these to zero. |
856 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 839 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
857 __ mov(edx, eax); // Save the value. | 840 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); |
858 __ mov(ecx, FieldOperand(ecx, ExternalArray::kExternalPointerOffset)); | |
859 // ebx: untagged index | 841 // ebx: untagged index |
860 // ecx: base pointer of external storage | 842 // edi: base pointer of external storage |
861 // top of FPU stack: value | 843 // top of FPU stack: value |
862 if (array_type == kExternalFloatArray) { | 844 if (array_type == kExternalFloatArray) { |
863 __ fstp_s(Operand(ecx, ebx, times_4, 0)); | 845 __ fstp_s(Operand(edi, ebx, times_4, 0)); |
864 __ mov(eax, edx); // Return the original value. | |
865 __ ret(0); | 846 __ ret(0); |
866 } else { | 847 } else { |
867 // Need to perform float-to-int conversion. | 848 // Need to perform float-to-int conversion. |
868 // Test the top of the FP stack for NaN. | 849 // Test the top of the FP stack for NaN. |
869 Label is_nan; | 850 Label is_nan; |
870 __ fucomi(0); | 851 __ fucomi(0); |
871 __ j(parity_even, &is_nan); | 852 __ j(parity_even, &is_nan); |
872 | 853 |
873 if (array_type != kExternalUnsignedIntArray) { | 854 if (array_type != kExternalUnsignedIntArray) { |
874 __ push(eax); // Make room on stack | 855 __ push(ecx); // Make room on stack |
875 __ fistp_s(Operand(esp, 0)); | 856 __ fistp_s(Operand(esp, 0)); |
876 __ pop(eax); | 857 __ pop(ecx); |
877 } else { | 858 } else { |
878 // fistp stores values as signed integers. | 859 // fistp stores values as signed integers. |
879 // To represent the entire range, we need to store as a 64-bit | 860 // To represent the entire range, we need to store as a 64-bit |
880 // int and discard the high 32 bits. | 861 // int and discard the high 32 bits. |
881 __ push(eax); // Make room on stack | 862 __ sub(Operand(esp), Immediate(2 * kPointerSize)); |
882 __ push(eax); // Make room on stack | |
883 __ fistp_d(Operand(esp, 0)); | 863 __ fistp_d(Operand(esp, 0)); |
884 __ pop(eax); | 864 __ pop(ecx); |
885 __ mov(Operand(esp, 0), eax); | 865 __ add(Operand(esp), Immediate(kPointerSize)); |
886 __ pop(eax); | |
887 } | 866 } |
888 // eax: untagged integer value | 867 // ecx: untagged integer value |
889 switch (array_type) { | 868 switch (array_type) { |
890 case kExternalByteArray: | 869 case kExternalByteArray: |
891 case kExternalUnsignedByteArray: | 870 case kExternalUnsignedByteArray: |
892 __ mov_b(Operand(ecx, ebx, times_1, 0), eax); | 871 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
893 break; | 872 break; |
894 case kExternalShortArray: | 873 case kExternalShortArray: |
895 case kExternalUnsignedShortArray: | 874 case kExternalUnsignedShortArray: |
896 __ mov_w(Operand(ecx, ebx, times_2, 0), eax); | 875 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); |
897 break; | 876 break; |
898 case kExternalIntArray: | 877 case kExternalIntArray: |
899 case kExternalUnsignedIntArray: { | 878 case kExternalUnsignedIntArray: { |
900 // We also need to explicitly check for +/-Infinity. These are | 879 // We also need to explicitly check for +/-Infinity. These are |
901 // converted to MIN_INT, but we need to be careful not to | 880 // converted to MIN_INT, but we need to be careful not to |
902 // confuse with legal uses of MIN_INT. | 881 // confuse with legal uses of MIN_INT. |
903 Label not_infinity; | 882 Label not_infinity; |
904 // This test would apparently detect both NaN and Infinity, | 883 // This test would apparently detect both NaN and Infinity, |
905 // but we've already checked for NaN using the FPU hardware | 884 // but we've already checked for NaN using the FPU hardware |
906 // above. | 885 // above. |
907 __ mov_w(edi, FieldOperand(edx, HeapNumber::kValueOffset + 6)); | 886 __ mov_w(edx, FieldOperand(eax, HeapNumber::kValueOffset + 6)); |
908 __ and_(edi, 0x7FF0); | 887 __ and_(edx, 0x7FF0); |
909 __ cmp(edi, 0x7FF0); | 888 __ cmp(edx, 0x7FF0); |
910 __ j(not_equal, ¬_infinity); | 889 __ j(not_equal, ¬_infinity); |
911 __ mov(eax, 0); | 890 __ mov(ecx, 0); |
912 __ bind(¬_infinity); | 891 __ bind(¬_infinity); |
913 __ mov(Operand(ecx, ebx, times_4, 0), eax); | 892 __ mov(Operand(edi, ebx, times_4, 0), ecx); |
914 break; | 893 break; |
915 } | 894 } |
916 default: | 895 default: |
917 UNREACHABLE(); | 896 UNREACHABLE(); |
918 break; | 897 break; |
919 } | 898 } |
920 __ mov(eax, edx); // Return the original value. | 899 __ ret(0); // Return original value. |
921 __ ret(0); | |
922 | 900 |
923 __ bind(&is_nan); | 901 __ bind(&is_nan); |
924 __ ffree(); | 902 __ ffree(); |
925 __ fincstp(); | 903 __ fincstp(); |
926 switch (array_type) { | 904 switch (array_type) { |
927 case kExternalByteArray: | 905 case kExternalByteArray: |
928 case kExternalUnsignedByteArray: | 906 case kExternalUnsignedByteArray: |
929 __ mov_b(Operand(ecx, ebx, times_1, 0), 0); | 907 __ mov_b(Operand(edi, ebx, times_1, 0), 0); |
930 break; | 908 break; |
931 case kExternalShortArray: | 909 case kExternalShortArray: |
932 case kExternalUnsignedShortArray: | 910 case kExternalUnsignedShortArray: |
933 __ mov(eax, 0); | 911 __ xor_(ecx, Operand(ecx)); |
934 __ mov_w(Operand(ecx, ebx, times_2, 0), eax); | 912 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); |
935 break; | 913 break; |
936 case kExternalIntArray: | 914 case kExternalIntArray: |
937 case kExternalUnsignedIntArray: | 915 case kExternalUnsignedIntArray: |
938 __ mov(Operand(ecx, ebx, times_4, 0), Immediate(0)); | 916 __ mov(Operand(edi, ebx, times_4, 0), Immediate(0)); |
939 break; | 917 break; |
940 default: | 918 default: |
941 UNREACHABLE(); | 919 UNREACHABLE(); |
942 break; | 920 break; |
943 } | 921 } |
944 __ mov(eax, edx); // Return the original value. | 922 __ ret(0); // Return the original value. |
945 __ ret(0); | |
946 } | 923 } |
947 | 924 |
948 // Slow case: call runtime. | 925 // Slow case: call runtime. |
949 __ bind(&slow); | 926 __ bind(&slow); |
950 GenerateRuntimeSetProperty(masm); | 927 GenerateRuntimeSetProperty(masm); |
951 } | 928 } |
952 | 929 |
953 | 930 |
954 // Defined in ic.cc. | 931 // Defined in ic.cc. |
955 Object* CallIC_Miss(Arguments args); | 932 Object* CallIC_Miss(Arguments args); |
(...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1490 GenerateMiss(masm); | 1467 GenerateMiss(masm); |
1491 } | 1468 } |
1492 | 1469 |
1493 | 1470 |
1494 // Defined in ic.cc. | 1471 // Defined in ic.cc. |
1495 Object* KeyedStoreIC_Miss(Arguments args); | 1472 Object* KeyedStoreIC_Miss(Arguments args); |
1496 | 1473 |
1497 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { | 1474 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { |
1498 // ----------- S t a t e ------------- | 1475 // ----------- S t a t e ------------- |
1499 // -- eax : value | 1476 // -- eax : value |
| 1477 // -- ecx : key |
| 1478 // -- edx : receiver |
1500 // -- esp[0] : return address | 1479 // -- esp[0] : return address |
1501 // -- esp[4] : key | |
1502 // -- esp[8] : receiver | |
1503 // ----------------------------------- | 1480 // ----------------------------------- |
1504 | 1481 |
1505 __ pop(ecx); | 1482 __ pop(ebx); |
1506 __ push(Operand(esp, 1 * kPointerSize)); | 1483 __ push(edx); |
1507 __ push(Operand(esp, 1 * kPointerSize)); | 1484 __ push(ecx); |
1508 __ push(eax); | 1485 __ push(eax); |
1509 __ push(ecx); | 1486 __ push(ebx); |
1510 | 1487 |
1511 // Do tail-call to runtime routine. | 1488 // Do tail-call to runtime routine. |
1512 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); | 1489 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); |
1513 } | 1490 } |
1514 | 1491 |
1515 | 1492 |
1516 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { | 1493 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { |
1517 // ----------- S t a t e ------------- | 1494 // ----------- S t a t e ------------- |
1518 // -- eax : value | 1495 // -- eax : value |
| 1496 // -- ecx : key |
| 1497 // -- edx : receiver |
1519 // -- esp[0] : return address | 1498 // -- esp[0] : return address |
1520 // -- esp[4] : key | |
1521 // -- esp[8] : receiver | |
1522 // ----------------------------------- | 1499 // ----------------------------------- |
1523 | 1500 |
1524 __ pop(ecx); | 1501 __ pop(ebx); |
1525 __ push(Operand(esp, 1 * kPointerSize)); | 1502 __ push(edx); |
1526 __ push(Operand(esp, 1 * kPointerSize)); | 1503 __ push(ecx); |
1527 __ push(eax); | 1504 __ push(eax); |
1528 __ push(ecx); | 1505 __ push(ebx); |
1529 | 1506 |
1530 // Do tail-call to runtime routine. | 1507 // Do tail-call to runtime routine. |
1531 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); | 1508 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); |
1532 __ TailCallExternalReference(ref, 3, 1); | 1509 __ TailCallExternalReference(ref, 3, 1); |
1533 } | 1510 } |
1534 | 1511 |
1535 #undef __ | 1512 #undef __ |
1536 | 1513 |
1537 | 1514 |
1538 } } // namespace v8::internal | 1515 } } // namespace v8::internal |
OLD | NEW |