mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[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:
parent
40535c3159
commit
1b94364da7
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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>);
|
||||
|
|
17
sdk/BUILD.gn
17
sdk/BUILD.gn
|
@ -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.
|
||||
|
|
24
third_party/wasmer/BUILD.gn
vendored
24
third_party/wasmer/BUILD.gn
vendored
|
@ -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"
|
||||
}
|
||||
|
|
6
third_party/wasmer/Cargo.toml
vendored
6
third_party/wasmer/Cargo.toml
vendored
|
@ -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
26
third_party/wasmer/finalizers.cc
vendored
Normal 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);
|
Loading…
Reference in a new issue