From 4dec24de90a4ee7f1db44691f8c1f723263cf7b0 Mon Sep 17 00:00:00 2001 From: Jan de Mooij Date: Tue, 16 Jul 2013 17:55:29 +0200 Subject: [PATCH] Bug 870356 - Fix IonMonkey Math.round bug on x86/x64 hardware without SSE 4.1. r=sstangl --- .../ion/shared/CodeGenerator-x86-shared.cpp | 21 +++++++----- js/src/ion/shared/CodeGenerator-x86-shared.h | 1 + js/src/jit-test/tests/ion/bug870356.js | 33 +++++++++++++++++++ 3 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 js/src/jit-test/tests/ion/bug870356.js diff --git a/js/src/ion/shared/CodeGenerator-x86-shared.cpp b/js/src/ion/shared/CodeGenerator-x86-shared.cpp index 064a87cfc81..5dc57ca77a2 100644 --- a/js/src/ion/shared/CodeGenerator-x86-shared.cpp +++ b/js/src/ion/shared/CodeGenerator-x86-shared.cpp @@ -326,6 +326,13 @@ CodeGeneratorX86Shared::bailoutIf(Assembler::Condition condition, LSnapshot *sna return bailout(BailoutJump(condition), snapshot); } +bool +CodeGeneratorX86Shared::bailoutIf(Assembler::DoubleCondition condition, LSnapshot *snapshot) +{ + JS_ASSERT(Assembler::NaNCondFromDoubleCondition(condition) == Assembler::NaN_HandledByCond); + return bailoutIf(Assembler::ConditionFromDoubleCondition(condition), snapshot); +} + bool CodeGeneratorX86Shared::bailoutFrom(Label *label, LSnapshot *snapshot) { @@ -1289,8 +1296,12 @@ CodeGeneratorX86Shared::visitRound(LRound *lir) masm.addsd(input, temp); // Round toward -Infinity without the benefit of ROUNDSD. - Label testZero; { + // If input + 0.5 >= 0, input is a negative number >= -0.5 and the result is -0. + masm.compareDouble(Assembler::DoubleGreaterThanOrEqual, temp, scratch); + if (!bailoutIf(Assembler::DoubleGreaterThanOrEqual, lir->snapshot())) + return false; + // Truncate and round toward zero. // This is off-by-one for everything but integer-valued inputs. masm.cvttsd2si(temp, output); @@ -1300,19 +1311,13 @@ CodeGeneratorX86Shared::visitRound(LRound *lir) // Test whether the truncated double was integer-valued. masm.cvtsi2sd(output, scratch); - masm.branchDouble(Assembler::DoubleEqualOrUnordered, temp, scratch, &testZero); + masm.branchDouble(Assembler::DoubleEqualOrUnordered, temp, scratch, &end); // Input is not integer-valued, so we rounded off-by-one in the // wrong direction. Correct by subtraction. masm.subl(Imm32(1), output); // Cannot overflow: output was already checked against INT_MIN. - - // Fall through to testZero. } - - masm.bind(&testZero); - if (!bailoutIf(Assembler::Zero, lir->snapshot())) - return false; } masm.bind(&end); diff --git a/js/src/ion/shared/CodeGenerator-x86-shared.h b/js/src/ion/shared/CodeGenerator-x86-shared.h index 8871170aa55..01135b71752 100644 --- a/js/src/ion/shared/CodeGenerator-x86-shared.h +++ b/js/src/ion/shared/CodeGenerator-x86-shared.h @@ -50,6 +50,7 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared MoveResolver::MoveOperand toMoveOperand(const LAllocation *a) const; bool bailoutIf(Assembler::Condition condition, LSnapshot *snapshot); + bool bailoutIf(Assembler::DoubleCondition condition, LSnapshot *snapshot); bool bailoutFrom(Label *label, LSnapshot *snapshot); bool bailout(LSnapshot *snapshot); diff --git a/js/src/jit-test/tests/ion/bug870356.js b/js/src/jit-test/tests/ion/bug870356.js new file mode 100644 index 00000000000..a634a181613 --- /dev/null +++ b/js/src/jit-test/tests/ion/bug870356.js @@ -0,0 +1,33 @@ +function f1(x) { + return Math.round(x); +} +assertEq(f1(3.3), 3); +assertEq(f1(-2.842170943040401e-14), -0); + +function f2(x) { + return Math.round(x); +} +assertEq(f2(3.3), 3); +assertEq(f2(-1.3), -1); +assertEq(f2(-1.8), -2); +assertEq(f2(-0.9), -1); +assertEq(f2(-0.6), -1); +assertEq(f2(-0.4), -0); + +function f3(x) { + return Math.round(x); +} +assertEq(f3(0.1), 0); +assertEq(f3(-0.5), -0); + +function f4(x) { + return Math.round(x); +} +assertEq(f4(0.1), 0); +assertEq(f4(-0), -0); + +function f5(x) { + return Math.round(x); +} +assertEq(f5(2.9), 3); +assertEq(f5(NaN), NaN);