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

Unified Diff: src/x64/lithium-codegen-x64.cc

Issue 6837018: Fix Math.round in runtime.cc and x64 optimized code. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 8 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 side-by-side diff with in-line comments
Download patch
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);
}
« no previous file with comments | « src/runtime.cc ('k') | test/mjsunit/math-round.js » ('j') | test/mjsunit/math-round.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698