Commit c3b5e227 authored by whesse@chromium.org's avatar whesse@chromium.org

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
parent 01bcdbcd
......@@ -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);
......
......@@ -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();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment