OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
154 void MacroAssembler::ClampUint8(Register reg) { | 154 void MacroAssembler::ClampUint8(Register reg) { |
155 Label done; | 155 Label done; |
156 test(reg, Immediate(0xFFFFFF00)); | 156 test(reg, Immediate(0xFFFFFF00)); |
157 j(zero, &done, Label::kNear); | 157 j(zero, &done, Label::kNear); |
158 setcc(negative, reg); // 1 if negative, 0 if positive. | 158 setcc(negative, reg); // 1 if negative, 0 if positive. |
159 dec_b(reg); // 0 if negative, 255 if positive. | 159 dec_b(reg); // 0 if negative, 255 if positive. |
160 bind(&done); | 160 bind(&done); |
161 } | 161 } |
162 | 162 |
163 | 163 |
164 void MacroAssembler::SlowTruncateToI(Register input_reg, Register result_reg, | |
165 int index) { | |
166 DoubleToIStub stub(input_reg, result_reg, index, true); | |
167 call(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); | |
168 } | |
169 | |
170 | |
171 void MacroAssembler::TruncateDoubleToI( | |
172 XMMRegister input_reg, Register result_reg) { | |
173 Label done; | |
174 cvttsd2si(result_reg, Operand(input_reg)); | |
175 cmp(result_reg, 0x80000000u); | |
176 j(not_equal, &done, Label::kNear); | |
177 | |
178 sub(esp, Immediate(kDoubleSize)); | |
179 movdbl(MemOperand(esp, 0), input_reg); | |
180 SlowTruncateToI(esp, result_reg, 0); | |
181 add(esp, Immediate(kDoubleSize)); | |
182 bind(&done); | |
183 } | |
184 | |
185 | |
186 void MacroAssembler::DoubleToI(XMMRegister input_reg, Register result_reg, | |
187 XMMRegister scratch, bool bailout_on_minus_zero, | |
188 Label* conversion_failed, Label::Distance dst) { | |
189 Label done; | |
190 cvttsd2si(result_reg, Operand(input_reg)); | |
191 cvtsi2sd(scratch, Operand(result_reg)); | |
192 ucomisd(scratch, input_reg); | |
193 j(not_equal, conversion_failed, dst); | |
194 j(parity_even, conversion_failed, dst); // NaN. | |
195 if (bailout_on_minus_zero) { | |
196 test(result_reg, Operand(result_reg)); | |
197 j(not_zero, &done, Label::kNear); | |
198 movmskpd(result_reg, input_reg); | |
199 and_(result_reg, 1); | |
200 j(not_zero, conversion_failed, dst); | |
201 } | |
202 bind(&done); | |
203 } | |
204 | |
205 | |
206 void MacroAssembler::TruncateHeapNumberToI(Register input_reg, | |
207 Register result_reg) { | |
208 Label done, slow_case; | |
209 | |
210 if (CpuFeatures::IsSupported(SSE3)) { | |
211 CpuFeatureScope scope(this, SSE3); | |
212 Label convert; | |
213 // Use more powerful conversion when sse3 is available. | |
214 // Load x87 register with heap number. | |
215 fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | |
216 // Get exponent alone and check for too-big exponent. | |
217 mov(result_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | |
218 and_(result_reg, HeapNumber::kExponentMask); | |
219 const uint32_t kTooBigExponent = | |
220 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; | |
221 cmp(Operand(result_reg), Immediate(kTooBigExponent)); | |
222 j(greater_equal, &slow_case, Label::kNear); | |
223 | |
224 // Reserve space for 64 bit answer. | |
225 sub(Operand(esp), Immediate(kDoubleSize)); | |
226 // Do conversion, which cannot fail because we checked the exponent. | |
227 fisttp_d(Operand(esp, 0)); | |
228 mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. | |
229 add(Operand(esp), Immediate(kDoubleSize)); | |
230 jmp(&done, Label::kNear); | |
231 | |
232 // Slow case. | |
233 bind(&slow_case); | |
234 if (input_reg.is(result_reg)) { | |
235 // Input is clobbered. Restore number from fpu stack | |
236 sub(Operand(esp), Immediate(kDoubleSize)); | |
237 fstp_d(Operand(esp, 0)); | |
238 SlowTruncateToI(esp, result_reg, 0); | |
239 add(esp, Immediate(kDoubleSize)); | |
240 } else { | |
241 fstp(0); | |
242 SlowTruncateToI(input_reg, result_reg); | |
243 } | |
244 } else if (CpuFeatures::IsSupported(SSE2)) { | |
245 CpuFeatureScope scope(this, SSE2); | |
246 movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | |
247 cvttsd2si(result_reg, Operand(xmm0)); | |
248 cmp(result_reg, 0x80000000u); | |
249 j(not_equal, &done, Label::kNear); | |
250 // Check if the input was 0x8000000 (kMinInt). | |
251 // If no, then we got an overflow and we deoptimize. | |
252 ExternalReference min_int = ExternalReference::address_of_min_int(); | |
253 ucomisd(xmm0, Operand::StaticVariable(min_int)); | |
254 j(not_equal, &slow_case, Label::kNear); | |
255 j(parity_even, &slow_case, Label::kNear); // NaN. | |
256 jmp(&done, Label::kNear); | |
257 | |
258 // Slow case. | |
259 bind(&slow_case); | |
260 if (input_reg.is(result_reg)) { | |
261 // Input is clobbered. Restore number from double scratch. | |
262 sub(esp, Immediate(kDoubleSize)); | |
263 movdbl(MemOperand(esp, 0), xmm0); | |
264 SlowTruncateToI(esp, result_reg, 0); | |
265 add(esp, Immediate(kDoubleSize)); | |
266 } else { | |
267 SlowTruncateToI(input_reg, result_reg); | |
268 } | |
269 } else { | |
270 ASSERT(Serializer::enabled()); | |
271 // TODO(olivf) If we ever hit this assert, it means that a DoubleToIStub is | |
272 // used in a snapshoted stub. In that case we should probably add a fast | |
273 // case here, which e.g. covers exponents < 31. | |
274 SlowTruncateToI(input_reg, result_reg); | |
275 } | |
276 bind(&done); | |
277 } | |
278 | |
279 | |
280 void MacroAssembler::TaggedToI(Register input_reg, Register result_reg, | |
281 XMMRegister temp, bool bailout_on_minus_zero, Label* bailout) { | |
danno
2013/08/13 13:04:20
perhaps a better name than bailout? lost_precision
| |
282 Label done; | |
283 | |
284 cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | |
285 isolate()->factory()->heap_number_map()); | |
286 j(not_equal, bailout, Label::kNear); | |
287 | |
288 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { | |
289 ASSERT(!temp.is(no_xmm_reg)); | |
290 CpuFeatureScope scope(this, SSE2); | |
291 | |
292 movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | |
293 cvttsd2si(result_reg, Operand(xmm0)); | |
294 cvtsi2sd(temp, Operand(result_reg)); | |
295 ucomisd(xmm0, temp); | |
296 RecordComment("Deferred TaggedToI: lost precision"); | |
297 j(not_equal, bailout, Label::kNear); | |
298 RecordComment("Deferred TaggedToI: NaN"); | |
299 j(parity_even, bailout, Label::kNear); | |
300 if (bailout_on_minus_zero) { | |
301 test(result_reg, Operand(result_reg)); | |
302 j(not_zero, &done, Label::kNear); | |
303 movmskpd(result_reg, xmm0); | |
304 and_(result_reg, 1); | |
305 RecordComment("Deferred TaggedToI: minus zero"); | |
306 j(not_zero, bailout, Label::kNear); | |
307 } | |
308 } else { | |
309 // TODO(olivf) Converting a number on the fpu is actually quite slow. We | |
310 // should first try a fast conversion and then bailout to this slow case. | |
311 Label bailout_pop, zero_check; | |
312 sub(esp, Immediate(kPointerSize)); | |
313 fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | |
314 if (bailout_on_minus_zero) fld(0); | |
315 fild_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | |
316 fist_s(MemOperand(esp, 0)); | |
317 FCmp(); | |
318 pop(result_reg); | |
319 j(not_equal, bailout_on_minus_zero ? &bailout_pop : bailout, | |
320 Label::kNear); | |
321 j(parity_even, bailout_on_minus_zero ? &bailout_pop : bailout, | |
322 Label::kNear); // NaN. | |
323 if (bailout_on_minus_zero) { | |
324 test(result_reg, Operand(result_reg)); | |
325 j(zero, &zero_check, Label::kNear); | |
326 fstp(0); | |
327 jmp(&done, Label::kNear); | |
328 bind(&zero_check); | |
329 // To check for minus zero, we load the value again as float, and check | |
330 // if that is still 0. | |
331 sub(esp, Immediate(kPointerSize)); | |
332 fstp_s(Operand(esp, 0)); | |
333 pop(result_reg); | |
334 test(result_reg, Operand(result_reg)); | |
335 j(zero, &done, Label::kNear); | |
336 jmp(bailout, Label::kNear); | |
337 | |
338 bind(&bailout_pop); | |
339 fstp(0); | |
340 jmp(bailout, Label::kNear); | |
341 } | |
342 } | |
343 bind(&done); | |
344 } | |
345 | |
346 | |
347 | |
164 static double kUint32Bias = | 348 static double kUint32Bias = |
165 static_cast<double>(static_cast<uint32_t>(0xFFFFFFFF)) + 1; | 349 static_cast<double>(static_cast<uint32_t>(0xFFFFFFFF)) + 1; |
166 | 350 |
167 | 351 |
168 void MacroAssembler::LoadUint32(XMMRegister dst, | 352 void MacroAssembler::LoadUint32(XMMRegister dst, |
169 Register src, | 353 Register src, |
170 XMMRegister scratch) { | 354 XMMRegister scratch) { |
171 Label done; | 355 Label done; |
172 cmp(src, Immediate(0)); | 356 cmp(src, Immediate(0)); |
173 movdbl(scratch, | 357 movdbl(scratch, |
(...skipping 3013 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3187 j(greater, &no_memento_available); | 3371 j(greater, &no_memento_available); |
3188 cmp(MemOperand(scratch_reg, -AllocationMemento::kSize), | 3372 cmp(MemOperand(scratch_reg, -AllocationMemento::kSize), |
3189 Immediate(Handle<Map>(isolate()->heap()->allocation_memento_map()))); | 3373 Immediate(Handle<Map>(isolate()->heap()->allocation_memento_map()))); |
3190 bind(&no_memento_available); | 3374 bind(&no_memento_available); |
3191 } | 3375 } |
3192 | 3376 |
3193 | 3377 |
3194 } } // namespace v8::internal | 3378 } } // namespace v8::internal |
3195 | 3379 |
3196 #endif // V8_TARGET_ARCH_IA32 | 3380 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |