Bug 944963 - IonMonkey: Add a ModSelf operator to fix an x86 constraint problem with x%x. r=bhackett

This commit is contained in:
Dan Gohman 2013-12-02 13:41:54 -08:00
Родитель 881a7c1554
Коммит c5f1ebea60
10 изменённых файлов: 746 добавлений и 34 удалений

Просмотреть файл

@ -1,13 +0,0 @@
function f(x) {
var a = x;
return a / 10;
}
for (var i=0; i<100; i++)
assertEq(f(i * 10), i);
function g(x) {
var y = x + 1;
return y / y;
}
for (var i=0; i<100; i++)
assertEq(g(i), 1);

Просмотреть файл

@ -1,6 +0,0 @@
function test() {
var x = 0.0;
for (var i = 0; i < 100; i++)
-("") >> (x / x);
}
test();

Просмотреть файл

@ -0,0 +1,652 @@
// |jit-test| ion-eager
// bug 944963
function bug944963(x, y) {
(+(xy))(y % y)
}
for (var i = 0; i < 10; i++) {
try {
(function() {
bug944963(0, (~Math.fround(-8)))
})()
} catch (e) {}
}
// bug 900437
function bug900437() {
var x = 0.0;
for (var i = 0; i < 10; i++)
-("") >> (x / x);
}
bug900437();
bug900437();
// bug 715460
function f(x) {
var a = x;
return a / 10;
}
function g(x) {
var y = x + 1;
return y / y;
}
for (var i=0; i<10; i++)
assertEq(f(i * 10), i);
for (var i=0; i<10; i++)
assertEq(g(i), 1);
// bug 939893
function bug939893() {
bug_g();
}
function bug_g() {
bug_h(undefined >>> 0, +undefined);
}
function bug_h(x) {
Math.max(x ? ((x / x) | 0) : 0);
}
for (var a = 0; a < 2; ++a) {
bug939893();
}
// Assorted tests.
function sdiv_truncate(y) {
return (y / y)|0;
}
assertEq(sdiv_truncate(5), 1);
assertEq(sdiv_truncate(1), 1);
assertEq(sdiv_truncate(-1), 1);
assertEq(sdiv_truncate(0), 0);
assertEq(sdiv_truncate(-0), 0);
assertEq(sdiv_truncate(1.1), 1);
assertEq(sdiv_truncate(-1.1), 1);
assertEq(sdiv_truncate(Infinity), 0);
assertEq(sdiv_truncate(NaN), 0);
assertEq(sdiv_truncate(undefined), 0);
assertEq(sdiv_truncate(null), 0);
function sdiv(y) {
return y / y;
}
assertEq(sdiv(5), 1);
assertEq(sdiv(1), 1);
assertEq(sdiv(-1), 1);
assertEq(sdiv(0), NaN);
assertEq(sdiv(-0), NaN);
assertEq(sdiv(1.1), 1);
assertEq(sdiv(-1.1), 1);
assertEq(sdiv(Infinity), NaN);
assertEq(sdiv(NaN), NaN);
assertEq(sdiv(undefined), NaN);
assertEq(sdiv(null), NaN);
function udiv_truncate(y) {
var yu = y>>>0;
return (yu / yu)|0;
}
assertEq(udiv_truncate(5), 1);
assertEq(udiv_truncate(1), 1);
assertEq(udiv_truncate(-1), 1);
assertEq(udiv_truncate(0), 0);
assertEq(udiv_truncate(-0), 0);
assertEq(udiv_truncate(1.1), 1);
assertEq(udiv_truncate(-1.1), 1);
assertEq(udiv_truncate(Infinity), 0);
assertEq(udiv_truncate(NaN), 0);
assertEq(udiv_truncate(undefined), 0);
assertEq(udiv_truncate(null), 0);
function shifted_udiv_truncate(y) {
var yu = y>>>1;
return (yu / yu)|0;
}
assertEq(shifted_udiv_truncate(5), 1);
assertEq(shifted_udiv_truncate(2), 1);
assertEq(shifted_udiv_truncate(1), 0);
assertEq(shifted_udiv_truncate(-1), 1);
assertEq(shifted_udiv_truncate(0), 0);
assertEq(shifted_udiv_truncate(-0), 0);
assertEq(shifted_udiv_truncate(1.1), 0);
assertEq(shifted_udiv_truncate(-1.1), 1);
assertEq(shifted_udiv_truncate(Infinity), 0);
assertEq(shifted_udiv_truncate(NaN), 0);
assertEq(shifted_udiv_truncate(undefined), 0);
assertEq(shifted_udiv_truncate(null), 0);
function udiv(y) {
var yu = y>>>0;
return yu / yu;
}
assertEq(udiv(5), 1);
assertEq(udiv(1), 1);
assertEq(udiv(-1), 1);
assertEq(udiv(0), NaN);
assertEq(udiv(-0), NaN);
assertEq(udiv(1.1), 1);
assertEq(udiv(-1.1), 1);
assertEq(udiv(Infinity), NaN);
assertEq(udiv(NaN), NaN);
assertEq(udiv(undefined), NaN);
assertEq(udiv(null), NaN);
function shifted_udiv(y) {
var yu = y>>>1;
return yu / yu;
}
assertEq(shifted_udiv(5), 1);
assertEq(shifted_udiv(2), 1);
assertEq(shifted_udiv(1), NaN);
assertEq(shifted_udiv(-1), 1);
assertEq(shifted_udiv(0), NaN);
assertEq(shifted_udiv(-0), NaN);
assertEq(shifted_udiv(1.1), NaN);
assertEq(shifted_udiv(-1.1), 1);
assertEq(shifted_udiv(Infinity), NaN);
assertEq(shifted_udiv(NaN), NaN);
assertEq(shifted_udiv(undefined), NaN);
assertEq(shifted_udiv(null), NaN);
function smod_truncate(y) {
return (y % y)|0;
}
assertEq(smod_truncate(5), 0);
assertEq(smod_truncate(1), 0);
assertEq(smod_truncate(-1), 0);
assertEq(smod_truncate(0), 0);
assertEq(smod_truncate(-0), 0);
assertEq(smod_truncate(1.1), 0);
assertEq(smod_truncate(-1.1), 0);
assertEq(smod_truncate(Infinity), 0);
assertEq(smod_truncate(NaN), 0);
assertEq(smod_truncate(undefined), 0);
assertEq(smod_truncate(null), 0);
function smod(y) {
return y % y;
}
assertEq(smod(5), 0);
assertEq(smod(1), 0);
assertEq(smod(-1), -0);
assertEq(smod(0), NaN);
assertEq(smod(-0), NaN);
assertEq(smod(1.1), 0);
assertEq(smod(-1.1), -0);
assertEq(smod(Infinity), NaN);
assertEq(smod(NaN), NaN);
assertEq(smod(undefined), NaN);
assertEq(smod(null), NaN);
function umod_truncate(y) {
var yu = y>>>0;
return (yu % yu)|0;
}
assertEq(umod_truncate(5), 0);
assertEq(umod_truncate(1), 0);
assertEq(umod_truncate(-1), 0);
assertEq(umod_truncate(0), 0);
assertEq(umod_truncate(-0), 0);
assertEq(umod_truncate(1.1), 0);
assertEq(umod_truncate(-1.1), 0);
assertEq(umod_truncate(Infinity), 0);
assertEq(umod_truncate(NaN), 0);
assertEq(umod_truncate(undefined), 0);
assertEq(umod_truncate(null), 0);
function shifted_umod_truncate(y) {
var yu = y>>>1;
return (yu % yu)|0;
}
assertEq(shifted_umod_truncate(5), 0);
assertEq(shifted_umod_truncate(2), 0);
assertEq(shifted_umod_truncate(1), 0);
assertEq(shifted_umod_truncate(-1), 0);
assertEq(shifted_umod_truncate(0), 0);
assertEq(shifted_umod_truncate(-0), 0);
assertEq(shifted_umod_truncate(1.1), 0);
assertEq(shifted_umod_truncate(-1.1), 0);
assertEq(shifted_umod_truncate(Infinity), 0);
assertEq(shifted_umod_truncate(NaN), 0);
assertEq(shifted_umod_truncate(undefined), 0);
assertEq(shifted_umod_truncate(null), 0);
function umod(y) {
var yu = y>>>0;
return yu % yu;
}
assertEq(umod(5), 0);
assertEq(umod(1), 0);
assertEq(umod(-1), 0);
assertEq(umod(0), NaN);
assertEq(umod(-0), NaN);
assertEq(umod(1.1), 0);
assertEq(umod(-1.1), 0);
assertEq(umod(Infinity), NaN);
assertEq(umod(NaN), NaN);
assertEq(umod(undefined), NaN);
assertEq(umod(null), NaN);
function shifted_umod(y) {
var yu = y>>>1;
return yu % yu;
}
assertEq(shifted_umod(5), 0);
assertEq(shifted_umod(2), 0);
assertEq(shifted_umod(1), NaN);
assertEq(shifted_umod(-1), 0);
assertEq(shifted_umod(0), NaN);
assertEq(shifted_umod(-0), NaN);
assertEq(shifted_umod(1.1), NaN);
assertEq(shifted_umod(-1.1), 0);
assertEq(shifted_umod(Infinity), NaN);
assertEq(shifted_umod(NaN), NaN);
assertEq(shifted_umod(undefined), NaN);
assertEq(shifted_umod(null), NaN);
function sdiv_truncate_nonzero(y) {
if (y == 0) return -202;
return (y / y)|0;
}
assertEq(sdiv_truncate_nonzero(5), 1);
assertEq(sdiv_truncate_nonzero(1), 1);
assertEq(sdiv_truncate_nonzero(-1), 1);
assertEq(sdiv_truncate_nonzero(0), -202);
assertEq(sdiv_truncate_nonzero(-0), -202);
assertEq(sdiv_truncate_nonzero(1.1), 1);
assertEq(sdiv_truncate_nonzero(-1.1), 1);
assertEq(sdiv_truncate_nonzero(Infinity), 0);
assertEq(sdiv_truncate_nonzero(NaN), 0);
assertEq(sdiv_truncate_nonzero(undefined), 0);
assertEq(sdiv_truncate_nonzero(null), 0);
function sdiv_nonzero(y) {
if (y == 0) return -202;
return y / y;
}
assertEq(sdiv_nonzero(5), 1);
assertEq(sdiv_nonzero(1), 1);
assertEq(sdiv_nonzero(-1), 1);
assertEq(sdiv_nonzero(0), -202);
assertEq(sdiv_nonzero(-0), -202);
assertEq(sdiv_nonzero(1.1), 1);
assertEq(sdiv_nonzero(-1.1), 1);
assertEq(sdiv_nonzero(Infinity), NaN);
assertEq(sdiv_nonzero(NaN), NaN);
assertEq(sdiv_nonzero(undefined), NaN);
assertEq(sdiv_nonzero(null), NaN);
function udiv_truncate_nonzero(y) {
var yu = y>>>0;
if (yu == 0) return -202;
return (yu / yu)|0;
}
assertEq(udiv_truncate_nonzero(5), 1);
assertEq(udiv_truncate_nonzero(1), 1);
assertEq(udiv_truncate_nonzero(-1), 1);
assertEq(udiv_truncate_nonzero(0), -202);
assertEq(udiv_truncate_nonzero(-0), -202);
assertEq(udiv_truncate_nonzero(1.1), 1);
assertEq(udiv_truncate_nonzero(-1.1), 1);
assertEq(udiv_truncate_nonzero(Infinity), -202);
assertEq(udiv_truncate_nonzero(NaN), -202);
assertEq(udiv_truncate_nonzero(undefined), -202);
assertEq(udiv_truncate_nonzero(null), -202);
function shifted_udiv_truncate_nonzero(y) {
var yu = y>>>1;
if (yu == 0) return -202;
return (yu / yu)|0;
}
assertEq(shifted_udiv_truncate_nonzero(5), 1);
assertEq(shifted_udiv_truncate_nonzero(2), 1);
assertEq(shifted_udiv_truncate_nonzero(1), -202);
assertEq(shifted_udiv_truncate_nonzero(-1), 1);
assertEq(shifted_udiv_truncate_nonzero(0), -202);
assertEq(shifted_udiv_truncate_nonzero(-0), -202);
assertEq(shifted_udiv_truncate_nonzero(1.1), -202);
assertEq(shifted_udiv_truncate_nonzero(-1.1), 1);
assertEq(shifted_udiv_truncate_nonzero(Infinity), -202);
assertEq(shifted_udiv_truncate_nonzero(NaN), -202);
assertEq(shifted_udiv_truncate_nonzero(undefined), -202);
assertEq(shifted_udiv_truncate_nonzero(null), -202);
function udiv_nonzero(y) {
var yu = y>>>0;
if (yu == 0) return -202;
return yu / yu;
}
assertEq(udiv_nonzero(5), 1);
assertEq(udiv_nonzero(1), 1);
assertEq(udiv_nonzero(-1), 1);
assertEq(udiv_nonzero(0), -202);
assertEq(udiv_nonzero(-0), -202);
assertEq(udiv_nonzero(1.1), 1);
assertEq(udiv_nonzero(-1.1), 1);
assertEq(udiv_nonzero(Infinity), -202);
assertEq(udiv_nonzero(NaN), -202);
assertEq(udiv_nonzero(undefined), -202);
assertEq(udiv_nonzero(null), -202);
function shifted_udiv_nonzero(y) {
var yu = y>>>1;
if (yu == 0) return -202;
return yu / yu;
}
assertEq(shifted_udiv_nonzero(5), 1);
assertEq(shifted_udiv_nonzero(2), 1);
assertEq(shifted_udiv_nonzero(1), -202);
assertEq(shifted_udiv_nonzero(-1), 1);
assertEq(shifted_udiv_nonzero(0), -202);
assertEq(shifted_udiv_nonzero(-0), -202);
assertEq(shifted_udiv_nonzero(1.1), -202);
assertEq(shifted_udiv_nonzero(-1.1), 1);
assertEq(shifted_udiv_nonzero(Infinity), -202);
assertEq(shifted_udiv_nonzero(NaN), -202);
assertEq(shifted_udiv_nonzero(undefined), -202);
assertEq(shifted_udiv_nonzero(null), -202);
function smod_truncate_nonzero(y) {
if (y == 0) return -202;
return (y % y)|0;
}
assertEq(smod_truncate_nonzero(5), 0);
assertEq(smod_truncate_nonzero(1), 0);
assertEq(smod_truncate_nonzero(-1), 0);
assertEq(smod_truncate_nonzero(0), -202);
assertEq(smod_truncate_nonzero(-0), -202);
assertEq(smod_truncate_nonzero(1.1), 0);
assertEq(smod_truncate_nonzero(-1.1), 0);
assertEq(smod_truncate_nonzero(Infinity), 0);
assertEq(smod_truncate_nonzero(NaN), 0);
assertEq(smod_truncate_nonzero(undefined), 0);
assertEq(smod_truncate_nonzero(null), 0);
function smod_nonzero(y) {
if (y == 0) return -202;
return y % y;
}
assertEq(smod_nonzero(5), 0);
assertEq(smod_nonzero(1), 0);
assertEq(smod_nonzero(-1), -0);
assertEq(smod_nonzero(0), -202);
assertEq(smod_nonzero(-0), -202);
assertEq(smod_nonzero(1.1), 0);
assertEq(smod_nonzero(-1.1), -0);
assertEq(smod_nonzero(Infinity), NaN);
assertEq(smod_nonzero(NaN), NaN);
assertEq(smod_nonzero(undefined), NaN);
assertEq(smod_nonzero(null), NaN);
function umod_truncate_nonzero(y) {
var yu = y>>>0;
if (yu == 0) return -202;
return (yu % yu)|0;
}
assertEq(umod_truncate_nonzero(5), 0);
assertEq(umod_truncate_nonzero(1), 0);
assertEq(umod_truncate_nonzero(-1), 0);
assertEq(umod_truncate_nonzero(0), -202);
assertEq(umod_truncate_nonzero(-0), -202);
assertEq(umod_truncate_nonzero(1.1), 0);
assertEq(umod_truncate_nonzero(-1.1), 0);
assertEq(umod_truncate_nonzero(Infinity), -202);
assertEq(umod_truncate_nonzero(NaN), -202);
assertEq(umod_truncate_nonzero(undefined), -202);
assertEq(umod_truncate_nonzero(null), -202);
function shifted_umod_truncate_nonzero(y) {
var yu = y>>>1;
if (yu == 0) return -202;
return (yu % yu)|0;
}
assertEq(shifted_umod_truncate_nonzero(5), 0);
assertEq(shifted_umod_truncate_nonzero(2), 0);
assertEq(shifted_umod_truncate_nonzero(1), -202);
assertEq(shifted_umod_truncate_nonzero(-1), 0);
assertEq(shifted_umod_truncate_nonzero(0), -202);
assertEq(shifted_umod_truncate_nonzero(-0), -202);
assertEq(shifted_umod_truncate_nonzero(1.1), -202);
assertEq(shifted_umod_truncate_nonzero(-1.1), 0);
assertEq(shifted_umod_truncate_nonzero(Infinity), -202);
assertEq(shifted_umod_truncate_nonzero(NaN), -202);
assertEq(shifted_umod_truncate_nonzero(undefined), -202);
assertEq(shifted_umod_truncate_nonzero(null), -202);
function umod_nonzero(y) {
var yu = y>>>0;
if (yu == 0) return -202;
return yu % yu;
}
assertEq(umod_nonzero(5), 0);
assertEq(umod_nonzero(1), 0);
assertEq(umod_nonzero(-1), 0);
assertEq(umod_nonzero(0), -202);
assertEq(umod_nonzero(-0), -202);
assertEq(umod_nonzero(1.1), 0);
assertEq(umod_nonzero(-1.1), 0);
assertEq(umod_nonzero(Infinity), -202);
assertEq(umod_nonzero(NaN), -202);
assertEq(umod_nonzero(undefined), -202);
assertEq(umod_nonzero(null), -202);
function shifted_umod_nonzero(y) {
var yu = y>>>1;
if (yu == 0) return -202;
return yu % yu;
}
assertEq(shifted_umod_nonzero(5), 0);
assertEq(shifted_umod_nonzero(2), 0);
assertEq(shifted_umod_nonzero(1), -202);
assertEq(shifted_umod_nonzero(-1), 0);
assertEq(shifted_umod_nonzero(0), -202);
assertEq(shifted_umod_nonzero(-0), -202);
assertEq(shifted_umod_nonzero(1.1), -202);
assertEq(shifted_umod_nonzero(-1.1), 0);
assertEq(shifted_umod_nonzero(Infinity), -202);
assertEq(shifted_umod_nonzero(NaN), -202);
assertEq(shifted_umod_nonzero(undefined), -202);
assertEq(shifted_umod_nonzero(null), -202);
function sdiv_truncate_positive(y) {
if (y <= 0) return -202;
return (y / y)|0;
}
assertEq(sdiv_truncate_positive(5), 1);
assertEq(sdiv_truncate_positive(1), 1);
assertEq(sdiv_truncate_positive(-1), -202);
assertEq(sdiv_truncate_positive(0), -202);
assertEq(sdiv_truncate_positive(-0), -202);
assertEq(sdiv_truncate_positive(1.1), 1);
assertEq(sdiv_truncate_positive(-1.1), -202);
assertEq(sdiv_truncate_positive(Infinity), 0);
assertEq(sdiv_truncate_positive(NaN), 0);
assertEq(sdiv_truncate_positive(undefined), 0);
assertEq(sdiv_truncate_positive(null), -202);
function sdiv_positive(y) {
if (y <= 0) return -202;
return y / y;
}
assertEq(sdiv_positive(5), 1);
assertEq(sdiv_positive(1), 1);
assertEq(sdiv_positive(-1), -202);
assertEq(sdiv_positive(0), -202);
assertEq(sdiv_positive(-0), -202);
assertEq(sdiv_positive(1.1), 1);
assertEq(sdiv_positive(-1.1), -202);
assertEq(sdiv_positive(Infinity), NaN);
assertEq(sdiv_positive(NaN), NaN);
assertEq(sdiv_positive(undefined), NaN);
assertEq(sdiv_positive(null), -202);
function udiv_truncate_positive(y) {
var yu = y>>>0;
if (yu <= 0) return -202;
return (yu / yu)|0;
}
assertEq(udiv_truncate_positive(5), 1);
assertEq(udiv_truncate_positive(1), 1);
assertEq(udiv_truncate_positive(-1), 1);
assertEq(udiv_truncate_positive(0), -202);
assertEq(udiv_truncate_positive(-0), -202);
assertEq(udiv_truncate_positive(1.1), 1);
assertEq(udiv_truncate_positive(-1.1), 1);
assertEq(udiv_truncate_positive(Infinity), -202);
assertEq(udiv_truncate_positive(NaN), -202);
assertEq(udiv_truncate_positive(undefined), -202);
assertEq(udiv_truncate_positive(null), -202);
function shifted_udiv_truncate_positive(y) {
var yu = y>>>1;
if (yu <= 0) return -202;
return (yu / yu)|0;
}
assertEq(shifted_udiv_truncate_positive(5), 1);
assertEq(shifted_udiv_truncate_positive(2), 1);
assertEq(shifted_udiv_truncate_positive(1), -202);
assertEq(shifted_udiv_truncate_positive(-1), 1);
assertEq(shifted_udiv_truncate_positive(0), -202);
assertEq(shifted_udiv_truncate_positive(-0), -202);
assertEq(shifted_udiv_truncate_positive(1.1), -202);
assertEq(shifted_udiv_truncate_positive(-1.1), 1);
assertEq(shifted_udiv_truncate_positive(Infinity), -202);
assertEq(shifted_udiv_truncate_positive(NaN), -202);
assertEq(shifted_udiv_truncate_positive(undefined), -202);
assertEq(shifted_udiv_truncate_positive(null), -202);
function udiv_positive(y) {
var yu = y>>>0;
if (yu <= 0) return -202;
return yu / yu;
}
assertEq(udiv_positive(5), 1);
assertEq(udiv_positive(1), 1);
assertEq(udiv_positive(-1), 1);
assertEq(udiv_positive(0), -202);
assertEq(udiv_positive(-0), -202);
assertEq(udiv_positive(1.1), 1);
assertEq(udiv_positive(-1.1), 1);
assertEq(udiv_positive(Infinity), -202);
assertEq(udiv_positive(NaN), -202);
assertEq(udiv_positive(undefined), -202);
assertEq(udiv_positive(null), -202);
function shifted_udiv_positive(y) {
var yu = y>>>1;
if (yu <= 0) return -202;
return yu / yu;
}
assertEq(shifted_udiv_positive(5), 1);
assertEq(shifted_udiv_positive(2), 1);
assertEq(shifted_udiv_positive(1), -202);
assertEq(shifted_udiv_positive(-1), 1);
assertEq(shifted_udiv_positive(0), -202);
assertEq(shifted_udiv_positive(-0), -202);
assertEq(shifted_udiv_positive(1.1), -202);
assertEq(shifted_udiv_positive(-1.1), 1);
assertEq(shifted_udiv_positive(Infinity), -202);
assertEq(shifted_udiv_positive(NaN), -202);
assertEq(shifted_udiv_positive(undefined), -202);
assertEq(shifted_udiv_positive(null), -202);
function smod_truncate_positive(y) {
if (y <= 0) return -202;
return (y % y)|0;
}
assertEq(smod_truncate_positive(5), 0);
assertEq(smod_truncate_positive(1), 0);
assertEq(smod_truncate_positive(-1), -202);
assertEq(smod_truncate_positive(0), -202);
assertEq(smod_truncate_positive(-0), -202);
assertEq(smod_truncate_positive(1.1), 0);
assertEq(smod_truncate_positive(-1.1), -202);
assertEq(smod_truncate_positive(Infinity), 0);
assertEq(smod_truncate_positive(NaN), 0);
assertEq(smod_truncate_positive(undefined), 0);
assertEq(smod_truncate_positive(null), -202);
function smod_positive(y) {
if (y <= 0) return -202;
return y % y;
}
assertEq(smod_positive(5), 0);
assertEq(smod_positive(1), 0);
assertEq(smod_positive(-1), -202);
assertEq(smod_positive(0), -202);
assertEq(smod_positive(-0), -202);
assertEq(smod_positive(1.1), 0);
assertEq(smod_positive(-1.1), -202);
assertEq(smod_positive(Infinity), NaN);
assertEq(smod_positive(NaN), NaN);
assertEq(smod_positive(undefined), NaN);
assertEq(smod_positive(null), -202);
function umod_truncate_positive(y) {
var yu = y>>>0;
if (yu <= 0) return -202;
return (yu % yu)|0;
}
assertEq(umod_truncate_positive(5), 0);
assertEq(umod_truncate_positive(1), 0);
assertEq(umod_truncate_positive(-1), 0);
assertEq(umod_truncate_positive(0), -202);
assertEq(umod_truncate_positive(-0), -202);
assertEq(umod_truncate_positive(1.1), 0);
assertEq(umod_truncate_positive(-1.1), 0);
assertEq(umod_truncate_positive(Infinity), -202);
assertEq(umod_truncate_positive(NaN), -202);
assertEq(umod_truncate_positive(undefined), -202);
assertEq(umod_truncate_positive(null), -202);
function shifted_umod_truncate_positive(y) {
var yu = y>>>1;
if (yu <= 0) return -202;
return (yu % yu)|0;
}
assertEq(shifted_umod_truncate_positive(5), 0);
assertEq(shifted_umod_truncate_positive(2), 0);
assertEq(shifted_umod_truncate_positive(1), -202);
assertEq(shifted_umod_truncate_positive(-1), 0);
assertEq(shifted_umod_truncate_positive(0), -202);
assertEq(shifted_umod_truncate_positive(-0), -202);
assertEq(shifted_umod_truncate_positive(1.1), -202);
assertEq(shifted_umod_truncate_positive(-1.1), 0);
assertEq(shifted_umod_truncate_positive(Infinity), -202);
assertEq(shifted_umod_truncate_positive(NaN), -202);
assertEq(shifted_umod_truncate_positive(undefined), -202);
assertEq(shifted_umod_truncate_positive(null), -202);
function umod_positive(y) {
var yu = y>>>0;
if (yu <= 0) return -202;
return yu % yu;
}
assertEq(umod_positive(5), 0);
assertEq(umod_positive(1), 0);
assertEq(umod_positive(-1), 0);
assertEq(umod_positive(0), -202);
assertEq(umod_positive(-0), -202);
assertEq(umod_positive(1.1), 0);
assertEq(umod_positive(-1.1), 0);
assertEq(umod_positive(Infinity), -202);
assertEq(umod_positive(NaN), -202);
assertEq(umod_positive(undefined), -202);
assertEq(umod_positive(null), -202);
function shifted_umod_positive(y) {
var yu = y>>>1;
if (yu <= 0) return -202;
return yu % yu;
}
assertEq(shifted_umod_positive(5), 0);
assertEq(shifted_umod_positive(2), 0);
assertEq(shifted_umod_positive(1), -202);
assertEq(shifted_umod_positive(-1), 0);
assertEq(shifted_umod_positive(0), -202);
assertEq(shifted_umod_positive(-0), -202);
assertEq(shifted_umod_positive(1.1), -202);
assertEq(shifted_umod_positive(-1.1), 0);
assertEq(shifted_umod_positive(Infinity), -202);
assertEq(shifted_umod_positive(NaN), -202);
assertEq(shifted_umod_positive(undefined), -202);
assertEq(shifted_umod_positive(null), -202);

Просмотреть файл

@ -1420,7 +1420,8 @@ MMod::foldsTo(TempAllocator &alloc, bool useValueNumbers)
bool
MMod::fallible() const
{
return !isTruncated();
return !isTruncated() &&
(isUnsigned() || canBeDivideByZero() || canBeNegativeDividend());
}
void

Просмотреть файл

@ -894,6 +894,7 @@ CodeGeneratorX86Shared::visitDivSelfI(LDivSelfI *ins)
Register output = ToRegister(ins->output());
MDiv *mir = ins->mir();
// If we can't divide by zero, lowering should have just used a constant one.
JS_ASSERT(mir->canBeDivideByZero());
masm.testl(op, op);
@ -991,6 +992,39 @@ CodeGeneratorX86Shared::visitDivI(LDivI *ins)
return true;
}
bool
CodeGeneratorX86Shared::visitModSelfI(LModSelfI *ins)
{
Register op = ToRegister(ins->op());
Register output = ToRegister(ins->output());
MMod *mir = ins->mir();
// If we're not fallible, lowering should have just used a constant zero.
JS_ASSERT(mir->fallible());
JS_ASSERT(mir->canBeDivideByZero() || (!mir->isUnsigned() && mir->canBeNegativeDividend()));
masm.testl(op, op);
// For a negative operand, we need to return negative zero. We can't
// represent that as an int32, so bail if that happens.
if (!mir->isUnsigned() && mir->canBeNegativeDividend()) {
if (!bailoutIf(Assembler::Signed, ins->snapshot()))
return false;
}
// For a zero operand, we need to return NaN. We can't
// represent that as an int32, so bail if that happens.
if (mir->canBeDivideByZero()) {
if (!bailoutIf(Assembler::Zero, ins->snapshot()))
return false;
}
// For any other value, return 0.
masm.mov(ImmWord(0), output);
return true;
}
bool
CodeGeneratorX86Shared::visitModPowTwoI(LModPowTwoI *ins)
{
@ -1068,16 +1102,11 @@ CodeGeneratorX86Shared::visitModI(LModI *ins)
Register remainder = ToRegister(ins->remainder());
Register lhs = ToRegister(ins->lhs());
Register rhs = ToRegister(ins->rhs());
Register temp = ToRegister(ins->getTemp(0));
// Required to use idiv.
JS_ASSERT(lhs == eax);
JS_ASSERT(remainder == edx);
JS_ASSERT(temp == eax);
if (lhs != temp) {
masm.mov(lhs, temp);
lhs = temp;
}
JS_ASSERT(ToRegister(ins->getTemp(0)) == eax);
Label done;
ReturnZero *ool = nullptr;

Просмотреть файл

@ -94,6 +94,7 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
virtual bool visitDivSelfI(LDivSelfI *ins);
virtual bool visitModI(LModI *ins);
virtual bool visitModPowTwoI(LModPowTwoI *ins);
virtual bool visitModSelfI(LModSelfI *ins);
virtual bool visitBitNotI(LBitNotI *ins);
virtual bool visitBitOpI(LBitOpI *ins);
virtual bool visitShiftI(LShiftI *ins);

Просмотреть файл

@ -114,6 +114,25 @@ class LModI : public LBinaryMath<1>
}
};
// Modulo of a number by itself. Returns 0 unless the number is zero.
class LModSelfI : public LInstructionHelper<1, 1, 0>
{
public:
LIR_HEADER(ModSelfI)
LModSelfI(const LAllocation &op) {
setOperand(0, op);
}
const LAllocation *op() {
return getOperand(0);
}
MMod *mir() const {
return mir_->toMod();
}
};
// This class performs a simple x86 'div', yielding either a quotient or remainder depending on
// whether this instruction is defined to output eax (quotient) or edx (remainder).
class LUDivOrMod : public LBinaryMath<1>

Просмотреть файл

@ -190,7 +190,23 @@ LIRGeneratorX86Shared::lowerModI(MMod *mod)
return defineReuseInput(lir, mod, 0);
}
}
LModI *lir = new LModI(useRegister(mod->lhs()), useRegister(mod->rhs()), tempFixed(eax));
// Optimize x%x. The comments in lowerDivI apply here as well, except
// that we return 0 for all cases except when x is 0 and we're not
// truncated.
if (mod->rhs() == mod->lhs()) {
if (mod->isTruncated())
return define(new LInteger(0), mod);
LModSelfI *lir = new LModSelfI(useRegisterAtStart(mod->lhs()));
if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
return false;
return define(lir, mod);
}
LModI *lir = new LModI(useFixedAtStart(mod->lhs(), eax),
useRegister(mod->rhs()),
tempFixed(eax));
if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
return false;
return defineFixed(lir, mod, LAllocation(AnyRegister(edx)));
@ -210,18 +226,18 @@ bool
LIRGeneratorX86Shared::lowerUDiv(MDiv *div)
{
// Optimize x/x. The comments in lowerDivI apply here as well.
if (div->getOperand(0) == div->getOperand(1)) {
if (div->lhs() == div->rhs()) {
if (!div->canBeDivideByZero())
return define(new LInteger(1), div);
LDivSelfI *lir = new LDivSelfI(useRegisterAtStart(div->getOperand(0)));
LDivSelfI *lir = new LDivSelfI(useRegisterAtStart(div->lhs()));
if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
return false;
return define(lir, div);
}
LUDivOrMod *lir = new LUDivOrMod(useFixedAtStart(div->getOperand(0), eax),
useRegister(div->getOperand(1)),
LUDivOrMod *lir = new LUDivOrMod(useFixedAtStart(div->lhs(), eax),
useRegister(div->rhs()),
tempFixed(edx));
if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
return false;
@ -231,8 +247,19 @@ LIRGeneratorX86Shared::lowerUDiv(MDiv *div)
bool
LIRGeneratorX86Shared::lowerUMod(MMod *mod)
{
LUDivOrMod *lir = new LUDivOrMod(useFixedAtStart(mod->getOperand(0), eax),
useRegister(mod->getOperand(1)),
// Optimize x%x. The comments in lowerModI apply here as well.
if (mod->lhs() == mod->rhs()) {
if (mod->isTruncated())
return define(new LInteger(0), mod);
LModSelfI *lir = new LModSelfI(useRegisterAtStart(mod->lhs()));
if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
return false;
return define(lir, mod);
}
LUDivOrMod *lir = new LUDivOrMod(useFixedAtStart(mod->lhs(), eax),
useRegister(mod->rhs()),
tempFixed(eax));
if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
return false;

Просмотреть файл

@ -16,6 +16,7 @@
_(DivSelfI) \
_(ModI) \
_(ModPowTwoI) \
_(ModSelfI) \
_(PowHalfD) \
_(AsmJSUInt32ToDouble) \
_(AsmJSUInt32ToFloat32) \

Просмотреть файл

@ -17,6 +17,7 @@
_(DivSelfI) \
_(ModI) \
_(ModPowTwoI) \
_(ModSelfI) \
_(PowHalfD) \
_(AsmJSUInt32ToDouble) \
_(AsmJSUInt32ToFloat32) \