Skip to content

Commit 45e60d8

Browse files
authored
Support 64-bit integers in acorn passes (#24283)
I noticed that acorn-optimizer transforms for ASan, SAFE_HEAP and GROWABLE_HEAP didn't cover the 64-bit integer support enabled by `WASM_BIGINT` (`HEAP64` and `HEAPU64` memory views).
1 parent 75b0b54 commit 45e60d8

15 files changed

+174
-3
lines changed

src/growableHeap.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,18 @@ function GROWABLE_HEAP_U32() {
4242
}
4343
return HEAPU32;
4444
}
45+
function GROWABLE_HEAP_I64() {
46+
if (wasmMemory.buffer != HEAP8.buffer) {
47+
updateMemoryViews();
48+
}
49+
return HEAP64;
50+
}
51+
function GROWABLE_HEAP_U64() {
52+
if (wasmMemory.buffer != HEAP8.buffer) {
53+
updateMemoryViews();
54+
}
55+
return HEAPU64;
56+
}
4557
function GROWABLE_HEAP_F32() {
4658
if (wasmMemory.buffer != HEAP8.buffer) {
4759
updateMemoryViews();

src/lib/liblittle_endian_heap.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ var LibraryLittleEndianHeap = {
1111
$LE_HEAP_STORE_I32: (byteOffset, value) =>
1212
HEAP_DATA_VIEW.setInt32(byteOffset, value, true),
1313

14+
$LE_HEAP_STORE_U64: (byteOffset, value) =>
15+
HEAP_DATA_VIEW.setBigUint64(byteOffset, value, true),
16+
17+
$LE_HEAP_STORE_I64: (byteOffset, value) =>
18+
HEAP_DATA_VIEW.setBigInt64(byteOffset, value, true),
19+
1420
$LE_HEAP_STORE_F32: (byteOffset, value) =>
1521
HEAP_DATA_VIEW.setFloat32(byteOffset, value, true),
1622

@@ -29,6 +35,12 @@ var LibraryLittleEndianHeap = {
2935
$LE_HEAP_LOAD_I32: (byteOffset) =>
3036
HEAP_DATA_VIEW.getInt32(byteOffset, true),
3137

38+
$LE_HEAP_LOAD_U64: (byteOffset) =>
39+
HEAP_DATA_VIEW.getBigUint64(byteOffset, true),
40+
41+
$LE_HEAP_LOAD_I64: (byteOffset) =>
42+
HEAP_DATA_VIEW.getBigInt64(byteOffset, true),
43+
3244
$LE_HEAP_LOAD_F32: (byteOffset) =>
3345
HEAP_DATA_VIEW.getFloat32(byteOffset, true),
3446

src/modules.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,8 @@ function exportRuntimeSymbols() {
462462
'GROWABLE_HEAP_U16',
463463
'GROWABLE_HEAP_I32',
464464
'GROWABLE_HEAP_U32',
465+
'GROWABLE_HEAP_I64',
466+
'GROWABLE_HEAP_U64',
465467
'GROWABLE_HEAP_F32',
466468
'GROWABLE_HEAP_F64',
467469
);

src/runtime_asan.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ function _asan_js_load_4u(ptr) {
4343
return HEAPU32[ptr];
4444
}
4545
/** @suppress{duplicate} */
46+
function _asan_js_load_8(ptr) {
47+
if (runtimeInitialized) return __asan_c_load_8(ptr);
48+
return HEAP64[ptr];
49+
}
50+
/** @suppress{duplicate} */
51+
function _asan_js_load_8u(ptr) {
52+
if (runtimeInitialized) return BigInt.asUintN(64, __asan_c_load_8u(ptr));
53+
return HEAPU64[ptr];
54+
}
55+
/** @suppress{duplicate} */
4656
function _asan_js_load_f(ptr) {
4757
if (runtimeInitialized) return __asan_c_load_f(ptr);
4858
return HEAPF32[ptr];
@@ -84,6 +94,19 @@ function _asan_js_store_4u(ptr, val) {
8494
return HEAPU32[ptr] = val;
8595
}
8696
/** @suppress{duplicate} */
97+
function _asan_js_store_8(ptr, val) {
98+
if (runtimeInitialized) return __asan_c_store_8(ptr, val);
99+
return HEAP64[ptr] = val;
100+
}
101+
/** @suppress{duplicate} */
102+
function _asan_js_store_8u(ptr, val) {
103+
if (runtimeInitialized) {
104+
__asan_c_store_8u(ptr, val);
105+
return val;
106+
}
107+
return HEAPU64[ptr] = val;
108+
}
109+
/** @suppress{duplicate} */
87110
function _asan_js_store_f(ptr, val) {
88111
if (runtimeInitialized) return __asan_c_store_f(ptr, val);
89112
return HEAPF32[ptr] = val;

system/lib/asan_js.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ uint32_t _asan_c_load_4u(uintptr_t shifted) {
4545
uint32_t* ptr = (uint32_t*)(shifted << 2);
4646
return *ptr;
4747
}
48+
int64_t _asan_c_load_8(uintptr_t shifted) {
49+
int64_t* ptr = (int64_t*)(shifted << 3);
50+
return *ptr;
51+
}
52+
uint64_t _asan_c_load_8u(uintptr_t shifted) {
53+
uint64_t* ptr = (uint64_t*)(shifted << 3);
54+
return *ptr;
55+
}
4856
float _asan_c_load_f(uintptr_t shifted) {
4957
float* ptr = (float*)(shifted << 2);
5058
return *ptr;
@@ -79,6 +87,14 @@ uint32_t _asan_c_store_4u(uintptr_t shifted, uint32_t val) {
7987
uint32_t* ptr = (uint32_t*)(shifted << 2);
8088
return *ptr = val;
8189
}
90+
int64_t _asan_c_store_8(uintptr_t shifted, int64_t val) {
91+
int64_t* ptr = (int64_t*)(shifted << 3);
92+
return *ptr = val;
93+
}
94+
uint64_t _asan_c_store_8u(uintptr_t shifted, uint64_t val) {
95+
uint64_t* ptr = (uint64_t*)(shifted << 3);
96+
return *ptr = val;
97+
}
8298
float _asan_c_store_f(uintptr_t shifted, float val) {
8399
float* ptr = (float*)(shifted << 2);
84100
return *ptr = val;

test/js_optimizer/asanify-output.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ _asan_js_store_f(x, 7);
1414

1515
_asan_js_store_d(x, 8);
1616

17+
_asan_js_store_8(x, 9n);
18+
19+
_asan_js_store_8u(x, 10n);
20+
1721
a1 = _asan_js_load_1(x);
1822

1923
a2 = _asan_js_load_2(x);
@@ -30,6 +34,10 @@ a7 = _asan_js_load_f(x);
3034

3135
a8 = _asan_js_load_d(x);
3236

37+
a9 = _asan_js_load_8(x);
38+
39+
a10 = _asan_js_load_8u(x);
40+
3341
foo = _asan_js_store_1u(1337, 42);
3442

3543
_asan_js_load_2(bar(_asan_js_load_d(5)));

test/js_optimizer/asanify.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ HEAPU16[x] = 5;
77
HEAPU32[x] = 6;
88
HEAPF32[x] = 7;
99
HEAPF64[x] = 8;
10+
HEAP64[x] = 9n;
11+
HEAPU64[x] = 10n;
1012

1113
// loads
1214
a1 = HEAP8[x];
@@ -17,6 +19,8 @@ a5 = HEAPU16[x];
1719
a6 = HEAPU32[x];
1820
a7 = HEAPF32[x];
1921
a8 = HEAPF64[x];
22+
a9 = HEAP64[x];
23+
a10 = HEAPU64[x];
2024

2125
// store return value
2226
foo = HEAPU8[1337] = 42;

test/js_optimizer/growableHeap-output.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ function f() {
33
GROWABLE_HEAP_I32()[$0 >> 2] = $2 + 1;
44
$9 = GROWABLE_HEAP_U8()[$2 >> 0] | 0;
55
+GROWABLE_HEAP_F64()[x >> 3];
6+
GROWABLE_HEAP_I64()[x >> 3] = GROWABLE_HEAP_I64()[y >> 3];
67
}
78

89
function libraryFunc(ptr, val) {

test/js_optimizer/growableHeap.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ function f() {
33
HEAP32[$0 >> 2] = $2 + 1;
44
$9 = HEAPU8[$2 >> 0] | 0;
55
+HEAPF64[x >> 3];
6+
HEAP64[x >> 3] = HEAP64[y >> 3];
67
}
78

89
function libraryFunc(ptr, val) {

test/js_optimizer/safeHeap-output.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ SAFE_HEAP_STORE_D(x * 4, 7, 4);
1414

1515
SAFE_HEAP_STORE_D(x * 8, 8, 8);
1616

17+
SAFE_HEAP_STORE(x * 8, 9n, 8);
18+
19+
SAFE_HEAP_STORE(x * 8, 10n, 8);
20+
1721
a1 = SAFE_HEAP_LOAD(x, 1, 0);
1822

1923
a2 = SAFE_HEAP_LOAD(x * 2, 2, 0);
@@ -30,6 +34,10 @@ a7 = SAFE_HEAP_LOAD_D(x * 4, 4, 0);
3034

3135
a8 = SAFE_HEAP_LOAD_D(x * 8, 8, 0);
3236

37+
a9 = SAFE_HEAP_LOAD(x * 8, 8, 0);
38+
39+
a10 = SAFE_HEAP_LOAD(x * 8, 8, 1);
40+
3341
foo = SAFE_HEAP_STORE(1337, 42, 1);
3442

3543
SAFE_HEAP_LOAD(bar(SAFE_HEAP_LOAD_D(5 * 8, 8, 0)) * 2, 2, 0);

test/js_optimizer/safeHeap.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ HEAPU16[x] = 5;
77
HEAPU32[x] = 6;
88
HEAPF32[x] = 7;
99
HEAPF64[x] = 8;
10+
HEAP64[x] = 9n;
11+
HEAPU64[x] = 10n;
1012

1113
// loads
1214
a1 = HEAP8[x];
@@ -17,6 +19,8 @@ a5 = HEAPU16[x];
1719
a6 = HEAPU32[x];
1820
a7 = HEAPF32[x];
1921
a8 = HEAPF64[x];
22+
a9 = HEAP64[x];
23+
a10 = HEAPU64[x];
2024

2125
// store return value
2226
foo = HEAPU8[1337] = 42;

test/js_optimizer/unsignPointers-output.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,16 @@ HEAPU8.subarray(x >>> 0);
2727

2828
HEAPU8.subarray(x >>> 0, y >>> 0);
2929

30+
// something completely different
3031
process.versions.node;
3132

32-
// something completely different
3333
insideCall(HEAP32[x >>> 2]);
3434

3535
heap[x >>> 0];
3636

3737
HEAP[x >>> 0];
3838

39+
// but not this
3940
HeAp[x];
41+
42+
HEAP64[x >>> 3] = HEAPU64[y >>> 0];

test/js_optimizer/unsignPointers.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,16 @@ HEAPU8.subarray(x);
3030

3131
HEAPU8.subarray(x, y);
3232

33-
process.versions.node; // something completely different
33+
// something completely different
34+
process.versions.node;
3435

3536
insideCall(HEAP32[x >> 2]);
3637

3738
heap[x];
3839

3940
HEAP[x];
4041

41-
HeAp[x]; // but not this
42+
// but not this
43+
HeAp[x];
44+
45+
HEAP64[x >> 3] = HEAPU64[y];

tools/acorn-optimizer.mjs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,6 +1114,8 @@ function isEmscriptenHEAP(name) {
11141114
case 'HEAPU16':
11151115
case 'HEAP32':
11161116
case 'HEAPU32':
1117+
case 'HEAP64':
1118+
case 'HEAPU64':
11171119
case 'HEAPF32':
11181120
case 'HEAPF64': {
11191121
return true;
@@ -1182,6 +1184,16 @@ function littleEndianHeap(ast) {
11821184
makeCallExpression(node, 'LE_HEAP_STORE_U32', [multiply(idx, 4), value]);
11831185
break;
11841186
}
1187+
case 'HEAP64': {
1188+
// change "name[idx] = value" to "LE_HEAP_STORE_I64(idx*8, value)"
1189+
makeCallExpression(node, 'LE_HEAP_STORE_I64', [multiply(idx, 8), value]);
1190+
break;
1191+
}
1192+
case 'HEAPU64': {
1193+
// change "name[idx] = value" to "LE_HEAP_STORE_U64(idx*8, value)"
1194+
makeCallExpression(node, 'LE_HEAP_STORE_U64', [multiply(idx, 8), value]);
1195+
break;
1196+
}
11851197
case 'HEAPF32': {
11861198
// change "name[idx] = value" to "LE_HEAP_STORE_F32(idx*4, value)"
11871199
makeCallExpression(node, 'LE_HEAP_STORE_F32', [multiply(idx, 4), value]);
@@ -1250,6 +1262,16 @@ function littleEndianHeap(ast) {
12501262
makeCallExpression(node, 'LE_HEAP_LOAD_U32', [multiply(idx, 4)]);
12511263
break;
12521264
}
1265+
case 'HEAP64': {
1266+
// change "name[idx]" to "LE_HEAP_LOAD_I64(idx*8)"
1267+
makeCallExpression(node, 'LE_HEAP_LOAD_I64', [multiply(idx, 8)]);
1268+
break;
1269+
}
1270+
case 'HEAPU64': {
1271+
// change "name[idx]" to "LE_HEAP_LOAD_U64(idx*8)"
1272+
makeCallExpression(node, 'LE_HEAP_LOAD_U64', [multiply(idx, 8)]);
1273+
break;
1274+
}
12531275
case 'HEAPF32': {
12541276
// change "name[idx]" to "LE_HEAP_LOAD_F32(idx*4)"
12551277
makeCallExpression(node, 'LE_HEAP_LOAD_F32', [multiply(idx, 4)]);
@@ -1328,6 +1350,14 @@ function growableHeap(ast) {
13281350
makeCallExpression(node, 'GROWABLE_HEAP_U32', []);
13291351
break;
13301352
}
1353+
case 'HEAP64': {
1354+
makeCallExpression(node, 'GROWABLE_HEAP_I64', []);
1355+
break;
1356+
}
1357+
case 'HEAPU64': {
1358+
makeCallExpression(node, 'GROWABLE_HEAP_U64', []);
1359+
break;
1360+
}
13311361
case 'HEAPF32': {
13321362
makeCallExpression(node, 'GROWABLE_HEAP_F32', []);
13331363
break;
@@ -1470,6 +1500,14 @@ function asanify(ast) {
14701500
makeCallExpression(node, '_asan_js_store_4u', [ptr, value]);
14711501
break;
14721502
}
1503+
case 'HEAP64': {
1504+
makeCallExpression(node, '_asan_js_store_8', [ptr, value]);
1505+
break;
1506+
}
1507+
case 'HEAPU64': {
1508+
makeCallExpression(node, '_asan_js_store_8u', [ptr, value]);
1509+
break;
1510+
}
14731511
case 'HEAPF32': {
14741512
makeCallExpression(node, '_asan_js_store_f', [ptr, value]);
14751513
break;
@@ -1515,6 +1553,14 @@ function asanify(ast) {
15151553
makeCallExpression(node, '_asan_js_load_4u', [ptr]);
15161554
break;
15171555
}
1556+
case 'HEAP64': {
1557+
makeCallExpression(node, '_asan_js_load_8', [ptr]);
1558+
break;
1559+
}
1560+
case 'HEAPU64': {
1561+
makeCallExpression(node, '_asan_js_load_8u', [ptr]);
1562+
break;
1563+
}
15181564
case 'HEAPF32': {
15191565
makeCallExpression(node, '_asan_js_load_f', [ptr]);
15201566
break;
@@ -1585,6 +1631,15 @@ function safeHeap(ast) {
15851631
]);
15861632
break;
15871633
}
1634+
case 'HEAP64':
1635+
case 'HEAPU64': {
1636+
makeCallExpression(node, 'SAFE_HEAP_STORE', [
1637+
multiply(ptr, 8),
1638+
value,
1639+
createLiteral(8),
1640+
]);
1641+
break;
1642+
}
15881643
case 'HEAPF32': {
15891644
makeCallExpression(node, 'SAFE_HEAP_STORE_D', [
15901645
multiply(ptr, 4),
@@ -1654,6 +1709,22 @@ function safeHeap(ast) {
16541709
]);
16551710
break;
16561711
}
1712+
case 'HEAP64': {
1713+
makeCallExpression(node, 'SAFE_HEAP_LOAD', [
1714+
multiply(ptr, 8),
1715+
createLiteral(8),
1716+
createLiteral(0),
1717+
]);
1718+
break;
1719+
}
1720+
case 'HEAPU64': {
1721+
makeCallExpression(node, 'SAFE_HEAP_LOAD', [
1722+
multiply(ptr, 8),
1723+
createLiteral(8),
1724+
createLiteral(1),
1725+
]);
1726+
break;
1727+
}
16571728
case 'HEAPF32': {
16581729
makeCallExpression(node, 'SAFE_HEAP_LOAD_D', [
16591730
multiply(ptr, 4),

tools/emscripten.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,12 @@
4444
'_asan_c_load_1', '_asan_c_load_1u',
4545
'_asan_c_load_2', '_asan_c_load_2u',
4646
'_asan_c_load_4', '_asan_c_load_4u',
47+
'_asan_c_load_8', '_asan_c_load_8u',
4748
'_asan_c_load_f', '_asan_c_load_d',
4849
'_asan_c_store_1', '_asan_c_store_1u',
4950
'_asan_c_store_2', '_asan_c_store_2u',
5051
'_asan_c_store_4', '_asan_c_store_4u',
52+
'_asan_c_store_8', '_asan_c_store_8u',
5153
'_asan_c_store_f', '_asan_c_store_d',
5254
]
5355

0 commit comments

Comments
 (0)