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

Side by Side Diff: src/ia32/ic-ia32.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/heap.h ('k') | src/ia32/stub-cache-ia32.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 700 matching lines...) Expand 10 before | Expand all | Expand 10 after
711 __ ret(0); 711 __ ret(0);
712 712
713 StubRuntimeCallHelper call_helper; 713 StubRuntimeCallHelper call_helper;
714 char_at_generator.GenerateSlow(masm, call_helper); 714 char_at_generator.GenerateSlow(masm, call_helper);
715 715
716 __ bind(&miss); 716 __ bind(&miss);
717 GenerateMiss(masm); 717 GenerateMiss(masm);
718 } 718 }
719 719
720 720
721 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm,
722 ExternalArrayType array_type) {
723 // ----------- S t a t e -------------
724 // -- eax : key
725 // -- edx : receiver
726 // -- esp[0] : return address
727 // -----------------------------------
728 Label slow, failed_allocation;
729
730 // Check that the object isn't a smi.
731 __ test(edx, Immediate(kSmiTagMask));
732 __ j(zero, &slow, not_taken);
733
734 // Check that the key is a smi.
735 __ test(eax, Immediate(kSmiTagMask));
736 __ j(not_zero, &slow, not_taken);
737
738 // Get the map of the receiver.
739 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
740 // Check that the receiver does not require access checks. We need
741 // to check this explicitly since this generic stub does not perform
742 // map checks.
743 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset),
744 1 << Map::kIsAccessCheckNeeded);
745 __ j(not_zero, &slow, not_taken);
746
747 __ CmpInstanceType(ecx, JS_OBJECT_TYPE);
748 __ j(not_equal, &slow, not_taken);
749
750 // Check that the elements array is the appropriate type of
751 // ExternalArray.
752 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
753 Handle<Map> map(Heap::MapForExternalArrayType(array_type));
754 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
755 Immediate(map));
756 __ j(not_equal, &slow, not_taken);
757
758 // eax: key, known to be a smi.
759 // edx: receiver, known to be a JSObject.
760 // ebx: elements object, known to be an external array.
761 // Check that the index is in range.
762 __ mov(ecx, eax);
763 __ SmiUntag(ecx); // Untag the index.
764 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset));
765 // Unsigned comparison catches both negative and too-large values.
766 __ j(above_equal, &slow);
767
768 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset));
769 // ebx: base pointer of external storage
770 switch (array_type) {
771 case kExternalByteArray:
772 __ movsx_b(ecx, Operand(ebx, ecx, times_1, 0));
773 break;
774 case kExternalUnsignedByteArray:
775 __ movzx_b(ecx, Operand(ebx, ecx, times_1, 0));
776 break;
777 case kExternalShortArray:
778 __ movsx_w(ecx, Operand(ebx, ecx, times_2, 0));
779 break;
780 case kExternalUnsignedShortArray:
781 __ movzx_w(ecx, Operand(ebx, ecx, times_2, 0));
782 break;
783 case kExternalIntArray:
784 case kExternalUnsignedIntArray:
785 __ mov(ecx, Operand(ebx, ecx, times_4, 0));
786 break;
787 case kExternalFloatArray:
788 __ fld_s(Operand(ebx, ecx, times_4, 0));
789 break;
790 default:
791 UNREACHABLE();
792 break;
793 }
794
795 // For integer array types:
796 // ecx: value
797 // For floating-point array type:
798 // FP(0): value
799
800 if (array_type == kExternalIntArray ||
801 array_type == kExternalUnsignedIntArray) {
802 // For the Int and UnsignedInt array types, we need to see whether
803 // the value can be represented in a Smi. If not, we need to convert
804 // it to a HeapNumber.
805 Label box_int;
806 if (array_type == kExternalIntArray) {
807 __ cmp(ecx, 0xC0000000);
808 __ j(sign, &box_int);
809 } else {
810 ASSERT_EQ(array_type, kExternalUnsignedIntArray);
811 // The test is different for unsigned int values. Since we need
812 // the value to be in the range of a positive smi, we can't
813 // handle either of the top two bits being set in the value.
814 __ test(ecx, Immediate(0xC0000000));
815 __ j(not_zero, &box_int);
816 }
817
818 __ mov(eax, ecx);
819 __ SmiTag(eax);
820 __ ret(0);
821
822 __ bind(&box_int);
823
824 // Allocate a HeapNumber for the int and perform int-to-double
825 // conversion.
826 if (array_type == kExternalIntArray) {
827 __ push(ecx);
828 __ fild_s(Operand(esp, 0));
829 __ pop(ecx);
830 } else {
831 ASSERT(array_type == kExternalUnsignedIntArray);
832 // Need to zero-extend the value.
833 // There's no fild variant for unsigned values, so zero-extend
834 // to a 64-bit int manually.
835 __ push(Immediate(0));
836 __ push(ecx);
837 __ fild_d(Operand(esp, 0));
838 __ pop(ecx);
839 __ pop(ecx);
840 }
841 // FP(0): value
842 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
843 // Set the value.
844 __ mov(eax, ecx);
845 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
846 __ ret(0);
847 } else if (array_type == kExternalFloatArray) {
848 // For the floating-point array type, we need to always allocate a
849 // HeapNumber.
850 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
851 // Set the value.
852 __ mov(eax, ecx);
853 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
854 __ ret(0);
855 } else {
856 __ mov(eax, ecx);
857 __ SmiTag(eax);
858 __ ret(0);
859 }
860
861 // If we fail allocation of the HeapNumber, we still have a value on
862 // top of the FPU stack. Remove it.
863 __ bind(&failed_allocation);
864 __ ffree();
865 __ fincstp();
866 // Fall through to slow case.
867
868 // Slow case: Jump to runtime.
869 __ bind(&slow);
870 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1);
871 GenerateRuntimeGetProperty(masm);
872 }
873
874
875 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { 721 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
876 // ----------- S t a t e ------------- 722 // ----------- S t a t e -------------
877 // -- eax : key 723 // -- eax : key
878 // -- edx : receiver 724 // -- edx : receiver
879 // -- esp[0] : return address 725 // -- esp[0] : return address
880 // ----------------------------------- 726 // -----------------------------------
881 Label slow; 727 Label slow;
882 728
883 // Check that the receiver isn't a smi. 729 // Check that the receiver isn't a smi.
884 __ test(edx, Immediate(kSmiTagMask)); 730 __ test(edx, Immediate(kSmiTagMask));
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
1024 // edx: receiver 870 // edx: receiver
1025 // edi: FixedArray receiver->elements 871 // edi: FixedArray receiver->elements
1026 __ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax); 872 __ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax);
1027 // Update write barrier for the elements array address. 873 // Update write barrier for the elements array address.
1028 __ mov(edx, Operand(eax)); 874 __ mov(edx, Operand(eax));
1029 __ RecordWrite(edi, 0, edx, ecx); 875 __ RecordWrite(edi, 0, edx, ecx);
1030 __ ret(0); 876 __ ret(0);
1031 } 877 }
1032 878
1033 879
1034 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm,
1035 ExternalArrayType array_type) {
1036 // ----------- S t a t e -------------
1037 // -- eax : value
1038 // -- ecx : key
1039 // -- edx : receiver
1040 // -- esp[0] : return address
1041 // -----------------------------------
1042 Label slow, check_heap_number;
1043
1044 // Check that the object isn't a smi.
1045 __ test(edx, Immediate(kSmiTagMask));
1046 __ j(zero, &slow);
1047 // Get the map from the receiver.
1048 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
1049 // Check that the receiver does not require access checks. We need
1050 // to do this because this generic stub does not perform map checks.
1051 __ test_b(FieldOperand(edi, Map::kBitFieldOffset),
1052 1 << Map::kIsAccessCheckNeeded);
1053 __ j(not_zero, &slow);
1054 // Check that the key is a smi.
1055 __ test(ecx, Immediate(kSmiTagMask));
1056 __ j(not_zero, &slow);
1057 // Get the instance type from the map of the receiver.
1058 __ CmpInstanceType(edi, JS_OBJECT_TYPE);
1059 __ j(not_equal, &slow);
1060
1061 // Check that the elements array is the appropriate type of
1062 // ExternalArray.
1063 // eax: value
1064 // edx: receiver, a JSObject
1065 // ecx: key, a smi
1066 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
1067 __ CheckMap(edi, Handle<Map>(Heap::MapForExternalArrayType(array_type)),
1068 &slow, true);
1069
1070 // Check that the index is in range.
1071 __ mov(ebx, ecx);
1072 __ SmiUntag(ebx);
1073 __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset));
1074 // Unsigned comparison catches both negative and too-large values.
1075 __ j(above_equal, &slow);
1076
1077 // Handle both smis and HeapNumbers in the fast path. Go to the
1078 // runtime for all other kinds of values.
1079 // eax: value
1080 // edx: receiver
1081 // ecx: key
1082 // edi: elements array
1083 // ebx: untagged index
1084 __ test(eax, Immediate(kSmiTagMask));
1085 __ j(not_equal, &check_heap_number);
1086 // smi case
1087 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed.
1088 __ SmiUntag(ecx);
1089 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
1090 // ecx: base pointer of external storage
1091 switch (array_type) {
1092 case kExternalByteArray:
1093 case kExternalUnsignedByteArray:
1094 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
1095 break;
1096 case kExternalShortArray:
1097 case kExternalUnsignedShortArray:
1098 __ mov_w(Operand(edi, ebx, times_2, 0), ecx);
1099 break;
1100 case kExternalIntArray:
1101 case kExternalUnsignedIntArray:
1102 __ mov(Operand(edi, ebx, times_4, 0), ecx);
1103 break;
1104 case kExternalFloatArray:
1105 // Need to perform int-to-float conversion.
1106 __ push(ecx);
1107 __ fild_s(Operand(esp, 0));
1108 __ pop(ecx);
1109 __ fstp_s(Operand(edi, ebx, times_4, 0));
1110 break;
1111 default:
1112 UNREACHABLE();
1113 break;
1114 }
1115 __ ret(0); // Return the original value.
1116
1117 __ bind(&check_heap_number);
1118 // eax: value
1119 // edx: receiver
1120 // ecx: key
1121 // edi: elements array
1122 // ebx: untagged index
1123 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
1124 Immediate(Factory::heap_number_map()));
1125 __ j(not_equal, &slow);
1126
1127 // The WebGL specification leaves the behavior of storing NaN and
1128 // +/-Infinity into integer arrays basically undefined. For more
1129 // reproducible behavior, convert these to zero.
1130 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
1131 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
1132 // ebx: untagged index
1133 // edi: base pointer of external storage
1134 // top of FPU stack: value
1135 if (array_type == kExternalFloatArray) {
1136 __ fstp_s(Operand(edi, ebx, times_4, 0));
1137 __ ret(0);
1138 } else {
1139 // Need to perform float-to-int conversion.
1140 // Test the top of the FP stack for NaN.
1141 Label is_nan;
1142 __ fucomi(0);
1143 __ j(parity_even, &is_nan);
1144
1145 if (array_type != kExternalUnsignedIntArray) {
1146 __ push(ecx); // Make room on stack
1147 __ fistp_s(Operand(esp, 0));
1148 __ pop(ecx);
1149 } else {
1150 // fistp stores values as signed integers.
1151 // To represent the entire range, we need to store as a 64-bit
1152 // int and discard the high 32 bits.
1153 __ sub(Operand(esp), Immediate(2 * kPointerSize));
1154 __ fistp_d(Operand(esp, 0));
1155 __ pop(ecx);
1156 __ add(Operand(esp), Immediate(kPointerSize));
1157 }
1158 // ecx: untagged integer value
1159 switch (array_type) {
1160 case kExternalByteArray:
1161 case kExternalUnsignedByteArray:
1162 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
1163 break;
1164 case kExternalShortArray:
1165 case kExternalUnsignedShortArray:
1166 __ mov_w(Operand(edi, ebx, times_2, 0), ecx);
1167 break;
1168 case kExternalIntArray:
1169 case kExternalUnsignedIntArray: {
1170 // We also need to explicitly check for +/-Infinity. These are
1171 // converted to MIN_INT, but we need to be careful not to
1172 // confuse with legal uses of MIN_INT.
1173 Label not_infinity;
1174 // This test would apparently detect both NaN and Infinity,
1175 // but we've already checked for NaN using the FPU hardware
1176 // above.
1177 __ mov_w(edx, FieldOperand(eax, HeapNumber::kValueOffset + 6));
1178 __ and_(edx, 0x7FF0);
1179 __ cmp(edx, 0x7FF0);
1180 __ j(not_equal, &not_infinity);
1181 __ mov(ecx, 0);
1182 __ bind(&not_infinity);
1183 __ mov(Operand(edi, ebx, times_4, 0), ecx);
1184 break;
1185 }
1186 default:
1187 UNREACHABLE();
1188 break;
1189 }
1190 __ ret(0); // Return original value.
1191
1192 __ bind(&is_nan);
1193 __ ffree();
1194 __ fincstp();
1195 switch (array_type) {
1196 case kExternalByteArray:
1197 case kExternalUnsignedByteArray:
1198 __ mov_b(Operand(edi, ebx, times_1, 0), 0);
1199 break;
1200 case kExternalShortArray:
1201 case kExternalUnsignedShortArray:
1202 __ Set(ecx, Immediate(0));
1203 __ mov_w(Operand(edi, ebx, times_2, 0), ecx);
1204 break;
1205 case kExternalIntArray:
1206 case kExternalUnsignedIntArray:
1207 __ mov(Operand(edi, ebx, times_4, 0), Immediate(0));
1208 break;
1209 default:
1210 UNREACHABLE();
1211 break;
1212 }
1213 __ ret(0); // Return the original value.
1214 }
1215
1216 // Slow case: call runtime.
1217 __ bind(&slow);
1218 GenerateRuntimeSetProperty(masm);
1219 }
1220
1221
1222 // The generated code does not accept smi keys. 880 // The generated code does not accept smi keys.
1223 // The generated code falls through if both probes miss. 881 // The generated code falls through if both probes miss.
1224 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, 882 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
1225 int argc, 883 int argc,
1226 Code::Kind kind) { 884 Code::Kind kind) {
1227 // ----------- S t a t e ------------- 885 // ----------- S t a t e -------------
1228 // -- ecx : name 886 // -- ecx : name
1229 // -- edx : receiver 887 // -- edx : receiver
1230 // ----------------------------------- 888 // -----------------------------------
1231 Label number, non_number, non_string, boolean, probe, miss; 889 Label number, non_number, non_string, boolean, probe, miss;
(...skipping 875 matching lines...) Expand 10 before | Expand all | Expand 10 after
2107 Condition cc = *jmp_address == Assembler::kJncShortOpcode 1765 Condition cc = *jmp_address == Assembler::kJncShortOpcode
2108 ? not_zero 1766 ? not_zero
2109 : zero; 1767 : zero;
2110 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); 1768 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
2111 } 1769 }
2112 1770
2113 1771
2114 } } // namespace v8::internal 1772 } } // namespace v8::internal
2115 1773
2116 #endif // V8_TARGET_ARCH_IA32 1774 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/heap.h ('k') | src/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698