[dart2wasm] Convert to/from externref via Wasm instructions
This adds support for the newly added `extern.externalize` and
`extern.internalize` instructions and uses these for converting to/from
`externref` instead of a JS round-trip.
Change-Id: If18d8f44ddf013d4c26bf1597be91bcd0db41c5a
Cq-Include-Trybots: luci.dart.try:dart2wasm-linux-x64-d8-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/255462
Commit-Queue: Aske Simon Christensen <askesc@google.com>
Reviewed-by: Joshua Litt <joshualitt@google.com>
diff --git a/pkg/dart2wasm/lib/intrinsics.dart b/pkg/dart2wasm/lib/intrinsics.dart
index 098c19f..fbc75b9 100644
--- a/pkg/dart2wasm/lib/intrinsics.dart
+++ b/pkg/dart2wasm/lib/intrinsics.dart
@@ -1007,6 +1007,29 @@
}
}
+ // dart:wasm static functions
+ if (node.target.enclosingLibrary.name == "dart.wasm") {
+ Expression value = node.arguments.positional.single;
+ switch (name) {
+ case "_externalizeNonNullable":
+ codeGen.wrap(value, w.RefType.any(nullable: false));
+ b.extern_externalize();
+ return w.RefType.extern(nullable: false);
+ case "_externalizeNullable":
+ codeGen.wrap(value, w.RefType.any(nullable: true));
+ b.extern_externalize();
+ return w.RefType.extern(nullable: true);
+ case "_internalizeNonNullable":
+ codeGen.wrap(value, w.RefType.extern(nullable: false));
+ b.extern_internalize();
+ return w.RefType.any(nullable: false);
+ case "_internalizeNullable":
+ codeGen.wrap(value, w.RefType.extern(nullable: true));
+ b.extern_internalize();
+ return w.RefType.any(nullable: true);
+ }
+ }
+
return null;
}
diff --git a/pkg/wasm_builder/lib/src/instructions.dart b/pkg/wasm_builder/lib/src/instructions.dart
index 69c210b..639657a 100644
--- a/pkg/wasm_builder/lib/src/instructions.dart
+++ b/pkg/wasm_builder/lib/src/instructions.dart
@@ -1251,6 +1251,22 @@
_writeLabel(label);
}
+ /// Emit an `extern.internalize` instruction.
+ void extern_internalize() {
+ assert(_verifyTypesFun(const [RefType.extern(nullable: true)],
+ (inputs) => [RefType.any(nullable: inputs.single.nullable)],
+ trace: ['extern.internalize']));
+ writeBytes(const [0xFB, 0x70]);
+ }
+
+ /// Emit an `extern.externalize` instruction.
+ void extern_externalize() {
+ assert(_verifyTypesFun(const [RefType.any(nullable: true)],
+ (inputs) => [RefType.extern(nullable: inputs.single.nullable)],
+ trace: ['extern.externalize']));
+ writeBytes(const [0xFB, 0x71]);
+ }
+
// Numeric instructions
/// Emit an `i32.const` instruction.
diff --git a/sdk/lib/wasm/wasm_types.dart b/sdk/lib/wasm/wasm_types.dart
index cda6ba4..b95e26d 100644
--- a/sdk/lib/wasm/wasm_types.dart
+++ b/sdk/lib/wasm/wasm_types.dart
@@ -52,15 +52,9 @@
WasmAnyRef? internalize() => _internalizeNullable(this);
}
-// TODO(askesc): Add intrinsics for these when the `extern.externalize` and
-// `extern.internalize` instructions are implemented in V8.
-@pragma("wasm:import", "dart2wasm.roundtrip")
external WasmExternRef _externalizeNonNullable(WasmAnyRef ref);
-@pragma("wasm:import", "dart2wasm.roundtrip")
external WasmExternRef? _externalizeNullable(WasmAnyRef? ref);
-@pragma("wasm:import", "dart2wasm.roundtrip")
external WasmAnyRef _internalizeNonNullable(WasmExternRef ref);
-@pragma("wasm:import", "dart2wasm.roundtrip")
external WasmAnyRef? _internalizeNullable(WasmExternRef? ref);
/// The Wasm `funcref` type.