Source code

Revision control

Copy as Markdown

Other Tools

// |jit-test| --disable-main-thread-denormals; skip-if: !getBuildConfiguration("can-disable-main-thread-denormals")
// A denormal built from raw bits survives here even though a denormal literal
// would not.
const f64 = new Float64Array(1);
const u32 = new Uint32Array(f64.buffer);
function fromBits(hi, lo) {
u32[0] = lo >>> 0;
u32[1] = hi >>> 0;
return f64[0];
}
const denormals = [
fromBits(0, 1), // smallest positive denormal
fromBits(0x80000000, 1), // smallest negative denormal
fromBits(0x000fffff, 0xffffffff), // largest positive denormal
fromBits(0x00080000, 0),
fromBits(0, 0x80000000),
];
// Any NaN produced by a Math operation must be the canonical NaN.
//
// The canonical NaN bit pattern is hardware-determined, so read it off the
// engine's own NaN value instead of hardcoding it.
f64[0] = NaN;
const canonHi = u32[1] >>> 0;
const canonLo = u32[0] >>> 0;
function assertCanonicalIfNaN(r) {
if (Number.isNaN(r)) {
f64[0] = r;
const hi = u32[1] >>> 0;
const lo = u32[0] >>> 0;
// A canonical NaN is allowed to have its sign bit set, so mask it off
// before comparing (see Value::setDoubleAssumeCanonicalNaN).
assertEq(hi & 0x7fffffff, canonHi & 0x7fffffff);
assertEq(lo, canonLo);
}
}
function test() {
// An array with all unary Math functions. Skip sumPrecise because it requires
// an iterable.
const unary = Object.getOwnPropertyNames(Math).filter(name => {
return typeof Math[name] === "function" && Math[name].length === 1 && name !== "sumPrecise";
}).map(name => Math[name]);
for (const fn of unary) {
for (const x of denormals) {
assertCanonicalIfNaN(fn(x));
}
}
for (const fn of [Math.pow, Math.atan2, Math.hypot]) {
for (const a of denormals) {
for (const b of denormals) {
assertCanonicalIfNaN(fn(a, b));
}
}
}
for (const arr of [denormals, [1, NaN, 2], [Infinity, -Infinity],
[1e308, 1e308, 1e308], []]) {
assertCanonicalIfNaN(Math.sumPrecise(arr));
}
}
// Run in a loop so the operations are also exercised after JIT compilation.
for (let i = 0; i < 100; i++) {
test();
}