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

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

Issue 6315004: Truncate rather than round to nearest when performing float-to-integer... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 11 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/disasm-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 709 matching lines...) Expand 10 before | Expand all | Expand 10 after
720 __ ret(0); 720 __ ret(0);
721 721
722 StubRuntimeCallHelper call_helper; 722 StubRuntimeCallHelper call_helper;
723 char_at_generator.GenerateSlow(masm, call_helper); 723 char_at_generator.GenerateSlow(masm, call_helper);
724 724
725 __ bind(&miss); 725 __ bind(&miss);
726 GenerateMiss(masm); 726 GenerateMiss(masm);
727 } 727 }
728 728
729 729
730 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm,
731 ExternalArrayType array_type) {
732 // ----------- S t a t e -------------
733 // -- rax : key
734 // -- rdx : receiver
735 // -- rsp[0] : return address
736 // -----------------------------------
737 Label slow;
738
739 // Check that the object isn't a smi.
740 __ JumpIfSmi(rdx, &slow);
741
742 // Check that the key is a smi.
743 __ JumpIfNotSmi(rax, &slow);
744
745 // Check that the object is a JS object.
746 __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx);
747 __ j(not_equal, &slow);
748 // Check that the receiver does not require access checks. We need
749 // to check this explicitly since this generic stub does not perform
750 // map checks. The map is already in rdx.
751 __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
752 Immediate(1 << Map::kIsAccessCheckNeeded));
753 __ j(not_zero, &slow);
754
755 // Check that the elements array is the appropriate type of
756 // ExternalArray.
757 // rax: index (as a smi)
758 // rdx: JSObject
759 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
760 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
761 Heap::RootIndexForExternalArrayType(array_type));
762 __ j(not_equal, &slow);
763
764 // Check that the index is in range.
765 __ SmiToInteger32(rcx, rax);
766 __ cmpl(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset));
767 // Unsigned comparison catches both negative and too-large values.
768 __ j(above_equal, &slow);
769
770 // rax: index (as a smi)
771 // rdx: receiver (JSObject)
772 // rcx: untagged index
773 // rbx: elements array
774 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
775 // rbx: base pointer of external storage
776 switch (array_type) {
777 case kExternalByteArray:
778 __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0));
779 break;
780 case kExternalUnsignedByteArray:
781 __ movzxbq(rcx, Operand(rbx, rcx, times_1, 0));
782 break;
783 case kExternalShortArray:
784 __ movsxwq(rcx, Operand(rbx, rcx, times_2, 0));
785 break;
786 case kExternalUnsignedShortArray:
787 __ movzxwq(rcx, Operand(rbx, rcx, times_2, 0));
788 break;
789 case kExternalIntArray:
790 __ movsxlq(rcx, Operand(rbx, rcx, times_4, 0));
791 break;
792 case kExternalUnsignedIntArray:
793 __ movl(rcx, Operand(rbx, rcx, times_4, 0));
794 break;
795 case kExternalFloatArray:
796 __ cvtss2sd(xmm0, Operand(rbx, rcx, times_4, 0));
797 break;
798 default:
799 UNREACHABLE();
800 break;
801 }
802
803 // rax: index
804 // rdx: receiver
805 // For integer array types:
806 // rcx: value
807 // For floating-point array type:
808 // xmm0: value as double.
809
810 ASSERT(kSmiValueSize == 32);
811 if (array_type == kExternalUnsignedIntArray) {
812 // For the UnsignedInt array type, we need to see whether
813 // the value can be represented in a Smi. If not, we need to convert
814 // it to a HeapNumber.
815 NearLabel box_int;
816
817 __ JumpIfUIntNotValidSmiValue(rcx, &box_int);
818
819 __ Integer32ToSmi(rax, rcx);
820 __ ret(0);
821
822 __ bind(&box_int);
823
824 // Allocate a HeapNumber for the int and perform int-to-double
825 // conversion.
826 // The value is zero-extended since we loaded the value from memory
827 // with movl.
828 __ cvtqsi2sd(xmm0, rcx);
829
830 __ AllocateHeapNumber(rcx, rbx, &slow);
831 // Set the value.
832 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
833 __ movq(rax, rcx);
834 __ ret(0);
835 } else if (array_type == kExternalFloatArray) {
836 // For the floating-point array type, we need to always allocate a
837 // HeapNumber.
838 __ AllocateHeapNumber(rcx, rbx, &slow);
839 // Set the value.
840 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
841 __ movq(rax, rcx);
842 __ ret(0);
843 } else {
844 __ Integer32ToSmi(rax, rcx);
845 __ ret(0);
846 }
847
848 // Slow case: Jump to runtime.
849 __ bind(&slow);
850 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1);
851 GenerateRuntimeGetProperty(masm);
852 }
853
854
855 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { 730 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
856 // ----------- S t a t e ------------- 731 // ----------- S t a t e -------------
857 // -- rax : key 732 // -- rax : key
858 // -- rdx : receiver 733 // -- rdx : receiver
859 // -- rsp[0] : return address 734 // -- rsp[0] : return address
860 // ----------------------------------- 735 // -----------------------------------
861 Label slow; 736 Label slow;
862 737
863 // Check that the receiver isn't a smi. 738 // Check that the receiver isn't a smi.
864 __ JumpIfSmi(rdx, &slow); 739 __ JumpIfSmi(rdx, &slow);
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
1016 __ ret(0); 891 __ ret(0);
1017 __ bind(&non_smi_value); 892 __ bind(&non_smi_value);
1018 // Slow case that needs to retain rcx for use by RecordWrite. 893 // Slow case that needs to retain rcx for use by RecordWrite.
1019 // Update write barrier for the elements array address. 894 // Update write barrier for the elements array address.
1020 __ movq(rdx, rax); 895 __ movq(rdx, rax);
1021 __ RecordWriteNonSmi(rbx, 0, rdx, rcx); 896 __ RecordWriteNonSmi(rbx, 0, rdx, rcx);
1022 __ ret(0); 897 __ ret(0);
1023 } 898 }
1024 899
1025 900
1026 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm,
1027 ExternalArrayType array_type) {
1028 // ----------- S t a t e -------------
1029 // -- rax : value
1030 // -- rcx : key
1031 // -- rdx : receiver
1032 // -- rsp[0] : return address
1033 // -----------------------------------
1034 Label slow;
1035
1036 // Check that the object isn't a smi.
1037 __ JumpIfSmi(rdx, &slow);
1038 // Get the map from the receiver.
1039 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
1040 // Check that the receiver does not require access checks. We need
1041 // to do this because this generic stub does not perform map checks.
1042 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
1043 Immediate(1 << Map::kIsAccessCheckNeeded));
1044 __ j(not_zero, &slow);
1045 // Check that the key is a smi.
1046 __ JumpIfNotSmi(rcx, &slow);
1047
1048 // Check that the object is a JS object.
1049 __ CmpInstanceType(rbx, JS_OBJECT_TYPE);
1050 __ j(not_equal, &slow);
1051
1052 // Check that the elements array is the appropriate type of
1053 // ExternalArray.
1054 // rax: value
1055 // rcx: key (a smi)
1056 // rdx: receiver (a JSObject)
1057 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
1058 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
1059 Heap::RootIndexForExternalArrayType(array_type));
1060 __ j(not_equal, &slow);
1061
1062 // Check that the index is in range.
1063 __ SmiToInteger32(rdi, rcx); // Untag the index.
1064 __ cmpl(rdi, FieldOperand(rbx, ExternalArray::kLengthOffset));
1065 // Unsigned comparison catches both negative and too-large values.
1066 __ j(above_equal, &slow);
1067
1068 // Handle both smis and HeapNumbers in the fast path. Go to the
1069 // runtime for all other kinds of values.
1070 // rax: value
1071 // rcx: key (a smi)
1072 // rdx: receiver (a JSObject)
1073 // rbx: elements array
1074 // rdi: untagged key
1075 NearLabel check_heap_number;
1076 __ JumpIfNotSmi(rax, &check_heap_number);
1077 // No more branches to slow case on this path. Key and receiver not needed.
1078 __ SmiToInteger32(rdx, rax);
1079 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
1080 // rbx: base pointer of external storage
1081 switch (array_type) {
1082 case kExternalByteArray:
1083 case kExternalUnsignedByteArray:
1084 __ movb(Operand(rbx, rdi, times_1, 0), rdx);
1085 break;
1086 case kExternalShortArray:
1087 case kExternalUnsignedShortArray:
1088 __ movw(Operand(rbx, rdi, times_2, 0), rdx);
1089 break;
1090 case kExternalIntArray:
1091 case kExternalUnsignedIntArray:
1092 __ movl(Operand(rbx, rdi, times_4, 0), rdx);
1093 break;
1094 case kExternalFloatArray:
1095 // Need to perform int-to-float conversion.
1096 __ cvtlsi2ss(xmm0, rdx);
1097 __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
1098 break;
1099 default:
1100 UNREACHABLE();
1101 break;
1102 }
1103 __ ret(0);
1104
1105 __ bind(&check_heap_number);
1106 // rax: value
1107 // rcx: key (a smi)
1108 // rdx: receiver (a JSObject)
1109 // rbx: elements array
1110 // rdi: untagged key
1111 __ CmpObjectType(rax, HEAP_NUMBER_TYPE, kScratchRegister);
1112 __ j(not_equal, &slow);
1113 // No more branches to slow case on this path.
1114
1115 // The WebGL specification leaves the behavior of storing NaN and
1116 // +/-Infinity into integer arrays basically undefined. For more
1117 // reproducible behavior, convert these to zero.
1118 __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
1119 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
1120 // rdi: untagged index
1121 // rbx: base pointer of external storage
1122 // top of FPU stack: value
1123 if (array_type == kExternalFloatArray) {
1124 __ cvtsd2ss(xmm0, xmm0);
1125 __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
1126 __ ret(0);
1127 } else {
1128 // Need to perform float-to-int conversion.
1129 // Test the value for NaN.
1130
1131 // Convert to int32 and store the low byte/word.
1132 // If the value is NaN or +/-infinity, the result is 0x80000000,
1133 // which is automatically zero when taken mod 2^n, n < 32.
1134 // rdx: value (converted to an untagged integer)
1135 // rdi: untagged index
1136 // rbx: base pointer of external storage
1137 switch (array_type) {
1138 case kExternalByteArray:
1139 case kExternalUnsignedByteArray:
1140 __ cvtsd2si(rdx, xmm0);
1141 __ movb(Operand(rbx, rdi, times_1, 0), rdx);
1142 break;
1143 case kExternalShortArray:
1144 case kExternalUnsignedShortArray:
1145 __ cvtsd2si(rdx, xmm0);
1146 __ movw(Operand(rbx, rdi, times_2, 0), rdx);
1147 break;
1148 case kExternalIntArray:
1149 case kExternalUnsignedIntArray: {
1150 // Convert to int64, so that NaN and infinities become
1151 // 0x8000000000000000, which is zero mod 2^32.
1152 __ cvtsd2siq(rdx, xmm0);
1153 __ movl(Operand(rbx, rdi, times_4, 0), rdx);
1154 break;
1155 }
1156 default:
1157 UNREACHABLE();
1158 break;
1159 }
1160 __ ret(0);
1161 }
1162
1163 // Slow case: call runtime.
1164 __ bind(&slow);
1165 GenerateRuntimeSetProperty(masm);
1166 }
1167
1168
1169 // The generated code does not accept smi keys. 901 // The generated code does not accept smi keys.
1170 // The generated code falls through if both probes miss. 902 // The generated code falls through if both probes miss.
1171 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, 903 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
1172 int argc, 904 int argc,
1173 Code::Kind kind) { 905 Code::Kind kind) {
1174 // ----------- S t a t e ------------- 906 // ----------- S t a t e -------------
1175 // rcx : function name 907 // rcx : function name
1176 // rdx : receiver 908 // rdx : receiver
1177 // ----------------------------------- 909 // -----------------------------------
1178 Label number, non_number, non_string, boolean, probe, miss; 910 Label number, non_number, non_string, boolean, probe, miss;
(...skipping 787 matching lines...) Expand 10 before | Expand all | Expand 10 after
1966 } 1698 }
1967 1699
1968 void PatchInlinedSmiCode(Address address) { 1700 void PatchInlinedSmiCode(Address address) {
1969 UNIMPLEMENTED(); 1701 UNIMPLEMENTED();
1970 } 1702 }
1971 1703
1972 1704
1973 } } // namespace v8::internal 1705 } } // namespace v8::internal
1974 1706
1975 #endif // V8_TARGET_ARCH_X64 1707 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/disasm-x64.cc ('k') | src/x64/stub-cache-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698