Fix an error in optimized modulus operator, add unit test.

Review URL: http://codereview.chromium.org/1118008

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4235 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
whesse@chromium.org 2010-03-23 15:18:00 +00:00
parent 01bcdbcdb1
commit c3b5e22764
2 changed files with 30 additions and 0 deletions

View File

@ -7380,6 +7380,15 @@ void CodeGenerator::Int32BinaryOperation(BinaryOperation* node) {
__ cdq(); // Sign-extend eax into edx:eax
__ idiv(right_reg);
if (op == Token::MOD) {
// Negative zero can arise as a negative divident with a zero result.
if (!node->no_negative_zero()) {
Label not_negative_zero;
__ test(edx, Operand(edx));
__ j(not_zero, &not_negative_zero);
__ test(eax, Operand(eax));
unsafe_bailout_->Branch(negative);
__ bind(&not_negative_zero);
}
Result edx_result(edx, NumberInfo::Integer32());
edx_result.set_untagged_int32(true);
frame_->Push(&edx_result);

View File

@ -169,3 +169,24 @@ function compute_mod(dividend, divisor) {
assertEquals(somenum, somenum % -0x40000000, "%minsmi-32");
assertEquals(somenum, somenum % -0x80000000, "%minsmi-64");
})();
// Side-effect-free expressions containing bit operations use
// an optimized compiler with int32 values. Ensure that modulus
// produces negative zeros correctly.
function negative_zero_modulus_test() {
var x = 4;
var y = -4;
x = x + x - x;
y = y + y - y;
var z = (y | y | y | y) % x;
assertEquals(-1 / 0, 1 / z);
z = (x | x | x | x) % x;
assertEquals(1 / 0, 1 / z);
z = (y | y | y | y) % y;
assertEquals(-1 / 0, 1 / z);
z = (x | x | x | x) % y;
assertEquals(1 / 0, 1 / z);
}
negative_zero_modulus_test();