Skip to content

Support lifting/lowering of functions as internrefs #2382

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/bindings/js.ts
Original file line number Diff line number Diff line change
Expand Up @@ -799,11 +799,13 @@ export class JSBuilder extends ExportsWalker {
}
`);
}
if (this.needsLiftInternref || this.needsLowerInternref) {
sb.push(" class Internref extends Number {}\n");
}
if (this.needsLiftInternref) {
this.needsRetain = true;
this.needsRelease = true;
sb.push(` const registry = new FinalizationRegistry(__release);
class Internref extends Number {}
function __liftInternref(pointer) {
if (!pointer) return null;
const sentinel = new Internref(__retain(pointer));
Expand Down Expand Up @@ -1031,7 +1033,7 @@ export class JSBuilder extends ExportsWalker {
makeLowerToValue(name: string, type: Type, sb: string[] = this.sb): void {
if (type.isInternalReference) {
// Lower reference types
const clazz = assert(type.getClass());
const clazz = assert(type.getClassOrWrapper(this.program));
if (clazz.extends(this.program.arrayBufferInstance.prototype)) {
sb.push("__lowerBuffer(");
this.needsLowerBuffer = true;
Expand Down
27 changes: 21 additions & 6 deletions tests/compiler/bindings/esm.debug.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,21 +124,32 @@ export declare function arrayFunction(a: Array<number>, b: Array<number>): Array
* @param b `bindings/esm/PlainObject`
* @returns `bindings/esm/PlainObject`
*/
export declare function objectFunction(a: __Record10<undefined>, b: __Record10<undefined>): __Record10<never>;
export declare function objectFunction(a: __Record11<undefined>, b: __Record11<undefined>): __Record11<never>;
/**
* bindings/esm/newInternref
* @returns `bindings/esm/NonPlainObject`
*/
export declare function newInternref(): __Internref13;
export declare function newInternref(): __Internref14;
/**
* bindings/esm/internrefFunction
* @param a `bindings/esm/NonPlainObject`
* @param b `bindings/esm/NonPlainObject`
* @returns `bindings/esm/NonPlainObject`
*/
export declare function internrefFunction(a: __Internref13, b: __Internref13): __Internref13;
export declare function internrefFunction(a: __Internref14, b: __Internref14): __Internref14;
/**
* bindings/esm/functionFunction
* @param fn `() => void`
* @returns `() => void`
*/
export declare function functionFunction(fn: __Internref3): __Internref3;
/** bindings/esm/fn */
export declare const fn: {
/** @type `() => void` */
get value(): __Internref3
};
/** bindings/esm/PlainObject */
declare interface __Record10<TOmittable> {
declare interface __Record11<TOmittable> {
/** @type `i8` */
a: number | TOmittable;
/** @type `i16` */
Expand Down Expand Up @@ -173,6 +184,10 @@ declare interface __Record10<TOmittable> {
p: Array<string> | null | TOmittable;
}
/** bindings/esm/NonPlainObject */
declare class __Internref13 extends Number {
private __nominal13: symbol;
declare class __Internref14 extends Number {
private __nominal14: symbol;
}
/** ~lib/function/Function<%28%29=>void> */
declare class __Internref3 extends Number {
private __nominal3: symbol;
}
50 changes: 32 additions & 18 deletions tests/compiler/bindings/esm.debug.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ async function instantiate(module, imports = {}) {
},
typedarrayFunction(a, b) {
// bindings/esm/typedarrayFunction(~lib/typedarray/Int16Array, ~lib/typedarray/Float32Array) => ~lib/typedarray/Uint64Array
a = __retain(__lowerTypedArray(Int16Array, 3, 1, a) || __notnull());
b = __lowerTypedArray(Float32Array, 4, 2, b) || __notnull();
a = __retain(__lowerTypedArray(Int16Array, 4, 1, a) || __notnull());
b = __lowerTypedArray(Float32Array, 5, 2, b) || __notnull();
try {
return __liftTypedArray(BigUint64Array, exports.typedarrayFunction(a, b) >>> 0);
} finally {
Expand All @@ -137,8 +137,8 @@ async function instantiate(module, imports = {}) {
},
staticarrayFunction(a, b) {
// bindings/esm/staticarrayFunction(~lib/staticarray/StaticArray<i32>, ~lib/staticarray/StaticArray<i32>) => ~lib/staticarray/StaticArray<i32>
a = __retain(__lowerStaticArray((pointer, value) => { new Int32Array(memory.buffer)[pointer >>> 2] = value; }, 6, 2, a, Int32Array) || __notnull());
b = __lowerStaticArray((pointer, value) => { new Int32Array(memory.buffer)[pointer >>> 2] = value; }, 6, 2, b, Int32Array) || __notnull();
a = __retain(__lowerStaticArray((pointer, value) => { new Int32Array(memory.buffer)[pointer >>> 2] = value; }, 7, 2, a, Int32Array) || __notnull());
b = __lowerStaticArray((pointer, value) => { new Int32Array(memory.buffer)[pointer >>> 2] = value; }, 7, 2, b, Int32Array) || __notnull();
try {
return __liftStaticArray(pointer => new Int32Array(memory.buffer)[pointer >>> 2], 2, exports.staticarrayFunction(a, b) >>> 0);
} finally {
Expand All @@ -147,18 +147,18 @@ async function instantiate(module, imports = {}) {
},
staticarrayU16(a) {
// bindings/esm/staticarrayU16(~lib/staticarray/StaticArray<u16>) => ~lib/staticarray/StaticArray<u16>
a = __lowerStaticArray((pointer, value) => { new Uint16Array(memory.buffer)[pointer >>> 1] = value; }, 7, 1, a, Uint16Array) || __notnull();
a = __lowerStaticArray((pointer, value) => { new Uint16Array(memory.buffer)[pointer >>> 1] = value; }, 8, 1, a, Uint16Array) || __notnull();
return __liftStaticArray(pointer => new Uint16Array(memory.buffer)[pointer >>> 1], 1, exports.staticarrayU16(a) >>> 0);
},
staticarrayI64(a) {
// bindings/esm/staticarrayI64(~lib/staticarray/StaticArray<i64>) => ~lib/staticarray/StaticArray<i64>
a = __lowerStaticArray((pointer, value) => { new BigInt64Array(memory.buffer)[pointer >>> 3] = value || 0n; }, 8, 3, a, BigInt64Array) || __notnull();
a = __lowerStaticArray((pointer, value) => { new BigInt64Array(memory.buffer)[pointer >>> 3] = value || 0n; }, 9, 3, a, BigInt64Array) || __notnull();
return __liftStaticArray(pointer => new BigInt64Array(memory.buffer)[pointer >>> 3], 3, exports.staticarrayI64(a) >>> 0);
},
arrayFunction(a, b) {
// bindings/esm/arrayFunction(~lib/array/Array<i32>, ~lib/array/Array<i32>) => ~lib/array/Array<i32>
a = __retain(__lowerArray((pointer, value) => { new Int32Array(memory.buffer)[pointer >>> 2] = value; }, 9, 2, a) || __notnull());
b = __lowerArray((pointer, value) => { new Int32Array(memory.buffer)[pointer >>> 2] = value; }, 9, 2, b) || __notnull();
a = __retain(__lowerArray((pointer, value) => { new Int32Array(memory.buffer)[pointer >>> 2] = value; }, 10, 2, a) || __notnull());
b = __lowerArray((pointer, value) => { new Int32Array(memory.buffer)[pointer >>> 2] = value; }, 10, 2, b) || __notnull();
try {
return __liftArray(pointer => new Int32Array(memory.buffer)[pointer >>> 2], 2, exports.arrayFunction(a, b) >>> 0);
} finally {
Expand All @@ -167,10 +167,10 @@ async function instantiate(module, imports = {}) {
},
objectFunction(a, b) {
// bindings/esm/objectFunction(bindings/esm/PlainObject, bindings/esm/PlainObject) => bindings/esm/PlainObject
a = __retain(__lowerRecord10(a) || __notnull());
b = __lowerRecord10(b) || __notnull();
a = __retain(__lowerRecord11(a) || __notnull());
b = __lowerRecord11(b) || __notnull();
try {
return __liftRecord10(exports.objectFunction(a, b) >>> 0);
return __liftRecord11(exports.objectFunction(a, b) >>> 0);
} finally {
__release(a);
}
Expand All @@ -189,12 +189,24 @@ async function instantiate(module, imports = {}) {
__release(a);
}
},
functionFunction(fn) {
// bindings/esm/functionFunction(() => void) => () => void
fn = __lowerInternref(fn) || __notnull();
return __liftInternref(exports.functionFunction(fn) >>> 0);
},
fn: {
// bindings/esm/fn: () => void
valueOf() { return this.value; },
get value() {
return __liftInternref(exports.fn.value >>> 0);
}
},
}, exports);
function __lowerRecord10(value) {
function __lowerRecord11(value) {
// bindings/esm/PlainObject
// Hint: Opt-out from lowering as a record by providing an empty constructor
if (value == null) return 0;
const pointer = exports.__pin(exports.__new(68, 10));
const pointer = exports.__pin(exports.__new(68, 11));
new Int8Array(memory.buffer)[pointer + 0 >>> 0] = value.a;
new Int16Array(memory.buffer)[pointer + 2 >>> 1] = value.b;
new Int32Array(memory.buffer)[pointer + 4 >>> 2] = value.c;
Expand All @@ -209,12 +221,12 @@ async function instantiate(module, imports = {}) {
new Float32Array(memory.buffer)[pointer + 44 >>> 2] = value.l;
new Float64Array(memory.buffer)[pointer + 48 >>> 3] = value.m;
new Uint32Array(memory.buffer)[pointer + 56 >>> 2] = __lowerString(value.n);
new Uint32Array(memory.buffer)[pointer + 60 >>> 2] = __lowerTypedArray(Uint8Array, 11, 0, value.o);
new Uint32Array(memory.buffer)[pointer + 64 >>> 2] = __lowerArray((pointer, value) => { new Uint32Array(memory.buffer)[pointer >>> 2] = __lowerString(value) || __notnull(); }, 12, 2, value.p);
new Uint32Array(memory.buffer)[pointer + 60 >>> 2] = __lowerTypedArray(Uint8Array, 12, 0, value.o);
new Uint32Array(memory.buffer)[pointer + 64 >>> 2] = __lowerArray((pointer, value) => { new Uint32Array(memory.buffer)[pointer >>> 2] = __lowerString(value) || __notnull(); }, 13, 2, value.p);
exports.__unpin(pointer);
return pointer;
}
function __liftRecord10(pointer) {
function __liftRecord11(pointer) {
// bindings/esm/PlainObject
// Hint: Opt-out from lifting as a record by providing an empty constructor
if (!pointer) return null;
Expand Down Expand Up @@ -337,8 +349,8 @@ async function instantiate(module, imports = {}) {
exports.__unpin(buffer);
return buffer;
}
const registry = new FinalizationRegistry(__release);
class Internref extends Number {}
const registry = new FinalizationRegistry(__release);
function __liftInternref(pointer) {
if (!pointer) return null;
const sentinel = new Internref(__retain(pointer));
Expand Down Expand Up @@ -395,7 +407,9 @@ export const {
arrayFunction,
objectFunction,
newInternref,
internrefFunction
internrefFunction,
functionFunction,
fn
} = await (async url => instantiate(
await (async () => {
try { return await globalThis.WebAssembly.compileStreaming(globalThis.fetch(url)); }
Expand Down
Loading