Skip to content

Commit 8ae086d

Browse files
authored
fix: Bindings: Expect memory growth when lowering references (#2568)
1 parent cb982b1 commit 8ae086d

File tree

5 files changed

+65
-38
lines changed

5 files changed

+65
-38
lines changed

Diff for: src/bindings/js.ts

+41-26
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ export class JSBuilder extends ExportsWalker {
119119
private needsRetain: bool = false;
120120
private needsRelease: bool = false;
121121
private needsNotNull: bool = false;
122+
private needsStoreRef: bool = false;
122123

123124
private deferredLifts: Set<Element> = new Set();
124125
private deferredLowers: Set<Element> = new Set();
@@ -851,6 +852,12 @@ export class JSBuilder extends ExportsWalker {
851852
}
852853
`);
853854
}
855+
if (this.needsStoreRef) {
856+
sb.push(` function __store_ref(pointer, value) {
857+
new Uint32Array(memory.buffer)[pointer >>> 2] = value;
858+
}
859+
`);
860+
}
854861

855862
let exportStart = options.exportStart;
856863
if (exportStart) {
@@ -1177,36 +1184,44 @@ export class JSBuilder extends ExportsWalker {
11771184
skipTail = false;
11781185
}
11791186
if (valueType.isInternalReference) {
1187+
// The RHS is typically another lowering to memory, which may trigger
1188+
// memory growth. Use a helper closure to delay evaluation of `memory`.
1189+
this.needsStoreRef = true;
1190+
sb.push("__store_ref(");
1191+
sb.push(targetName);
1192+
sb.push(", ");
1193+
this.makeLowerToValue(valueName, valueType, sb);
1194+
sb.push(")");
1195+
if (!skipTail) sb.push("; }");
1196+
return;
1197+
}
1198+
if (valueType == Type.i8) {
1199+
sb.push("new Int8Array(memory.buffer)[");
1200+
} else if (valueType == Type.u8 || valueType == Type.bool) {
1201+
sb.push("new Uint8Array(memory.buffer)[");
1202+
} else if (valueType == Type.i16) {
1203+
sb.push("new Int16Array(memory.buffer)[");
1204+
} else if (valueType == Type.u16) {
1205+
sb.push("new Uint16Array(memory.buffer)[");
1206+
} else if (valueType == Type.i32 || valueType == Type.isize32) {
1207+
sb.push("new Int32Array(memory.buffer)[");
1208+
} else if (valueType == Type.u32 || valueType == Type.usize32) {
11801209
sb.push("new Uint32Array(memory.buffer)[");
1210+
} else if (valueType == Type.i64 || valueType == Type.isize64) {
1211+
sb.push("new BigInt64Array(memory.buffer)[");
1212+
} else if (valueType == Type.u64 || valueType == Type.usize64) {
1213+
sb.push("new BigUint64Array(memory.buffer)[");
1214+
} else if (valueType == Type.f32) {
1215+
sb.push("new Float32Array(memory.buffer)[");
1216+
} else if (valueType == Type.f64) {
1217+
sb.push("new Float64Array(memory.buffer)[");
11811218
} else {
1182-
if (valueType == Type.i8) {
1183-
sb.push("new Int8Array(memory.buffer)[");
1184-
} else if (valueType == Type.u8 || valueType == Type.bool) {
1185-
sb.push("new Uint8Array(memory.buffer)[");
1186-
} else if (valueType == Type.i16) {
1187-
sb.push("new Int16Array(memory.buffer)[");
1188-
} else if (valueType == Type.u16) {
1189-
sb.push("new Uint16Array(memory.buffer)[");
1190-
} else if (valueType == Type.i32 || valueType == Type.isize32) {
1191-
sb.push("new Int32Array(memory.buffer)[");
1192-
} else if (valueType == Type.u32 || valueType == Type.usize32) {
1193-
sb.push("new Uint32Array(memory.buffer)[");
1194-
} else if (valueType == Type.i64 || valueType == Type.isize64) {
1195-
sb.push("new BigInt64Array(memory.buffer)[");
1196-
} else if (valueType == Type.u64 || valueType == Type.usize64) {
1197-
sb.push("new BigUint64Array(memory.buffer)[");
1198-
} else if (valueType == Type.f32) {
1199-
sb.push("new Float32Array(memory.buffer)[");
1200-
} else if (valueType == Type.f64) {
1201-
sb.push("new Float64Array(memory.buffer)[");
1219+
if (skipTail) {
1220+
sb.push("(() => { throw Error(\"unsupported type\") })()");
12021221
} else {
1203-
if (skipTail) {
1204-
sb.push("(() => { throw Error(\"unsupported type\") })()");
1205-
} else {
1206-
sb.push("throw Error(\"unsupported type\"); }");
1207-
}
1208-
return;
1222+
sb.push("throw Error(\"unsupported type\"); }");
12091223
}
1224+
return;
12101225
}
12111226
sb.push(targetName);
12121227
sb.push(" >>> ");

Diff for: tests/compiler/bindings/esm.debug.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,9 @@ async function instantiate(module, imports = {}) {
220220
new Uint8Array(memory.buffer)[pointer + 40 >>> 0] = value.k ? 1 : 0;
221221
new Float32Array(memory.buffer)[pointer + 44 >>> 2] = value.l;
222222
new Float64Array(memory.buffer)[pointer + 48 >>> 3] = value.m;
223-
new Uint32Array(memory.buffer)[pointer + 56 >>> 2] = __lowerString(value.n);
224-
new Uint32Array(memory.buffer)[pointer + 60 >>> 2] = __lowerTypedArray(Uint8Array, 13, 0, value.o);
225-
new Uint32Array(memory.buffer)[pointer + 64 >>> 2] = __lowerArray((pointer, value) => { new Uint32Array(memory.buffer)[pointer >>> 2] = __lowerString(value) || __notnull(); }, 14, 2, value.p);
223+
__store_ref(pointer + 56, __lowerString(value.n));
224+
__store_ref(pointer + 60, __lowerTypedArray(Uint8Array, 13, 0, value.o));
225+
__store_ref(pointer + 64, __lowerArray((pointer, value) => { __store_ref(pointer, __lowerString(value) || __notnull()); }, 14, 2, value.p));
226226
exports.__unpin(pointer);
227227
return pointer;
228228
}
@@ -382,6 +382,9 @@ async function instantiate(module, imports = {}) {
382382
function __notnull() {
383383
throw TypeError("value must not be null");
384384
}
385+
function __store_ref(pointer, value) {
386+
new Uint32Array(memory.buffer)[pointer >>> 2] = value;
387+
}
385388
exports._start();
386389
return adaptedExports;
387390
}

Diff for: tests/compiler/bindings/esm.release.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,9 @@ async function instantiate(module, imports = {}) {
220220
new Uint8Array(memory.buffer)[pointer + 40 >>> 0] = value.k ? 1 : 0;
221221
new Float32Array(memory.buffer)[pointer + 44 >>> 2] = value.l;
222222
new Float64Array(memory.buffer)[pointer + 48 >>> 3] = value.m;
223-
new Uint32Array(memory.buffer)[pointer + 56 >>> 2] = __lowerString(value.n);
224-
new Uint32Array(memory.buffer)[pointer + 60 >>> 2] = __lowerTypedArray(Uint8Array, 13, 0, value.o);
225-
new Uint32Array(memory.buffer)[pointer + 64 >>> 2] = __lowerArray((pointer, value) => { new Uint32Array(memory.buffer)[pointer >>> 2] = __lowerString(value) || __notnull(); }, 14, 2, value.p);
223+
__store_ref(pointer + 56, __lowerString(value.n));
224+
__store_ref(pointer + 60, __lowerTypedArray(Uint8Array, 13, 0, value.o));
225+
__store_ref(pointer + 64, __lowerArray((pointer, value) => { __store_ref(pointer, __lowerString(value) || __notnull()); }, 14, 2, value.p));
226226
exports.__unpin(pointer);
227227
return pointer;
228228
}
@@ -382,6 +382,9 @@ async function instantiate(module, imports = {}) {
382382
function __notnull() {
383383
throw TypeError("value must not be null");
384384
}
385+
function __store_ref(pointer, value) {
386+
new Uint32Array(memory.buffer)[pointer >>> 2] = value;
387+
}
385388
exports._start();
386389
return adaptedExports;
387390
}

Diff for: tests/compiler/bindings/raw.debug.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,9 @@ export async function instantiate(module, imports = {}) {
220220
new Uint8Array(memory.buffer)[pointer + 40 >>> 0] = value.k ? 1 : 0;
221221
new Float32Array(memory.buffer)[pointer + 44 >>> 2] = value.l;
222222
new Float64Array(memory.buffer)[pointer + 48 >>> 3] = value.m;
223-
new Uint32Array(memory.buffer)[pointer + 56 >>> 2] = __lowerString(value.n);
224-
new Uint32Array(memory.buffer)[pointer + 60 >>> 2] = __lowerTypedArray(Uint8Array, 13, 0, value.o);
225-
new Uint32Array(memory.buffer)[pointer + 64 >>> 2] = __lowerArray((pointer, value) => { new Uint32Array(memory.buffer)[pointer >>> 2] = __lowerString(value) || __notnull(); }, 14, 2, value.p);
223+
__store_ref(pointer + 56, __lowerString(value.n));
224+
__store_ref(pointer + 60, __lowerTypedArray(Uint8Array, 13, 0, value.o));
225+
__store_ref(pointer + 64, __lowerArray((pointer, value) => { __store_ref(pointer, __lowerString(value) || __notnull()); }, 14, 2, value.p));
226226
exports.__unpin(pointer);
227227
return pointer;
228228
}
@@ -382,6 +382,9 @@ export async function instantiate(module, imports = {}) {
382382
function __notnull() {
383383
throw TypeError("value must not be null");
384384
}
385+
function __store_ref(pointer, value) {
386+
new Uint32Array(memory.buffer)[pointer >>> 2] = value;
387+
}
385388
exports._start();
386389
return adaptedExports;
387390
}

Diff for: tests/compiler/bindings/raw.release.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,9 @@ export async function instantiate(module, imports = {}) {
220220
new Uint8Array(memory.buffer)[pointer + 40 >>> 0] = value.k ? 1 : 0;
221221
new Float32Array(memory.buffer)[pointer + 44 >>> 2] = value.l;
222222
new Float64Array(memory.buffer)[pointer + 48 >>> 3] = value.m;
223-
new Uint32Array(memory.buffer)[pointer + 56 >>> 2] = __lowerString(value.n);
224-
new Uint32Array(memory.buffer)[pointer + 60 >>> 2] = __lowerTypedArray(Uint8Array, 13, 0, value.o);
225-
new Uint32Array(memory.buffer)[pointer + 64 >>> 2] = __lowerArray((pointer, value) => { new Uint32Array(memory.buffer)[pointer >>> 2] = __lowerString(value) || __notnull(); }, 14, 2, value.p);
223+
__store_ref(pointer + 56, __lowerString(value.n));
224+
__store_ref(pointer + 60, __lowerTypedArray(Uint8Array, 13, 0, value.o));
225+
__store_ref(pointer + 64, __lowerArray((pointer, value) => { __store_ref(pointer, __lowerString(value) || __notnull()); }, 14, 2, value.p));
226226
exports.__unpin(pointer);
227227
return pointer;
228228
}
@@ -382,6 +382,9 @@ export async function instantiate(module, imports = {}) {
382382
function __notnull() {
383383
throw TypeError("value must not be null");
384384
}
385+
function __store_ref(pointer, value) {
386+
new Uint32Array(memory.buffer)[pointer >>> 2] = value;
387+
}
385388
exports._start();
386389
return adaptedExports;
387390
}

0 commit comments

Comments
 (0)