Chromium Code Reviews| Index: src/x64/lithium-codegen-x64.cc |
| diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc |
| index 202e7a24fcd239a7fe47aacf26ac24f9fce5b33a..9e7e228dadb9138f393f7319128329d8391dffad 100644 |
| --- a/src/x64/lithium-codegen-x64.cc |
| +++ b/src/x64/lithium-codegen-x64.cc |
| @@ -2721,33 +2721,44 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
| Register output_reg = ToRegister(instr->result()); |
| XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
| + Label done; |
| // xmm_scratch = 0.5 |
| __ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE); |
| __ movq(xmm_scratch, kScratchRegister); |
| - |
| + NearLabel below_half; |
| + __ ucomisd(xmm_scratch, input_reg); |
| + __ j(above, &below_half); // If input_reg is NaN, this doesn't jump. |
| // input = input + 0.5 |
| + // This addition might give a result that isn't the correct for |
| + // rounding, due to loss of precission, but only for a number that's |
|
William Hesse
2011/04/13 09:12:45
precision
Lasse Reichstein
2011/04/13 09:35:23
Fixed, thanks.
|
| + // so big that the conversion below will overflow anyway. |
| __ addsd(input_reg, xmm_scratch); |
| + // Compute Math.floor(input). |
| + // Use truncating instruction (OK because input is positive). |
| + __ cvttsd2si(output_reg, input_reg); |
| + // Overflow is signalled with minint. |
| + __ cmpl(output_reg, Immediate(0x80000000)); |
| + DeoptimizeIf(equal, instr->environment()); |
| + __ jmp(&done); |
| - // We need to return -0 for the input range [-0.5, 0[, otherwise |
| - // compute Math.floor(value + 0.5). |
| + __ bind(&below_half); |
| if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| - __ ucomisd(input_reg, xmm_scratch); |
| - DeoptimizeIf(below_equal, instr->environment()); |
| + // Bailout if negative (including -0). |
| + __ movq(output_reg, input_reg); |
| + __ testq(output_reg, output_reg); |
| + DeoptimizeIf(negative, instr->environment()); |
| } else { |
| - // If we don't need to bailout on -0, we check only bailout |
| - // on negative inputs. |
| - __ xorpd(xmm_scratch, xmm_scratch); // Zero the register. |
| + // Bailout if below -0.5, otherwise round to (positive) zero, even |
| + // if negative. |
| + // xmm_scrach = -0.5 |
| + __ movq(kScratchRegister, V8_INT64_C(0xBFE0000000000000), RelocInfo::NONE); |
| + __ movq(xmm_scratch, kScratchRegister); |
| __ ucomisd(input_reg, xmm_scratch); |
| DeoptimizeIf(below, instr->environment()); |
| } |
| + __ xorl(output_reg, output_reg); |
| - // Compute Math.floor(value + 0.5). |
| - // Use truncating instruction (OK because input is positive). |
| - __ cvttsd2si(output_reg, input_reg); |
| - |
| - // Overflow is signalled with minint. |
| - __ cmpl(output_reg, Immediate(0x80000000)); |
| - DeoptimizeIf(equal, instr->environment()); |
| + __ bind(&done); |
| } |