Index: src/x87/lithium-codegen-x87.cc |
diff --git a/src/x87/lithium-codegen-x87.cc b/src/x87/lithium-codegen-x87.cc |
index 0bd32fe1b1c67aa8a05daeee6777a3bdc3253ddc..30e1c03c4011529a0b03d9622f5c5c6530519e5a 100644 |
--- a/src/x87/lithium-codegen-x87.cc |
+++ b/src/x87/lithium-codegen-x87.cc |
@@ -4730,12 +4730,61 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) { |
DeoptimizeIf(not_equal, instr->environment()); |
__ Move(input_reg, Immediate(0)); |
} else { |
- Label bailout; |
- __ TaggedToI(input_reg, input_reg, |
- instr->hydrogen()->GetMinusZeroMode(), &bailout); |
- __ jmp(done); |
- __ bind(&bailout); |
- DeoptimizeIf(no_condition, instr->environment()); |
+ // TODO(olivf) Converting a number on the fpu is actually quite slow. We |
+ // should first try a fast conversion and then bailout to this slow case. |
+ __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
+ isolate()->factory()->heap_number_map()); |
+ __ RecordComment("Deferred TaggedToI: not a heap number"); |
+ DeoptimizeIf(not_equal, instr->environment()); |
+ |
+ __ sub(esp, Immediate(kPointerSize)); |
+ __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); |
+ |
+ if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) { |
+ Label no_precision_lost, not_nan, zero_check; |
+ __ fld(0); |
+ |
+ __ fist_s(MemOperand(esp, 0)); |
+ __ fild_s(MemOperand(esp, 0)); |
+ __ FCmp(); |
+ __ pop(input_reg); |
+ |
+ __ j(equal, &no_precision_lost, Label::kNear); |
+ __ fstp(0); |
+ __ RecordComment("Deferred TaggedToI: lost precision"); |
+ DeoptimizeIf(no_condition, instr->environment()); |
+ __ bind(&no_precision_lost); |
+ |
+ __ j(parity_odd, ¬_nan); |
+ __ fstp(0); |
+ __ RecordComment("Deferred TaggedToI: NaN"); |
+ DeoptimizeIf(no_condition, instr->environment()); |
+ __ bind(¬_nan); |
+ |
+ __ test(input_reg, Operand(input_reg)); |
+ __ j(zero, &zero_check, Label::kNear); |
+ __ fstp(0); |
+ __ jmp(done); |
+ |
+ __ bind(&zero_check); |
+ // To check for minus zero, we load the value again as float, and check |
+ // if that is still 0. |
+ __ sub(esp, Immediate(kPointerSize)); |
+ __ fstp_s(Operand(esp, 0)); |
+ __ pop(input_reg); |
+ __ test(input_reg, Operand(input_reg)); |
+ __ RecordComment("Deferred TaggedToI: minus zero"); |
+ DeoptimizeIf(not_zero, instr->environment()); |
+ } else { |
+ __ fist_s(MemOperand(esp, 0)); |
+ __ fild_s(MemOperand(esp, 0)); |
+ __ FCmp(); |
+ __ pop(input_reg); |
+ __ RecordComment("Deferred TaggedToI: lost precision"); |
+ DeoptimizeIf(not_equal, instr->environment()); |
+ __ RecordComment("Deferred TaggedToI: NaN"); |
+ DeoptimizeIf(parity_even, instr->environment()); |
+ } |
} |
} |