Skip to content

Commit ff57030

Browse files
authored
Change %mulint primitive behavior (#7358)
* Change `%mulint` primitive behavior * add changelog
1 parent 2fb6cc8 commit ff57030

32 files changed

+54
-58
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
- Replace ~date with ~day in Date.make\*. https://github.com/rescript-lang/rescript/pull/7324
2929
- Remove `-bs-jsx-mode`. https://github.com/rescript-lang/rescript/pull/7327
3030
- Drop Node.js version <20 support, as it is reaching End-of-Life. https://github.com/rescript-lang/rescript-compiler/pull/7354
31+
- Treat `int` multiplication as a normal int32 operation instead of using `Math.imul`. https://github.com/rescript-lang/rescript/pull/7358
3132

3233
#### :house: Internal
3334

compiler/core/js_exp_make.ml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,14 +1607,8 @@ let int32_mul ?comment (e1 : J.expression) (e2 : J.expression) : J.expression =
16071607
| {expression_desc = Number (Int {i = i0}); _}, e ->
16081608
let i = is_pos_pow i0 in
16091609
if i >= 0 then int32_lsl e (small_int i)
1610-
else
1611-
call ?comment ~info:Js_call_info.builtin_runtime_call
1612-
(dot (js_global "Math") Literals.imul)
1613-
[e1; e2]
1614-
| _ ->
1615-
call ?comment ~info:Js_call_info.builtin_runtime_call
1616-
(dot (js_global "Math") Literals.imul)
1617-
[e1; e2]
1610+
else to_int32 (float_mul ?comment e1 e2)
1611+
| _ -> to_int32 (float_mul ?comment e1 e2)
16181612

16191613
let unchecked_int32_mul ?comment e1 e2 : J.expression =
16201614
{comment; expression_desc = Bin (Mul, e1, e2)}

compiler/ext/literals.ml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ let runtime = "runtime" (* runtime directory *)
5050

5151
let stdlib = "stdlib"
5252

53-
let imul = "imul" (* signed int32 mul *)
54-
5553
let setter_suffix = "#="
5654

5755
let setter_suffix_len = String.length setter_suffix

lib/es6/Primitive_hash.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ function unsafe_pop(q) {
3636
RE_EXN_ID: "Assert_failure",
3737
_1: [
3838
"Primitive_hash.res",
39-
70,
39+
73,
4040
12
4141
],
4242
Error: new Error()

lib/es6/Stdlib_Int.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ function range(start, end, optionsOpt) {
4646
let range$2 = options.inclusive === true ? range$1 + 1 | 0 : range$1;
4747
length = Math.ceil(range$2 / abs(step)) | 0;
4848
}
49-
return Stdlib_Array.fromInitializer(length, i => start + Math.imul(i, step) | 0);
49+
return Stdlib_Array.fromInitializer(length, i => start + (i * step | 0) | 0);
5050
}
5151

5252
function rangeWithOptions(start, end, options) {

lib/js/Primitive_hash.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ function unsafe_pop(q) {
3636
RE_EXN_ID: "Assert_failure",
3737
_1: [
3838
"Primitive_hash.res",
39-
70,
39+
73,
4040
12
4141
],
4242
Error: new Error()

lib/js/Stdlib_Int.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ function range(start, end, optionsOpt) {
4646
let range$2 = options.inclusive === true ? range$1 + 1 | 0 : range$1;
4747
length = Math.ceil(range$2 / abs(step)) | 0;
4848
}
49-
return Stdlib_Array.fromInitializer(length, i => start + Math.imul(i, step) | 0);
49+
return Stdlib_Array.fromInitializer(length, i => start + (i * step | 0) | 0);
5050
}
5151

5252
function rangeWithOptions(start, end, options) {

runtime/Primitive_hash.res

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ module String = Primitive_string_extern
2929

3030
@send external charCodeAt: (string, int) => int = "charCodeAt"
3131

32+
// Multiply int32 with C-style overflow behavior
33+
external imul: (int, int) => int = "Math.imul"
34+
3235
type rec cell<'a> = {
3336
content: 'a,
3437
mutable next: option<cell<'a>>,
@@ -85,19 +88,19 @@ let rotl32 = (x: int, n) => lor(lsl(x, n), lsr(x, 32 - n))
8588

8689
let hash_mix_int = (h, d) => {
8790
let d = ref(d)
88-
d.contents = d.contents * 0xcc9e2d51
91+
d.contents = imul(d.contents, 0xcc9e2d51)
8992
d.contents = rotl32(d.contents, 15)
90-
d.contents = d.contents * 0x1b873593
93+
d.contents = imul(d.contents, 0x1b873593)
9194
let h = ref(lxor(h, d.contents))
9295
h.contents = rotl32(h.contents, 13)
9396
h.contents + lsl(h.contents, 2) + 0xe6546b64
9497
}
9598

9699
let hash_final_mix = h => {
97100
let h = ref(lxor(h, lsr(h, 16)))
98-
h.contents = h.contents * 0x85ebca6b
101+
h.contents = imul(h.contents, 0x85ebca6b)
99102
h.contents = lxor(h.contents, lsr(h.contents, 13))
100-
h.contents = h.contents * 0xc2b2ae35
103+
h.contents = imul(h.contents, 0xc2b2ae35)
101104
lxor(h.contents, lsr(h.contents, 16))
102105
}
103106

tests/gentype_tests/typescript-react-example/src/Records.res.js

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

tests/gentype_tests/typescript-react-example/src/nested/Tuples.res.js

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

tests/tests/src/a_scope_bug.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
function odd(_z) {
55
while (true) {
66
let z = _z;
7-
let even = Math.imul(z, z);
7+
let even = z * z | 0;
88
let a = (even + 4 | 0) + even | 0;
99
console.log(a.toString());
1010
_z = 32;

tests/tests/src/bdd.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ let seed = {
348348
};
349349

350350
function random() {
351-
seed.contents = Math.imul(seed.contents, 25173) + 17431 | 0;
351+
seed.contents = (seed.contents * 25173 | 0) + 17431 | 0;
352352
return (seed.contents & 1) > 0;
353353
}
354354

tests/tests/src/belt_list_test.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ function sum2(xs, ys) {
2929

3030
Mocha.describe("Belt_list_test", () => {
3131
Mocha.test("makeBy", () => {
32-
let u = Belt_List.makeBy(5, i => Math.imul(i, i));
33-
let f = i => Test_utils.eq("File \"belt_list_test.res\", line 23, characters 20-27", Belt_List.getExn(u, i), Math.imul(i, i));
32+
let u = Belt_List.makeBy(5, i => i * i | 0);
33+
let f = i => Test_utils.eq("File \"belt_list_test.res\", line 23, characters 20-27", Belt_List.getExn(u, i), i * i | 0);
3434
for (let i = 0; i <= 4; ++i) {
3535
f(i);
3636
}

tests/tests/src/core/Core_ArrayTests.mjs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ Test.run([
257257
6
258258
], n => {
259259
if (n % 2 === 0) {
260-
return Math.imul(n, n);
260+
return n * n | 0;
261261
}
262262

263263
}), eq, [
@@ -293,7 +293,7 @@ Test.run([
293293
"filterMap - empty"
294294
], Stdlib_Array.filterMap([], n => {
295295
if (n % 2 === 0) {
296-
return Math.imul(n, n);
296+
return n * n | 0;
297297
}
298298

299299
}), eq, []);
@@ -406,7 +406,7 @@ Test.run([
406406
"findMap - empty"
407407
], Stdlib_Array.findMap([], n => {
408408
if (n % 2 === 0) {
409-
return Math.imul(n, n);
409+
return n * n | 0;
410410
}
411411

412412
}), eq, undefined);

tests/tests/src/core/Core_ResultTests.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ Test.run([
6363
], Stdlib_Result.mapError({
6464
TAG: "Ok",
6565
_0: 5
66-
}, i => Math.imul(i, 3)), eq, {
66+
}, i => i * 3 | 0), eq, {
6767
TAG: "Ok",
6868
_0: 5
6969
});
@@ -79,7 +79,7 @@ Test.run([
7979
], Stdlib_Result.mapError({
8080
TAG: "Error",
8181
_0: 5
82-
}, i => Math.imul(i, 3)), eq, {
82+
}, i => i * 3 | 0), eq, {
8383
TAG: "Error",
8484
_0: 15
8585
});

tests/tests/src/dollar_escape_test.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ function $$(x, y) {
3232
let v = 3;
3333

3434
function $$$plus(x, y) {
35-
return Math.imul(x, y);
35+
return x * y | 0;
3636
}
3737

3838
let u = 3;

tests/tests/src/ext_pervasives_test.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function $$finally(v, action, f) {
1616
function hash_variant(s) {
1717
let accu = 0;
1818
for (let i = 0, i_finish = s.length; i < i_finish; ++i) {
19-
accu = Math.imul(223, accu) + s.codePointAt(i) | 0;
19+
accu = (223 * accu | 0) + s.codePointAt(i) | 0;
2020
}
2121
accu = accu & 2147483647;
2222
if (accu > 1073741823) {

tests/tests/src/ffi_arity_test.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as Mt from "./mt.mjs";
44

55
function f(v) {
66
if (v % 2 === 0) {
7-
return v => Math.imul(v, v);
7+
return v => v * v | 0;
88
} else {
99
return v => v + v | 0;
1010
}

tests/tests/src/for_loop_test.mjs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ function for_5(x, u) {
4040
};
4141
let arr = Belt_Array.map(x, param => (() => {}));
4242
for (let i = 0, i_finish = x.length; i < i_finish; ++i) {
43-
let k = Math.imul((u << 1), u);
43+
let k = (u << 1) * u | 0;
4444
arr[i] = () => {
4545
v.contents = v.contents + k | 0;
4646
};
@@ -68,7 +68,7 @@ function for_6(x, u) {
6868
contents: 0
6969
};
7070
for (let i = 0, i_finish = x.length; i < i_finish; ++i) {
71-
let k = Math.imul((u << 1), u);
71+
let k = (u << 1) * u | 0;
7272
let h = (v5.contents << 1);
7373
v2.contents = v2.contents + 1 | 0;
7474
arr[i] = () => {
@@ -93,7 +93,7 @@ function for_7() {
9393
let arr = Belt_Array.make(21, () => {});
9494
for (let i = 0; i <= 6; ++i) {
9595
for (let j = 0; j <= 2; ++j) {
96-
arr[Math.imul(i, 3) + j | 0] = () => {
96+
arr[(i * 3 | 0) + j | 0] = () => {
9797
v.contents = (v.contents + i | 0) + j | 0;
9898
};
9999
}
@@ -111,7 +111,7 @@ function for_8() {
111111
let k = (i << 1);
112112
for (let j = 0; j <= 2; ++j) {
113113
let h = i + j | 0;
114-
arr[Math.imul(i, 3) + j | 0] = () => {
114+
arr[(i * 3 | 0) + j | 0] = () => {
115115
v.contents = (((v.contents + i | 0) + j | 0) + h | 0) + k | 0;
116116
};
117117
}

tests/tests/src/gpr_1822_test.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ let myShape = {
3232

3333
let area;
3434

35-
area = myShape.TAG === "Circle" ? 100 * 3.14 : Math.imul(10, myShape._1);
35+
area = myShape.TAG === "Circle" ? 100 * 3.14 : 10 * myShape._1 | 0;
3636

3737
eq("File \"gpr_1822_test.res\", line 23, characters 3-10", area, 314);
3838

tests/tests/src/gpr_2413_test.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function f(x) {
1616
break;
1717
}
1818
let a$3 = x._0._0;
19-
return Math.imul(a$3, a$3);
19+
return a$3 * a$3 | 0;
2020
}
2121

2222
function ff(c) {

tests/tests/src/gpr_3536_test.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ function xx(obj, a0, a1, a2, a3, a4, a5) {
2222

2323
eq("File \"gpr_3536_test.res\", line 18, characters 12-19", 5, 5);
2424

25-
eq("File \"gpr_3536_test.res\", line 20, characters 12-19", xx(3, (prim0, prim1) => prim0 - prim1 | 0, 2, (prim0, prim1) => prim0 + prim1 | 0, 4, (prim0, prim1) => Math.imul(prim0, prim1), 3), 11);
25+
eq("File \"gpr_3536_test.res\", line 20, characters 12-19", xx(3, (prim0, prim1) => prim0 - prim1 | 0, 2, (prim0, prim1) => prim0 + prim1 | 0, 4, (prim0, prim1) => prim0 * prim1 | 0, 3), 11);
2626

2727
Mt.from_pair_suites("Gpr_3536_test", suites.contents);
2828

tests/tests/src/int_overflow_test.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import * as Mt from "./mt.mjs";
55
function hash_variant(s) {
66
let accu = 0;
77
for (let i = 0, i_finish = s.length; i < i_finish; ++i) {
8-
accu = Math.imul(223, accu) + s.codePointAt(i) & 2147483647;
8+
accu = (223 * accu | 0) + s.codePointAt(i) & 2147483647;
99
}
1010
if (accu > 1073741823) {
1111
return accu - -2147483648 | 0;
@@ -17,7 +17,7 @@ function hash_variant(s) {
1717
function hash_variant2(s) {
1818
let accu = 0;
1919
for (let i = 0, i_finish = s.length; i < i_finish; ++i) {
20-
accu = Math.imul(223, accu) + s.codePointAt(i) | 0;
20+
accu = (223 * accu | 0) + s.codePointAt(i) | 0;
2121
}
2222
accu = accu & 2147483647;
2323
if (accu > 1073741823) {

tests/tests/src/mario_game.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1999,7 +1999,7 @@ function process_collision(dir, c1, c2, state) {
19991999
evolve_enemy(o1.dir, typ, s2, o2, context)
20002000
];
20012001
}
2002-
let score = Math.imul(100, state.multiplier);
2002+
let score = 100 * state.multiplier | 0;
20032003
update_score(state, score);
20042004
o2.score = score;
20052005
state.multiplier = (state.multiplier << 1);

tests/tests/src/miss_colon_test.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ function $star$colon(_f, _g) {
5555
if (g.TAG === "Int") {
5656
return {
5757
TAG: "Int",
58-
_0: Math.imul(n, g._0)
58+
_0: n * g._0 | 0
5959
};
6060
}
6161
if (n === 0) {

tests/tests/src/recursive_module_test.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ function fact(n) {
6969
if (n <= 1) {
7070
return 1;
7171
} else {
72-
return Math.imul(n, M.fact(n - 1 | 0));
72+
return n * M.fact(n - 1 | 0) | 0;
7373
}
7474
}
7575

tests/tests/src/recursive_records_test.mjs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ rec_cell.next = rec_cell;
2525
function f0(x) {
2626
let rec_cell = {};
2727
Primitive_object.updateDummy(rec_cell, {
28-
content: Math.imul(x, x) - 6 | 0,
28+
content: (x * x | 0) - 6 | 0,
2929
next: rec_cell
3030
});
3131
return rec_cell;
@@ -49,7 +49,7 @@ function f2(x) {
4949
let rec_cell2 = {};
5050
Primitive_object.updateDummy(rec_cell2, {
5151
TAG: "Cons",
52-
content: Math.imul(x, x) - 6 | 0,
52+
content: (x * x | 0) - 6 | 0,
5353
next: rec_cell2
5454
});
5555
return rec_cell2;
@@ -93,7 +93,7 @@ rec_cell3.tl = rec_cell3;
9393
function f3(x) {
9494
let rec_cell3 = {};
9595
Primitive_object.updateDummy(rec_cell3, {
96-
hd: Math.imul(x, x) - 6 | 0,
96+
hd: (x * x | 0) - 6 | 0,
9797
tl: rec_cell3
9898
});
9999
return rec_cell3;

tests/tests/src/tagged_template_test.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ function foo(strings, values) {
2626
let res = "";
2727
let valueCount = values.length;
2828
for (let i = 0; i < valueCount; ++i) {
29-
res = res + Primitive_array.get(strings, i) + Math.imul(Primitive_array.get(values, i), 10).toString();
29+
res = res + Primitive_array.get(strings, i) + (Primitive_array.get(values, i) * 10 | 0).toString();
3030
}
3131
return res + Primitive_array.get(strings, valueCount);
3232
}

tests/tests/src/test_export2.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33

44
function f(x, y) {
5-
return Math.imul(x, y);
5+
return x * y | 0;
66
}
77

88
export {

0 commit comments

Comments
 (0)