Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1884)

Side by Side Diff: src/x64/ic-x64.cc

Issue 2111011: Change keyed store IC interface on x64 to take value, key, and receiver in re... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/full-codegen-x64.cc ('k') | src/x64/stub-cache-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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, &not_infinity); 1093 __ j(not_equal, &not_infinity);
1094 __ movq(rax, Immediate(0)); 1094 __ movq(rdx, Immediate(0));
1095 __ bind(&not_infinity); 1095 __ bind(&not_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
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
OLDNEW
« no previous file with comments | « src/x64/full-codegen-x64.cc ('k') | src/x64/stub-cache-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698