Bug 1010747: Factor out floating-point conversion to int32 and bailout code; r=sunfish

This commit is contained in:
Benjamin Bouvier 2014-05-22 12:03:13 +02:00
parent c350674971
commit 13719bae70
2 changed files with 33 additions and 61 deletions

View File

@ -1590,9 +1590,7 @@ CodeGeneratorX86Shared::visitFloor(LFloor *lir)
// Round toward -Infinity.
masm.roundsd(input, scratch, JSC::X86Assembler::RoundDown);
masm.cvttsd2si(scratch, output);
masm.cmp32(output, Imm32(INT_MIN));
if (!bailoutIf(Assembler::Equal, lir->snapshot()))
if (!bailoutCvttsd2si(scratch, output, lir->snapshot()))
return false;
} else {
Label negative, end;
@ -1607,9 +1605,7 @@ CodeGeneratorX86Shared::visitFloor(LFloor *lir)
return false;
// Input is non-negative, so truncation correctly rounds.
masm.cvttsd2si(input, output);
masm.cmp32(output, Imm32(INT_MIN));
if (!bailoutIf(Assembler::Equal, lir->snapshot()))
if (!bailoutCvttsd2si(input, output, lir->snapshot()))
return false;
masm.jump(&end);
@ -1621,9 +1617,7 @@ CodeGeneratorX86Shared::visitFloor(LFloor *lir)
{
// Truncate and round toward zero.
// This is off-by-one for everything but integer-valued inputs.
masm.cvttsd2si(input, output);
masm.cmp32(output, Imm32(INT_MIN));
if (!bailoutIf(Assembler::Equal, lir->snapshot()))
if (!bailoutCvttsd2si(input, output, lir->snapshot()))
return false;
// Test whether the input double was integer-valued.
@ -1659,9 +1653,7 @@ CodeGeneratorX86Shared::visitFloorF(LFloorF *lir)
// Round toward -Infinity.
masm.roundss(input, scratch, JSC::X86Assembler::RoundDown);
masm.cvttss2si(scratch, output);
masm.cmp32(output, Imm32(INT_MIN));
if (!bailoutIf(Assembler::Equal, lir->snapshot()))
if (!bailoutCvttss2si(scratch, output, lir->snapshot()))
return false;
} else {
Label negative, end;
@ -1676,9 +1668,7 @@ CodeGeneratorX86Shared::visitFloorF(LFloorF *lir)
return false;
// Input is non-negative, so truncation correctly rounds.
masm.cvttss2si(input, output);
masm.cmp32(output, Imm32(INT_MIN));
if (!bailoutIf(Assembler::Equal, lir->snapshot()))
if (!bailoutCvttss2si(input, output, lir->snapshot()))
return false;
masm.jump(&end);
@ -1690,9 +1680,7 @@ CodeGeneratorX86Shared::visitFloorF(LFloorF *lir)
{
// Truncate and round toward zero.
// This is off-by-one for everything but integer-valued inputs.
masm.cvttss2si(input, output);
masm.cmp32(output, Imm32(INT_MIN));
if (!bailoutIf(Assembler::Equal, lir->snapshot()))
if (!bailoutCvttss2si(input, output, lir->snapshot()))
return false;
// Test whether the input double was integer-valued.
@ -1735,12 +1723,7 @@ CodeGeneratorX86Shared::visitCeil(LCeil *lir)
masm.bind(&lessThanMinusOne);
// Round toward +Infinity.
masm.roundsd(input, scratch, JSC::X86Assembler::RoundUp);
masm.cvttsd2si(scratch, output);
masm.cmp32(output, Imm32(1));
if (!bailoutIf(Assembler::Overflow, lir->snapshot()))
return false;
return true;
return bailoutCvttsd2si(scratch, output, lir->snapshot());
}
// No SSE4.1
@ -1750,9 +1733,7 @@ CodeGeneratorX86Shared::visitCeil(LCeil *lir)
// integer (resp. non-integer) values.
// Will also work for values >= INT_MAX + 1, as the truncate
// operation will return INT_MIN and there'll be a bailout.
masm.cvttsd2si(input, output);
masm.cmp32(output, Imm32(1));
if (!bailoutIf(Assembler::Overflow, lir->snapshot()))
if (!bailoutCvttsd2si(input, output, lir->snapshot()))
return false;
masm.convertInt32ToDouble(output, scratch);
masm.branchDouble(Assembler::DoubleEqualOrUnordered, input, scratch, &end);
@ -1766,9 +1747,7 @@ CodeGeneratorX86Shared::visitCeil(LCeil *lir)
// x <= -1, truncation is the way to go.
masm.bind(&lessThanMinusOne);
masm.cvttsd2si(input, output);
masm.cmp32(output, Imm32(1));
if (!bailoutIf(Assembler::Overflow, lir->snapshot()))
if (!bailoutCvttsd2si(input, output, lir->snapshot()))
return false;
masm.bind(&end);
@ -1800,12 +1779,7 @@ CodeGeneratorX86Shared::visitCeilF(LCeilF *lir)
masm.bind(&lessThanMinusOne);
// Round toward +Infinity.
masm.roundss(input, scratch, JSC::X86Assembler::RoundUp);
masm.cvttss2si(scratch, output);
masm.cmp32(output, Imm32(1));
if (!bailoutIf(Assembler::Overflow, lir->snapshot()))
return false;
return true;
return bailoutCvttss2si(scratch, output, lir->snapshot());
}
// No SSE4.1
@ -1815,9 +1789,7 @@ CodeGeneratorX86Shared::visitCeilF(LCeilF *lir)
// integer (resp. non-integer) values.
// Will also work for values >= INT_MAX + 1, as the truncate
// operation will return INT_MIN and there'll be a bailout.
masm.cvttss2si(input, output);
masm.cmp32(output, Imm32(1));
if (!bailoutIf(Assembler::Overflow, lir->snapshot()))
if (!bailoutCvttss2si(input, output, lir->snapshot()))
return false;
masm.convertInt32ToFloat32(output, scratch);
masm.branchFloat(Assembler::DoubleEqualOrUnordered, input, scratch, &end);
@ -1831,9 +1803,7 @@ CodeGeneratorX86Shared::visitCeilF(LCeilF *lir)
// x <= -1, truncation is the way to go.
masm.bind(&lessThanMinusOne);
masm.cvttss2si(input, output);
masm.cmp32(output, Imm32(1));
if (!bailoutIf(Assembler::Overflow, lir->snapshot()))
if (!bailoutCvttss2si(input, output, lir->snapshot()))
return false;
masm.bind(&end);
@ -1866,10 +1836,7 @@ CodeGeneratorX86Shared::visitRound(LRound *lir)
// have to add the input to the temp register (which contains 0.5) because
// we're not allowed to modify the input register.
masm.addsd(input, temp);
masm.cvttsd2si(temp, output);
masm.cmp32(output, Imm32(INT_MIN));
if (!bailoutIf(Assembler::Equal, lir->snapshot()))
if (!bailoutCvttsd2si(temp, output, lir->snapshot()))
return false;
masm.jump(&end);
@ -1885,9 +1852,7 @@ CodeGeneratorX86Shared::visitRound(LRound *lir)
masm.roundsd(temp, scratch, JSC::X86Assembler::RoundDown);
// Truncate.
masm.cvttsd2si(scratch, output);
masm.cmp32(output, Imm32(INT_MIN));
if (!bailoutIf(Assembler::Equal, lir->snapshot()))
if (!bailoutCvttsd2si(scratch, output, lir->snapshot()))
return false;
// If the result is positive zero, then the actual result is -0. Bail.
@ -1908,9 +1873,7 @@ CodeGeneratorX86Shared::visitRound(LRound *lir)
// Truncate and round toward zero.
// This is off-by-one for everything but integer-valued inputs.
masm.cvttsd2si(temp, output);
masm.cmp32(output, Imm32(INT_MIN));
if (!bailoutIf(Assembler::Equal, lir->snapshot()))
if (!bailoutCvttsd2si(temp, output, lir->snapshot()))
return false;
// Test whether the truncated double was integer-valued.
@ -1955,9 +1918,7 @@ CodeGeneratorX86Shared::visitRoundF(LRoundF *lir)
// we're not allowed to modify the input register.
masm.addss(input, temp);
masm.cvttss2si(temp, output);
masm.cmp32(output, Imm32(INT_MIN));
if (!bailoutIf(Assembler::Equal, lir->snapshot()))
if (!bailoutCvttss2si(temp, output, lir->snapshot()))
return false;
masm.jump(&end);
@ -1973,9 +1934,7 @@ CodeGeneratorX86Shared::visitRoundF(LRoundF *lir)
masm.roundss(temp, scratch, JSC::X86Assembler::RoundDown);
// Truncate.
masm.cvttss2si(scratch, output);
masm.cmp32(output, Imm32(INT_MIN));
if (!bailoutIf(Assembler::Equal, lir->snapshot()))
if (!bailoutCvttss2si(scratch, output, lir->snapshot()))
return false;
// If the result is positive zero, then the actual result is -0. Bail.
@ -1995,9 +1954,7 @@ CodeGeneratorX86Shared::visitRoundF(LRoundF *lir)
// Truncate and round toward zero.
// This is off-by-one for everything but integer-valued inputs.
masm.cvttss2si(temp, output);
masm.cmp32(output, Imm32(INT_MIN));
if (!bailoutIf(Assembler::Equal, lir->snapshot()))
if (!bailoutCvttss2si(temp, output, lir->snapshot()))
return false;
// Test whether the truncated double was integer-valued.

View File

@ -75,6 +75,21 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
masm.test32(lhs, rhs);
return bailoutIf(c, snapshot);
}
bool bailoutCvttsd2si(FloatRegister src, Register dest, LSnapshot *snapshot) {
// cvttsd2si returns 0x80000000 on failure. Test for it by
// subtracting 1 and testing overflow. The other possibility is to test
// equality for INT_MIN after a comparison, but 1 costs fewer bytes to
// materialize.
masm.cvttsd2si(src, dest);
masm.cmp32(dest, Imm32(1));
return bailoutIf(Assembler::Overflow, snapshot);
}
bool bailoutCvttss2si(FloatRegister src, Register dest, LSnapshot *snapshot) {
// Same trick as explained in the above comment.
masm.cvttss2si(src, dest);
masm.cmp32(dest, Imm32(1));
return bailoutIf(Assembler::Overflow, snapshot);
}
protected:
bool generatePrologue();