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 762 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
773 IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1); | 773 IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1); |
774 | 774 |
775 __ bind(&slow); | 775 __ bind(&slow); |
776 GenerateMiss(masm); | 776 GenerateMiss(masm); |
777 } | 777 } |
778 | 778 |
779 | 779 |
780 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { | 780 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { |
781 // ----------- S t a t e ------------- | 781 // ----------- S t a t e ------------- |
782 // -- rax : value | 782 // -- rax : value |
| 783 // -- rcx : key |
| 784 // -- rdx : receiver |
783 // -- rsp[0] : return address | 785 // -- rsp[0] : return address |
784 // -- rsp[8] : key | |
785 // -- rsp[16] : receiver | |
786 // ----------------------------------- | 786 // ----------------------------------- |
787 | 787 |
788 __ pop(rcx); | 788 __ pop(rbx); |
789 __ push(Operand(rsp, 1 * kPointerSize)); // receiver | 789 __ push(rdx); // receiver |
790 __ push(Operand(rsp, 1 * kPointerSize)); // key | 790 __ push(rcx); // key |
791 __ push(rax); // value | 791 __ push(rax); // value |
792 __ push(rcx); // return address | 792 __ push(rbx); // return address |
793 | 793 |
794 // Do tail-call to runtime routine. | 794 // Do tail-call to runtime routine. |
795 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); | 795 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); |
796 __ TailCallExternalReference(ref, 3, 1); | 796 __ TailCallExternalReference(ref, 3, 1); |
797 } | 797 } |
798 | 798 |
799 | 799 |
800 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { | 800 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { |
801 // ----------- S t a t e ------------- | 801 // ----------- S t a t e ------------- |
802 // -- rax : value | 802 // -- rax : value |
| 803 // -- rcx : key |
| 804 // -- rdx : receiver |
803 // -- rsp[0] : return address | 805 // -- rsp[0] : return address |
804 // -- rsp[8] : key | |
805 // -- rsp[16] : receiver | |
806 // ----------------------------------- | 806 // ----------------------------------- |
807 | 807 |
808 __ pop(rcx); | 808 __ pop(rbx); |
809 __ push(Operand(rsp, 1 * kPointerSize)); // receiver | 809 __ push(rdx); // receiver |
810 __ push(Operand(rsp, 1 * kPointerSize)); // key | 810 __ push(rcx); // key |
811 __ push(rax); // value | 811 __ push(rax); // value |
812 __ push(rcx); // return address | 812 __ push(rbx); // return address |
813 | 813 |
814 // Do tail-call to runtime routine. | 814 // Do tail-call to runtime routine. |
815 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); | 815 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); |
816 } | 816 } |
817 | 817 |
818 | 818 |
819 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { | 819 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { |
820 // ----------- S t a t e ------------- | 820 // ----------- S t a t e ------------- |
821 // -- rax : value | 821 // -- rax : value |
822 // -- rsp[0] : return address | 822 // -- rcx : key |
823 // -- rsp[8] : key | 823 // -- rdx : receiver |
824 // -- rsp[16] : receiver | 824 // -- rsp[0] : return address |
825 // ----------------------------------- | 825 // ----------------------------------- |
826 Label slow, fast, array, extra, check_pixel_array; | 826 Label slow, fast, array, extra, check_pixel_array; |
827 | 827 |
828 // Get the receiver from the stack. | |
829 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // 2 ~ return address, key | |
830 // Check that the object isn't a smi. | 828 // Check that the object isn't a smi. |
831 __ JumpIfSmi(rdx, &slow); | 829 __ JumpIfSmi(rdx, &slow); |
832 // Get the map from the receiver. | 830 // Get the map from the receiver. |
833 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); | 831 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); |
834 // Check that the receiver does not require access checks. We need | 832 // Check that the receiver does not require access checks. We need |
835 // to do this because this generic stub does not perform map checks. | 833 // to do this because this generic stub does not perform map checks. |
836 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), | 834 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), |
837 Immediate(1 << Map::kIsAccessCheckNeeded)); | 835 Immediate(1 << Map::kIsAccessCheckNeeded)); |
838 __ j(not_zero, &slow); | 836 __ j(not_zero, &slow); |
839 // Get the key from the stack. | |
840 __ movq(rbx, Operand(rsp, 1 * kPointerSize)); // 1 ~ return address | |
841 // Check that the key is a smi. | 837 // Check that the key is a smi. |
842 __ JumpIfNotSmi(rbx, &slow); | 838 __ JumpIfNotSmi(rcx, &slow); |
843 | 839 |
844 __ CmpInstanceType(rcx, JS_ARRAY_TYPE); | 840 __ CmpInstanceType(rbx, JS_ARRAY_TYPE); |
845 __ j(equal, &array); | 841 __ j(equal, &array); |
846 // Check that the object is some kind of JS object. | 842 // Check that the object is some kind of JS object. |
847 __ CmpInstanceType(rcx, FIRST_JS_OBJECT_TYPE); | 843 __ CmpInstanceType(rbx, FIRST_JS_OBJECT_TYPE); |
848 __ j(below, &slow); | 844 __ j(below, &slow); |
849 | 845 |
850 // Object case: Check key against length in the elements array. | 846 // Object case: Check key against length in the elements array. |
851 // rax: value | 847 // rax: value |
852 // rdx: JSObject | 848 // rdx: JSObject |
853 // rbx: index (as a smi) | 849 // rcx: index (as a smi) |
854 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); | 850 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); |
855 // Check that the object is in fast mode (not dictionary). | 851 // Check that the object is in fast mode (not dictionary). |
856 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), | 852 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), |
857 Heap::kFixedArrayMapRootIndex); | 853 Heap::kFixedArrayMapRootIndex); |
858 __ j(not_equal, &check_pixel_array); | 854 __ j(not_equal, &check_pixel_array); |
859 // Untag the key (for checking against untagged length in the fixed array). | 855 // Untag the key (for checking against untagged length in the fixed array). |
860 __ SmiToInteger32(rdx, rbx); | 856 __ SmiToInteger32(rdi, rcx); |
861 __ cmpl(rdx, FieldOperand(rcx, Array::kLengthOffset)); | 857 __ cmpl(rdi, FieldOperand(rbx, Array::kLengthOffset)); |
862 // rax: value | 858 // rax: value |
863 // rcx: FixedArray | 859 // rbx: FixedArray |
864 // rbx: index (as a smi) | 860 // rcx: index (as a smi) |
865 __ j(below, &fast); | 861 __ j(below, &fast); |
866 | 862 |
867 // Slow case: call runtime. | 863 // Slow case: call runtime. |
868 __ bind(&slow); | 864 __ bind(&slow); |
869 GenerateRuntimeSetProperty(masm); | 865 GenerateRuntimeSetProperty(masm); |
870 | 866 |
871 // Check whether the elements is a pixel array. | 867 // Check whether the elements is a pixel array. |
872 // rax: value | 868 // rax: value |
873 // rcx: elements array | 869 // rdx: receiver |
874 // rbx: index (as a smi), zero-extended. | 870 // rbx: receiver's elements array |
| 871 // rcx: index (as a smi), zero-extended. |
875 __ bind(&check_pixel_array); | 872 __ bind(&check_pixel_array); |
876 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), | 873 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), |
877 Heap::kPixelArrayMapRootIndex); | 874 Heap::kPixelArrayMapRootIndex); |
878 __ j(not_equal, &slow); | 875 __ j(not_equal, &slow); |
879 // Check that the value is a smi. If a conversion is needed call into the | 876 // Check that the value is a smi. If a conversion is needed call into the |
880 // runtime to convert and clamp. | 877 // runtime to convert and clamp. |
881 __ JumpIfNotSmi(rax, &slow); | 878 __ JumpIfNotSmi(rax, &slow); |
882 __ SmiToInteger32(rbx, rbx); | 879 __ SmiToInteger32(rdi, rcx); |
883 __ cmpl(rbx, FieldOperand(rcx, PixelArray::kLengthOffset)); | 880 __ cmpl(rdi, FieldOperand(rbx, PixelArray::kLengthOffset)); |
884 __ j(above_equal, &slow); | 881 __ j(above_equal, &slow); |
885 __ movq(rdx, rax); // Save the value. | 882 // No more bailouts to slow case on this path, so key not needed. |
886 __ SmiToInteger32(rax, rax); | 883 __ SmiToInteger32(rcx, rax); |
887 { // Clamp the value to [0..255]. | 884 { // Clamp the value to [0..255]. |
888 Label done; | 885 Label done; |
889 __ testl(rax, Immediate(0xFFFFFF00)); | 886 __ testl(rcx, Immediate(0xFFFFFF00)); |
890 __ j(zero, &done); | 887 __ j(zero, &done); |
891 __ setcc(negative, rax); // 1 if negative, 0 if positive. | 888 __ setcc(negative, rcx); // 1 if negative, 0 if positive. |
892 __ decb(rax); // 0 if negative, 255 if positive. | 889 __ decb(rcx); // 0 if negative, 255 if positive. |
893 __ bind(&done); | 890 __ bind(&done); |
894 } | 891 } |
895 __ movq(rcx, FieldOperand(rcx, PixelArray::kExternalPointerOffset)); | 892 __ movq(rbx, FieldOperand(rbx, PixelArray::kExternalPointerOffset)); |
896 __ movb(Operand(rcx, rbx, times_1, 0), rax); | 893 __ movb(Operand(rbx, rdi, times_1, 0), rcx); |
897 __ movq(rax, rdx); // Return the original value. | |
898 __ ret(0); | 894 __ ret(0); |
899 | 895 |
900 // Extra capacity case: Check if there is extra capacity to | 896 // Extra capacity case: Check if there is extra capacity to |
901 // perform the store and update the length. Used for adding one | 897 // perform the store and update the length. Used for adding one |
902 // element to the array by writing to array[array.length]. | 898 // element to the array by writing to array[array.length]. |
903 __ bind(&extra); | 899 __ bind(&extra); |
904 // rax: value | 900 // rax: value |
905 // rdx: JSArray | 901 // rdx: receiver (a JSArray) |
906 // rcx: FixedArray | 902 // rbx: receiver's elements array (a FixedArray) |
907 // rbx: index (as a smi) | 903 // rcx: index (as a smi) |
908 // flags: smicompare (rdx.length(), rbx) | 904 // flags: smicompare (rdx.length(), rbx) |
909 __ j(not_equal, &slow); // do not leave holes in the array | 905 __ j(not_equal, &slow); // do not leave holes in the array |
910 __ SmiToInteger64(rbx, rbx); | 906 __ SmiToInteger64(rdi, rcx); |
911 __ cmpl(rbx, FieldOperand(rcx, FixedArray::kLengthOffset)); | 907 __ cmpl(rdi, FieldOperand(rbx, FixedArray::kLengthOffset)); |
912 __ j(above_equal, &slow); | 908 __ j(above_equal, &slow); |
913 // Increment and restore smi-tag. | 909 // Increment and restore smi-tag. |
914 __ Integer64PlusConstantToSmi(rbx, rbx, 1); | 910 __ Integer64PlusConstantToSmi(rdi, rdi, 1); |
915 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rbx); | 911 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rdi); |
916 __ SmiSubConstant(rbx, rbx, Smi::FromInt(1)); | |
917 __ jmp(&fast); | 912 __ jmp(&fast); |
918 | 913 |
919 // Array case: Get the length and the elements array from the JS | 914 // Array case: Get the length and the elements array from the JS |
920 // array. Check that the array is in fast mode; if it is the | 915 // array. Check that the array is in fast mode; if it is the |
921 // length is always a smi. | 916 // length is always a smi. |
922 __ bind(&array); | 917 __ bind(&array); |
923 // rax: value | 918 // rax: value |
924 // rdx: JSArray | 919 // rdx: receiver (a JSArray) |
925 // rbx: index (as a smi) | 920 // rcx: index (as a smi) |
926 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); | 921 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); |
927 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), | 922 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), |
928 Heap::kFixedArrayMapRootIndex); | 923 Heap::kFixedArrayMapRootIndex); |
929 __ j(not_equal, &slow); | 924 __ j(not_equal, &slow); |
930 | 925 |
931 // Check the key against the length in the array, compute the | 926 // Check the key against the length in the array, compute the |
932 // address to store into and fall through to fast case. | 927 // address to store into and fall through to fast case. |
933 __ SmiCompare(FieldOperand(rdx, JSArray::kLengthOffset), rbx); | 928 __ SmiCompare(FieldOperand(rdx, JSArray::kLengthOffset), rcx); |
934 __ j(below_equal, &extra); | 929 __ j(below_equal, &extra); |
935 | 930 |
936 // Fast case: Do the store. | 931 // Fast case: Do the store. |
937 __ bind(&fast); | 932 __ bind(&fast); |
938 // rax: value | 933 // rax: value |
939 // rcx: FixedArray | 934 // rbx: receiver's elements array (a FixedArray) |
940 // rbx: index (as a smi) | 935 // rcx: index (as a smi) |
941 Label non_smi_value; | 936 Label non_smi_value; |
942 __ JumpIfNotSmi(rax, &non_smi_value); | 937 __ JumpIfNotSmi(rax, &non_smi_value); |
943 SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2); | 938 SmiIndex index = masm->SmiToIndex(rcx, rcx, kPointerSizeLog2); |
944 __ movq(Operand(rcx, index.reg, index.scale, | 939 __ movq(Operand(rbx, index.reg, index.scale, |
945 FixedArray::kHeaderSize - kHeapObjectTag), | 940 FixedArray::kHeaderSize - kHeapObjectTag), |
946 rax); | 941 rax); |
947 __ ret(0); | 942 __ ret(0); |
948 __ bind(&non_smi_value); | 943 __ bind(&non_smi_value); |
949 // Slow case that needs to retain rbx for use by RecordWrite. | 944 // Slow case that needs to retain rcx for use by RecordWrite. |
950 // Update write barrier for the elements array address. | 945 // Update write barrier for the elements array address. |
951 SmiIndex index2 = masm->SmiToIndex(kScratchRegister, rbx, kPointerSizeLog2); | 946 SmiIndex index2 = masm->SmiToIndex(kScratchRegister, rcx, kPointerSizeLog2); |
952 __ movq(Operand(rcx, index2.reg, index2.scale, | 947 __ movq(Operand(rbx, index2.reg, index2.scale, |
953 FixedArray::kHeaderSize - kHeapObjectTag), | 948 FixedArray::kHeaderSize - kHeapObjectTag), |
954 rax); | 949 rax); |
955 __ movq(rdx, rax); | 950 __ movq(rdx, rax); |
956 __ RecordWriteNonSmi(rcx, 0, rdx, rbx); | 951 __ RecordWriteNonSmi(rbx, 0, rdx, rcx); |
957 __ ret(0); | 952 __ ret(0); |
958 } | 953 } |
959 | 954 |
960 | 955 |
961 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, | 956 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, |
962 ExternalArrayType array_type) { | 957 ExternalArrayType array_type) { |
963 // ----------- S t a t e ------------- | 958 // ----------- S t a t e ------------- |
964 // -- rax : value | 959 // -- rax : value |
965 // -- rsp[0] : return address | 960 // -- rcx : key |
966 // -- rsp[8] : key | 961 // -- rdx : receiver |
967 // -- rsp[16] : receiver | 962 // -- rsp[0] : return address |
968 // ----------------------------------- | 963 // ----------------------------------- |
969 Label slow, check_heap_number; | 964 Label slow, check_heap_number; |
970 | 965 |
971 // Get the receiver from the stack. | |
972 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); | |
973 // Check that the object isn't a smi. | 966 // Check that the object isn't a smi. |
974 __ JumpIfSmi(rdx, &slow); | 967 __ JumpIfSmi(rdx, &slow); |
975 // Get the map from the receiver. | 968 // Get the map from the receiver. |
976 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); | 969 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); |
977 // Check that the receiver does not require access checks. We need | 970 // Check that the receiver does not require access checks. We need |
978 // to do this because this generic stub does not perform map checks. | 971 // to do this because this generic stub does not perform map checks. |
979 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), | 972 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), |
980 Immediate(1 << Map::kIsAccessCheckNeeded)); | 973 Immediate(1 << Map::kIsAccessCheckNeeded)); |
981 __ j(not_zero, &slow); | 974 __ j(not_zero, &slow); |
982 // Get the key from the stack. | |
983 __ movq(rbx, Operand(rsp, 1 * kPointerSize)); // 1 ~ return address | |
984 // Check that the key is a smi. | 975 // Check that the key is a smi. |
985 __ JumpIfNotSmi(rbx, &slow); | 976 __ JumpIfNotSmi(rcx, &slow); |
986 | 977 |
987 // Check that the object is a JS object. | 978 // Check that the object is a JS object. |
988 __ CmpInstanceType(rcx, JS_OBJECT_TYPE); | 979 __ CmpInstanceType(rbx, JS_OBJECT_TYPE); |
989 __ j(not_equal, &slow); | 980 __ j(not_equal, &slow); |
990 | 981 |
991 // Check that the elements array is the appropriate type of | 982 // Check that the elements array is the appropriate type of |
992 // ExternalArray. | 983 // ExternalArray. |
993 // rax: value | 984 // rax: value |
994 // rdx: JSObject | 985 // rcx: key (a smi) |
995 // rbx: index (as a smi) | 986 // rdx: receiver (a JSObject) |
996 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); | 987 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); |
997 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), | 988 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), |
998 Heap::RootIndexForExternalArrayType(array_type)); | 989 Heap::RootIndexForExternalArrayType(array_type)); |
999 __ j(not_equal, &slow); | 990 __ j(not_equal, &slow); |
1000 | 991 |
1001 // Check that the index is in range. | 992 // Check that the index is in range. |
1002 __ SmiToInteger32(rbx, rbx); // Untag the index. | 993 __ SmiToInteger32(rdi, rcx); // Untag the index. |
1003 __ cmpl(rbx, FieldOperand(rcx, ExternalArray::kLengthOffset)); | 994 __ cmpl(rdi, FieldOperand(rbx, ExternalArray::kLengthOffset)); |
1004 // Unsigned comparison catches both negative and too-large values. | 995 // Unsigned comparison catches both negative and too-large values. |
1005 __ j(above_equal, &slow); | 996 __ j(above_equal, &slow); |
1006 | 997 |
1007 // Handle both smis and HeapNumbers in the fast path. Go to the | 998 // Handle both smis and HeapNumbers in the fast path. Go to the |
1008 // runtime for all other kinds of values. | 999 // runtime for all other kinds of values. |
1009 // rax: value | 1000 // rax: value |
1010 // rcx: elements array | 1001 // rcx: key (a smi) |
1011 // rbx: untagged index | 1002 // rdx: receiver (a JSObject) |
| 1003 // rbx: elements array |
| 1004 // rdi: untagged key |
1012 __ JumpIfNotSmi(rax, &check_heap_number); | 1005 __ JumpIfNotSmi(rax, &check_heap_number); |
1013 __ movq(rdx, rax); // Save the value. | 1006 // No more branches to slow case on this path. Key and receiver not needed. |
1014 __ SmiToInteger32(rax, rax); | 1007 __ SmiToInteger32(rdx, rax); |
1015 __ movq(rcx, FieldOperand(rcx, ExternalArray::kExternalPointerOffset)); | 1008 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); |
1016 // rcx: base pointer of external storage | 1009 // rbx: base pointer of external storage |
1017 switch (array_type) { | 1010 switch (array_type) { |
1018 case kExternalByteArray: | 1011 case kExternalByteArray: |
1019 case kExternalUnsignedByteArray: | 1012 case kExternalUnsignedByteArray: |
1020 __ movb(Operand(rcx, rbx, times_1, 0), rax); | 1013 __ movb(Operand(rbx, rdi, times_1, 0), rdx); |
1021 break; | 1014 break; |
1022 case kExternalShortArray: | 1015 case kExternalShortArray: |
1023 case kExternalUnsignedShortArray: | 1016 case kExternalUnsignedShortArray: |
1024 __ movw(Operand(rcx, rbx, times_2, 0), rax); | 1017 __ movw(Operand(rbx, rdi, times_2, 0), rdx); |
1025 break; | 1018 break; |
1026 case kExternalIntArray: | 1019 case kExternalIntArray: |
1027 case kExternalUnsignedIntArray: | 1020 case kExternalUnsignedIntArray: |
1028 __ movl(Operand(rcx, rbx, times_4, 0), rax); | 1021 __ movl(Operand(rbx, rdi, times_4, 0), rdx); |
1029 break; | 1022 break; |
1030 case kExternalFloatArray: | 1023 case kExternalFloatArray: |
1031 // Need to perform int-to-float conversion. | 1024 // Need to perform int-to-float conversion. |
1032 __ push(rax); | 1025 __ push(rdx); |
1033 __ fild_s(Operand(rsp, 0)); | 1026 __ fild_s(Operand(rsp, 0)); |
1034 __ pop(rax); | 1027 __ pop(rdx); |
1035 __ fstp_s(Operand(rcx, rbx, times_4, 0)); | 1028 __ fstp_s(Operand(rbx, rdi, times_4, 0)); |
1036 break; | 1029 break; |
1037 default: | 1030 default: |
1038 UNREACHABLE(); | 1031 UNREACHABLE(); |
1039 break; | 1032 break; |
1040 } | 1033 } |
1041 __ movq(rax, rdx); // Return the original value. | |
1042 __ ret(0); | 1034 __ ret(0); |
1043 | 1035 |
1044 __ bind(&check_heap_number); | 1036 __ bind(&check_heap_number); |
1045 __ CmpObjectType(rax, HEAP_NUMBER_TYPE, rdx); | 1037 // rax: value |
| 1038 // rcx: key (a smi) |
| 1039 // rdx: receiver (a JSObject) |
| 1040 // rbx: elements array |
| 1041 // rdi: untagged key |
| 1042 __ CmpObjectType(rax, HEAP_NUMBER_TYPE, kScratchRegister); |
1046 __ j(not_equal, &slow); | 1043 __ j(not_equal, &slow); |
| 1044 // No more branches to slow case on this path. |
1047 | 1045 |
1048 // The WebGL specification leaves the behavior of storing NaN and | 1046 // The WebGL specification leaves the behavior of storing NaN and |
1049 // +/-Infinity into integer arrays basically undefined. For more | 1047 // +/-Infinity into integer arrays basically undefined. For more |
1050 // reproducible behavior, convert these to zero. | 1048 // reproducible behavior, convert these to zero. |
1051 __ fld_d(FieldOperand(rax, HeapNumber::kValueOffset)); | 1049 __ fld_d(FieldOperand(rax, HeapNumber::kValueOffset)); |
1052 __ movq(rdx, rax); // Save the value. | 1050 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); |
1053 __ movq(rcx, FieldOperand(rcx, ExternalArray::kExternalPointerOffset)); | 1051 // rdi: untagged index |
1054 // rbx: untagged index | 1052 // rbx: base pointer of external storage |
1055 // rcx: base pointer of external storage | |
1056 // top of FPU stack: value | 1053 // top of FPU stack: value |
1057 if (array_type == kExternalFloatArray) { | 1054 if (array_type == kExternalFloatArray) { |
1058 __ fstp_s(Operand(rcx, rbx, times_4, 0)); | 1055 __ fstp_s(Operand(rbx, rdi, times_4, 0)); |
1059 __ movq(rax, rdx); // Return the original value. | |
1060 __ ret(0); | 1056 __ ret(0); |
1061 } else { | 1057 } else { |
1062 // Need to perform float-to-int conversion. | 1058 // Need to perform float-to-int conversion. |
1063 // Test the top of the FP stack for NaN. | 1059 // Test the top of the FP stack for NaN. |
1064 Label is_nan; | 1060 Label is_nan; |
1065 __ fucomi(0); | 1061 __ fucomi(0); |
1066 __ j(parity_even, &is_nan); | 1062 __ j(parity_even, &is_nan); |
1067 | 1063 |
1068 __ push(rax); // Make room on stack | 1064 __ push(rdx); // Make room on the stack. Receiver is no longer needed. |
1069 __ fistp_d(Operand(rsp, 0)); | 1065 __ fistp_d(Operand(rsp, 0)); |
1070 __ pop(rax); | 1066 __ pop(rdx); |
1071 // rax: untagged integer value | 1067 // rdx: value (converted to an untagged integer) |
| 1068 // rdi: untagged index |
| 1069 // rbx: base pointer of external storage |
1072 switch (array_type) { | 1070 switch (array_type) { |
1073 case kExternalByteArray: | 1071 case kExternalByteArray: |
1074 case kExternalUnsignedByteArray: | 1072 case kExternalUnsignedByteArray: |
1075 __ movb(Operand(rcx, rbx, times_1, 0), rax); | 1073 __ movb(Operand(rbx, rdi, times_1, 0), rdx); |
1076 break; | 1074 break; |
1077 case kExternalShortArray: | 1075 case kExternalShortArray: |
1078 case kExternalUnsignedShortArray: | 1076 case kExternalUnsignedShortArray: |
1079 __ movw(Operand(rcx, rbx, times_2, 0), rax); | 1077 __ movw(Operand(rbx, rdi, times_2, 0), rdx); |
1080 break; | 1078 break; |
1081 case kExternalIntArray: | 1079 case kExternalIntArray: |
1082 case kExternalUnsignedIntArray: { | 1080 case kExternalUnsignedIntArray: { |
1083 // We also need to explicitly check for +/-Infinity. These are | 1081 // We also need to explicitly check for +/-Infinity. These are |
1084 // converted to MIN_INT, but we need to be careful not to | 1082 // converted to MIN_INT, but we need to be careful not to |
1085 // confuse with legal uses of MIN_INT. | 1083 // confuse with legal uses of MIN_INT. Since MIN_INT truncated |
| 1084 // to 8 or 16 bits is zero, we only perform this test when storing |
| 1085 // 32-bit ints. |
1086 Label not_infinity; | 1086 Label not_infinity; |
1087 // This test would apparently detect both NaN and Infinity, | 1087 // This test would apparently detect both NaN and Infinity, |
1088 // but we've already checked for NaN using the FPU hardware | 1088 // but we've already checked for NaN using the FPU hardware |
1089 // above. | 1089 // above. |
1090 __ movzxwq(rdi, FieldOperand(rdx, HeapNumber::kValueOffset + 6)); | 1090 __ movzxwq(rcx, FieldOperand(rax, HeapNumber::kValueOffset + 6)); |
1091 __ and_(rdi, Immediate(0x7FF0)); | 1091 __ and_(rcx, Immediate(0x7FF0)); |
1092 __ cmpw(rdi, Immediate(0x7FF0)); | 1092 __ cmpw(rcx, Immediate(0x7FF0)); |
1093 __ j(not_equal, ¬_infinity); | 1093 __ j(not_equal, ¬_infinity); |
1094 __ movq(rax, Immediate(0)); | 1094 __ movq(rdx, Immediate(0)); |
1095 __ bind(¬_infinity); | 1095 __ bind(¬_infinity); |
1096 __ movl(Operand(rcx, rbx, times_4, 0), rax); | 1096 __ movl(Operand(rbx, rdi, times_4, 0), rdx); |
1097 break; | 1097 break; |
1098 } | 1098 } |
1099 default: | 1099 default: |
1100 UNREACHABLE(); | 1100 UNREACHABLE(); |
1101 break; | 1101 break; |
1102 } | 1102 } |
1103 __ movq(rax, rdx); // Return the original value. | |
1104 __ ret(0); | 1103 __ ret(0); |
1105 | 1104 |
1106 __ bind(&is_nan); | 1105 __ bind(&is_nan); |
| 1106 // rdi: untagged index |
| 1107 // rbx: base pointer of external storage |
1107 __ ffree(); | 1108 __ ffree(); |
1108 __ fincstp(); | 1109 __ fincstp(); |
1109 __ movq(rax, Immediate(0)); | 1110 __ movq(rdx, Immediate(0)); |
1110 switch (array_type) { | 1111 switch (array_type) { |
1111 case kExternalByteArray: | 1112 case kExternalByteArray: |
1112 case kExternalUnsignedByteArray: | 1113 case kExternalUnsignedByteArray: |
1113 __ movb(Operand(rcx, rbx, times_1, 0), rax); | 1114 __ movb(Operand(rbx, rdi, times_1, 0), rdx); |
1114 break; | 1115 break; |
1115 case kExternalShortArray: | 1116 case kExternalShortArray: |
1116 case kExternalUnsignedShortArray: | 1117 case kExternalUnsignedShortArray: |
1117 __ movw(Operand(rcx, rbx, times_2, 0), rax); | 1118 __ movw(Operand(rbx, rdi, times_2, 0), rdx); |
1118 break; | 1119 break; |
1119 case kExternalIntArray: | 1120 case kExternalIntArray: |
1120 case kExternalUnsignedIntArray: | 1121 case kExternalUnsignedIntArray: |
1121 __ movl(Operand(rcx, rbx, times_4, 0), rax); | 1122 __ movl(Operand(rbx, rdi, times_4, 0), rdx); |
1122 break; | 1123 break; |
1123 default: | 1124 default: |
1124 UNREACHABLE(); | 1125 UNREACHABLE(); |
1125 break; | 1126 break; |
1126 } | 1127 } |
1127 __ movq(rax, rdx); // Return the original value. | |
1128 __ ret(0); | 1128 __ ret(0); |
1129 } | 1129 } |
1130 | 1130 |
1131 // Slow case: call runtime. | 1131 // Slow case: call runtime. |
1132 __ bind(&slow); | 1132 __ bind(&slow); |
1133 GenerateRuntimeSetProperty(masm); | 1133 GenerateRuntimeSetProperty(masm); |
1134 } | 1134 } |
1135 | 1135 |
1136 | 1136 |
1137 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { | 1137 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { |
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1616 GenerateMiss(masm); | 1616 GenerateMiss(masm); |
1617 } | 1617 } |
1618 | 1618 |
1619 | 1619 |
1620 #undef __ | 1620 #undef __ |
1621 | 1621 |
1622 | 1622 |
1623 } } // namespace v8::internal | 1623 } } // namespace v8::internal |
1624 | 1624 |
1625 #endif // V8_TARGET_ARCH_X64 | 1625 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |