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.