[dart2wasm] Avoid calling out to generic array copy for typed data arrays
The generic array copy in JS will call back into wasm to access each
list element. Though the list elements will be accessed via dispatch
table calls. This also means the wasm is too complex to get inlined into
the generic list copy JS function.
Since it doesn't pay off to do this, we instead use normal code to copy
the JS typed arrays.
Change-Id: Iff2bbf4a50cfcb89fd1b339660dc9f8a8e0099f6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/414761
Reviewed-by: Ömer Ağacan <omersa@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
diff --git a/sdk/lib/_internal/wasm/lib/js_helper_patch.dart b/sdk/lib/_internal/wasm/lib/js_helper_patch.dart
index 96cb39c..9952d52 100644
--- a/sdk/lib/_internal/wasm/lib/js_helper_patch.dart
+++ b/sdk/lib/_internal/wasm/lib/js_helper_patch.dart
@@ -257,136 +257,146 @@
@pragma('wasm:prefer-inline')
WasmExternRef jsInt8ArrayFromDartInt8List(Int8List l) {
assert(l is! JSArrayBase);
+ final length = l.length;
+ final jsArray = JSInt8Array.withLength(length);
+ final jsArrayRef = (jsArray as JSValue).toExternRef!;
if (l is I8List) {
- final length = l.length;
- final jsArray = (JSInt8Array.withLength(length) as JSValue).toExternRef!;
- _copyFromWasmI8Array(jsArray, 0, l.data, l.offsetInElements, length);
- return jsArray;
+ _copyFromWasmI8Array(jsArrayRef, 0, l.data, l.offsetInElements, length);
+ } else {
+ jsArray.toDart.setRange(0, length, l);
}
-
- return JS<WasmExternRef>('l => arrayFromDartList(Int8Array, l)', l);
+ return jsArrayRef;
}
@patch
@pragma('wasm:prefer-inline')
WasmExternRef? jsUint8ArrayFromDartUint8List(Uint8List l) {
assert(l is! JSArrayBase);
+ final length = l.length;
+ final jsArray = JSUint8Array.withLength(length);
+ final jsArrayRef = (jsArray as JSValue).toExternRef!;
if (l is U8List) {
- final length = l.length;
- final jsArray = (JSUint8Array.withLength(length) as JSValue).toExternRef!;
- _copyFromWasmI8Array(jsArray, 0, l.data, l.offsetInElements, length);
- return jsArray;
+ _copyFromWasmI8Array(jsArrayRef, 0, l.data, l.offsetInElements, length);
+ } else {
+ jsArray.toDart.setRange(0, length, l);
}
- return JS<WasmExternRef>('l => arrayFromDartList(Uint8Array, l)', l);
+ return jsArrayRef;
}
@patch
@pragma('wasm:prefer-inline')
WasmExternRef? jsUint8ClampedArrayFromDartUint8ClampedList(Uint8ClampedList l) {
assert(l is! JSArrayBase);
+ final length = l.length;
+ final jsArray = JSUint8ClampedArray.withLength(length);
+ final jsArrayRef = (jsArray as JSValue).toExternRef!;
if (l is U8ClampedList) {
- final length = l.length;
- final jsArray =
- (JSUint8ClampedArray.withLength(length) as JSValue).toExternRef!;
- _copyFromWasmI8Array(jsArray, 0, l.data, l.offsetInElements, length);
- return jsArray;
+ _copyFromWasmI8Array(jsArrayRef, 0, l.data, l.offsetInElements, length);
+ } else {
+ jsArray.toDart.setRange(0, length, l);
}
-
- return JS<WasmExternRef>('l => arrayFromDartList(Uint8ClampedArray, l)', l);
+ return jsArrayRef;
}
@patch
@pragma('wasm:prefer-inline')
WasmExternRef jsInt16ArrayFromDartInt16List(Int16List l) {
assert(l is! JSArrayBase);
+ final length = l.length;
+ final jsArray = JSInt16Array.withLength(length);
+ final jsArrayRef = (jsArray as JSValue).toExternRef!;
if (l is I16List) {
- final length = l.length;
- final jsArray = (JSInt16Array.withLength(length) as JSValue).toExternRef!;
- _copyFromWasmI16Array(jsArray, 0, l.data, l.offsetInElements, length);
- return jsArray;
+ _copyFromWasmI16Array(jsArrayRef, 0, l.data, l.offsetInElements, length);
+ } else {
+ jsArray.toDart.setRange(0, length, l);
}
-
- return JS<WasmExternRef>('l => arrayFromDartList(Int16Array, l)', l);
+ return jsArrayRef;
}
@patch
@pragma('wasm:prefer-inline')
WasmExternRef jsUint16ArrayFromDartUint16List(Uint16List l) {
assert(l is! JSArrayBase);
+ final length = l.length;
+ final jsArray = JSUint16Array.withLength(length);
+ final jsArrayRef = (jsArray as JSValue).toExternRef!;
if (l is U16List) {
- final length = l.length;
- final jsArray = (JSUint16Array.withLength(length) as JSValue).toExternRef!;
- _copyFromWasmI16Array(jsArray, 0, l.data, l.offsetInElements, length);
- return jsArray;
+ _copyFromWasmI16Array(jsArrayRef, 0, l.data, l.offsetInElements, length);
+ } else {
+ jsArray.toDart.setRange(0, length, l);
}
-
- return JS<WasmExternRef>('l => arrayFromDartList(Uint16Array, l)', l);
+ return jsArrayRef;
}
@patch
@pragma('wasm:prefer-inline')
WasmExternRef jsInt32ArrayFromDartInt32List(Int32List l) {
assert(l is! JSArrayBase);
+ final length = l.length;
+ final jsArray = JSInt32Array.withLength(length);
+ final jsArrayRef = (jsArray as JSValue).toExternRef!;
if (l is I32List) {
- final length = l.length;
- final jsArray = (JSInt32Array.withLength(length) as JSValue).toExternRef!;
- _copyFromWasmI32Array(jsArray, 0, l.data, l.offsetInElements, length);
- return jsArray;
+ _copyFromWasmI32Array(jsArrayRef, 0, l.data, l.offsetInElements, length);
+ } else {
+ jsArray.toDart.setRange(0, length, l);
}
- return JS<WasmExternRef>('l => arrayFromDartList(Int32Array, l)', l);
+ return jsArrayRef;
}
@patch
@pragma('wasm:prefer-inline')
WasmExternRef jsUint32ArrayFromDartUint32List(Uint32List l) {
assert(l is! JSArrayBase);
+ final length = l.length;
+ final jsArray = JSUint32Array.withLength(length);
+ final jsArrayRef = (jsArray as JSValue).toExternRef!;
if (l is U32List) {
- final length = l.length;
- final jsArray = (JSUint32Array.withLength(length) as JSValue).toExternRef!;
- _copyFromWasmI32Array(jsArray, 0, l.data, l.offsetInElements, length);
- return jsArray;
+ _copyFromWasmI32Array(jsArrayRef, 0, l.data, l.offsetInElements, length);
+ } else {
+ jsArray.toDart.setRange(0, length, l);
}
-
- return JS<WasmExternRef>('l => arrayFromDartList(Uint32Array, l)', l);
+ return jsArrayRef;
}
@patch
@pragma('wasm:prefer-inline')
WasmExternRef jsFloat32ArrayFromDartFloat32List(Float32List l) {
assert(l is! JSArrayBase);
+ final length = l.length;
+ final jsArray = JSFloat32Array.withLength(length);
+ final jsArrayRef = (jsArray as JSValue).toExternRef!;
if (l is F32List) {
- final length = l.length;
- final jsArray = (JSFloat32Array.withLength(length) as JSValue).toExternRef!;
- _copyFromWasmF32Array(jsArray, 0, l.data, l.offsetInElements, length);
- return jsArray;
+ _copyFromWasmF32Array(jsArrayRef, 0, l.data, l.offsetInElements, length);
+ } else {
+ jsArray.toDart.setRange(0, length, l);
}
-
- return JS<WasmExternRef>('l => arrayFromDartList(Float32Array, l)', l);
+ return jsArrayRef;
}
@patch
@pragma('wasm:prefer-inline')
WasmExternRef jsFloat64ArrayFromDartFloat64List(Float64List l) {
assert(l is! JSArrayBase);
+ final length = l.length;
+ final jsArray = JSFloat64Array.withLength(length);
+ final jsArrayRef = (jsArray as JSValue).toExternRef!;
if (l is F64List) {
- final length = l.length;
- final jsArray = (JSFloat64Array.withLength(length) as JSValue).toExternRef!;
- _copyFromWasmF64Array(jsArray, 0, l.data, l.offsetInElements, length);
- return jsArray;
+ _copyFromWasmF64Array(jsArrayRef, 0, l.data, l.offsetInElements, length);
+ } else {
+ jsArray.toDart.setRange(0, length, l);
}
-
- return JS<WasmExternRef>('l => arrayFromDartList(Float64Array, l)', l);
+ return jsArrayRef;
}
@patch
@@ -394,9 +404,9 @@
WasmExternRef jsDataViewFromDartByteData(ByteData l, int length) {
assert(l is! JSDataViewImpl);
+ final jsArrayBuffer = JSArrayBuffer(length);
+ final jsArray = JSUint8Array(jsArrayBuffer, 0, length);
if (l is I8ByteData) {
- final jsArrayBuffer = JSArrayBuffer(length);
- final jsArray = JSUint8Array(jsArrayBuffer, 0, length);
_copyFromWasmI8Array(
(jsArray as JSValue).toExternRef!,
0,
@@ -404,21 +414,11 @@
l.offsetInBytes,
length,
);
- return (JSDataView(jsArrayBuffer, 0, length) as JSValue).toExternRef!;
+ } else {
+ jsArray.toDart.setRange(0, length, Uint8List.sublistView(l, length));
}
- return JS<WasmExternRef>(
- """(data, length) => {
- const getValue = dartInstance.exports.\$byteDataGetUint8;
- const view = new DataView(new ArrayBuffer(length));
- for (let i = 0; i < length; i++) {
- view.setUint8(i, getValue(data, i));
- }
- return view;
- }""",
- l,
- length.toWasmI32(),
- );
+ return (JSDataView(jsArrayBuffer, 0, length) as JSValue).toExternRef!;
}
@pragma("wasm:export", "\$wasmI8ArrayGet")
@@ -500,11 +500,3 @@
);
array[index.toIntUnsigned()] = value;
}
-
-@pragma("wasm:export", "\$byteDataGetUint8")
-WasmI32 _byteDataGetUint8(WasmExternRef? ref, WasmI32 index) {
- final byteData = unsafeCastOpaque<ByteData>(
- unsafeCast<WasmExternRef>(ref).internalize(),
- );
- return byteData.getUint8(index.toIntSigned()).toWasmI32();
-}