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

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

Issue 2084017: Version 2.2.11... (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
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/jump-target-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
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #if defined(V8_TARGET_ARCH_X64)
31
30 #include "codegen-inl.h" 32 #include "codegen-inl.h"
31 #include "ic-inl.h" 33 #include "ic-inl.h"
32 #include "runtime.h" 34 #include "runtime.h"
33 #include "stub-cache.h" 35 #include "stub-cache.h"
34 #include "utils.h" 36 #include "utils.h"
35 37
36 namespace v8 { 38 namespace v8 {
37 namespace internal { 39 namespace internal {
38 40
39 // ---------------------------------------------------------------------------- 41 // ----------------------------------------------------------------------------
(...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after
771 IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1); 773 IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1);
772 774
773 __ bind(&slow); 775 __ bind(&slow);
774 GenerateMiss(masm); 776 GenerateMiss(masm);
775 } 777 }
776 778
777 779
778 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { 780 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
779 // ----------- S t a t e ------------- 781 // ----------- S t a t e -------------
780 // -- rax : value 782 // -- rax : value
783 // -- rcx : key
784 // -- rdx : receiver
781 // -- rsp[0] : return address 785 // -- rsp[0] : return address
782 // -- rsp[8] : key
783 // -- rsp[16] : receiver
784 // ----------------------------------- 786 // -----------------------------------
785 787
786 __ pop(rcx); 788 __ pop(rbx);
787 __ push(Operand(rsp, 1 * kPointerSize)); // receiver 789 __ push(rdx); // receiver
788 __ push(Operand(rsp, 1 * kPointerSize)); // key 790 __ push(rcx); // key
789 __ push(rax); // value 791 __ push(rax); // value
790 __ push(rcx); // return address 792 __ push(rbx); // return address
791 793
792 // Do tail-call to runtime routine. 794 // Do tail-call to runtime routine.
793 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); 795 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss));
794 __ TailCallExternalReference(ref, 3, 1); 796 __ TailCallExternalReference(ref, 3, 1);
795 } 797 }
796 798
797 799
798 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { 800 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) {
799 // ----------- S t a t e ------------- 801 // ----------- S t a t e -------------
800 // -- rax : value 802 // -- rax : value
803 // -- rcx : key
804 // -- rdx : receiver
801 // -- rsp[0] : return address 805 // -- rsp[0] : return address
802 // -- rsp[8] : key
803 // -- rsp[16] : receiver
804 // ----------------------------------- 806 // -----------------------------------
805 807
806 __ pop(rcx); 808 __ pop(rbx);
807 __ push(Operand(rsp, 1 * kPointerSize)); // receiver 809 __ push(rdx); // receiver
808 __ push(Operand(rsp, 1 * kPointerSize)); // key 810 __ push(rcx); // key
809 __ push(rax); // value 811 __ push(rax); // value
810 __ push(rcx); // return address 812 __ push(rbx); // return address
811 813
812 // Do tail-call to runtime routine. 814 // Do tail-call to runtime routine.
813 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); 815 __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
814 } 816 }
815 817
816 818
817 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { 819 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
818 // ----------- S t a t e ------------- 820 // ----------- S t a t e -------------
819 // -- rax : value 821 // -- rax : value
820 // -- rsp[0] : return address 822 // -- rcx : key
821 // -- rsp[8] : key 823 // -- rdx : receiver
822 // -- rsp[16] : receiver 824 // -- rsp[0] : return address
823 // ----------------------------------- 825 // -----------------------------------
824 Label slow, fast, array, extra, check_pixel_array; 826 Label slow, fast, array, extra, check_pixel_array;
825 827
826 // Get the receiver from the stack.
827 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // 2 ~ return address, key
828 // Check that the object isn't a smi. 828 // Check that the object isn't a smi.
829 __ JumpIfSmi(rdx, &slow); 829 __ JumpIfSmi(rdx, &slow);
830 // Get the map from the receiver. 830 // Get the map from the receiver.
831 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); 831 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
832 // Check that the receiver does not require access checks. We need 832 // Check that the receiver does not require access checks. We need
833 // 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.
834 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), 834 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
835 Immediate(1 << Map::kIsAccessCheckNeeded)); 835 Immediate(1 << Map::kIsAccessCheckNeeded));
836 __ j(not_zero, &slow); 836 __ j(not_zero, &slow);
837 // Get the key from the stack.
838 __ movq(rbx, Operand(rsp, 1 * kPointerSize)); // 1 ~ return address
839 // Check that the key is a smi. 837 // Check that the key is a smi.
840 __ JumpIfNotSmi(rbx, &slow); 838 __ JumpIfNotSmi(rcx, &slow);
841 839
842 __ CmpInstanceType(rcx, JS_ARRAY_TYPE); 840 __ CmpInstanceType(rbx, JS_ARRAY_TYPE);
843 __ j(equal, &array); 841 __ j(equal, &array);
844 // Check that the object is some kind of JS object. 842 // Check that the object is some kind of JS object.
845 __ CmpInstanceType(rcx, FIRST_JS_OBJECT_TYPE); 843 __ CmpInstanceType(rbx, FIRST_JS_OBJECT_TYPE);
846 __ j(below, &slow); 844 __ j(below, &slow);
847 845
848 // Object case: Check key against length in the elements array. 846 // Object case: Check key against length in the elements array.
849 // rax: value 847 // rax: value
850 // rdx: JSObject 848 // rdx: JSObject
851 // rbx: index (as a smi) 849 // rcx: index (as a smi)
852 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); 850 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
853 // Check that the object is in fast mode (not dictionary). 851 // Check that the object is in fast mode (not dictionary).
854 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 852 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
855 Heap::kFixedArrayMapRootIndex); 853 Heap::kFixedArrayMapRootIndex);
856 __ j(not_equal, &check_pixel_array); 854 __ j(not_equal, &check_pixel_array);
857 // 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).
858 __ SmiToInteger32(rdx, rbx); 856 __ SmiToInteger32(rdi, rcx);
859 __ cmpl(rdx, FieldOperand(rcx, Array::kLengthOffset)); 857 __ cmpl(rdi, FieldOperand(rbx, Array::kLengthOffset));
860 // rax: value 858 // rax: value
861 // rcx: FixedArray 859 // rbx: FixedArray
862 // rbx: index (as a smi) 860 // rcx: index (as a smi)
863 __ j(below, &fast); 861 __ j(below, &fast);
864 862
865 // Slow case: call runtime. 863 // Slow case: call runtime.
866 __ bind(&slow); 864 __ bind(&slow);
867 GenerateRuntimeSetProperty(masm); 865 GenerateRuntimeSetProperty(masm);
868 866
869 // Check whether the elements is a pixel array. 867 // Check whether the elements is a pixel array.
870 // rax: value 868 // rax: value
871 // rcx: elements array 869 // rdx: receiver
872 // rbx: index (as a smi), zero-extended. 870 // rbx: receiver's elements array
871 // rcx: index (as a smi), zero-extended.
873 __ bind(&check_pixel_array); 872 __ bind(&check_pixel_array);
874 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 873 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
875 Heap::kPixelArrayMapRootIndex); 874 Heap::kPixelArrayMapRootIndex);
876 __ j(not_equal, &slow); 875 __ j(not_equal, &slow);
877 // 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
878 // runtime to convert and clamp. 877 // runtime to convert and clamp.
879 __ JumpIfNotSmi(rax, &slow); 878 __ JumpIfNotSmi(rax, &slow);
880 __ SmiToInteger32(rbx, rbx); 879 __ SmiToInteger32(rdi, rcx);
881 __ cmpl(rbx, FieldOperand(rcx, PixelArray::kLengthOffset)); 880 __ cmpl(rdi, FieldOperand(rbx, PixelArray::kLengthOffset));
882 __ j(above_equal, &slow); 881 __ j(above_equal, &slow);
883 __ movq(rdx, rax); // Save the value. 882 // No more bailouts to slow case on this path, so key not needed.
884 __ SmiToInteger32(rax, rax); 883 __ SmiToInteger32(rcx, rax);
885 { // Clamp the value to [0..255]. 884 { // Clamp the value to [0..255].
886 Label done; 885 Label done;
887 __ testl(rax, Immediate(0xFFFFFF00)); 886 __ testl(rcx, Immediate(0xFFFFFF00));
888 __ j(zero, &done); 887 __ j(zero, &done);
889 __ setcc(negative, rax); // 1 if negative, 0 if positive. 888 __ setcc(negative, rcx); // 1 if negative, 0 if positive.
890 __ decb(rax); // 0 if negative, 255 if positive. 889 __ decb(rcx); // 0 if negative, 255 if positive.
891 __ bind(&done); 890 __ bind(&done);
892 } 891 }
893 __ movq(rcx, FieldOperand(rcx, PixelArray::kExternalPointerOffset)); 892 __ movq(rbx, FieldOperand(rbx, PixelArray::kExternalPointerOffset));
894 __ movb(Operand(rcx, rbx, times_1, 0), rax); 893 __ movb(Operand(rbx, rdi, times_1, 0), rcx);
895 __ movq(rax, rdx); // Return the original value.
896 __ ret(0); 894 __ ret(0);
897 895
898 // Extra capacity case: Check if there is extra capacity to 896 // Extra capacity case: Check if there is extra capacity to
899 // perform the store and update the length. Used for adding one 897 // perform the store and update the length. Used for adding one
900 // element to the array by writing to array[array.length]. 898 // element to the array by writing to array[array.length].
901 __ bind(&extra); 899 __ bind(&extra);
902 // rax: value 900 // rax: value
903 // rdx: JSArray 901 // rdx: receiver (a JSArray)
904 // rcx: FixedArray 902 // rbx: receiver's elements array (a FixedArray)
905 // rbx: index (as a smi) 903 // rcx: index (as a smi)
906 // flags: smicompare (rdx.length(), rbx) 904 // flags: smicompare (rdx.length(), rbx)
907 __ j(not_equal, &slow); // do not leave holes in the array 905 __ j(not_equal, &slow); // do not leave holes in the array
908 __ SmiToInteger64(rbx, rbx); 906 __ SmiToInteger64(rdi, rcx);
909 __ cmpl(rbx, FieldOperand(rcx, FixedArray::kLengthOffset)); 907 __ cmpl(rdi, FieldOperand(rbx, FixedArray::kLengthOffset));
910 __ j(above_equal, &slow); 908 __ j(above_equal, &slow);
911 // Increment and restore smi-tag. 909 // Increment and restore smi-tag.
912 __ Integer64PlusConstantToSmi(rbx, rbx, 1); 910 __ Integer64PlusConstantToSmi(rdi, rdi, 1);
913 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rbx); 911 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rdi);
914 __ SmiSubConstant(rbx, rbx, Smi::FromInt(1));
915 __ jmp(&fast); 912 __ jmp(&fast);
916 913
917 // 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
918 // 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
919 // length is always a smi. 916 // length is always a smi.
920 __ bind(&array); 917 __ bind(&array);
921 // rax: value 918 // rax: value
922 // rdx: JSArray 919 // rdx: receiver (a JSArray)
923 // rbx: index (as a smi) 920 // rcx: index (as a smi)
924 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); 921 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
925 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 922 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
926 Heap::kFixedArrayMapRootIndex); 923 Heap::kFixedArrayMapRootIndex);
927 __ j(not_equal, &slow); 924 __ j(not_equal, &slow);
928 925
929 // Check the key against the length in the array, compute the 926 // Check the key against the length in the array, compute the
930 // address to store into and fall through to fast case. 927 // address to store into and fall through to fast case.
931 __ SmiCompare(FieldOperand(rdx, JSArray::kLengthOffset), rbx); 928 __ SmiCompare(FieldOperand(rdx, JSArray::kLengthOffset), rcx);
932 __ j(below_equal, &extra); 929 __ j(below_equal, &extra);
933 930
934 // Fast case: Do the store. 931 // Fast case: Do the store.
935 __ bind(&fast); 932 __ bind(&fast);
936 // rax: value 933 // rax: value
937 // rcx: FixedArray 934 // rbx: receiver's elements array (a FixedArray)
938 // rbx: index (as a smi) 935 // rcx: index (as a smi)
939 Label non_smi_value; 936 Label non_smi_value;
940 __ JumpIfNotSmi(rax, &non_smi_value); 937 __ JumpIfNotSmi(rax, &non_smi_value);
941 SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2); 938 SmiIndex index = masm->SmiToIndex(rcx, rcx, kPointerSizeLog2);
942 __ movq(Operand(rcx, index.reg, index.scale, 939 __ movq(Operand(rbx, index.reg, index.scale,
943 FixedArray::kHeaderSize - kHeapObjectTag), 940 FixedArray::kHeaderSize - kHeapObjectTag),
944 rax); 941 rax);
945 __ ret(0); 942 __ ret(0);
946 __ bind(&non_smi_value); 943 __ bind(&non_smi_value);
947 // Slow case that needs to retain rbx for use by RecordWrite. 944 // Slow case that needs to retain rcx for use by RecordWrite.
948 // Update write barrier for the elements array address. 945 // Update write barrier for the elements array address.
949 SmiIndex index2 = masm->SmiToIndex(kScratchRegister, rbx, kPointerSizeLog2); 946 SmiIndex index2 = masm->SmiToIndex(kScratchRegister, rcx, kPointerSizeLog2);
950 __ movq(Operand(rcx, index2.reg, index2.scale, 947 __ movq(Operand(rbx, index2.reg, index2.scale,
951 FixedArray::kHeaderSize - kHeapObjectTag), 948 FixedArray::kHeaderSize - kHeapObjectTag),
952 rax); 949 rax);
953 __ movq(rdx, rax); 950 __ movq(rdx, rax);
954 __ RecordWriteNonSmi(rcx, 0, rdx, rbx); 951 __ RecordWriteNonSmi(rbx, 0, rdx, rcx);
955 __ ret(0); 952 __ ret(0);
956 } 953 }
957 954
958 955
959 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, 956 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm,
960 ExternalArrayType array_type) { 957 ExternalArrayType array_type) {
961 // ----------- S t a t e ------------- 958 // ----------- S t a t e -------------
962 // -- rax : value 959 // -- rax : value
963 // -- rsp[0] : return address 960 // -- rcx : key
964 // -- rsp[8] : key 961 // -- rdx : receiver
965 // -- rsp[16] : receiver 962 // -- rsp[0] : return address
966 // ----------------------------------- 963 // -----------------------------------
967 Label slow, check_heap_number; 964 Label slow, check_heap_number;
968 965
969 // Get the receiver from the stack.
970 __ movq(rdx, Operand(rsp, 2 * kPointerSize));
971 // Check that the object isn't a smi. 966 // Check that the object isn't a smi.
972 __ JumpIfSmi(rdx, &slow); 967 __ JumpIfSmi(rdx, &slow);
973 // Get the map from the receiver. 968 // Get the map from the receiver.
974 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); 969 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
975 // Check that the receiver does not require access checks. We need 970 // Check that the receiver does not require access checks. We need
976 // 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.
977 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), 972 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
978 Immediate(1 << Map::kIsAccessCheckNeeded)); 973 Immediate(1 << Map::kIsAccessCheckNeeded));
979 __ j(not_zero, &slow); 974 __ j(not_zero, &slow);
980 // Get the key from the stack.
981 __ movq(rbx, Operand(rsp, 1 * kPointerSize)); // 1 ~ return address
982 // Check that the key is a smi. 975 // Check that the key is a smi.
983 __ JumpIfNotSmi(rbx, &slow); 976 __ JumpIfNotSmi(rcx, &slow);
984 977
985 // Check that the object is a JS object. 978 // Check that the object is a JS object.
986 __ CmpInstanceType(rcx, JS_OBJECT_TYPE); 979 __ CmpInstanceType(rbx, JS_OBJECT_TYPE);
987 __ j(not_equal, &slow); 980 __ j(not_equal, &slow);
988 981
989 // Check that the elements array is the appropriate type of 982 // Check that the elements array is the appropriate type of
990 // ExternalArray. 983 // ExternalArray.
991 // rax: value 984 // rax: value
992 // rdx: JSObject 985 // rcx: key (a smi)
993 // rbx: index (as a smi) 986 // rdx: receiver (a JSObject)
994 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); 987 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
995 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 988 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
996 Heap::RootIndexForExternalArrayType(array_type)); 989 Heap::RootIndexForExternalArrayType(array_type));
997 __ j(not_equal, &slow); 990 __ j(not_equal, &slow);
998 991
999 // Check that the index is in range. 992 // Check that the index is in range.
1000 __ SmiToInteger32(rbx, rbx); // Untag the index. 993 __ SmiToInteger32(rdi, rcx); // Untag the index.
1001 __ cmpl(rbx, FieldOperand(rcx, ExternalArray::kLengthOffset)); 994 __ cmpl(rdi, FieldOperand(rbx, ExternalArray::kLengthOffset));
1002 // Unsigned comparison catches both negative and too-large values. 995 // Unsigned comparison catches both negative and too-large values.
1003 __ j(above_equal, &slow); 996 __ j(above_equal, &slow);
1004 997
1005 // 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
1006 // runtime for all other kinds of values. 999 // runtime for all other kinds of values.
1007 // rax: value 1000 // rax: value
1008 // rcx: elements array 1001 // rcx: key (a smi)
1009 // rbx: untagged index 1002 // rdx: receiver (a JSObject)
1003 // rbx: elements array
1004 // rdi: untagged key
1010 __ JumpIfNotSmi(rax, &check_heap_number); 1005 __ JumpIfNotSmi(rax, &check_heap_number);
1011 __ movq(rdx, rax); // Save the value. 1006 // No more branches to slow case on this path. Key and receiver not needed.
1012 __ SmiToInteger32(rax, rax); 1007 __ SmiToInteger32(rdx, rax);
1013 __ movq(rcx, FieldOperand(rcx, ExternalArray::kExternalPointerOffset)); 1008 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
1014 // rcx: base pointer of external storage 1009 // rbx: base pointer of external storage
1015 switch (array_type) { 1010 switch (array_type) {
1016 case kExternalByteArray: 1011 case kExternalByteArray:
1017 case kExternalUnsignedByteArray: 1012 case kExternalUnsignedByteArray:
1018 __ movb(Operand(rcx, rbx, times_1, 0), rax); 1013 __ movb(Operand(rbx, rdi, times_1, 0), rdx);
1019 break; 1014 break;
1020 case kExternalShortArray: 1015 case kExternalShortArray:
1021 case kExternalUnsignedShortArray: 1016 case kExternalUnsignedShortArray:
1022 __ movw(Operand(rcx, rbx, times_2, 0), rax); 1017 __ movw(Operand(rbx, rdi, times_2, 0), rdx);
1023 break; 1018 break;
1024 case kExternalIntArray: 1019 case kExternalIntArray:
1025 case kExternalUnsignedIntArray: 1020 case kExternalUnsignedIntArray:
1026 __ movl(Operand(rcx, rbx, times_4, 0), rax); 1021 __ movl(Operand(rbx, rdi, times_4, 0), rdx);
1027 break; 1022 break;
1028 case kExternalFloatArray: 1023 case kExternalFloatArray:
1029 // Need to perform int-to-float conversion. 1024 // Need to perform int-to-float conversion.
1030 __ push(rax); 1025 __ push(rdx);
1031 __ fild_s(Operand(rsp, 0)); 1026 __ fild_s(Operand(rsp, 0));
1032 __ pop(rax); 1027 __ pop(rdx);
1033 __ fstp_s(Operand(rcx, rbx, times_4, 0)); 1028 __ fstp_s(Operand(rbx, rdi, times_4, 0));
1034 break; 1029 break;
1035 default: 1030 default:
1036 UNREACHABLE(); 1031 UNREACHABLE();
1037 break; 1032 break;
1038 } 1033 }
1039 __ movq(rax, rdx); // Return the original value.
1040 __ ret(0); 1034 __ ret(0);
1041 1035
1042 __ bind(&check_heap_number); 1036 __ bind(&check_heap_number);
1043 __ 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);
1044 __ j(not_equal, &slow); 1043 __ j(not_equal, &slow);
1044 // No more branches to slow case on this path.
1045 1045
1046 // The WebGL specification leaves the behavior of storing NaN and 1046 // The WebGL specification leaves the behavior of storing NaN and
1047 // +/-Infinity into integer arrays basically undefined. For more 1047 // +/-Infinity into integer arrays basically undefined. For more
1048 // reproducible behavior, convert these to zero. 1048 // reproducible behavior, convert these to zero.
1049 __ fld_d(FieldOperand(rax, HeapNumber::kValueOffset)); 1049 __ fld_d(FieldOperand(rax, HeapNumber::kValueOffset));
1050 __ movq(rdx, rax); // Save the value. 1050 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
1051 __ movq(rcx, FieldOperand(rcx, ExternalArray::kExternalPointerOffset)); 1051 // rdi: untagged index
1052 // rbx: untagged index 1052 // rbx: base pointer of external storage
1053 // rcx: base pointer of external storage
1054 // top of FPU stack: value 1053 // top of FPU stack: value
1055 if (array_type == kExternalFloatArray) { 1054 if (array_type == kExternalFloatArray) {
1056 __ fstp_s(Operand(rcx, rbx, times_4, 0)); 1055 __ fstp_s(Operand(rbx, rdi, times_4, 0));
1057 __ movq(rax, rdx); // Return the original value.
1058 __ ret(0); 1056 __ ret(0);
1059 } else { 1057 } else {
1060 // Need to perform float-to-int conversion. 1058 // Need to perform float-to-int conversion.
1061 // Test the top of the FP stack for NaN. 1059 // Test the top of the FP stack for NaN.
1062 Label is_nan; 1060 Label is_nan;
1063 __ fucomi(0); 1061 __ fucomi(0);
1064 __ j(parity_even, &is_nan); 1062 __ j(parity_even, &is_nan);
1065 1063
1066 __ push(rax); // Make room on stack 1064 __ push(rdx); // Make room on the stack. Receiver is no longer needed.
1067 __ fistp_d(Operand(rsp, 0)); 1065 __ fistp_d(Operand(rsp, 0));
1068 __ pop(rax); 1066 __ pop(rdx);
1069 // rax: untagged integer value 1067 // rdx: value (converted to an untagged integer)
1068 // rdi: untagged index
1069 // rbx: base pointer of external storage
1070 switch (array_type) { 1070 switch (array_type) {
1071 case kExternalByteArray: 1071 case kExternalByteArray:
1072 case kExternalUnsignedByteArray: 1072 case kExternalUnsignedByteArray:
1073 __ movb(Operand(rcx, rbx, times_1, 0), rax); 1073 __ movb(Operand(rbx, rdi, times_1, 0), rdx);
1074 break; 1074 break;
1075 case kExternalShortArray: 1075 case kExternalShortArray:
1076 case kExternalUnsignedShortArray: 1076 case kExternalUnsignedShortArray:
1077 __ movw(Operand(rcx, rbx, times_2, 0), rax); 1077 __ movw(Operand(rbx, rdi, times_2, 0), rdx);
1078 break; 1078 break;
1079 case kExternalIntArray: 1079 case kExternalIntArray:
1080 case kExternalUnsignedIntArray: { 1080 case kExternalUnsignedIntArray: {
1081 // We also need to explicitly check for +/-Infinity. These are 1081 // We also need to explicitly check for +/-Infinity. These are
1082 // 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
1083 // 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.
1084 Label not_infinity; 1086 Label not_infinity;
1085 // This test would apparently detect both NaN and Infinity, 1087 // This test would apparently detect both NaN and Infinity,
1086 // but we've already checked for NaN using the FPU hardware 1088 // but we've already checked for NaN using the FPU hardware
1087 // above. 1089 // above.
1088 __ movzxwq(rdi, FieldOperand(rdx, HeapNumber::kValueOffset + 6)); 1090 __ movzxwq(rcx, FieldOperand(rax, HeapNumber::kValueOffset + 6));
1089 __ and_(rdi, Immediate(0x7FF0)); 1091 __ and_(rcx, Immediate(0x7FF0));
1090 __ cmpw(rdi, Immediate(0x7FF0)); 1092 __ cmpw(rcx, Immediate(0x7FF0));
1091 __ j(not_equal, &not_infinity); 1093 __ j(not_equal, &not_infinity);
1092 __ movq(rax, Immediate(0)); 1094 __ movq(rdx, Immediate(0));
1093 __ bind(&not_infinity); 1095 __ bind(&not_infinity);
1094 __ movl(Operand(rcx, rbx, times_4, 0), rax); 1096 __ movl(Operand(rbx, rdi, times_4, 0), rdx);
1095 break; 1097 break;
1096 } 1098 }
1097 default: 1099 default:
1098 UNREACHABLE(); 1100 UNREACHABLE();
1099 break; 1101 break;
1100 } 1102 }
1101 __ movq(rax, rdx); // Return the original value.
1102 __ ret(0); 1103 __ ret(0);
1103 1104
1104 __ bind(&is_nan); 1105 __ bind(&is_nan);
1106 // rdi: untagged index
1107 // rbx: base pointer of external storage
1105 __ ffree(); 1108 __ ffree();
1106 __ fincstp(); 1109 __ fincstp();
1107 __ movq(rax, Immediate(0)); 1110 __ movq(rdx, Immediate(0));
1108 switch (array_type) { 1111 switch (array_type) {
1109 case kExternalByteArray: 1112 case kExternalByteArray:
1110 case kExternalUnsignedByteArray: 1113 case kExternalUnsignedByteArray:
1111 __ movb(Operand(rcx, rbx, times_1, 0), rax); 1114 __ movb(Operand(rbx, rdi, times_1, 0), rdx);
1112 break; 1115 break;
1113 case kExternalShortArray: 1116 case kExternalShortArray:
1114 case kExternalUnsignedShortArray: 1117 case kExternalUnsignedShortArray:
1115 __ movw(Operand(rcx, rbx, times_2, 0), rax); 1118 __ movw(Operand(rbx, rdi, times_2, 0), rdx);
1116 break; 1119 break;
1117 case kExternalIntArray: 1120 case kExternalIntArray:
1118 case kExternalUnsignedIntArray: 1121 case kExternalUnsignedIntArray:
1119 __ movl(Operand(rcx, rbx, times_4, 0), rax); 1122 __ movl(Operand(rbx, rdi, times_4, 0), rdx);
1120 break; 1123 break;
1121 default: 1124 default:
1122 UNREACHABLE(); 1125 UNREACHABLE();
1123 break; 1126 break;
1124 } 1127 }
1125 __ movq(rax, rdx); // Return the original value.
1126 __ ret(0); 1128 __ ret(0);
1127 } 1129 }
1128 1130
1129 // Slow case: call runtime. 1131 // Slow case: call runtime.
1130 __ bind(&slow); 1132 __ bind(&slow);
1131 GenerateRuntimeSetProperty(masm); 1133 GenerateRuntimeSetProperty(masm);
1132 } 1134 }
1133 1135
1134 1136
1135 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { 1137 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
1612 __ bind(&miss); 1614 __ bind(&miss);
1613 1615
1614 GenerateMiss(masm); 1616 GenerateMiss(masm);
1615 } 1617 }
1616 1618
1617 1619
1618 #undef __ 1620 #undef __
1619 1621
1620 1622
1621 } } // namespace v8::internal 1623 } } // namespace v8::internal
1624
1625 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/full-codegen-x64.cc ('k') | src/x64/jump-target-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698