Skip to content

Commit 9d0ae7d

Browse files
liamappelbecommit-bot@chromium.org
authored andcommitted
Switch wasmer FFI boilerplate to new API
Broadly speaking, the new API is very similar to the old one. The only public facing change is that you can't make a memory by itself anymore. You need to construct if from a store, which is owned by a module. The new API no longer passes structs by value, so I was able to delete the wasmer_wrapper.cc, and the files I had copied from the wasmer repo. The new API is also a lot more verbose, so it made more sense to write a script to generate the FFI boilerplate, rather that write it all manually. All the migrated tests that were passing before this refactor are still passing. Bug: #37882 Change-Id: I52ca54b982a27f1d851c630d3e09833b8810060c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164081 Reviewed-by: Siva Annamalai <[email protected]> Commit-Queue: Liam Appelbe <[email protected]>
1 parent 976a0da commit 9d0ae7d

21 files changed

+1558
-2093
lines changed

pkg/wasm/lib/src/function.dart

+32-24
Original file line numberDiff line numberDiff line change
@@ -10,35 +10,43 @@ import 'package:ffi/ffi.dart';
1010
/// WasmFunction is a callable function from a WasmInstance.
1111
class WasmFunction {
1212
String _name;
13-
Pointer<WasmerExportFunc> _func;
13+
Pointer<WasmerFunc> _func;
1414
List<int> _argTypes;
1515
int _returnType;
16-
Pointer<WasmerValue> _args;
17-
Pointer<WasmerValue> _result;
16+
Pointer<WasmerVal> _args;
17+
Pointer<WasmerVal> _results;
1818

1919
WasmFunction(this._name, this._func, this._argTypes, this._returnType)
20-
: _args = allocate<WasmerValue>(count: _argTypes.length),
21-
_result = allocate<WasmerValue>() {
20+
: _args = _argTypes.length == 0
21+
? nullptr
22+
: allocate<WasmerVal>(count: _argTypes.length),
23+
_results =
24+
_returnType == WasmerValKindVoid ? nullptr : allocate<WasmerVal>() {
2225
for (var i = 0; i < _argTypes.length; ++i) {
23-
_args[i].tag = _argTypes[i];
26+
_args[i].kind = _argTypes[i];
2427
}
2528
}
2629

30+
String toString() {
31+
return "${wasmerValKindName(_returnType)} $_name" +
32+
"(${_argTypes.map(wasmerValKindName).join(", ")})";
33+
}
34+
2735
bool _fillArg(dynamic arg, int i) {
2836
switch (_argTypes[i]) {
29-
case WasmerValueTagI32:
37+
case WasmerValKindI32:
3038
if (arg is! int) return false;
3139
_args[i].i32 = arg;
3240
return true;
33-
case WasmerValueTagI64:
41+
case WasmerValKindI64:
3442
if (arg is! int) return false;
3543
_args[i].i64 = arg;
3644
return true;
37-
case WasmerValueTagF32:
45+
case WasmerValKindF32:
3846
if (arg is! num) return false;
3947
_args[i].f32 = arg;
4048
return true;
41-
case WasmerValueTagF64:
49+
case WasmerValKindF64:
4250
if (arg is! num) return false;
4351
_args[i].f64 = arg;
4452
return true;
@@ -48,29 +56,29 @@ class WasmFunction {
4856

4957
dynamic apply(List<dynamic> args) {
5058
if (args.length != _argTypes.length) {
51-
throw ArgumentError("Wrong number arguments for WASM function: $_name");
59+
throw ArgumentError("Wrong number arguments for WASM function: $this");
5260
}
5361
for (var i = 0; i < args.length; ++i) {
5462
if (!_fillArg(args[i], i)) {
55-
throw ArgumentError("Bad argument type for WASM function: $_name");
63+
throw ArgumentError("Bad argument type for WASM function: $this");
5664
}
5765
}
58-
WasmRuntime().call(_func, _args, _argTypes.length, _result,
59-
_returnType == WasmerValueTagVoid ? 0 : 1);
66+
WasmRuntime().call(_func, _args, _results);
6067

61-
if (_returnType == WasmerValueTagVoid) {
68+
if (_returnType == WasmerValKindVoid) {
6269
return null;
6370
}
64-
assert(_returnType == _result.ref.tag);
71+
var result = _results[0];
72+
assert(_returnType == result.kind);
6573
switch (_returnType) {
66-
case WasmerValueTagI32:
67-
return _result.ref.i32;
68-
case WasmerValueTagI64:
69-
return _result.ref.i64;
70-
case WasmerValueTagF32:
71-
return _result.ref.f32;
72-
case WasmerValueTagF64:
73-
return _result.ref.f64;
74+
case WasmerValKindI32:
75+
return result.i32;
76+
case WasmerValKindI64:
77+
return result.i64;
78+
case WasmerValKindF32:
79+
return result.f32;
80+
case WasmerValKindF64:
81+
return result.f64;
7482
}
7583
}
7684

pkg/wasm/lib/src/module.dart

+34-20
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,23 @@ import 'package:ffi/ffi.dart';
1111

1212
/// WasmModule is a compiled module that can be instantiated.
1313
class WasmModule {
14-
Pointer<WasmerModule> _module;
14+
Pointer<WasmerStore> _store;
15+
late Pointer<WasmerModule> _module;
1516

1617
/// Compile a module.
17-
WasmModule(Uint8List data) : _module = WasmRuntime().compile(data) {}
18+
WasmModule(Uint8List data) : _store = WasmRuntime().newStore() {
19+
_module = WasmRuntime().compile(_store, data);
20+
}
1821

1922
/// Instantiate the module with the given imports.
2023
WasmInstance instantiate(WasmImports imports) {
21-
return WasmInstance(_module, imports);
24+
return WasmInstance(_store, _module, imports);
25+
}
26+
27+
/// Create a new memory with the given number of initial pages, and optional
28+
/// maximum number of pages.
29+
WasmMemory createMemory(int pages, [int? maxPages]) {
30+
return WasmMemory._create(_store, pages, maxPages);
2231
}
2332

2433
/// Returns a description of all of the module's imports and exports, for
@@ -28,12 +37,12 @@ class WasmModule {
2837
var runtime = WasmRuntime();
2938
var imports = runtime.importDescriptors(_module);
3039
for (var imp in imports) {
31-
var kind = wasmerImpExpKindName(imp.kind);
40+
var kind = wasmerExternKindName(imp.kind);
3241
description.write('import $kind: ${imp.moduleName}::${imp.name}\n');
3342
}
3443
var exports = runtime.exportDescriptors(_module);
3544
for (var exp in exports) {
36-
var kind = wasmerImpExpKindName(exp.kind);
45+
var kind = wasmerExternKindName(exp.kind);
3746
description.write('export $kind: ${exp.name}\n');
3847
}
3948
return description.toString();
@@ -42,13 +51,13 @@ class WasmModule {
4251

4352
/// WasmImports holds all the imports for a WasmInstance.
4453
class WasmImports {
45-
Pointer<WasmerImport> _imports;
54+
Pointer<Pointer<WasmerExtern>> _imports;
4655
int _capacity;
4756
int _length;
4857

4958
/// Create an imports object.
5059
WasmImports([this._capacity = 4])
51-
: _imports = allocate<WasmerImport>(count: _capacity),
60+
: _imports = allocate<Pointer<WasmerExtern>>(count: _capacity),
5261
_length = 0 {}
5362

5463
/// Returns the number of imports.
@@ -57,26 +66,31 @@ class WasmImports {
5766

5867
/// WasmInstance is an instantiated WasmModule.
5968
class WasmInstance {
69+
Pointer<WasmerStore> _store;
6070
Pointer<WasmerModule> _module;
6171
Pointer<WasmerInstance> _instance;
6272
Pointer<WasmerMemory>? _exportedMemory;
6373
Map<String, WasmFunction> _functions = {};
6474

65-
WasmInstance(this._module, WasmImports imports)
75+
WasmInstance(this._store, this._module, WasmImports imports)
6676
: _instance = WasmRuntime()
67-
.instantiate(_module, imports._imports, imports.length) {
77+
.instantiate(_store, _module, imports._imports, imports.length) {
6878
var runtime = WasmRuntime();
69-
var exps = runtime.exports(_instance);
70-
for (var e in exps) {
71-
var kind = runtime.exportKind(e);
72-
String name = runtime.exportName(e);
73-
if (kind == WasmerImpExpKindFunction) {
74-
var f = runtime.exportToFunction(e);
79+
var exports = runtime.exports(_instance);
80+
var exportDescs = runtime.exportDescriptors(_module);
81+
assert(exports.ref.length == exportDescs.length);
82+
for (var i = 0; i < exports.ref.length; ++i) {
83+
var e = exports.ref.data[i];
84+
var kind = runtime.externKind(exports.ref.data[i]);
85+
String name = exportDescs[i].name;
86+
if (kind == WasmerExternKindFunction) {
87+
var f = runtime.externToFunction(e);
88+
var ft = exportDescs[i].funcType;
7589
_functions[name] = WasmFunction(
76-
name, f, runtime.getArgTypes(f), runtime.getReturnType(f));
77-
} else if (kind == WasmerImpExpKindMemory) {
90+
name, f, runtime.getArgTypes(ft), runtime.getReturnType(ft));
91+
} else if (kind == WasmerExternKindMemory) {
7892
// WASM currently allows only one memory per module.
79-
_exportedMemory = runtime.exportToMemory(e);
93+
_exportedMemory = runtime.externToMemory(e);
8094
}
8195
}
8296
}
@@ -107,8 +121,8 @@ class WasmMemory {
107121

108122
/// Create a new memory with the given number of initial pages, and optional
109123
/// maximum number of pages.
110-
WasmMemory(int pages, [int? maxPages])
111-
: _mem = WasmRuntime().newMemory(pages, maxPages) {
124+
WasmMemory._create(Pointer<WasmerStore> store, int pages, int? maxPages)
125+
: _mem = WasmRuntime().newMemory(store, pages, maxPages) {
112126
_view = WasmRuntime().memoryView(_mem);
113127
}
114128

0 commit comments

Comments
 (0)