[wasm] Clean up native objects using finalizers

The finalizers associate each native object with a Dart object that owns
them. The finalizers need to be in native code, so I had to go back to
the old approach of linking Wasmer and my native code into a single .so.

TEST=I tried running the wasm tests using asan, but it didn't detect any
leaks even before the finalizers. So I put printfs in all the
set_finalizer and finalizer functions and manually verified that all the
finalizers were being run.

Bug: https://github.com/dart-lang/sdk/issues/37882
Change-Id: I38303ae0c6c446a23562c1b157c92ccc9af2dc34
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/172680
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Commit-Queue: Liam Appelbe <liama@google.com>
This commit is contained in:
Liam Appelbe 2020-11-24 21:12:09 +00:00 committed by commit-bot@chromium.org
parent 40535c3159
commit 1b94364da7
9 changed files with 298 additions and 59 deletions

View file

@ -11,12 +11,14 @@ import 'package:ffi/ffi.dart';
/// WasmModule is a compiled module that can be instantiated.
class WasmModule {
Pointer<WasmerStore> _store;
late Pointer<WasmerStore> _store;
late Pointer<WasmerModule> _module;
/// Compile a module.
WasmModule(Uint8List data) : _store = WasmRuntime().newStore() {
_module = WasmRuntime().compile(_store, data);
WasmModule(Uint8List data) {
var runtime = WasmRuntime();
_store = runtime.newStore(this);
_module = runtime.compile(this, _store, data);
}
/// Returns a WasmInstanceBuilder that is used to add all the imports that the
@ -115,6 +117,7 @@ class WasmInstanceBuilder {
Map<String, int> _importIndex;
Pointer<WasmerExternVec> _imports = allocate<WasmerExternVec>();
Pointer<WasmerWasiEnv> _wasiEnv = nullptr;
Object _importOwner = Object();
WasmInstanceBuilder(this._module) : _importIndex = {} {
_importDescs = WasmRuntime().importDescriptors(_module._module);
@ -168,6 +171,7 @@ class WasmInstanceBuilder {
wasmFnImport.ref.store = _module._store;
_wasmFnImportToFn[wasmFnImport.address] = fn;
var fnImp = runtime.newFunc(
_importOwner,
_module._store,
imp.funcType,
_wasmFnImportTrampolineNative,
@ -199,24 +203,26 @@ class WasmInstanceBuilder {
throw Exception("Missing import: ${_importDescs[i]}");
}
}
return WasmInstance(_module, _imports, _wasiEnv);
return WasmInstance(_module, _imports, _wasiEnv, _importOwner);
}
}
/// WasmInstance is an instantiated WasmModule.
class WasmInstance {
WasmModule _module;
Pointer<WasmerInstance> _instance;
late Pointer<WasmerInstance> _instance;
Pointer<WasmerMemory>? _exportedMemory;
Pointer<WasmerWasiEnv> _wasiEnv;
Stream<List<int>>? _stdout;
Stream<List<int>>? _stderr;
Map<String, WasmFunction> _functions = {};
Object _importOwner;
WasmInstance(this._module, Pointer<WasmerExternVec> imports, this._wasiEnv)
: _instance = WasmRuntime()
.instantiate(_module._store, _module._module, imports) {
WasmInstance(this._module, Pointer<WasmerExternVec> imports, this._wasiEnv,
this._importOwner) {
var runtime = WasmRuntime();
_instance =
runtime.instantiate(this, _module._store, _module._module, imports);
var exports = runtime.exports(_instance);
var exportDescs = runtime.exportDescriptors(_module._module);
assert(exports.ref.length == exportDescs.length);
@ -275,7 +281,7 @@ class WasmInstance {
/// WasmMemory contains the memory of a WasmInstance.
class WasmMemory {
Pointer<WasmerMemory> _mem;
late Pointer<WasmerMemory> _mem;
late Uint8List _view;
WasmMemory._fromExport(this._mem) {
@ -284,8 +290,8 @@ class WasmMemory {
/// Create a new memory with the given number of initial pages, and optional
/// maximum number of pages.
WasmMemory._create(Pointer<WasmerStore> store, int pages, int? maxPages)
: _mem = WasmRuntime().newMemory(store, pages, maxPages) {
WasmMemory._create(Pointer<WasmerStore> store, int pages, int? maxPages) {
_mem = WasmRuntime().newMemory(this, store, pages, maxPages);
_view = WasmRuntime().memoryView(_mem);
}

View file

@ -54,12 +54,26 @@ class WasmExportDescriptor {
}
}
class _WasmTrapsEntry {
dynamic exception;
_WasmTrapsEntry(this.exception);
}
class WasmRuntime {
static WasmRuntime? _inst;
DynamicLibrary _lib;
late Pointer<WasmerEngine> _engine;
Map<int, dynamic> traps = {};
Map<int, _WasmTrapsEntry> traps = {};
late WasmerDartInitializeApiDLFn _Dart_InitializeApiDL;
late WasmerSetFinalizerForEngineFn _set_finalizer_for_engine;
late WasmerSetFinalizerForFuncFn _set_finalizer_for_func;
late WasmerSetFinalizerForInstanceFn _set_finalizer_for_instance;
late WasmerSetFinalizerForMemoryFn _set_finalizer_for_memory;
late WasmerSetFinalizerForMemorytypeFn _set_finalizer_for_memorytype;
late WasmerSetFinalizerForModuleFn _set_finalizer_for_module;
late WasmerSetFinalizerForStoreFn _set_finalizer_for_store;
late WasmerSetFinalizerForTrapFn _set_finalizer_for_trap;
late WasmerWasiConfigInheritStderrFn _wasi_config_inherit_stderr;
late WasmerWasiConfigInheritStdoutFn _wasi_config_inherit_stdout;
late WasmerWasiConfigNewFn _wasi_config_new;
@ -178,6 +192,33 @@ class WasmRuntime {
WasmRuntime._init()
: _lib = DynamicLibrary.open(path.join(_getLibDir(), _getLibName())) {
_Dart_InitializeApiDL = _lib.lookupFunction<
NativeWasmerDartInitializeApiDLFn,
WasmerDartInitializeApiDLFn>('Dart_InitializeApiDL');
_set_finalizer_for_engine = _lib.lookupFunction<
NativeWasmerSetFinalizerForEngineFn,
WasmerSetFinalizerForEngineFn>('set_finalizer_for_engine');
_set_finalizer_for_func = _lib.lookupFunction<
NativeWasmerSetFinalizerForFuncFn,
WasmerSetFinalizerForFuncFn>('set_finalizer_for_func');
_set_finalizer_for_instance = _lib.lookupFunction<
NativeWasmerSetFinalizerForInstanceFn,
WasmerSetFinalizerForInstanceFn>('set_finalizer_for_instance');
_set_finalizer_for_memory = _lib.lookupFunction<
NativeWasmerSetFinalizerForMemoryFn,
WasmerSetFinalizerForMemoryFn>('set_finalizer_for_memory');
_set_finalizer_for_memorytype = _lib.lookupFunction<
NativeWasmerSetFinalizerForMemorytypeFn,
WasmerSetFinalizerForMemorytypeFn>('set_finalizer_for_memorytype');
_set_finalizer_for_module = _lib.lookupFunction<
NativeWasmerSetFinalizerForModuleFn,
WasmerSetFinalizerForModuleFn>('set_finalizer_for_module');
_set_finalizer_for_store = _lib.lookupFunction<
NativeWasmerSetFinalizerForStoreFn,
WasmerSetFinalizerForStoreFn>('set_finalizer_for_store');
_set_finalizer_for_trap = _lib.lookupFunction<
NativeWasmerSetFinalizerForTrapFn,
WasmerSetFinalizerForTrapFn>('set_finalizer_for_trap');
_wasi_config_inherit_stderr = _lib.lookupFunction<
NativeWasmerWasiConfigInheritStderrFn,
WasmerWasiConfigInheritStderrFn>('wasi_config_inherit_stderr');
@ -377,14 +418,23 @@ class WasmRuntime {
NativeWasmerWasmerLastErrorMessageFn,
WasmerWasmerLastErrorMessageFn>('wasmer_last_error_message');
if (_Dart_InitializeApiDL(NativeApi.initializeApiDLData) != 0) {
throw Exception("Failed to initialize Dart API");
}
_engine = _engine_new();
_checkNotEqual(_engine, nullptr, "Failed to initialize Wasm engine.");
_set_finalizer_for_engine(this, _engine);
}
Pointer<WasmerStore> newStore() {
return _store_new(_engine);
Pointer<WasmerStore> newStore(Object owner) {
Pointer<WasmerStore> store = _checkNotEqual(
_store_new(_engine), nullptr, "Failed to create Wasm store.");
_set_finalizer_for_store(owner, store);
return store;
}
Pointer<WasmerModule> compile(Pointer<WasmerStore> store, Uint8List data) {
Pointer<WasmerModule> compile(
Object owner, Pointer<WasmerStore> store, Uint8List data) {
var dataPtr = allocate<Uint8>(count: data.length);
for (int i = 0; i < data.length; ++i) {
dataPtr[i] = data[i];
@ -398,7 +448,9 @@ class WasmRuntime {
free(dataPtr);
free(dataVec);
return _checkNotEqual(modulePtr, nullptr, "Wasm module compile failed.");
_checkNotEqual(modulePtr, nullptr, "Wasm module compile failed.");
_set_finalizer_for_module(owner, modulePtr);
return modulePtr;
}
List<WasmExportDescriptor> exportDescriptors(Pointer<WasmerModule> module) {
@ -442,37 +494,51 @@ class WasmRuntime {
void maybeThrowTrap(Pointer<WasmerTrap> trap, String source) {
if (trap != nullptr) {
var stashedException = traps[trap.address];
if (stashedException != null) {
traps.remove(stashedException);
throw stashedException;
// There are 2 kinds of trap, and their memory is managed differently.
// Traps created in the newTrap method below are stored in the traps map
// with a corresponding exception, and their memory is managed using a
// finalizer on the _WasmTrapsEntry. Traps can also be created by WASM
// code, and in that case we delete them in this function.
var entry = traps[trap.address];
if (entry != null) {
traps.remove(entry);
throw entry.exception;
} else {
var trapMessage = allocate<WasmerByteVec>();
_trap_message(trap, trapMessage);
var message = "Wasm trap when calling $source: ${trapMessage.ref}";
free(trapMessage.ref.data);
_byte_vec_delete(trapMessage);
free(trapMessage);
_trap_delete(trap);
throw Exception(message);
}
}
}
Pointer<WasmerInstance> instantiate(Pointer<WasmerStore> store,
Pointer<WasmerInstance> instantiate(Object owner, Pointer<WasmerStore> store,
Pointer<WasmerModule> module, Pointer<WasmerExternVec> imports) {
var trap = allocate<Pointer<WasmerTrap>>();
trap.value = nullptr;
var inst = _instance_new(store, module, imports, trap);
maybeThrowTrap(trap.value, "module initialization function");
free(trap);
return _checkNotEqual(inst, nullptr, "Wasm module instantiation failed.");
_checkNotEqual(inst, nullptr, "Wasm module instantiation failed.");
_set_finalizer_for_instance(owner, inst);
return inst;
}
// Clean up the exports after use, with deleteExports.
Pointer<WasmerExternVec> exports(Pointer<WasmerInstance> instancePtr) {
var exports = allocate<WasmerExternVec>();
_instance_exports(instancePtr, exports);
return exports;
}
void deleteExports(Pointer<WasmerExternVec> exports) {
_extern_vec_delete(exports);
free(exports);
}
int externKind(Pointer<WasmerExtern> extern) {
return _extern_kind(extern);
}
@ -518,14 +584,18 @@ class WasmRuntime {
}
Pointer<WasmerMemory> newMemory(
Pointer<WasmerStore> store, int pages, int? maxPages) {
Object owner, Pointer<WasmerStore> store, int pages, int? maxPages) {
var limPtr = allocate<WasmerLimits>();
limPtr.ref.min = pages;
limPtr.ref.max = maxPages ?? wasm_limits_max_default;
var memType = _memorytype_new(limPtr);
free(limPtr);
return _checkNotEqual(
_checkNotEqual(memType, nullptr, "Failed to create memory type.");
_set_finalizer_for_memorytype(owner, memType);
var memory = _checkNotEqual(
_memory_new(store, memType), nullptr, "Failed to create memory.");
_set_finalizer_for_memory(owner, memory);
return memory;
}
void growMemory(Pointer<WasmerMemory> memory, int deltaPages) {
@ -542,13 +612,17 @@ class WasmRuntime {
}
Pointer<WasmerFunc> newFunc(
Object owner,
Pointer<WasmerStore> store,
Pointer<WasmerFunctype> funcType,
Pointer func,
Pointer env,
Pointer finalizer) {
return _func_new_with_env(
var f = _func_new_with_env(
store, funcType, func.cast(), env.cast(), finalizer.cast());
_checkNotEqual(f, nullptr, "Failed to create function.");
_set_finalizer_for_func(owner, f);
return f;
}
Pointer<WasmerTrap> newTrap(Pointer<WasmerStore> store, dynamic exception) {
@ -557,10 +631,13 @@ class WasmRuntime {
msg.ref.data[0] = 0;
msg.ref.length = 0;
var trap = _trap_new(store, msg);
traps[trap.address] = exception;
free(msg.ref.data);
free(msg);
return _checkNotEqual(trap, nullptr, "Failed to create trap.");
_checkNotEqual(trap, nullptr, "Failed to create trap.");
var entry = _WasmTrapsEntry(exception);
_set_finalizer_for_trap(entry, trap);
traps[trap.address] = entry;
return trap;
}
Pointer<WasmerWasiConfig> newWasiConfig() {

View file

@ -35,12 +35,14 @@ def ptrWrap(t, n):
def removePrefix(t):
assert (t.startswith('wasm_') or t.startswith('wasi_') or
t.startswith('wasmer_'))
t.startswith('wasmer_') or t.startswith('Dart_') or
t.startswith('set_finalizer_'))
return t[(5 if t.startswith('wasm_') else 0):]
def addPrefix(t):
if t.startswith('wasi_') or t.startswith('wasmer_'):
if t.startswith('wasi_') or t.startswith('wasmer_') or t.startswith(
'Dart_') or t.startswith('set_finalizer_'):
return t
return 'wasm_' + t
@ -251,6 +253,7 @@ predefinedType('float32_t', 'Float32', 'double')
predefinedType('float64_t', 'Float64', 'double')
predefinedType('wasm_limits_t', 'WasmerLimits', 'WasmerLimits')
predefinedType('wasm_val_t', 'WasmerVal', 'WasmerVal')
predefinedType('Dart_Handle', 'Handle', 'Object')
declareOwn('engine')
declareOwn('store')
@ -310,6 +313,7 @@ WASM_API_EXTERN own wasm_trap_t* wasm_func_call(const wasm_func_t*, const wasm_v
WASM_API_EXTERN own wasm_trap_t* wasm_trap_new(wasm_store_t* store, const wasm_message_t*);
WASM_API_EXTERN void wasm_trap_message(const wasm_trap_t*, own wasm_message_t* out);
WASM_API_EXTERN wasm_valkind_t wasm_valtype_kind(const wasm_valtype_t*);
wasi_config_t* wasi_config_new(const uint8_t* program_name);
wasi_env_t* wasi_env_new(wasi_config_t* config);
bool wasi_get_imports(const wasm_store_t* store, const wasm_module_t* module, const wasi_env_t* wasi_env, wasm_extern_vec_t* imports);
@ -320,6 +324,16 @@ void wasi_config_inherit_stdout(wasi_config_t* config);
void wasi_config_inherit_stderr(wasi_config_t* config);
intptr_t wasi_env_read_stderr(wasi_env_t* env, uint8_t* buffer, uintptr_t buffer_len);
intptr_t wasi_env_read_stdout(wasi_env_t* env, uint8_t* buffer, uintptr_t buffer_len);
intptr_t Dart_InitializeApiDL(void* data);
void set_finalizer_for_engine(Dart_Handle, wasm_engine_t*);
void set_finalizer_for_store(Dart_Handle, wasm_store_t*);
void set_finalizer_for_module(Dart_Handle, wasm_module_t*);
void set_finalizer_for_instance(Dart_Handle, wasm_instance_t*);
void set_finalizer_for_trap(Dart_Handle, wasm_trap_t*);
void set_finalizer_for_memorytype(Dart_Handle, wasm_memorytype_t*);
void set_finalizer_for_memory(Dart_Handle, wasm_memory_t*);
void set_finalizer_for_func(Dart_Handle, wasm_func_t*);
'''
for f in rawFns.split('\n'):
if len(f.strip()) > 0:

View file

@ -52,12 +52,17 @@ class WasmExportDescriptor {
}
}
class _WasmTrapsEntry {
dynamic exception;
_WasmTrapsEntry(this.exception);
}
class WasmRuntime {
static WasmRuntime? _inst;
DynamicLibrary _lib;
late Pointer<WasmerEngine> _engine;
Map<int, dynamic> traps = {};
Map<int, _WasmTrapsEntry> traps = {};
/* <RUNTIME_MEMB> */
factory WasmRuntime() {
@ -104,14 +109,23 @@ class WasmRuntime {
: _lib = DynamicLibrary.open(path.join(_getLibDir(), _getLibName())) {
/* <RUNTIME_LOAD> */
if (_Dart_InitializeApiDL(NativeApi.initializeApiDLData) != 0) {
throw Exception("Failed to initialize Dart API");
}
_engine = _engine_new();
_checkNotEqual(_engine, nullptr, "Failed to initialize Wasm engine.");
_set_finalizer_for_engine(this, _engine);
}
Pointer<WasmerStore> newStore() {
return _store_new(_engine);
Pointer<WasmerStore> newStore(Object owner) {
Pointer<WasmerStore> store = _checkNotEqual(
_store_new(_engine), nullptr, "Failed to create Wasm store.");
_set_finalizer_for_store(owner, store);
return store;
}
Pointer<WasmerModule> compile(Pointer<WasmerStore> store, Uint8List data) {
Pointer<WasmerModule> compile(
Object owner, Pointer<WasmerStore> store, Uint8List data) {
var dataPtr = allocate<Uint8>(count: data.length);
for (int i = 0; i < data.length; ++i) {
dataPtr[i] = data[i];
@ -125,7 +139,9 @@ class WasmRuntime {
free(dataPtr);
free(dataVec);
return _checkNotEqual(modulePtr, nullptr, "Wasm module compile failed.");
_checkNotEqual(modulePtr, nullptr, "Wasm module compile failed.");
_set_finalizer_for_module(owner, modulePtr);
return modulePtr;
}
List<WasmExportDescriptor> exportDescriptors(Pointer<WasmerModule> module) {
@ -169,37 +185,51 @@ class WasmRuntime {
void maybeThrowTrap(Pointer<WasmerTrap> trap, String source) {
if (trap != nullptr) {
var stashedException = traps[trap.address];
if (stashedException != null) {
traps.remove(stashedException);
throw stashedException;
// There are 2 kinds of trap, and their memory is managed differently.
// Traps created in the newTrap method below are stored in the traps map
// with a corresponding exception, and their memory is managed using a
// finalizer on the _WasmTrapsEntry. Traps can also be created by WASM
// code, and in that case we delete them in this function.
var entry = traps[trap.address];
if (entry != null) {
traps.remove(entry);
throw entry.exception;
} else {
var trapMessage = allocate<WasmerByteVec>();
_trap_message(trap, trapMessage);
var message = "Wasm trap when calling $source: ${trapMessage.ref}";
free(trapMessage.ref.data);
_byte_vec_delete(trapMessage);
free(trapMessage);
_trap_delete(trap);
throw Exception(message);
}
}
}
Pointer<WasmerInstance> instantiate(Pointer<WasmerStore> store,
Pointer<WasmerInstance> instantiate(Object owner, Pointer<WasmerStore> store,
Pointer<WasmerModule> module, Pointer<WasmerExternVec> imports) {
var trap = allocate<Pointer<WasmerTrap>>();
trap.value = nullptr;
var inst = _instance_new(store, module, imports, trap);
maybeThrowTrap(trap.value, "module initialization function");
free(trap);
return _checkNotEqual(inst, nullptr, "Wasm module instantiation failed.");
_checkNotEqual(inst, nullptr, "Wasm module instantiation failed.");
_set_finalizer_for_instance(owner, inst);
return inst;
}
// Clean up the exports after use, with deleteExports.
Pointer<WasmerExternVec> exports(Pointer<WasmerInstance> instancePtr) {
var exports = allocate<WasmerExternVec>();
_instance_exports(instancePtr, exports);
return exports;
}
void deleteExports(Pointer<WasmerExternVec> exports) {
_extern_vec_delete(exports);
free(exports);
}
int externKind(Pointer<WasmerExtern> extern) {
return _extern_kind(extern);
}
@ -245,14 +275,18 @@ class WasmRuntime {
}
Pointer<WasmerMemory> newMemory(
Pointer<WasmerStore> store, int pages, int? maxPages) {
Object owner, Pointer<WasmerStore> store, int pages, int? maxPages) {
var limPtr = allocate<WasmerLimits>();
limPtr.ref.min = pages;
limPtr.ref.max = maxPages ?? wasm_limits_max_default;
var memType = _memorytype_new(limPtr);
free(limPtr);
return _checkNotEqual(
_checkNotEqual(memType, nullptr, "Failed to create memory type.");
_set_finalizer_for_memorytype(owner, memType);
var memory = _checkNotEqual(
_memory_new(store, memType), nullptr, "Failed to create memory.");
_set_finalizer_for_memory(owner, memory);
return memory;
}
void growMemory(Pointer<WasmerMemory> memory, int deltaPages) {
@ -269,13 +303,17 @@ class WasmRuntime {
}
Pointer<WasmerFunc> newFunc(
Object owner,
Pointer<WasmerStore> store,
Pointer<WasmerFunctype> funcType,
Pointer func,
Pointer env,
Pointer finalizer) {
return _func_new_with_env(
var f = _func_new_with_env(
store, funcType, func.cast(), env.cast(), finalizer.cast());
_checkNotEqual(f, nullptr, "Failed to create function.");
_set_finalizer_for_func(owner, f);
return f;
}
Pointer<WasmerTrap> newTrap(Pointer<WasmerStore> store, dynamic exception) {
@ -284,10 +322,13 @@ class WasmRuntime {
msg.ref.data[0] = 0;
msg.ref.length = 0;
var trap = _trap_new(store, msg);
traps[trap.address] = exception;
free(msg.ref.data);
free(msg);
return _checkNotEqual(trap, nullptr, "Failed to create trap.");
_checkNotEqual(trap, nullptr, "Failed to create trap.");
var entry = _WasmTrapsEntry(exception);
_set_finalizer_for_trap(entry, trap);
traps[trap.address] = entry;
return trap;
}
Pointer<WasmerWasiConfig> newWasiConfig() {

View file

@ -214,6 +214,58 @@ class WasmerValtypeVec extends Struct {
external Pointer<Pointer<WasmerValtype>> data;
}
// Dart_InitializeApiDL
typedef NativeWasmerDartInitializeApiDLFn = Int64 Function(Pointer<Void>);
typedef WasmerDartInitializeApiDLFn = int Function(Pointer<Void>);
// set_finalizer_for_engine
typedef NativeWasmerSetFinalizerForEngineFn = Void Function(
Handle, Pointer<WasmerEngine>);
typedef WasmerSetFinalizerForEngineFn = void Function(
Object, Pointer<WasmerEngine>);
// set_finalizer_for_func
typedef NativeWasmerSetFinalizerForFuncFn = Void Function(
Handle, Pointer<WasmerFunc>);
typedef WasmerSetFinalizerForFuncFn = void Function(
Object, Pointer<WasmerFunc>);
// set_finalizer_for_instance
typedef NativeWasmerSetFinalizerForInstanceFn = Void Function(
Handle, Pointer<WasmerInstance>);
typedef WasmerSetFinalizerForInstanceFn = void Function(
Object, Pointer<WasmerInstance>);
// set_finalizer_for_memory
typedef NativeWasmerSetFinalizerForMemoryFn = Void Function(
Handle, Pointer<WasmerMemory>);
typedef WasmerSetFinalizerForMemoryFn = void Function(
Object, Pointer<WasmerMemory>);
// set_finalizer_for_memorytype
typedef NativeWasmerSetFinalizerForMemorytypeFn = Void Function(
Handle, Pointer<WasmerMemorytype>);
typedef WasmerSetFinalizerForMemorytypeFn = void Function(
Object, Pointer<WasmerMemorytype>);
// set_finalizer_for_module
typedef NativeWasmerSetFinalizerForModuleFn = Void Function(
Handle, Pointer<WasmerModule>);
typedef WasmerSetFinalizerForModuleFn = void Function(
Object, Pointer<WasmerModule>);
// set_finalizer_for_store
typedef NativeWasmerSetFinalizerForStoreFn = Void Function(
Handle, Pointer<WasmerStore>);
typedef WasmerSetFinalizerForStoreFn = void Function(
Object, Pointer<WasmerStore>);
// set_finalizer_for_trap
typedef NativeWasmerSetFinalizerForTrapFn = Void Function(
Handle, Pointer<WasmerTrap>);
typedef WasmerSetFinalizerForTrapFn = void Function(
Object, Pointer<WasmerTrap>);
// wasi_config_inherit_stderr
typedef NativeWasmerWasiConfigInheritStderrFn = Void Function(
Pointer<WasmerWasiConfig>);

View file

@ -545,18 +545,23 @@ copy("copy_wasmer") {
visibility = [ ":create_common_sdk" ]
deps = [
":copy_libraries",
"../third_party/wasmer:wasmer",
"../third_party/wasmer:wasmer_wrap",
]
outputs =
[ "$root_out_dir/dart-sdk/bin/third_party/wasmer/{{source_file_part}}" ]
if (is_win) {
sources = [ "$target_out_dir/../third_party/wasmer/wasmer.dll" ]
prefix = ""
suffix = "dll"
} else if (is_mac) {
sources = [ "$target_out_dir/../third_party/wasmer/libwasmer.dylib" ]
prefix = "lib"
suffix = "dylib"
} else {
# TODO(dartbug.com/37882): Support Fuchsia.
sources = [ "$target_out_dir/../third_party/wasmer/libwasmer.so" ]
prefix = "lib"
suffix = "so"
}
sources = [ "$root_out_dir/${prefix}wasmer_wrap.$suffix" ]
outputs = [
"$root_out_dir/dart-sdk/bin/third_party/wasmer/${prefix}wasmer.$suffix",
]
}
# This rule copies dill files to lib/_internal.

View file

@ -1,6 +1,24 @@
import("../../build/rust/rust.gni")
rust_library("wasmer") {
lib_name = "wasmer"
shared = true
shared_library("wasmer_wrap") {
sources = [
"../../runtime/include/dart_api_dl.c",
"finalizers.cc",
]
deps = [
":wasmer_lib",
"../../runtime/bin:dart",
]
include_dirs = [ "../../runtime" ]
defines = [ "DART_SHARED_LIB" ]
if (is_linux) {
libs = [ "rt" ]
}
# Force linking of all wasmer symbols.
ldflags = [ "-Wl,--no-as-needed" ]
}
rust_library("wasmer_lib") {
lib_name = "wasmer"
}

View file

@ -1,13 +1,13 @@
[package]
name = "wasmer"
version = "1.0.0-alpha4"
version = "1.0.0-alpha5"
[lib]
name = "wasmer"
crate-type = ["dylib"]
crate-type = ["staticlib"]
path = "wasmer.rs"
[dependencies.wasmer-c-api]
version = "1.0.0-alpha4"
version = "1.0.0-alpha5"
default-features = false
features = ["jit", "cranelift", "wasi"]

26
third_party/wasmer/finalizers.cc vendored Normal file
View file

@ -0,0 +1,26 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "include/dart_api.h"
#include "include/dart_api_dl.h"
#define FINALIZER(type) \
extern "C" void wasm_##type##_delete(void*); \
extern "C" void wasm_##type##_finalizer(void*, void* native_object) { \
wasm_##type##_delete(native_object); \
} \
DART_EXPORT void set_finalizer_for_##type(Dart_Handle dart_object, \
void* native_object) { \
Dart_NewFinalizableHandle_DL(dart_object, native_object, 0, \
wasm_##type##_finalizer); \
}
FINALIZER(engine);
FINALIZER(store);
FINALIZER(module);
FINALIZER(instance);
FINALIZER(trap);
FINALIZER(memorytype);
FINALIZER(memory);
FINALIZER(func);