From 1d8dde36e166db5b62ef08d0dab0031dae0148f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Mon, 17 Jul 2023 16:51:25 +0000 Subject: [PATCH] [dart2wasm] Add array.copy instruction and intrinsics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `array.copy` is used in [1] in `setRange` when source and destinations are both typed arrays with the same Wasm array type. [1]: https://dart-review.googlesource.com/c/sdk/+/312907 Change-Id: Iaeecea43c22805eca64b7d98751a52e607210a70 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/314080 Reviewed-by: Joshua Litt Commit-Queue: Ömer Ağacan --- pkg/dart2wasm/lib/intrinsics.dart | 28 ++++++++++++++++++++-- pkg/wasm_builder/lib/src/instructions.dart | 17 +++++++++++++ sdk/lib/_wasm/wasm_types.dart | 4 ++++ 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/pkg/dart2wasm/lib/intrinsics.dart b/pkg/dart2wasm/lib/intrinsics.dart index fa0f763d03f..7e0fa32e042 100644 --- a/pkg/dart2wasm/lib/intrinsics.dart +++ b/pkg/dart2wasm/lib/intrinsics.dart @@ -410,11 +410,35 @@ class Intrinsifier { } b.array_set(arrayType); return codeGen.voidMarker; - default: - throw "Unsupported array method: $name"; } } + // WasmIntArray.copy + // WasmFloatArray.copy + if (cls.superclass == translator.wasmArrayRefClass && name == 'copy') { + final DartType elementType = + (receiverType as InterfaceType).typeArguments.single; + final w.ArrayType arrayType = + translator.arrayTypeForDartType(elementType); + + final Expression destArray = receiver; + final Expression destOffset = node.arguments.positional[0]; + final Expression sourceArray = node.arguments.positional[1]; + final Expression sourceOffset = node.arguments.positional[2]; + final Expression size = node.arguments.positional[3]; + + codeGen.wrap(destArray, w.RefType.def(arrayType, nullable: false)); + codeGen.wrap(destOffset, w.NumType.i64); + b.i32_wrap_i64(); + codeGen.wrap(sourceArray, w.RefType.def(arrayType, nullable: false)); + codeGen.wrap(sourceOffset, w.NumType.i64); + b.i32_wrap_i64(); + codeGen.wrap(size, w.NumType.i64); + b.i32_wrap_i64(); + b.array_copy(arrayType, arrayType); + return codeGen.voidMarker; + } + // Wasm(I32|I64|F32|F64) conversions if (cls.superclass?.superclass == translator.wasmTypesBaseClass) { w.StorageType receiverType = translator.builtinTypes[cls]!; diff --git a/pkg/wasm_builder/lib/src/instructions.dart b/pkg/wasm_builder/lib/src/instructions.dart index e0d78eb4400..f2027dc67d2 100644 --- a/pkg/wasm_builder/lib/src/instructions.dart +++ b/pkg/wasm_builder/lib/src/instructions.dart @@ -1111,6 +1111,23 @@ class Instructions with SerializerMixin { if (isGlobalInitializer) module.dataReferencedFromGlobalInitializer = true; } + void array_copy(ArrayType destArrayType, ArrayType sourceArrayType) { + assert(_verifyTypes([ + RefType.def(destArrayType, nullable: true), // dest + NumType.i32, // dest_offset + RefType.def(sourceArrayType, nullable: true), // source + NumType.i32, // source_offset + NumType.i32 // size + ], [], trace: [ + 'array.copy', + destArrayType, + sourceArrayType + ])); + writeBytes(const [0xFB, 0x18]); + writeUnsigned(destArrayType.index); + writeUnsigned(sourceArrayType.index); + } + /// Emit an `i31.new` instruction. void i31_new() { assert(_verifyTypes( diff --git a/sdk/lib/_wasm/wasm_types.dart b/sdk/lib/_wasm/wasm_types.dart index 91d00605426..6d3432a61f8 100644 --- a/sdk/lib/_wasm/wasm_types.dart +++ b/sdk/lib/_wasm/wasm_types.dart @@ -180,6 +180,8 @@ class WasmIntArray extends WasmArrayRef { external int readSigned(int index); external int readUnsigned(int index); external void write(int index, int value); + external void copy( + int offset, WasmIntArray source, int sourceOffset, int size); } /// A Wasm array with float element type. @@ -189,6 +191,8 @@ class WasmFloatArray extends WasmArrayRef { external double read(int index); external void write(int index, double value); + external void copy( + int offset, WasmFloatArray source, int sourceOffset, int size); } /// A Wasm array with reference element type, containing Dart objects.