mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 12:30:03 +00:00
[wasm] Wasm function imports.
I switched from a WasmImports object to a builder pattern: module.instantiate().addMemory(...).addFunction(...).build(); Bug: https://github.com/dart-lang/sdk/issues/37882 Change-Id: I381aa0f7df1fa006ce8d051cd5b4a1bcc1835e46 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/167460 Reviewed-by: Ryan Macnak <rmacnak@google.com> Commit-Queue: Liam Appelbe <liama@google.com>
This commit is contained in:
parent
f0052ef52e
commit
89dbc35fca
2
DEPS
2
DEPS
|
@ -133,7 +133,7 @@ vars = {
|
|||
"quiver-dart_tag": "246e754fe45cecb6aa5f3f13b4ed61037ff0d784",
|
||||
"resource_rev": "f8e37558a1c4f54550aa463b88a6a831e3e33cd6",
|
||||
"root_certificates_rev": "7e5ec82c99677a2e5b95ce296c4d68b0d3378ed8",
|
||||
"rust_revision": "cbe7c5ce705896d4e22bf6096590bc1f17993b78",
|
||||
"rust_revision": "b7856f695d65a8ebc846754f97d15814bcb1c244",
|
||||
"shelf_static_rev": "v0.2.8",
|
||||
"shelf_packages_handler_tag": "2.0.0",
|
||||
"shelf_proxy_tag": "0.1.0+7",
|
||||
|
|
|
@ -28,8 +28,7 @@ class WasmFunction {
|
|||
}
|
||||
|
||||
String toString() {
|
||||
return "${wasmerValKindName(_returnType)} $_name" +
|
||||
"(${_argTypes.map(wasmerValKindName).join(", ")})";
|
||||
return WasmRuntime.getSignatureString(_name, _argTypes, _returnType);
|
||||
}
|
||||
|
||||
bool _fillArg(dynamic arg, int i) {
|
||||
|
|
|
@ -19,9 +19,10 @@ class WasmModule {
|
|||
_module = WasmRuntime().compile(_store, data);
|
||||
}
|
||||
|
||||
/// Instantiate the module with the given imports.
|
||||
WasmInstance instantiate(WasmImports imports) {
|
||||
return WasmInstance(_store, _module, imports);
|
||||
/// Returns a WasmInstanceBuilder that is used to add all the imports that the
|
||||
/// module needs, and then instantiate it.
|
||||
WasmInstanceBuilder instantiate() {
|
||||
return WasmInstanceBuilder(this);
|
||||
}
|
||||
|
||||
/// Create a new memory with the given number of initial pages, and optional
|
||||
|
@ -37,47 +38,166 @@ class WasmModule {
|
|||
var runtime = WasmRuntime();
|
||||
var imports = runtime.importDescriptors(_module);
|
||||
for (var imp in imports) {
|
||||
var kind = wasmerExternKindName(imp.kind);
|
||||
description.write('import $kind: ${imp.moduleName}::${imp.name}\n');
|
||||
description.write("import $imp\n");
|
||||
}
|
||||
var exports = runtime.exportDescriptors(_module);
|
||||
for (var exp in exports) {
|
||||
var kind = wasmerExternKindName(exp.kind);
|
||||
description.write('export $kind: ${exp.name}\n');
|
||||
description.write("export $exp\n");
|
||||
}
|
||||
return description.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/// WasmImports holds all the imports for a WasmInstance.
|
||||
class WasmImports {
|
||||
Pointer<Pointer<WasmerExtern>> _imports;
|
||||
int _capacity;
|
||||
int _length;
|
||||
Pointer<WasmerTrap> _wasmFnImportTrampoline(Pointer<_WasmFnImport> imp,
|
||||
Pointer<WasmerVal> args, Pointer<WasmerVal> results) {
|
||||
try {
|
||||
_WasmFnImport._call(imp, args, results);
|
||||
} catch (e) {
|
||||
// TODO: Use WasmerTrap to handle this case. For now just print the
|
||||
// exception (if we ignore it, FFI will silently return a default result).
|
||||
print(e);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Create an imports object.
|
||||
WasmImports([this._capacity = 4])
|
||||
: _imports = allocate<Pointer<WasmerExtern>>(count: _capacity),
|
||||
_length = 0 {}
|
||||
void _wasmFnImportFinalizer(Pointer<_WasmFnImport> imp) {
|
||||
_wasmFnImportToFn.remove(imp.address);
|
||||
free(imp);
|
||||
}
|
||||
|
||||
/// Returns the number of imports.
|
||||
int get length => _length;
|
||||
final _wasmFnImportTrampolineNative = Pointer.fromFunction<
|
||||
Pointer<WasmerTrap> Function(Pointer<_WasmFnImport>, Pointer<WasmerVal>,
|
||||
Pointer<WasmerVal>)>(_wasmFnImportTrampoline);
|
||||
final _wasmFnImportToFn = <int, Function>{};
|
||||
final _wasmFnImportFinalizerNative =
|
||||
Pointer.fromFunction<Void Function(Pointer<_WasmFnImport>)>(
|
||||
_wasmFnImportFinalizer);
|
||||
|
||||
class _WasmFnImport extends Struct {
|
||||
@Int32()
|
||||
external int numArgs;
|
||||
|
||||
@Int32()
|
||||
external int returnType;
|
||||
|
||||
static void _call(Pointer<_WasmFnImport> imp, Pointer<WasmerVal> rawArgs,
|
||||
Pointer<WasmerVal> rawResult) {
|
||||
Function fn = _wasmFnImportToFn[imp.address] as Function;
|
||||
var args = [];
|
||||
for (var i = 0; i < imp.ref.numArgs; ++i) {
|
||||
args.add(rawArgs[i].toDynamic);
|
||||
}
|
||||
var result = Function.apply(fn, args);
|
||||
switch (imp.ref.returnType) {
|
||||
case WasmerValKindI32:
|
||||
rawResult.ref.i32 = result;
|
||||
break;
|
||||
case WasmerValKindI64:
|
||||
rawResult.ref.i64 = result;
|
||||
break;
|
||||
case WasmerValKindF32:
|
||||
rawResult.ref.f32 = result;
|
||||
break;
|
||||
case WasmerValKindF64:
|
||||
rawResult.ref.f64 = result;
|
||||
break;
|
||||
case WasmerValKindVoid:
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// WasmInstanceBuilder is used collect all the imports that a WasmModule
|
||||
/// requires before it is instantiated.
|
||||
class WasmInstanceBuilder {
|
||||
WasmModule _module;
|
||||
late List<WasmImportDescriptor> _importDescs;
|
||||
Map<String, int> _importIndex;
|
||||
late Pointer<Pointer<WasmerExtern>> _imports;
|
||||
|
||||
WasmInstanceBuilder(this._module) : _importIndex = {} {
|
||||
_importDescs = WasmRuntime().importDescriptors(_module._module);
|
||||
_imports = allocate<Pointer<WasmerExtern>>(count: _importDescs.length);
|
||||
for (var i = 0; i < _importDescs.length; ++i) {
|
||||
var imp = _importDescs[i];
|
||||
_importIndex["${imp.moduleName}::${imp.name}"] = i;
|
||||
_imports[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int _getIndex(String moduleName, String name) {
|
||||
var index = _importIndex["${moduleName}::${name}"];
|
||||
if (index == null) {
|
||||
throw Exception("Import not found: ${moduleName}::${name}");
|
||||
} else if (_imports[index] != nullptr) {
|
||||
throw Exception("Import already filled: ${moduleName}::${name}");
|
||||
} else {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a WasmMemory to the imports.
|
||||
WasmInstanceBuilder addMemory(
|
||||
String moduleName, String name, WasmMemory memory) {
|
||||
var index = _getIndex(moduleName, name);
|
||||
var imp = _importDescs[index];
|
||||
if (imp.kind != WasmerExternKindMemory) {
|
||||
throw Exception("Import is not a memory: $imp");
|
||||
}
|
||||
_imports[index] = WasmRuntime().memoryToExtern(memory._mem);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// Add a function to the imports.
|
||||
WasmInstanceBuilder addFunction(String moduleName, String name, Function fn) {
|
||||
var index = _getIndex(moduleName, name);
|
||||
var imp = _importDescs[index];
|
||||
var runtime = WasmRuntime();
|
||||
|
||||
if (imp.kind != WasmerExternKindFunction) {
|
||||
throw Exception("Import is not a function: $imp");
|
||||
}
|
||||
|
||||
var argTypes = runtime.getArgTypes(imp.funcType);
|
||||
var returnType = runtime.getReturnType(imp.funcType);
|
||||
var wasmFnImport = allocate<_WasmFnImport>();
|
||||
wasmFnImport.ref.numArgs = argTypes.length;
|
||||
wasmFnImport.ref.returnType = returnType;
|
||||
_wasmFnImportToFn[wasmFnImport.address] = fn;
|
||||
var fnImp = runtime.newFunc(
|
||||
_module._store,
|
||||
imp.funcType,
|
||||
_wasmFnImportTrampolineNative,
|
||||
wasmFnImport,
|
||||
_wasmFnImportFinalizerNative);
|
||||
_imports[index] = runtime.functionToExtern(fnImp);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// Build the module instance.
|
||||
WasmInstance build() {
|
||||
for (var i = 0; i < _importDescs.length; ++i) {
|
||||
if (_imports[i] == nullptr) {
|
||||
throw Exception("Missing import: ${_importDescs[i]}");
|
||||
}
|
||||
}
|
||||
return WasmInstance(_module, _imports);
|
||||
}
|
||||
}
|
||||
|
||||
/// WasmInstance is an instantiated WasmModule.
|
||||
class WasmInstance {
|
||||
Pointer<WasmerStore> _store;
|
||||
Pointer<WasmerModule> _module;
|
||||
WasmModule _module;
|
||||
Pointer<WasmerInstance> _instance;
|
||||
Pointer<WasmerMemory>? _exportedMemory;
|
||||
Map<String, WasmFunction> _functions = {};
|
||||
|
||||
WasmInstance(this._store, this._module, WasmImports imports)
|
||||
WasmInstance(this._module, Pointer<Pointer<WasmerExtern>> imports)
|
||||
: _instance = WasmRuntime()
|
||||
.instantiate(_store, _module, imports._imports, imports.length) {
|
||||
.instantiate(_module._store, _module._module, imports) {
|
||||
var runtime = WasmRuntime();
|
||||
var exports = runtime.exports(_instance);
|
||||
var exportDescs = runtime.exportDescriptors(_module);
|
||||
var exportDescs = runtime.exportDescriptors(_module._module);
|
||||
assert(exports.ref.length == exportDescs.length);
|
||||
for (var i = 0; i < exports.ref.length; ++i) {
|
||||
var e = exports.ref.data[i];
|
||||
|
|
|
@ -20,6 +20,18 @@ class WasmImportDescriptor {
|
|||
String name;
|
||||
Pointer<WasmerFunctype> funcType;
|
||||
WasmImportDescriptor(this.kind, this.moduleName, this.name, this.funcType);
|
||||
|
||||
String toString() {
|
||||
var kindName = wasmerExternKindName(kind);
|
||||
if (kind == WasmerExternKindFunction) {
|
||||
var runtime = WasmRuntime();
|
||||
var sig = WasmRuntime.getSignatureString("${moduleName}::${name}",
|
||||
runtime.getArgTypes(funcType), runtime.getReturnType(funcType));
|
||||
return "$kindName: $sig";
|
||||
} else {
|
||||
return "$kindName: ${moduleName}::${name}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class WasmExportDescriptor {
|
||||
|
@ -27,6 +39,18 @@ class WasmExportDescriptor {
|
|||
String name;
|
||||
Pointer<WasmerFunctype> funcType;
|
||||
WasmExportDescriptor(this.kind, this.name, this.funcType);
|
||||
|
||||
String toString() {
|
||||
var kindName = wasmerExternKindName(kind);
|
||||
if (kind == WasmerExternKindFunction) {
|
||||
var runtime = WasmRuntime();
|
||||
var sig = WasmRuntime.getSignatureString(
|
||||
name, runtime.getArgTypes(funcType), runtime.getReturnType(funcType));
|
||||
return "$kindName: $sig";
|
||||
} else {
|
||||
return "$kindName: ${name}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class WasmRuntime {
|
||||
|
@ -57,8 +81,10 @@ class WasmRuntime {
|
|||
late WasmerExterntypeAsFunctypeFn _externtype_as_functype;
|
||||
late WasmerExterntypeDeleteFn _externtype_delete;
|
||||
late WasmerExterntypeKindFn _externtype_kind;
|
||||
late WasmerFuncAsExternFn _func_as_extern;
|
||||
late WasmerFuncCallFn _func_call;
|
||||
late WasmerFuncDeleteFn _func_delete;
|
||||
late WasmerFuncNewWithEnvFn _func_new_with_env;
|
||||
late WasmerFunctypeDeleteFn _functype_delete;
|
||||
late WasmerFunctypeParamsFn _functype_params;
|
||||
late WasmerFunctypeResultsFn _functype_results;
|
||||
|
@ -72,6 +98,7 @@ class WasmRuntime {
|
|||
late WasmerInstanceDeleteFn _instance_delete;
|
||||
late WasmerInstanceExportsFn _instance_exports;
|
||||
late WasmerInstanceNewFn _instance_new;
|
||||
late WasmerMemoryAsExternFn _memory_as_extern;
|
||||
late WasmerMemoryDataFn _memory_data;
|
||||
late WasmerMemoryDataSizeFn _memory_data_size;
|
||||
late WasmerMemoryDeleteFn _memory_delete;
|
||||
|
@ -199,11 +226,16 @@ class WasmRuntime {
|
|||
WasmerExterntypeDeleteFn>('wasm_externtype_delete');
|
||||
_externtype_kind = _lib.lookupFunction<NativeWasmerExterntypeKindFn,
|
||||
WasmerExterntypeKindFn>('wasm_externtype_kind');
|
||||
_func_as_extern =
|
||||
_lib.lookupFunction<NativeWasmerFuncAsExternFn, WasmerFuncAsExternFn>(
|
||||
'wasm_func_as_extern');
|
||||
_func_call = _lib.lookupFunction<NativeWasmerFuncCallFn, WasmerFuncCallFn>(
|
||||
'wasm_func_call');
|
||||
_func_delete =
|
||||
_lib.lookupFunction<NativeWasmerFuncDeleteFn, WasmerFuncDeleteFn>(
|
||||
'wasm_func_delete');
|
||||
_func_new_with_env = _lib.lookupFunction<NativeWasmerFuncNewWithEnvFn,
|
||||
WasmerFuncNewWithEnvFn>('wasm_func_new_with_env');
|
||||
_functype_delete = _lib.lookupFunction<NativeWasmerFunctypeDeleteFn,
|
||||
WasmerFunctypeDeleteFn>('wasm_functype_delete');
|
||||
_functype_params = _lib.lookupFunction<NativeWasmerFunctypeParamsFn,
|
||||
|
@ -235,6 +267,8 @@ class WasmRuntime {
|
|||
_instance_new =
|
||||
_lib.lookupFunction<NativeWasmerInstanceNewFn, WasmerInstanceNewFn>(
|
||||
'wasm_instance_new');
|
||||
_memory_as_extern = _lib.lookupFunction<NativeWasmerMemoryAsExternFn,
|
||||
WasmerMemoryAsExternFn>('wasm_memory_as_extern');
|
||||
_memory_data =
|
||||
_lib.lookupFunction<NativeWasmerMemoryDataFn, WasmerMemoryDataFn>(
|
||||
'wasm_memory_data');
|
||||
|
@ -363,20 +397,8 @@ class WasmRuntime {
|
|||
return imps;
|
||||
}
|
||||
|
||||
Pointer<WasmerInstance> instantiate(
|
||||
Pointer<WasmerStore> store,
|
||||
Pointer<WasmerModule> module,
|
||||
Pointer<Pointer<WasmerExtern>> imports,
|
||||
int numImports) {
|
||||
var importsVec = allocate<WasmerImporttypeVec>();
|
||||
_module_imports(module, importsVec);
|
||||
if (importsVec.ref.length != numImports) {
|
||||
throw Exception(
|
||||
"Wrong number of imports. Expected ${importsVec.ref.length} but " +
|
||||
"found $numImports.");
|
||||
}
|
||||
free(importsVec);
|
||||
|
||||
Pointer<WasmerInstance> instantiate(Pointer<WasmerStore> store,
|
||||
Pointer<WasmerModule> module, Pointer<Pointer<WasmerExtern>> imports) {
|
||||
var instancePtr = _instance_new(store, module, imports, nullptr);
|
||||
if (instancePtr == nullptr) {
|
||||
throw Exception("Wasm module instantiation failed");
|
||||
|
@ -399,6 +421,10 @@ class WasmRuntime {
|
|||
return _extern_as_func(extern);
|
||||
}
|
||||
|
||||
Pointer<WasmerExtern> functionToExtern(Pointer<WasmerFunc> func) {
|
||||
return _func_as_extern(func);
|
||||
}
|
||||
|
||||
List<int> getArgTypes(Pointer<WasmerFunctype> funcType) {
|
||||
var types = <int>[];
|
||||
var args = _functype_params(funcType);
|
||||
|
@ -427,6 +453,10 @@ class WasmRuntime {
|
|||
return _extern_as_memory(extern);
|
||||
}
|
||||
|
||||
Pointer<WasmerExtern> memoryToExtern(Pointer<WasmerMemory> memory) {
|
||||
return _memory_as_extern(memory);
|
||||
}
|
||||
|
||||
Pointer<WasmerMemory> newMemory(
|
||||
Pointer<WasmerStore> store, int pages, int? maxPages) {
|
||||
var limPtr = allocate<WasmerLimits>();
|
||||
|
@ -456,4 +486,20 @@ class WasmRuntime {
|
|||
Uint8List memoryView(Pointer<WasmerMemory> memory) {
|
||||
return _memory_data(memory).asTypedList(_memory_data_size(memory));
|
||||
}
|
||||
|
||||
Pointer<WasmerFunc> newFunc(
|
||||
Pointer<WasmerStore> store,
|
||||
Pointer<WasmerFunctype> funcType,
|
||||
Pointer func,
|
||||
Pointer env,
|
||||
Pointer finalizer) {
|
||||
return _func_new_with_env(
|
||||
store, funcType, func.cast(), env.cast(), finalizer.cast());
|
||||
}
|
||||
|
||||
static String getSignatureString(
|
||||
String name, List<int> argTypes, int returnType) {
|
||||
return "${wasmerValKindName(returnType)} $name" +
|
||||
"(${argTypes.map(wasmerValKindName).join(", ")})";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -283,9 +283,12 @@ WASM_API_EXTERN wasm_memory_pages_t wasm_memory_size(const wasm_memory_t*);
|
|||
WASM_API_EXTERN bool wasm_memory_grow(wasm_memory_t*, wasm_memory_pages_t delta);
|
||||
WASM_API_EXTERN wasm_externkind_t wasm_extern_kind(const wasm_extern_t*);
|
||||
WASM_API_EXTERN wasm_func_t* wasm_extern_as_func(wasm_extern_t*);
|
||||
WASM_API_EXTERN wasm_extern_t* wasm_func_as_extern(wasm_func_t*);
|
||||
WASM_API_EXTERN wasm_memory_t* wasm_extern_as_memory(wasm_extern_t*);
|
||||
WASM_API_EXTERN wasm_extern_t* wasm_memory_as_extern(wasm_memory_t*);
|
||||
WASM_API_EXTERN const wasm_valtype_vec_t* wasm_functype_params(const wasm_functype_t*);
|
||||
WASM_API_EXTERN const wasm_valtype_vec_t* wasm_functype_results(const wasm_functype_t*);
|
||||
WASM_API_EXTERN own wasm_func_t* wasm_func_new_with_env( wasm_store_t*, const wasm_functype_t* type, void* fn, void* env, void *finalizer);
|
||||
WASM_API_EXTERN own wasm_trap_t* wasm_func_call(const wasm_func_t*, const wasm_val_t args[], wasm_val_t results[]);
|
||||
WASM_API_EXTERN wasm_valkind_t wasm_valtype_kind(const wasm_valtype_t*);
|
||||
'''
|
||||
|
|
|
@ -18,6 +18,18 @@ class WasmImportDescriptor {
|
|||
String name;
|
||||
Pointer<WasmerFunctype> funcType;
|
||||
WasmImportDescriptor(this.kind, this.moduleName, this.name, this.funcType);
|
||||
|
||||
String toString() {
|
||||
var kindName = wasmerExternKindName(kind);
|
||||
if (kind == WasmerExternKindFunction) {
|
||||
var runtime = WasmRuntime();
|
||||
var sig = WasmRuntime.getSignatureString("${moduleName}::${name}",
|
||||
runtime.getArgTypes(funcType), runtime.getReturnType(funcType));
|
||||
return "$kindName: $sig";
|
||||
} else {
|
||||
return "$kindName: ${moduleName}::${name}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class WasmExportDescriptor {
|
||||
|
@ -25,6 +37,18 @@ class WasmExportDescriptor {
|
|||
String name;
|
||||
Pointer<WasmerFunctype> funcType;
|
||||
WasmExportDescriptor(this.kind, this.name, this.funcType);
|
||||
|
||||
String toString() {
|
||||
var kindName = wasmerExternKindName(kind);
|
||||
if (kind == WasmerExternKindFunction) {
|
||||
var runtime = WasmRuntime();
|
||||
var sig = WasmRuntime.getSignatureString(
|
||||
name, runtime.getArgTypes(funcType), runtime.getReturnType(funcType));
|
||||
return "$kindName: $sig";
|
||||
} else {
|
||||
return "$kindName: ${name}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class WasmRuntime {
|
||||
|
@ -147,20 +171,8 @@ class WasmRuntime {
|
|||
return imps;
|
||||
}
|
||||
|
||||
Pointer<WasmerInstance> instantiate(
|
||||
Pointer<WasmerStore> store,
|
||||
Pointer<WasmerModule> module,
|
||||
Pointer<Pointer<WasmerExtern>> imports,
|
||||
int numImports) {
|
||||
var importsVec = allocate<WasmerImporttypeVec>();
|
||||
_module_imports(module, importsVec);
|
||||
if (importsVec.ref.length != numImports) {
|
||||
throw Exception(
|
||||
"Wrong number of imports. Expected ${importsVec.ref.length} but " +
|
||||
"found $numImports.");
|
||||
}
|
||||
free(importsVec);
|
||||
|
||||
Pointer<WasmerInstance> instantiate(Pointer<WasmerStore> store,
|
||||
Pointer<WasmerModule> module, Pointer<Pointer<WasmerExtern>> imports) {
|
||||
var instancePtr = _instance_new(store, module, imports, nullptr);
|
||||
if (instancePtr == nullptr) {
|
||||
throw Exception("Wasm module instantiation failed");
|
||||
|
@ -183,6 +195,10 @@ class WasmRuntime {
|
|||
return _extern_as_func(extern);
|
||||
}
|
||||
|
||||
Pointer<WasmerExtern> functionToExtern(Pointer<WasmerFunc> func) {
|
||||
return _func_as_extern(func);
|
||||
}
|
||||
|
||||
List<int> getArgTypes(Pointer<WasmerFunctype> funcType) {
|
||||
var types = <int>[];
|
||||
var args = _functype_params(funcType);
|
||||
|
@ -211,6 +227,10 @@ class WasmRuntime {
|
|||
return _extern_as_memory(extern);
|
||||
}
|
||||
|
||||
Pointer<WasmerExtern> memoryToExtern(Pointer<WasmerMemory> memory) {
|
||||
return _memory_as_extern(memory);
|
||||
}
|
||||
|
||||
Pointer<WasmerMemory> newMemory(
|
||||
Pointer<WasmerStore> store, int pages, int? maxPages) {
|
||||
var limPtr = allocate<WasmerLimits>();
|
||||
|
@ -240,4 +260,20 @@ class WasmRuntime {
|
|||
Uint8List memoryView(Pointer<WasmerMemory> memory) {
|
||||
return _memory_data(memory).asTypedList(_memory_data_size(memory));
|
||||
}
|
||||
|
||||
Pointer<WasmerFunc> newFunc(
|
||||
Pointer<WasmerStore> store,
|
||||
Pointer<WasmerFunctype> funcType,
|
||||
Pointer func,
|
||||
Pointer env,
|
||||
Pointer finalizer) {
|
||||
return _func_new_with_env(
|
||||
store, funcType, func.cast(), env.cast(), finalizer.cast());
|
||||
}
|
||||
|
||||
static String getSignatureString(
|
||||
String name, List<int> argTypes, int returnType) {
|
||||
return "${wasmerValKindName(returnType)} $name" +
|
||||
"(${argTypes.map(wasmerValKindName).join(", ")})";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,6 +86,19 @@ class WasmerVal extends Struct {
|
|||
bool get isI64 => kind == WasmerValKindI64;
|
||||
bool get isF32 => kind == WasmerValKindF32;
|
||||
bool get isF64 => kind == WasmerValKindF64;
|
||||
|
||||
dynamic get toDynamic {
|
||||
switch (kind) {
|
||||
case WasmerValKindI32:
|
||||
return i32;
|
||||
case WasmerValKindI64:
|
||||
return i64;
|
||||
case WasmerValKindF32:
|
||||
return f32;
|
||||
case WasmerValKindF64:
|
||||
return f64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// wasmer_limits_t
|
||||
|
|
|
@ -88,6 +88,19 @@ class WasmerVal extends Struct {
|
|||
bool get isI64 => kind == WasmerValKindI64;
|
||||
bool get isF32 => kind == WasmerValKindF32;
|
||||
bool get isF64 => kind == WasmerValKindF64;
|
||||
|
||||
dynamic get toDynamic {
|
||||
switch (kind) {
|
||||
case WasmerValKindI32:
|
||||
return i32;
|
||||
case WasmerValKindI64:
|
||||
return i64;
|
||||
case WasmerValKindF32:
|
||||
return f32;
|
||||
case WasmerValKindF64:
|
||||
return f64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// wasmer_limits_t
|
||||
|
@ -316,6 +329,12 @@ typedef NativeWasmerExterntypeKindFn = Uint8 Function(
|
|||
Pointer<WasmerExterntype>);
|
||||
typedef WasmerExterntypeKindFn = int Function(Pointer<WasmerExterntype>);
|
||||
|
||||
// wasm_func_as_extern
|
||||
typedef NativeWasmerFuncAsExternFn = Pointer<WasmerExtern> Function(
|
||||
Pointer<WasmerFunc>);
|
||||
typedef WasmerFuncAsExternFn = Pointer<WasmerExtern> Function(
|
||||
Pointer<WasmerFunc>);
|
||||
|
||||
// wasm_func_call
|
||||
typedef NativeWasmerFuncCallFn = Pointer<WasmerTrap> Function(
|
||||
Pointer<WasmerFunc>, Pointer<WasmerVal>, Pointer<WasmerVal>);
|
||||
|
@ -326,6 +345,20 @@ typedef WasmerFuncCallFn = Pointer<WasmerTrap> Function(
|
|||
typedef NativeWasmerFuncDeleteFn = Void Function(Pointer<WasmerFunc>);
|
||||
typedef WasmerFuncDeleteFn = void Function(Pointer<WasmerFunc>);
|
||||
|
||||
// wasm_func_new_with_env
|
||||
typedef NativeWasmerFuncNewWithEnvFn = Pointer<WasmerFunc> Function(
|
||||
Pointer<WasmerStore>,
|
||||
Pointer<WasmerFunctype>,
|
||||
Pointer<Void>,
|
||||
Pointer<Void>,
|
||||
Pointer<Void>);
|
||||
typedef WasmerFuncNewWithEnvFn = Pointer<WasmerFunc> Function(
|
||||
Pointer<WasmerStore>,
|
||||
Pointer<WasmerFunctype>,
|
||||
Pointer<Void>,
|
||||
Pointer<Void>,
|
||||
Pointer<Void>);
|
||||
|
||||
// wasm_functype_delete
|
||||
typedef NativeWasmerFunctypeDeleteFn = Void Function(Pointer<WasmerFunctype>);
|
||||
typedef WasmerFunctypeDeleteFn = void Function(Pointer<WasmerFunctype>);
|
||||
|
@ -406,6 +439,12 @@ typedef WasmerInstanceNewFn = Pointer<WasmerInstance> Function(
|
|||
Pointer<Pointer<WasmerExtern>>,
|
||||
Pointer<Pointer<WasmerTrap>>);
|
||||
|
||||
// wasm_memory_as_extern
|
||||
typedef NativeWasmerMemoryAsExternFn = Pointer<WasmerExtern> Function(
|
||||
Pointer<WasmerMemory>);
|
||||
typedef WasmerMemoryAsExternFn = Pointer<WasmerExtern> Function(
|
||||
Pointer<WasmerMemory>);
|
||||
|
||||
// wasm_memory_data
|
||||
typedef NativeWasmerMemoryDataFn = Pointer<Uint8> Function(
|
||||
Pointer<WasmerMemory>);
|
||||
|
|
|
@ -20,7 +20,7 @@ void main() {
|
|||
0x7e, 0x0b,
|
||||
]);
|
||||
|
||||
var inst = WasmModule(data).instantiate(WasmImports());
|
||||
var inst = WasmModule(data).instantiate().build();
|
||||
var fn = inst.lookupFunction("square");
|
||||
int n = fn(1234);
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ void main() {
|
|||
0x7e, 0x0b,
|
||||
]);
|
||||
|
||||
var inst = WasmModule(data).instantiate(WasmImports());
|
||||
var inst = WasmModule(data).instantiate().build();
|
||||
var fn = inst.lookupFunction("square");
|
||||
|
||||
Expect.throwsArgumentError(() => fn());
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// Test errors thrown by function imports.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
import "dart:wasm";
|
||||
import "package:wasm/wasm.dart";
|
||||
import "dart:typed_data";
|
||||
|
||||
void main() {
|
||||
|
@ -25,36 +25,27 @@ void main() {
|
|||
]);
|
||||
|
||||
var mod = WasmModule(data);
|
||||
var imp = WasmImports()
|
||||
..addFunction<Int64 Function(Int32, Int64, Float, Double)>(
|
||||
"env", "someFn", (num a, num b, num c, num d) => 123);
|
||||
mod.instantiate(imp);
|
||||
|
||||
imp = WasmImports();
|
||||
Expect.throwsArgumentError(() => mod.instantiate(imp));
|
||||
// Valid instantiation.
|
||||
var inst = mod.instantiate()
|
||||
.addFunction(
|
||||
"env", "someFn", (int a, int b, num c, double d) => 123).build();
|
||||
|
||||
imp = WasmImports()
|
||||
..addFunction<Int64 Function(Int32)>("env", "someFn", (num a) => 123);
|
||||
Expect.throwsArgumentError(() => mod.instantiate(imp));
|
||||
// Missing imports.
|
||||
Expect.throws(() => mod.instantiate().build(), (Exception e) => "$e".contains("Missing import"));
|
||||
|
||||
imp = WasmImports()
|
||||
..addFunction<Double Function(Int32, Int64, Float, Double)>(
|
||||
"env", "someFn", (num a, num b, num c, num d) => 123);
|
||||
Expect.throwsArgumentError(() => mod.instantiate(imp));
|
||||
// Wrong kind of import.
|
||||
Expect.throws(() => mod.instantiate().addMemory("env", "someFn", mod.createMemory(10)), (Exception e) => "$e".contains("Import is not a memory"));
|
||||
|
||||
imp = WasmImports()
|
||||
..addFunction<Int64 Function(Int32, Int64, Float, Float)>(
|
||||
"env", "someFn", (num a, num b, num c, num d) => 123);
|
||||
Expect.throwsArgumentError(() => mod.instantiate(imp));
|
||||
// Wrong namespace.
|
||||
Expect.throws(() => mod.instantiate().addFunction("foo", "someFn", (int a, int b, num c, double d) => 123).build(), (Exception e) => "$e".contains("Import not found"));
|
||||
|
||||
Expect.throwsArgumentError(() => WasmImports()
|
||||
..addFunction<dynamic Function(Int32, Int64, Float, Double)>(
|
||||
"env", "someFn", (num a, num b, num c, num d) => 123));
|
||||
// Wrong name.
|
||||
Expect.throws(() => mod.instantiate().addFunction("env", "otherFn", (int a, int b, num c, double d) => 123).build(), (Exception e) => "$e".contains("Import not found"));
|
||||
|
||||
Expect.throwsArgumentError(() => WasmImports()
|
||||
..addFunction<Int64 Function(Int32, Int64, dynamic, Double)>(
|
||||
"env", "someFn", (num a, num b, num c, num d) => 123));
|
||||
|
||||
imp = WasmImports()..addGlobal<Int64>("env", "someFn", 123, false);
|
||||
Expect.throwsArgumentError(() => mod.instantiate(imp));
|
||||
// Already filled.
|
||||
Expect.throws(() => mod.instantiate()
|
||||
.addFunction("env", "someFn", (int a, int b, num c, double d) => 123)
|
||||
.addFunction("env", "someFn", (int a, int b, num c, double d) => 456)
|
||||
.build(), (Exception e) => "$e".contains("Import already filled"));
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// Test that we can load a wasm module, find a function, and call it.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
import "dart:wasm";
|
||||
import "package:wasm/wasm.dart";
|
||||
import "dart:typed_data";
|
||||
|
||||
void main() {
|
||||
|
@ -25,13 +25,13 @@ void main() {
|
|||
int report_x = -1;
|
||||
int report_y = -1;
|
||||
|
||||
var inst = WasmModule(data).instantiate(WasmImports()
|
||||
..addFunction<Void Function(Int64, Int64)>("env", "report", (int x, int y) {
|
||||
var inst = WasmModule(data).instantiate()
|
||||
.addFunction("env", "report", (int x, int y) {
|
||||
report_x = x;
|
||||
report_y = y;
|
||||
}));
|
||||
var fn = inst.lookupFunction<Void Function()>("reportStuff");
|
||||
fn.call([]);
|
||||
}).build();
|
||||
var fn = inst.lookupFunction("reportStuff");
|
||||
fn();
|
||||
Expect.equals(report_x, 123);
|
||||
Expect.equals(report_y, 456);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// Test for hello world built using emscripten with WASI.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
import "dart:wasm";
|
||||
import "package:wasm/wasm.dart";
|
||||
import "dart:typed_data";
|
||||
|
||||
void main() {
|
||||
|
@ -169,7 +169,7 @@ void main() {
|
|||
0x0b, 0x05, 0x0a, 0xff, 0xff, 0xff, 0xff,
|
||||
]);
|
||||
|
||||
WasmMemory mem = null;
|
||||
late WasmMemory mem;
|
||||
String out = "";
|
||||
var getI32 = (int p) {
|
||||
// Read a little-endian I32.
|
||||
|
@ -180,9 +180,9 @@ void main() {
|
|||
}
|
||||
return n;
|
||||
};
|
||||
var inst = WasmModule(data).instantiate(WasmImports()
|
||||
..addFunction<Int32 Function(Int32, Int32, Int32, Int32)>(
|
||||
"wasi_unstable", "fd_write",
|
||||
var inst = WasmModule(data)
|
||||
.instantiate()
|
||||
.addFunction("wasi_unstable", "fd_write",
|
||||
(int fd, int iovs, int iovs_len, int unused) {
|
||||
// iovs points to an array of length iovs_len. Each element is two I32s,
|
||||
// a char* and a length.
|
||||
|
@ -196,10 +196,10 @@ void main() {
|
|||
}
|
||||
out += o;
|
||||
return o.length;
|
||||
}));
|
||||
}).build();
|
||||
mem = inst.memory;
|
||||
|
||||
var fn = inst.lookupFunction<Void Function()>("_start");
|
||||
fn.call([]);
|
||||
var fn = inst.lookupFunction("_start");
|
||||
fn();
|
||||
Expect.equals("hello, world!\n", out);
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ void main() {
|
|||
0x01, 0x92, 0x0b,
|
||||
]);
|
||||
|
||||
var inst = WasmModule(data).instantiate(WasmImports());
|
||||
var inst = WasmModule(data).instantiate().build();
|
||||
var addI64 = inst.lookupFunction("addI64");
|
||||
var addI32 = inst.lookupFunction("addI32");
|
||||
var addF64 = inst.lookupFunction("addF64");
|
||||
|
|
|
@ -25,7 +25,7 @@ void main() {
|
|||
0x80, 0x08, 0x0b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
]);
|
||||
|
||||
var inst = WasmModule(data).instantiate(WasmImports());
|
||||
var inst = WasmModule(data).instantiate().build();
|
||||
var setFn = inst.lookupFunction("set");
|
||||
var getFn = inst.lookupFunction("get");
|
||||
Expect.isNull(setFn(123, 456));
|
||||
|
|
|
@ -20,7 +20,7 @@ void main() {
|
|||
0x7e, 0x0b,
|
||||
]);
|
||||
|
||||
var inst = WasmModule(data).instantiate(WasmImports());
|
||||
var inst = WasmModule(data).instantiate().build();
|
||||
var fn = inst.lookupFunction("square");
|
||||
int n = fn(1234);
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ void main() {
|
|||
0x7e, 0x0b,
|
||||
]);
|
||||
|
||||
var inst = WasmModule(data).instantiate(WasmImports());
|
||||
var inst = WasmModule(data).instantiate().build();
|
||||
var fn = inst.lookupFunction("square");
|
||||
|
||||
Expect.throwsArgumentError(() => fn());
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// Test errors thrown by function imports.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
import "dart:wasm";
|
||||
import "package:wasm/wasm.dart";
|
||||
import "dart:typed_data";
|
||||
|
||||
void main() {
|
||||
|
@ -25,36 +25,27 @@ void main() {
|
|||
]);
|
||||
|
||||
var mod = WasmModule(data);
|
||||
var imp = WasmImports()
|
||||
..addFunction<Int64 Function(Int32, Int64, Float, Double)>(
|
||||
"env", "someFn", (num a, num b, num c, num d) => 123);
|
||||
mod.instantiate(imp);
|
||||
|
||||
imp = WasmImports();
|
||||
Expect.throwsArgumentError(() => mod.instantiate(imp));
|
||||
// Valid instantiation.
|
||||
var inst = mod.instantiate()
|
||||
.addFunction(
|
||||
"env", "someFn", (int a, int b, num c, double d) => 123).build();
|
||||
|
||||
imp = WasmImports()
|
||||
..addFunction<Int64 Function(Int32)>("env", "someFn", (num a) => 123);
|
||||
Expect.throwsArgumentError(() => mod.instantiate(imp));
|
||||
// Missing imports.
|
||||
Expect.throws(() => mod.instantiate().build(), (Exception e) => "$e".contains("Missing import"));
|
||||
|
||||
imp = WasmImports()
|
||||
..addFunction<Double Function(Int32, Int64, Float, Double)>(
|
||||
"env", "someFn", (num a, num b, num c, num d) => 123);
|
||||
Expect.throwsArgumentError(() => mod.instantiate(imp));
|
||||
// Wrong kind of import.
|
||||
Expect.throws(() => mod.instantiate().addMemory("env", "someFn", mod.createMemory(10)), (Exception e) => "$e".contains("Import is not a memory"));
|
||||
|
||||
imp = WasmImports()
|
||||
..addFunction<Int64 Function(Int32, Int64, Float, Float)>(
|
||||
"env", "someFn", (num a, num b, num c, num d) => 123);
|
||||
Expect.throwsArgumentError(() => mod.instantiate(imp));
|
||||
// Wrong namespace.
|
||||
Expect.throws(() => mod.instantiate().addFunction("foo", "someFn", (int a, int b, num c, double d) => 123).build(), (Exception e) => "$e".contains("Import not found"));
|
||||
|
||||
Expect.throwsArgumentError(() => WasmImports()
|
||||
..addFunction<dynamic Function(Int32, Int64, Float, Double)>(
|
||||
"env", "someFn", (num a, num b, num c, num d) => 123));
|
||||
// Wrong name.
|
||||
Expect.throws(() => mod.instantiate().addFunction("env", "otherFn", (int a, int b, num c, double d) => 123).build(), (Exception e) => "$e".contains("Import not found"));
|
||||
|
||||
Expect.throwsArgumentError(() => WasmImports()
|
||||
..addFunction<Int64 Function(Int32, Int64, dynamic, Double)>(
|
||||
"env", "someFn", (num a, num b, num c, num d) => 123));
|
||||
|
||||
imp = WasmImports()..addGlobal<Int64>("env", "someFn", 123, false);
|
||||
Expect.throwsArgumentError(() => mod.instantiate(imp));
|
||||
// Already filled.
|
||||
Expect.throws(() => mod.instantiate()
|
||||
.addFunction("env", "someFn", (int a, int b, num c, double d) => 123)
|
||||
.addFunction("env", "someFn", (int a, int b, num c, double d) => 456)
|
||||
.build(), (Exception e) => "$e".contains("Import already filled"));
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// Test that we can load a wasm module, find a function, and call it.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
import "dart:wasm";
|
||||
import "package:wasm/wasm.dart";
|
||||
import "dart:typed_data";
|
||||
|
||||
void main() {
|
||||
|
@ -25,13 +25,13 @@ void main() {
|
|||
int report_x = -1;
|
||||
int report_y = -1;
|
||||
|
||||
var inst = WasmModule(data).instantiate(WasmImports()
|
||||
..addFunction<Void Function(Int64, Int64)>("env", "report", (int x, int y) {
|
||||
var inst = WasmModule(data).instantiate()
|
||||
.addFunction("env", "report", (int x, int y) {
|
||||
report_x = x;
|
||||
report_y = y;
|
||||
}));
|
||||
var fn = inst.lookupFunction<Void Function()>("reportStuff");
|
||||
fn.call([]);
|
||||
}).build();
|
||||
var fn = inst.lookupFunction("reportStuff");
|
||||
fn();
|
||||
Expect.equals(report_x, 123);
|
||||
Expect.equals(report_y, 456);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// Test for hello world built using emscripten with WASI.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
import "dart:wasm";
|
||||
import "package:wasm/wasm.dart";
|
||||
import "dart:typed_data";
|
||||
|
||||
void main() {
|
||||
|
@ -180,9 +180,9 @@ void main() {
|
|||
}
|
||||
return n;
|
||||
};
|
||||
var inst = WasmModule(data).instantiate(WasmImports()
|
||||
..addFunction<Int32 Function(Int32, Int32, Int32, Int32)>(
|
||||
"wasi_unstable", "fd_write",
|
||||
var inst = WasmModule(data)
|
||||
.instantiate()
|
||||
.addFunction("wasi_unstable", "fd_write",
|
||||
(int fd, int iovs, int iovs_len, int unused) {
|
||||
// iovs points to an array of length iovs_len. Each element is two I32s,
|
||||
// a char* and a length.
|
||||
|
@ -196,10 +196,10 @@ void main() {
|
|||
}
|
||||
out += o;
|
||||
return o.length;
|
||||
}));
|
||||
}).build();
|
||||
mem = inst.memory;
|
||||
|
||||
var fn = inst.lookupFunction<Void Function()>("_start");
|
||||
fn.call([]);
|
||||
var fn = inst.lookupFunction("_start");
|
||||
fn();
|
||||
Expect.equals("hello, world!\n", out);
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ void main() {
|
|||
0x01, 0x92, 0x0b,
|
||||
]);
|
||||
|
||||
var inst = WasmModule(data).instantiate(WasmImports());
|
||||
var inst = WasmModule(data).instantiate().build();
|
||||
var addI64 = inst.lookupFunction("addI64");
|
||||
var addI32 = inst.lookupFunction("addI32");
|
||||
var addF64 = inst.lookupFunction("addF64");
|
||||
|
|
|
@ -25,7 +25,7 @@ void main() {
|
|||
0x80, 0x08, 0x0b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
]);
|
||||
|
||||
var inst = WasmModule(data).instantiate(WasmImports());
|
||||
var inst = WasmModule(data).instantiate().build();
|
||||
var setFn = inst.lookupFunction("set");
|
||||
var getFn = inst.lookupFunction("get");
|
||||
Expect.isNull(setFn(123, 456));
|
||||
|
|
4
third_party/wasmer/Cargo.toml
vendored
4
third_party/wasmer/Cargo.toml
vendored
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "wasmer"
|
||||
version = "1.0.0-alpha3"
|
||||
version = "1.0.0-alpha4"
|
||||
|
||||
[lib]
|
||||
name = "wasmer"
|
||||
|
@ -8,6 +8,6 @@ crate-type = ["dylib"]
|
|||
path = "wasmer.rs"
|
||||
|
||||
[dependencies.wasmer-c-api]
|
||||
version = "1.0.0-alpha3"
|
||||
version = "1.0.0-alpha4"
|
||||
default-features = false
|
||||
features = ["jit", "cranelift", "wasi"]
|
||||
|
|
Loading…
Reference in a new issue