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 773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
784 | 784 |
785 __ JumpIfUIntNotValidSmiValue(rcx, &box_int); | 785 __ JumpIfUIntNotValidSmiValue(rcx, &box_int); |
786 | 786 |
787 __ Integer32ToSmi(rax, rcx); | 787 __ Integer32ToSmi(rax, rcx); |
788 __ ret(0); | 788 __ ret(0); |
789 | 789 |
790 __ bind(&box_int); | 790 __ bind(&box_int); |
791 | 791 |
792 // Allocate a HeapNumber for the int and perform int-to-double | 792 // Allocate a HeapNumber for the int and perform int-to-double |
793 // conversion. | 793 // conversion. |
794 ASSERT(array_type == kExternalUnsignedIntArray); | |
795 // The value is zero-extended since we loaded the value from memory | 794 // The value is zero-extended since we loaded the value from memory |
796 // with movl. | 795 // with movl. |
797 __ cvtqsi2sd(xmm0, rcx); | 796 __ cvtqsi2sd(xmm0, rcx); |
798 | 797 |
799 __ AllocateHeapNumber(rcx, rbx, &slow); | 798 __ AllocateHeapNumber(rcx, rbx, &slow); |
800 // Set the value. | 799 // Set the value. |
801 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); | 800 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); |
802 __ movq(rax, rcx); | 801 __ movq(rax, rcx); |
803 __ ret(0); | 802 __ ret(0); |
804 } else if (array_type == kExternalFloatArray) { | 803 } else if (array_type == kExternalFloatArray) { |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1114 // rdx: receiver (a JSObject) | 1113 // rdx: receiver (a JSObject) |
1115 // rbx: elements array | 1114 // rbx: elements array |
1116 // rdi: untagged key | 1115 // rdi: untagged key |
1117 __ CmpObjectType(rax, HEAP_NUMBER_TYPE, kScratchRegister); | 1116 __ CmpObjectType(rax, HEAP_NUMBER_TYPE, kScratchRegister); |
1118 __ j(not_equal, &slow); | 1117 __ j(not_equal, &slow); |
1119 // No more branches to slow case on this path. | 1118 // No more branches to slow case on this path. |
1120 | 1119 |
1121 // The WebGL specification leaves the behavior of storing NaN and | 1120 // The WebGL specification leaves the behavior of storing NaN and |
1122 // +/-Infinity into integer arrays basically undefined. For more | 1121 // +/-Infinity into integer arrays basically undefined. For more |
1123 // reproducible behavior, convert these to zero. | 1122 // reproducible behavior, convert these to zero. |
1124 __ fld_d(FieldOperand(rax, HeapNumber::kValueOffset)); | 1123 __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); |
1125 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); | 1124 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); |
1126 // rdi: untagged index | 1125 // rdi: untagged index |
1127 // rbx: base pointer of external storage | 1126 // rbx: base pointer of external storage |
1128 // top of FPU stack: value | 1127 // top of FPU stack: value |
1129 if (array_type == kExternalFloatArray) { | 1128 if (array_type == kExternalFloatArray) { |
1130 __ fstp_s(Operand(rbx, rdi, times_4, 0)); | 1129 __ cvtsd2ss(xmm0, xmm0); |
| 1130 __ movss(Operand(rbx, rdi, times_4, 0), xmm0); |
1131 __ ret(0); | 1131 __ ret(0); |
1132 } else { | 1132 } else { |
1133 // Need to perform float-to-int conversion. | 1133 // Need to perform float-to-int conversion. |
1134 // Test the top of the FP stack for NaN. | 1134 // Test the value for NaN. |
1135 Label is_nan; | |
1136 __ fucomi(0); | |
1137 __ j(parity_even, &is_nan); | |
1138 | 1135 |
1139 __ push(rdx); // Make room on the stack. Receiver is no longer needed. | 1136 // Convert to int32 and store the low byte/word. |
1140 // TODO(lrn): If the rounding of this conversion is not deliberate, maybe | 1137 // If the value is NaN or +/-infinity, the result is 0x80000000, |
1141 // switch to xmm registers. | 1138 // which is automatically zero when taken mod 2^n, n < 32. |
1142 __ fistp_d(Operand(rsp, 0)); | |
1143 __ pop(rdx); | |
1144 // rdx: value (converted to an untagged integer) | 1139 // rdx: value (converted to an untagged integer) |
1145 // rdi: untagged index | 1140 // rdi: untagged index |
1146 // rbx: base pointer of external storage | 1141 // rbx: base pointer of external storage |
1147 switch (array_type) { | 1142 switch (array_type) { |
1148 case kExternalByteArray: | 1143 case kExternalByteArray: |
1149 case kExternalUnsignedByteArray: | 1144 case kExternalUnsignedByteArray: |
| 1145 __ cvtsd2si(rdx, xmm0); |
1150 __ movb(Operand(rbx, rdi, times_1, 0), rdx); | 1146 __ movb(Operand(rbx, rdi, times_1, 0), rdx); |
1151 break; | 1147 break; |
1152 case kExternalShortArray: | 1148 case kExternalShortArray: |
1153 case kExternalUnsignedShortArray: | 1149 case kExternalUnsignedShortArray: |
| 1150 __ cvtsd2si(rdx, xmm0); |
1154 __ movw(Operand(rbx, rdi, times_2, 0), rdx); | 1151 __ movw(Operand(rbx, rdi, times_2, 0), rdx); |
1155 break; | 1152 break; |
1156 case kExternalIntArray: | 1153 case kExternalIntArray: |
1157 case kExternalUnsignedIntArray: { | 1154 case kExternalUnsignedIntArray: { |
1158 // We also need to explicitly check for +/-Infinity. These are | 1155 // Convert to int64, so that NaN and infinities become |
1159 // converted to MIN_INT, but we need to be careful not to | 1156 // 0x8000000000000000, which is zero mod 2^32. |
1160 // confuse with legal uses of MIN_INT. Since MIN_INT truncated | 1157 __ cvtsd2siq(rdx, xmm0); |
1161 // to 8 or 16 bits is zero, we only perform this test when storing | |
1162 // 32-bit ints. | |
1163 Label not_infinity; | |
1164 // This test would apparently detect both NaN and Infinity, | |
1165 // but we've already checked for NaN using the FPU hardware | |
1166 // above. | |
1167 __ movzxwq(rcx, FieldOperand(rax, HeapNumber::kValueOffset + 6)); | |
1168 __ and_(rcx, Immediate(0x7FF0)); | |
1169 __ cmpw(rcx, Immediate(0x7FF0)); | |
1170 __ j(not_equal, ¬_infinity); | |
1171 __ movq(rdx, Immediate(0)); | |
1172 __ bind(¬_infinity); | |
1173 __ movl(Operand(rbx, rdi, times_4, 0), rdx); | 1158 __ movl(Operand(rbx, rdi, times_4, 0), rdx); |
1174 break; | 1159 break; |
1175 } | 1160 } |
1176 default: | 1161 default: |
1177 UNREACHABLE(); | 1162 UNREACHABLE(); |
1178 break; | 1163 break; |
1179 } | 1164 } |
1180 __ ret(0); | 1165 __ ret(0); |
1181 | |
1182 __ bind(&is_nan); | |
1183 // rdi: untagged index | |
1184 // rbx: base pointer of external storage | |
1185 __ ffree(); | |
1186 __ fincstp(); | |
1187 __ Set(rdx, 0); | |
1188 switch (array_type) { | |
1189 case kExternalByteArray: | |
1190 case kExternalUnsignedByteArray: | |
1191 __ movb(Operand(rbx, rdi, times_1, 0), rdx); | |
1192 break; | |
1193 case kExternalShortArray: | |
1194 case kExternalUnsignedShortArray: | |
1195 __ movw(Operand(rbx, rdi, times_2, 0), rdx); | |
1196 break; | |
1197 case kExternalIntArray: | |
1198 case kExternalUnsignedIntArray: | |
1199 __ movl(Operand(rbx, rdi, times_4, 0), rdx); | |
1200 break; | |
1201 default: | |
1202 UNREACHABLE(); | |
1203 break; | |
1204 } | |
1205 __ ret(0); | |
1206 } | 1166 } |
1207 | 1167 |
1208 // Slow case: call runtime. | 1168 // Slow case: call runtime. |
1209 __ bind(&slow); | 1169 __ bind(&slow); |
1210 GenerateRuntimeSetProperty(masm); | 1170 GenerateRuntimeSetProperty(masm); |
1211 } | 1171 } |
1212 | 1172 |
1213 | 1173 |
1214 // Defined in ic.cc. | 1174 // Defined in ic.cc. |
1215 Object* CallIC_Miss(Arguments args); | 1175 Object* CallIC_Miss(Arguments args); |
(...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1799 GenerateMiss(masm); | 1759 GenerateMiss(masm); |
1800 } | 1760 } |
1801 | 1761 |
1802 | 1762 |
1803 #undef __ | 1763 #undef __ |
1804 | 1764 |
1805 | 1765 |
1806 } } // namespace v8::internal | 1766 } } // namespace v8::internal |
1807 | 1767 |
1808 #endif // V8_TARGET_ARCH_X64 | 1768 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |