Skip to content

Commit ae8c46c

Browse files
authored
fix: Math.pow constant optimization behaves inconsistently in different versions of node (#2920)
use the pow function compiled by AS bootstrap to optimize the constant propagation of pow
1 parent f16b08f commit ae8c46c

File tree

5 files changed

+24
-10
lines changed

5 files changed

+24
-10
lines changed

package-lock.json

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"@types/node": "^18.19.75",
3333
"@typescript-eslint/eslint-plugin": "^5.62.0",
3434
"@typescript-eslint/parser": "^5.62.0",
35+
"as-float": "^1.0.1",
3536
"diff": "^7.0.0",
3637
"esbuild": "^0.25.0",
3738
"eslint": "^8.57.1",

src/glue/js/float.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ declare function f32_as_i32(value: f32): i32;
77
declare function i32_as_f32(value: i32): f32;
88
declare function f64_as_i64(value: f64): i64;
99
declare function i64_as_f64(value: i64): f64;
10+
declare function f64_pow(value: f64, exponent: f64): f64;

src/glue/js/float.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* @license Apache-2.0
44
*/
55

6+
import { f64_pow } from "as-float";
7+
68
/* eslint-disable no-undef */
79

810
const F64 = new Float64Array(1);
@@ -29,3 +31,5 @@ globalThis.i64_as_f64 = function i64_as_f64(value) {
2931
I32[1] = i64_high(value);
3032
return F64[0];
3133
};
34+
35+
globalThis.f64_pow = f64_pow;

src/util/math.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,10 @@ export function isPowerOf2(x: i32): bool {
1111
export function accuratePow64(x: f64, y: f64): f64 {
1212
if (!ASC_TARGET) { // ASC_TARGET == JS
1313
// Engines like V8, WebKit and SpiderMonkey uses powi fast path if exponent is integer
14-
// This speculative optimization leads to loose precisions like 10 ** 208 != 1e208
15-
// or/and 10 ** -5 != 1e-5 anymore. For avoid this behaviour we are forcing exponent
16-
// to fractional form and compensate this afterwards.
17-
if (isFinite(y) && Math.abs(y) >= 2 && Math.trunc(y) == y) {
18-
if (y < 0) {
19-
return Math.pow(x, y + 0.5) / Math.pow(x, 0.5);
20-
} else {
21-
return Math.pow(x, y - 0.5) * Math.pow(x, 0.5);
22-
}
23-
}
14+
// This speculative optimization leads to loose precisions like 10 ** -5 != 1e-5 anymore
15+
// and introduces inconsistencies between different engines and versions
16+
// For avoid this behavior we using bootstrap f64_pow function.
17+
return f64_pow(x, y);
2418
}
2519
return Math.pow(x, y);
2620
}

0 commit comments

Comments
 (0)