Skip to content

Add fast-path for staticarray lowering if values is typedarray in bindings #2370

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 11 commits into from
Jul 20, 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
41 changes: 38 additions & 3 deletions src/bindings/js.ts
Original file line number Diff line number Diff line change
Expand Up @@ -784,12 +784,16 @@ export class JSBuilder extends ExportsWalker {
`);
}
if (this.needsLowerStaticArray) {
sb.push(` function __lowerStaticArray(lowerElement, id, align, values) {
sb.push(` function __lowerStaticArray(lowerElement, id, align, values, typedConstructor) {
if (values == null) return 0;
const
length = values.length,
buffer = exports.__pin(exports.__new(length << align, id)) >>> 0;
for (let i = 0; i < length; i++) lowerElement(buffer + (i << align >>> 0), values[i]);
if (typedConstructor) {
new typedConstructor(memory.buffer, buffer, length).set(values);
} else {
for (let i = 0; i < length; i++) lowerElement(buffer + (i << align >>> 0), values[i]);
}
exports.__unpin(buffer);
return buffer;
}
Expand Down Expand Up @@ -1051,7 +1055,7 @@ export class JSBuilder extends ExportsWalker {
sb.push(", ");
sb.push(clazz.id.toString());
sb.push(", ");
sb.push(clazz.getArrayValueType().alignLog2.toString());
sb.push(valueType.alignLog2.toString());
sb.push(", ");
this.needsLowerStaticArray = true;
} else if (clazz.extends(this.program.arrayBufferViewInstance.prototype)) {
Expand Down Expand Up @@ -1086,6 +1090,37 @@ export class JSBuilder extends ExportsWalker {
this.needsLowerInternref = true;
}
sb.push(name);
if (clazz.extends(this.program.staticArrayPrototype)) {
// optional last argument for __lowerStaticArray
let valueType = clazz.getArrayValueType();
if (valueType.isNumericValue) {
sb.push(", ");
if (valueType == Type.u8 || valueType == Type.bool) {
sb.push("Uint8Array");
} else if (valueType == Type.i8) {
sb.push("Int8Array");
} else if (valueType == Type.u16) {
sb.push("Uint16Array");
} else if (valueType == Type.i16) {
sb.push("Int16Array");
} else if (valueType == Type.u32) {
sb.push("Uint32Array");
} else if (valueType == Type.i32) {
sb.push("Int32Array");
} else if (valueType == Type.u64) {
sb.push("BigUint64Array");
} else if (valueType == Type.i64) {
sb.push("BigInt64Array");
} else if (valueType == Type.f32) {
sb.push("Float32Array");
} else if (valueType == Type.f64) {
sb.push("Float64Array");
} else {
// unreachable
assert(false);
}
}
}
sb.push(")");
if (!type.is(TypeFlags.NULLABLE)) {
this.needsNotNull = true;
Expand Down
10 changes: 6 additions & 4 deletions src/bindings/tsd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,14 +253,16 @@ export class TSDBuilder extends ExportsWalker {
sb.push("ArrayBuffer");
} else if (clazz.extends(this.program.stringInstance.prototype)) {
sb.push("string");
} else if (
clazz.extends(this.program.arrayPrototype) ||
clazz.extends(this.program.staticArrayPrototype)
) {
} else if (clazz.extends(this.program.arrayPrototype)) {
const valueType = clazz.getArrayValueType();
sb.push("Array<");
sb.push(this.toTypeScriptType(valueType, mode));
sb.push(">");
} else if (clazz.extends(this.program.staticArrayPrototype)) {
const valueType = clazz.getArrayValueType();
sb.push("ArrayLike<");
sb.push(this.toTypeScriptType(valueType, mode));
sb.push(">");
} else if (clazz.extends(this.program.arrayBufferViewInstance.prototype)) {
const valueType = clazz.getArrayValueType();
if (valueType == Type.i8) {
Expand Down
26 changes: 19 additions & 7 deletions tests/compiler/bindings/esm.debug.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,19 @@ export declare function typedarrayFunction(a: Int16Array, b: Float32Array): BigU
* @param b `~lib/staticarray/StaticArray<i32>`
* @returns `~lib/staticarray/StaticArray<i32>`
*/
export declare function staticarrayFunction(a: Array<number>, b: Array<number>): Array<number>;
export declare function staticarrayFunction(a: ArrayLike<number>, b: ArrayLike<number>): ArrayLike<number>;
/**
* bindings/esm/staticarrayU16
* @param a `~lib/staticarray/StaticArray<u16>`
* @returns `~lib/staticarray/StaticArray<u16>`
*/
export declare function staticarrayU16(a: ArrayLike<number>): ArrayLike<number>;
/**
* bindings/esm/staticarrayI64
* @param a `~lib/staticarray/StaticArray<i64>`
* @returns `~lib/staticarray/StaticArray<i64>`
*/
export declare function staticarrayI64(a: ArrayLike<bigint>): ArrayLike<bigint>;
/**
* bindings/esm/arrayFunction
* @param a `~lib/array/Array<i32>`
Expand All @@ -112,21 +124,21 @@ 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: __Record8<undefined>, b: __Record8<undefined>): __Record8<never>;
export declare function objectFunction(a: __Record10<undefined>, b: __Record10<undefined>): __Record10<never>;
/**
* bindings/esm/newInternref
* @returns `bindings/esm/NonPlainObject`
*/
export declare function newInternref(): __Internref11;
export declare function newInternref(): __Internref13;
/**
* bindings/esm/internrefFunction
* @param a `bindings/esm/NonPlainObject`
* @param b `bindings/esm/NonPlainObject`
* @returns `bindings/esm/NonPlainObject`
*/
export declare function internrefFunction(a: __Internref11, b: __Internref11): __Internref11;
export declare function internrefFunction(a: __Internref13, b: __Internref13): __Internref13;
/** bindings/esm/PlainObject */
declare interface __Record8<TOmittable> {
declare interface __Record10<TOmittable> {
/** @type `i8` */
a: number | TOmittable;
/** @type `i16` */
Expand Down Expand Up @@ -161,6 +173,6 @@ declare interface __Record8<TOmittable> {
p: Array<string> | null | TOmittable;
}
/** bindings/esm/NonPlainObject */
declare class __Internref11 extends Number {
private __nominal11: symbol;
declare class __Internref13 extends Number {
private __nominal13: symbol;
}
44 changes: 30 additions & 14 deletions tests/compiler/bindings/esm.debug.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,18 +137,28 @@ 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) || __notnull());
b = __lowerStaticArray((pointer, value) => { new Int32Array(memory.buffer)[pointer >>> 2] = value; }, 6, 2, b) || __notnull();
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();
try {
return __liftStaticArray(pointer => new Int32Array(memory.buffer)[pointer >>> 2], 2, exports.staticarrayFunction(a, b) >>> 0);
} finally {
__release(a);
}
},
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();
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();
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; }, 7, 2, a) || __notnull());
b = __lowerArray((pointer, value) => { new Int32Array(memory.buffer)[pointer >>> 2] = value; }, 7, 2, b) || __notnull();
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();
try {
return __liftArray(pointer => new Int32Array(memory.buffer)[pointer >>> 2], 2, exports.arrayFunction(a, b) >>> 0);
} finally {
Expand All @@ -157,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(__lowerRecord8(a) || __notnull());
b = __lowerRecord8(b) || __notnull();
a = __retain(__lowerRecord10(a) || __notnull());
b = __lowerRecord10(b) || __notnull();
try {
return __liftRecord8(exports.objectFunction(a, b) >>> 0);
return __liftRecord10(exports.objectFunction(a, b) >>> 0);
} finally {
__release(a);
}
Expand All @@ -180,11 +190,11 @@ async function instantiate(module, imports = {}) {
}
},
}, exports);
function __lowerRecord8(value) {
function __lowerRecord10(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, 8));
const pointer = exports.__pin(exports.__new(68, 10));
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 @@ -199,12 +209,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, 9, 0, value.o);
new Uint32Array(memory.buffer)[pointer + 64 >>> 2] = __lowerArray((pointer, value) => { new Uint32Array(memory.buffer)[pointer >>> 2] = __lowerString(value) || __notnull(); }, 10, 2, value.p);
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);
exports.__unpin(pointer);
return pointer;
}
function __liftRecord8(pointer) {
function __liftRecord10(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 @@ -314,12 +324,16 @@ async function instantiate(module, imports = {}) {
for (let i = 0; i < length; ++i) values[i] = liftElement(pointer + (i << align >>> 0));
return values;
}
function __lowerStaticArray(lowerElement, id, align, values) {
function __lowerStaticArray(lowerElement, id, align, values, typedConstructor) {
if (values == null) return 0;
const
length = values.length,
buffer = exports.__pin(exports.__new(length << align, id)) >>> 0;
for (let i = 0; i < length; i++) lowerElement(buffer + (i << align >>> 0), values[i]);
if (typedConstructor) {
new typedConstructor(memory.buffer, buffer, length).set(values);
} else {
for (let i = 0; i < length; i++) lowerElement(buffer + (i << align >>> 0), values[i]);
}
exports.__unpin(buffer);
return buffer;
}
Expand Down Expand Up @@ -376,6 +390,8 @@ export const {
stringFunctionOptional,
typedarrayFunction,
staticarrayFunction,
staticarrayU16,
staticarrayI64,
arrayFunction,
objectFunction,
newInternref,
Expand Down
Loading