diff --git a/CHANGELOG.md b/CHANGELOG.md index fda945847..eb308babc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,9 +12,13 @@ * [#1894](https://github.com/wasmerio/wasmer/pull/1894) Added exports `wasmer::{CraneliftOptLevel, LLVMOptLevel}` to allow using `Cranelift::opt_level` and `LLVM::opt_level` directly via the `wasmer` crate ### Changed +* [#1944](https://github.com/wasmerio/wasmer/pull/1944) Require `WasmerEnv` to be `Send + Sync` even in dynamic functions. ### Fixed +- [#1949](https://github.com/wasmerio/wasmer/pull/1949) `wasm__vec_delete` functions no longer crash when the given vector is uninitialized, in the Wasmer C API +- [#1949](https://github.com/wasmerio/wasmer/pull/1949) The `wasm_frame_vec_t`, `wasm_functype_vec_t`, `wasm_globaltype_vec_t`, `wasm_memorytype_vec_t`, and `wasm_tabletype_vec_t` are now boxed vectors in the Wasmer C API + ## 1.0.0-beta2 - 2020-12-16 ### Added diff --git a/Makefile b/Makefile index cf5e15fd5..f64666f5a 100644 --- a/Makefile +++ b/Makefile @@ -229,10 +229,13 @@ test-packages: cargo test -p wasmer-wasi --release cargo test -p wasmer-object --release cargo test -p wasmer-engine-native --release --no-default-features + cargo test -p wasmer-engine-jit --release --no-default-features + cargo test -p wasmer-compiler --release cargo test -p wasmer-cli --release cargo test -p wasmer-cache --release cargo test -p wasmer-engine --release + # The test-capi rules depend on the build-capi rules to build the .a files to # link the tests against. cargo test doesn't know that the tests will be running test-capi: $(foreach compiler_engine,$(test_compilers_engines),test-capi-$(compiler_engine)) @@ -355,10 +358,26 @@ endif update-testsuite: git subtree pull --prefix tests/wast/spec https://github.com/WebAssembly/testsuite.git master --squash -RUSTFLAGS := "-D dead-code -D nonstandard-style -D unused-imports -D unused-mut -D unused-variables -D unused-unsafe -D unreachable-patterns -D bad-style -D improper-ctypes -D unused-allocation -D unused-comparisons -D while-true -D unconditional-recursion -D bare-trait-objects -D function_item_references" # TODO: add `-D missing-docs` -lint: +RUSTFLAGS := "-D dead-code -D nonstandard-style -D unused-imports -D unused-mut -D unused-variables -D unused-unsafe -D unreachable-patterns -D bad-style -D improper-ctypes -D unused-allocation -D unused-comparisons -D while-true -D unconditional-recursion -D bare-trait-objects" # TODO: add `-D missing-docs` # TODO: add `-D function_item_references` (not available on Rust 1.47, try when upgrading) +lint-packages: + RUSTFLAGS=${RUSTFLAGS} cargo clippy -p wasmer + RUSTFLAGS=${RUSTFLAGS} cargo clippy -p wasmer-vm + RUSTFLAGS=${RUSTFLAGS} cargo clippy -p wasmer-types + RUSTFLAGS=${RUSTFLAGS} cargo clippy -p wasmer-wasi + RUSTFLAGS=${RUSTFLAGS} cargo clippy -p wasmer-object + RUSTFLAGS=${RUSTFLAGS} cargo clippy -p wasmer-engine-native + RUSTFLAGS=${RUSTFLAGS} cargo clippy -p wasmer-engine-jit + RUSTFLAGS=${RUSTFLAGS} cargo clippy -p wasmer-compiler + RUSTFLAGS=${RUSTFLAGS} cargo clippy -p wasmer-compiler-cranelift + RUSTFLAGS=${RUSTFLAGS} cargo clippy -p wasmer-compiler-singlepass + RUSTFLAGS=${RUSTFLAGS} cargo clippy -p wasmer-cli + RUSTFLAGS=${RUSTFLAGS} cargo clippy -p wasmer-cache + RUSTFLAGS=${RUSTFLAGS} cargo clippy -p wasmer-engine + +lint-formatting: cargo fmt --all -- --check - RUSTFLAGS=${RUSTFLAGS} cargo clippy $(compiler_features) + +lint: lint-formatting lint-packages install-local: package tar -C ~/.wasmer -zxvf wasmer.tar.gz diff --git a/lib/api/src/externals/function.rs b/lib/api/src/externals/function.rs index f961ceeda..1faa69273 100644 --- a/lib/api/src/externals/function.rs +++ b/lib/api/src/externals/function.rs @@ -67,6 +67,49 @@ pub struct Function { pub(crate) exported: ExportFunction, } +fn build_export_function_metadata( + env: Env, + import_init_function_ptr: for<'a> fn( + &'a mut Env, + &'a crate::Instance, + ) -> Result<(), crate::HostEnvInitError>, +) -> (*mut std::ffi::c_void, ExportFunctionMetadata) +where + Env: Clone + Sized + 'static + Send + Sync, +{ + let import_init_function_ptr = Some(unsafe { + std::mem::transmute:: Result<(), _>, fn(_, _) -> Result<(), _>>( + import_init_function_ptr, + ) + }); + let host_env_clone_fn: fn(*mut std::ffi::c_void) -> *mut std::ffi::c_void = |ptr| { + let env_ref: &Env = unsafe { + ptr.cast::() + .as_ref() + .expect("`ptr` to the environment is null when cloning it") + }; + Box::into_raw(Box::new(env_ref.clone())) as _ + }; + let host_env_drop_fn: fn(*mut std::ffi::c_void) = |ptr| { + unsafe { Box::from_raw(ptr.cast::()) }; + }; + let env = Box::into_raw(Box::new(env)) as _; + + // # Safety + // - All these functions work on all threads + // - The host env is `Send`. + let metadata = unsafe { + ExportFunctionMetadata::new( + env, + import_init_function_ptr, + host_env_clone_fn, + host_env_drop_fn, + ) + }; + + (env, metadata) +} + impl Function { /// Creates a new host `Function` (dynamic) with the provided signature. /// @@ -104,7 +147,7 @@ impl Function { pub fn new(store: &Store, ty: FT, func: F) -> Self where FT: Into, - F: Fn(&[Val]) -> Result, RuntimeError> + 'static, + F: Fn(&[Val]) -> Result, RuntimeError> + 'static + Send + Sync, { let ty: FunctionType = ty.into(); let dynamic_ctx: VMDynamicFunctionContext = @@ -209,7 +252,7 @@ impl Function { pub fn new_with_env(store: &Store, ty: FT, env: Env, func: F) -> Self where FT: Into, - F: Fn(&Env, &[Val]) -> Result, RuntimeError> + 'static, + F: Fn(&Env, &[Val]) -> Result, RuntimeError> + 'static + Send + Sync, Env: Sized + WasmerEnv + 'static, { let ty: FunctionType = ty.into(); @@ -220,58 +263,27 @@ impl Function { function_type: ty.clone(), }); + let import_init_function_ptr: for<'a> fn(&'a mut _, &'a _) -> Result<(), _> = + |env: &mut VMDynamicFunctionContext>, + instance: &crate::Instance| { + Env::init_with_instance(&mut *env.ctx.env, instance) + }; + + let (host_env, metadata) = build_export_function_metadata::< + VMDynamicFunctionContext>, + >(dynamic_ctx, import_init_function_ptr); + // We don't yet have the address with the Wasm ABI signature. // The engine linker will replace the address with one pointing to a // generated dynamic trampoline. let address = std::ptr::null() as *const VMFunctionBody; - let host_env = Box::into_raw(Box::new(dynamic_ctx)) as *mut _; let vmctx = VMFunctionEnvironment { host_env }; - let import_init_function_ptr: fn(_, _) -> Result<(), _> = - |ptr: *mut std::ffi::c_void, instance: *const std::ffi::c_void| { - let ptr = ptr as *mut VMDynamicFunctionContext>; - unsafe { - let env = &mut *ptr; - let env: &mut Env = &mut *env.ctx.env; - let instance = &*(instance as *const crate::Instance); - Env::init_with_instance(env, instance) - } - }; - let import_init_function_ptr = Some(unsafe { - std::mem::transmute:: Result<(), _>, fn(_, _) -> Result<(), _>>( - import_init_function_ptr, - ) - }); - let host_env_clone_fn: fn(*mut std::ffi::c_void) -> *mut std::ffi::c_void = |ptr| { - let duped_env: VMDynamicFunctionContext> = unsafe { - let ptr: *mut VMDynamicFunctionContext> = ptr as _; - let item: &VMDynamicFunctionContext> = &*ptr; - item.clone() - }; - Box::into_raw(Box::new(duped_env)) as _ - }; - let host_env_drop_fn: fn(*mut std::ffi::c_void) = |ptr: *mut std::ffi::c_void| { - unsafe { - Box::from_raw(ptr as *mut VMDynamicFunctionContext>) - }; - }; Self { store: store.clone(), definition: FunctionDefinition::Host(HostFunctionDefinition { has_env: true }), exported: ExportFunction { - metadata: Some(Arc::new( - // # Safety - // - All these functions work on all threads - // - The host env is `Send`. - unsafe { - ExportFunctionMetadata::new( - host_env, - import_init_function_ptr, - host_env_clone_fn, - host_env_drop_fn, - ) - }, - )), + metadata: Some(Arc::new(metadata)), vm_function: VMExportFunction { address, kind: VMFunctionKind::Dynamic, @@ -374,50 +386,17 @@ impl Function { let function = inner::Function::::new(func); let address = function.address(); - // TODO: We need to refactor the Function context. - // Right now is structured as it's always a `VMContext`. However, only - // Wasm-defined functions have a `VMContext`. - // In the case of Host-defined functions `VMContext` is whatever environment - // the user want to attach to the function. - let host_env = Box::into_raw(Box::new(env)) as *mut _; - let vmctx = VMFunctionEnvironment { host_env }; - let host_env_clone_fn: fn(*mut std::ffi::c_void) -> *mut std::ffi::c_void = |ptr| { - let duped_env = unsafe { - let ptr: *mut Env = ptr as _; - let item: &Env = &*ptr; - item.clone() - }; - Box::into_raw(Box::new(duped_env)) as _ - }; - let host_env_drop_fn: fn(*mut std::ffi::c_void) = |ptr: *mut std::ffi::c_void| { - unsafe { Box::from_raw(ptr as *mut Env) }; - }; + let (host_env, metadata) = + build_export_function_metadata::(env, Env::init_with_instance); - // TODO: look into removing transmute by changing API type signatures - let import_init_function_ptr = Some(unsafe { - std::mem::transmute:: Result<(), _>, fn(_, _) -> Result<(), _>>( - Env::init_with_instance, - ) - }); + let vmctx = VMFunctionEnvironment { host_env }; let signature = function.ty(); Self { store: store.clone(), definition: FunctionDefinition::Host(HostFunctionDefinition { has_env: true }), exported: ExportFunction { - metadata: Some(Arc::new( - // # Safety - // - All these functions work on all threads - // - The host env is `Send`. - unsafe { - ExportFunctionMetadata::new( - host_env, - import_init_function_ptr, - host_env_clone_fn, - host_env_drop_fn, - ) - }, - )), + metadata: Some(Arc::new(metadata)), vm_function: VMExportFunction { address, kind: VMFunctionKind::Static, @@ -455,43 +434,17 @@ impl Function { let function = inner::Function::::new(func); let address = function.address(); - let box_env = Box::new(env); - let host_env = Box::into_raw(box_env) as *mut _; - let vmctx = VMFunctionEnvironment { host_env }; - let host_env_clone_fn: fn(*mut std::ffi::c_void) -> *mut std::ffi::c_void = |ptr| { - let duped_env: Env = { - let ptr: *mut Env = ptr as _; - let item: &Env = &*ptr; - item.clone() - }; - Box::into_raw(Box::new(duped_env)) as _ - }; - let host_env_drop_fn: fn(*mut std::ffi::c_void) = |ptr: *mut std::ffi::c_void| { - Box::from_raw(ptr as *mut Env); - }; + let (host_env, metadata) = + build_export_function_metadata::(env, Env::init_with_instance); + let vmctx = VMFunctionEnvironment { host_env }; let signature = function.ty(); - // TODO: look into removing transmute by changing API type signatures - let import_init_function_ptr = Some(std::mem::transmute::< - fn(_, _) -> Result<(), _>, - fn(_, _) -> Result<(), _>, - >(Env::init_with_instance)); Self { store: store.clone(), definition: FunctionDefinition::Host(HostFunctionDefinition { has_env: true }), exported: ExportFunction { - metadata: Some(Arc::new( - // # Safety - // - All these functions work on all threads - // - The host env is `Send`. - ExportFunctionMetadata::new( - host_env, - import_init_function_ptr, - host_env_clone_fn, - host_env_drop_fn, - ), - )), + metadata: Some(Arc::new(metadata)), vm_function: VMExportFunction { address, kind: VMFunctionKind::Static, @@ -855,7 +808,7 @@ impl fmt::Debug for Function { } /// This trait is one that all dynamic functions must fulfill. -pub(crate) trait VMDynamicFunction { +pub(crate) trait VMDynamicFunction: Send + Sync { fn call(&self, args: &[Val]) -> Result, RuntimeError>; fn function_type(&self) -> &FunctionType; } @@ -863,7 +816,7 @@ pub(crate) trait VMDynamicFunction { #[derive(Clone)] pub(crate) struct DynamicFunctionWithoutEnv { #[allow(clippy::type_complexity)] - func: Arc Result, RuntimeError> + 'static>, + func: Arc Result, RuntimeError> + 'static + Send + Sync>, function_type: FunctionType, } @@ -878,15 +831,15 @@ impl VMDynamicFunction for DynamicFunctionWithoutEnv { pub(crate) struct DynamicFunctionWithEnv where - Env: Sized + 'static, + Env: Sized + 'static + Send + Sync, { function_type: FunctionType, #[allow(clippy::type_complexity)] - func: Arc Result, RuntimeError> + 'static>, + func: Arc Result, RuntimeError> + 'static + Send + Sync>, env: Box, } -impl Clone for DynamicFunctionWithEnv { +impl Clone for DynamicFunctionWithEnv { fn clone(&self) -> Self { Self { env: self.env.clone(), @@ -898,7 +851,7 @@ impl Clone for DynamicFunctionWithEnv { impl VMDynamicFunction for DynamicFunctionWithEnv where - Env: Sized + 'static, + Env: Sized + 'static + Send + Sync, { fn call(&self, args: &[Val]) -> Result, RuntimeError> { (*self.func)(&*self.env, &args) diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs index 333a81c64..0996513fb 100644 --- a/lib/c-api/src/wasm_c_api/macros.rs +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -3,8 +3,31 @@ macro_rules! wasm_declare_vec_inner { ($name:ident) => { paste::paste! { - /// Creates an empty vector of - #[doc = "Creates an empty vector of [`wasm_" $name "_t`]."] + #[doc = "Creates an empty vector of [`wasm_" $name "_t`]. + +# Example + +```rust +# use inline_c::assert_c; +# fn main() { +# (assert_c! { +# #include \"tests/wasmer_wasm.h\" +# +int main() { + // Creates an empty vector of `wasm_" $name "_t`. + wasm_" $name "_vec_t vector; + wasm_" $name "_vec_new_empty(&vector); + + // Check that it is empty. + assert(vector.size == 0); + + // Free it. + wasm_" $name "_vec_delete(&vector); +} +# }) +# .success(); +# } +```"] #[no_mangle] pub unsafe extern "C" fn [](out: *mut []) { // TODO: actually implement this @@ -19,7 +42,37 @@ macro_rules! wasm_declare_vec_inner { macro_rules! wasm_declare_vec { ($name:ident) => { paste::paste! { - #[doc = "Represents of a vector of [`wasm_" $name "_t`]."] + #[doc = "Represents a vector of `wasm_" $name "_t`. + +Read the documentation of [`wasm_" $name "_t`] to see more concrete examples. + +# Example + +```rust +# use inline_c::assert_c; +# fn main() { +# (assert_c! { +# #include \"tests/wasmer_wasm.h\" +# +int main() { + // Create a vector of 2 `wasm_" $name "_t`. + wasm_" $name "_t x; + wasm_" $name "_t y; + wasm_" $name "_t* items[2] = {&x, &y}; + + wasm_" $name "_vec_t vector; + wasm_" $name "_vec_new(&vector, 2, (wasm_" $name "_t*) items); + + // Check that it contains 2 items. + assert(vector.size == 2); + + // Free it. + wasm_" $name "_vec_delete(&vector); +} +# }) +# .success(); +# } +```"] #[derive(Debug)] #[repr(C)] pub struct [] { @@ -81,6 +134,7 @@ macro_rules! wasm_declare_vec { .into_boxed_slice(); let data = copied_data.as_mut_ptr(); ::std::mem::forget(copied_data); + Self { size, data, @@ -111,27 +165,60 @@ macro_rules! wasm_declare_vec { } // TODO: investigate possible memory leak on `init` (owned pointer) - #[doc = "Creates a new vector of [`wasm_" $name "_t`]."] + #[doc = "Creates a new vector of [`wasm_" $name "_t`]. + +# Example + +See the [`wasm_" $name "_vec_t`] type to get an example."] #[no_mangle] pub unsafe extern "C" fn [](out: *mut [], length: usize, init: *mut []) { let mut bytes: Vec<[]> = Vec::with_capacity(length); + for i in 0..length { bytes.push(::std::ptr::read(init.add(i))); } + let pointer = bytes.as_mut_ptr(); debug_assert!(bytes.len() == bytes.capacity()); + (*out).data = pointer; (*out).size = length; ::std::mem::forget(bytes); } - #[doc = "Creates a new uninitialized vector of [`wasm_" $name "_t`]."] + #[doc = "Creates a new uninitialized vector of [`wasm_" $name "_t`]. + +# Example + +```rust +# use inline_c::assert_c; +# fn main() { +# (assert_c! { +# #include \"tests/wasmer_wasm.h\" +# +int main() { + // Creates an empty vector of `wasm_" $name "_t`. + wasm_" $name "_vec_t vector; + wasm_" $name "_vec_new_uninitialized(&vector, 3); + + // Check that it contains 3 items. + assert(vector.size == 3); + + // Free it. + wasm_" $name "_vec_delete(&vector); +} +# }) +# .success(); +# } +```"] #[no_mangle] pub unsafe extern "C" fn [](out: *mut [], length: usize) { let mut bytes: Vec<[]> = Vec::with_capacity(length); let pointer = bytes.as_mut_ptr(); + (*out).data = pointer; (*out).size = length; + ::std::mem::forget(bytes); } @@ -144,7 +231,11 @@ macro_rules! wasm_declare_vec { *out_ptr = in_ptr.clone(); } - #[doc = "Deletes a vector of [`wasm_" $name "_t`]."] + #[doc = "Deletes a vector of [`wasm_" $name "_t`]. + +# Example + +See the [`wasm_" $name "_vec_t`] type to get an example."] #[no_mangle] pub unsafe extern "C" fn [](ptr: Option<&mut []>) { if let Some(vec) = ptr { @@ -166,7 +257,9 @@ macro_rules! wasm_declare_vec { macro_rules! wasm_declare_boxed_vec { ($name:ident) => { paste::paste! { - #[doc = "Represents of a vector of [`wasm_" $name "_t`]."] + #[doc = "Represents a vector of `wasm_" $name "_t`. + +Read the documentation of [`wasm_" $name "_t`] to see more concrete examples."] #[derive(Debug)] #[repr(C)] pub struct [] { @@ -217,6 +310,27 @@ macro_rules! wasm_declare_boxed_vec { } } + impl<'a, T: Into<[]> + Clone> From<&'a [T]> for [] { + fn from(other: &'a [T]) -> Self { + let size = other.len(); + let mut copied_data = other + .iter() + .cloned() + .map(Into::into) + .map(Box::new) + .map(Box::into_raw) + .collect::]>>() + .into_boxed_slice(); + let data = copied_data.as_mut_ptr(); + ::std::mem::forget(copied_data); + + Self { + size, + data, + } + } + } + // TODO: do this properly impl [] { pub unsafe fn into_slice(&self) -> Option<&[Box<[]>]>{ @@ -235,23 +349,53 @@ macro_rules! wasm_declare_boxed_vec { #[no_mangle] pub unsafe extern "C" fn [](out: *mut [], length: usize, init: *const *mut []) { let mut bytes: Vec<*mut []> = Vec::with_capacity(length); + for i in 0..length { bytes.push(*init.add(i)); } + let mut boxed_vec = bytes.into_boxed_slice(); let pointer = boxed_vec.as_mut_ptr(); + (*out).data = pointer; (*out).size = length; + ::std::mem::forget(boxed_vec); } - #[doc = "Creates a new uninitialized vector of [`wasm_" $name "_t`]."] + #[doc = "Creates a new uninitialized vector of [`wasm_" $name "_t`]. + +# Example + +```rust +# use inline_c::assert_c; +# fn main() { +# (assert_c! { +# #include \"tests/wasmer_wasm.h\" +# +int main() { + // Creates an empty vector of `wasm_" $name "_t`. + wasm_" $name "_vec_t vector; + wasm_" $name "_vec_new_uninitialized(&vector, 3); + + // Check that it contains 3 items. + assert(vector.size == 3); + + // Free it. + wasm_" $name "_vec_delete(&vector); +} +# }) +# .success(); +# } +```"] #[no_mangle] pub unsafe extern "C" fn [](out: *mut [], length: usize) { - let mut bytes: Vec<*mut []> = Vec::with_capacity(length); + let mut bytes: Vec<*mut []> = vec![::std::ptr::null_mut(); length]; let pointer = bytes.as_mut_ptr(); + (*out).data = pointer; (*out).size = length; + ::std::mem::forget(bytes); } @@ -264,11 +408,14 @@ macro_rules! wasm_declare_boxed_vec { *out_ptr = in_ptr.clone(); } + #[doc = "Deletes a vector of [`wasm_" $name "_t`]. - #[doc = "Deletes a vector of [`wasm_" $name "_t`]."] +# Example + +See the [`wasm_" $name "_vec_t`] type to get an example."] #[no_mangle] - pub unsafe extern "C" fn [](ptr: Option<&mut[]>) { - if let Some(vec) = ptr { + pub unsafe extern "C" fn [](ptr: Option<&mut []>) { + if let Some(vec) = ptr { if !vec.data.is_null() { let ptr: *mut Option]>> = vec.data as _; let data: Vec]>>> = Vec::from_raw_parts(ptr, vec.size, vec.size); @@ -298,7 +445,6 @@ macro_rules! wasm_declare_ref_base { } // TODO: finish this... - } }; } diff --git a/lib/c-api/src/wasm_c_api/types/frame.rs b/lib/c-api/src/wasm_c_api/types/frame.rs index d926ce977..99f3361ab 100644 --- a/lib/c-api/src/wasm_c_api/types/frame.rs +++ b/lib/c-api/src/wasm_c_api/types/frame.rs @@ -48,4 +48,4 @@ pub unsafe extern "C" fn wasm_frame_module_offset(frame: &wasm_frame_t) -> usize frame.info.module_offset() } -wasm_declare_vec!(frame); +wasm_declare_boxed_vec!(frame); diff --git a/lib/c-api/src/wasm_c_api/types/function.rs b/lib/c-api/src/wasm_c_api/types/function.rs index ae355993d..131a79461 100644 --- a/lib/c-api/src/wasm_c_api/types/function.rs +++ b/lib/c-api/src/wasm_c_api/types/function.rs @@ -1,7 +1,4 @@ -use super::{ - wasm_externtype_t, wasm_valtype_t, wasm_valtype_vec_delete, wasm_valtype_vec_t, WasmExternType, -}; -use std::mem; +use super::{wasm_externtype_t, wasm_valtype_vec_delete, wasm_valtype_vec_t, WasmExternType}; use wasmer::{ExternType, FunctionType, ValType}; #[derive(Debug)] @@ -13,44 +10,8 @@ pub(crate) struct WasmFunctionType { impl WasmFunctionType { pub(crate) fn new(function_type: FunctionType) -> Self { - let params = { - let mut valtypes = function_type - .params() - .iter() - .cloned() - .map(Into::into) - .map(Box::new) - .map(Box::into_raw) - .collect::>(); - - let valtypes_vec = Box::new(wasm_valtype_vec_t { - size: valtypes.len(), - data: valtypes.as_mut_ptr(), - }); - - mem::forget(valtypes); - - valtypes_vec - }; - let results = { - let mut valtypes = function_type - .results() - .iter() - .cloned() - .map(Into::into) - .map(Box::new) - .map(Box::into_raw) - .collect::>(); - - let valtypes_vec = Box::new(wasm_valtype_vec_t { - size: valtypes.len(), - data: valtypes.as_mut_ptr(), - }); - - mem::forget(valtypes); - - valtypes_vec - }; + let params: Box = Box::new(function_type.params().into()); + let results: Box = Box::new(function_type.results().into()); Self { function_type, @@ -90,12 +51,12 @@ impl wasm_functype_t { } } -wasm_declare_vec!(functype); +wasm_declare_boxed_vec!(functype); #[no_mangle] pub unsafe extern "C" fn wasm_functype_new( - params: Option>, - results: Option>, + params: Option<&mut wasm_valtype_vec_t>, + results: Option<&mut wasm_valtype_vec_t>, ) -> Option> { let params = params?; let results = results?; @@ -111,8 +72,8 @@ pub unsafe extern "C" fn wasm_functype_new( .map(|val| val.as_ref().into()) .collect::>(); - wasm_valtype_vec_delete(Some(&mut *Box::into_raw(params))); - wasm_valtype_vec_delete(Some(&mut *Box::into_raw(results))); + wasm_valtype_vec_delete(Some(params)); + wasm_valtype_vec_delete(Some(results)); Some(Box::new(wasm_functype_t::new(FunctionType::new( params_as_valtype, diff --git a/lib/c-api/src/wasm_c_api/types/global.rs b/lib/c-api/src/wasm_c_api/types/global.rs index d64e282e9..769002802 100644 --- a/lib/c-api/src/wasm_c_api/types/global.rs +++ b/lib/c-api/src/wasm_c_api/types/global.rs @@ -46,7 +46,7 @@ impl wasm_globaltype_t { } } -wasm_declare_vec!(globaltype); +wasm_declare_boxed_vec!(globaltype); #[no_mangle] pub unsafe extern "C" fn wasm_globaltype_new( diff --git a/lib/c-api/src/wasm_c_api/types/memory.rs b/lib/c-api/src/wasm_c_api/types/memory.rs index 12cedfac6..6565fbe69 100644 --- a/lib/c-api/src/wasm_c_api/types/memory.rs +++ b/lib/c-api/src/wasm_c_api/types/memory.rs @@ -48,7 +48,7 @@ impl wasm_memorytype_t { } } -wasm_declare_vec!(memorytype); +wasm_declare_boxed_vec!(memorytype); #[no_mangle] pub unsafe extern "C" fn wasm_memorytype_new(limits: &wasm_limits_t) -> Box { diff --git a/lib/c-api/src/wasm_c_api/types/table.rs b/lib/c-api/src/wasm_c_api/types/table.rs index d968cae0d..40ea30037 100644 --- a/lib/c-api/src/wasm_c_api/types/table.rs +++ b/lib/c-api/src/wasm_c_api/types/table.rs @@ -53,7 +53,7 @@ impl wasm_tabletype_t { } } -wasm_declare_vec!(tabletype); +wasm_declare_boxed_vec!(tabletype); #[no_mangle] pub unsafe extern "C" fn wasm_tabletype_new( diff --git a/lib/compiler-cranelift/src/translator/code_translator.rs b/lib/compiler-cranelift/src/translator/code_translator.rs index b52d34e0b..4afc3d4cb 100644 --- a/lib/compiler-cranelift/src/translator/code_translator.rs +++ b/lib/compiler-cranelift/src/translator/code_translator.rs @@ -216,15 +216,15 @@ pub fn translate_operator( // destination block following the whole `if...end`. If we do end // up discovering an `else`, then we will allocate a block for it // and go back and patch the jump. - let destination = block_with_params(builder, results.clone(), environ)?; + let destination = block_with_params(builder, results, environ)?; let branch_inst = canonicalise_then_brz(builder, val, destination, state.peekn(params.len())); (destination, ElseData::NoElse { branch_inst }) } else { // The `if` type signature is not valid without an `else` block, // so we eagerly allocate the `else` block here. - let destination = block_with_params(builder, results.clone(), environ)?; - let else_block = block_with_params(builder, params.clone(), environ)?; + let destination = block_with_params(builder, results, environ)?; + let else_block = block_with_params(builder, params, environ)?; canonicalise_then_brz(builder, val, else_block, state.peekn(params.len())); builder.seal_block(else_block); (destination, ElseData::WithElse { else_block }) @@ -271,8 +271,7 @@ pub fn translate_operator( let (params, _results) = module_translation_state.blocktype_params_results(blocktype)?; debug_assert_eq!(params.len(), num_return_values); - let else_block = - block_with_params(builder, params.clone(), environ)?; + let else_block = block_with_params(builder, params, environ)?; canonicalise_then_jump( builder, destination, diff --git a/lib/deprecated/runtime-core/Cargo.lock b/lib/deprecated/runtime-core/Cargo.lock index c22464150..18ff6d815 100644 --- a/lib/deprecated/runtime-core/Cargo.lock +++ b/lib/deprecated/runtime-core/Cargo.lock @@ -1158,7 +1158,7 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasmer" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "cfg-if 0.1.10", "indexmap", @@ -1181,7 +1181,7 @@ dependencies = [ [[package]] name = "wasmer-cache" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "blake3", "hex", @@ -1191,7 +1191,7 @@ dependencies = [ [[package]] name = "wasmer-compiler" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "enumset", "raw-cpuid", @@ -1207,7 +1207,7 @@ dependencies = [ [[package]] name = "wasmer-compiler-cranelift" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "cranelift-codegen", "cranelift-frontend", @@ -1224,7 +1224,7 @@ dependencies = [ [[package]] name = "wasmer-compiler-llvm" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "byteorder", "cc", @@ -1246,7 +1246,7 @@ dependencies = [ [[package]] name = "wasmer-compiler-singlepass" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "byteorder", "dynasm", @@ -1263,7 +1263,7 @@ dependencies = [ [[package]] name = "wasmer-derive" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "proc-macro-error", "proc-macro2", @@ -1273,7 +1273,7 @@ dependencies = [ [[package]] name = "wasmer-engine" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "backtrace", "bincode", @@ -1292,7 +1292,7 @@ dependencies = [ [[package]] name = "wasmer-engine-jit" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "bincode", "cfg-if 0.1.10", @@ -1308,7 +1308,7 @@ dependencies = [ [[package]] name = "wasmer-engine-native" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "bincode", "cfg-if 0.1.10", @@ -1327,7 +1327,7 @@ dependencies = [ [[package]] name = "wasmer-object" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "object 0.22.0", "thiserror", @@ -1355,7 +1355,7 @@ dependencies = [ [[package]] name = "wasmer-types" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "cranelift-entity", "serde", @@ -1364,7 +1364,7 @@ dependencies = [ [[package]] name = "wasmer-vm" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "backtrace", "cc", diff --git a/lib/deprecated/runtime-core/src/module.rs b/lib/deprecated/runtime-core/src/module.rs index a122d0f8e..7bcd9b6d5 100644 --- a/lib/deprecated/runtime-core/src/module.rs +++ b/lib/deprecated/runtime-core/src/module.rs @@ -10,10 +10,10 @@ use crate::{ }; use new::wasmer::Export; use std::{ - cell::RefCell, collections::HashMap, convert::{AsRef, Infallible}, ptr, + sync::{Arc, Mutex}, }; pub use new::wasmer_types::{DataInitializer, ExportIndex, TableInitializer}; @@ -126,20 +126,22 @@ impl Module { // is the same! struct VMDynamicFunctionWithEnv where - Env: Sized + 'static, + Env: Sized + 'static + Send + Sync, { #[allow(unused)] function_type: FuncSig, #[allow(unused)] - func: Box< + func: Arc< dyn Fn( &mut Env, &[Value], ) -> Result, RuntimeError> - + 'static, + + 'static + + Send + + Sync, >, - env: RefCell, + env: Box>, } // Get back the `vmctx` as it is @@ -154,7 +156,10 @@ impl Module { }; // Replace the environment by ours. - vmctx.ctx.env.borrow_mut().vmctx = pre_instance.vmctx(); + { + let mut guard = vmctx.ctx.env.lock().unwrap(); + guard.vmctx = pre_instance.vmctx(); + } // … without anyone noticing… function.vm_function.vmctx.host_env = Box::into_raw(vmctx) as _; diff --git a/lib/deprecated/runtime/Cargo.lock b/lib/deprecated/runtime/Cargo.lock index c41e11990..068083724 100644 --- a/lib/deprecated/runtime/Cargo.lock +++ b/lib/deprecated/runtime/Cargo.lock @@ -1158,7 +1158,7 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasmer" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "cfg-if 0.1.10", "indexmap", @@ -1181,7 +1181,7 @@ dependencies = [ [[package]] name = "wasmer-cache" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "blake3", "hex", @@ -1191,7 +1191,7 @@ dependencies = [ [[package]] name = "wasmer-compiler" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "enumset", "raw-cpuid", @@ -1207,7 +1207,7 @@ dependencies = [ [[package]] name = "wasmer-compiler-cranelift" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "cranelift-codegen", "cranelift-frontend", @@ -1224,7 +1224,7 @@ dependencies = [ [[package]] name = "wasmer-compiler-llvm" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "byteorder", "cc", @@ -1246,7 +1246,7 @@ dependencies = [ [[package]] name = "wasmer-compiler-singlepass" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "byteorder", "dynasm", @@ -1263,7 +1263,7 @@ dependencies = [ [[package]] name = "wasmer-derive" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "proc-macro-error", "proc-macro2", @@ -1273,7 +1273,7 @@ dependencies = [ [[package]] name = "wasmer-engine" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "backtrace", "bincode", @@ -1292,7 +1292,7 @@ dependencies = [ [[package]] name = "wasmer-engine-jit" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "bincode", "cfg-if 0.1.10", @@ -1308,7 +1308,7 @@ dependencies = [ [[package]] name = "wasmer-engine-native" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "bincode", "cfg-if 0.1.10", @@ -1327,7 +1327,7 @@ dependencies = [ [[package]] name = "wasmer-object" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "object 0.22.0", "thiserror", @@ -1362,7 +1362,7 @@ dependencies = [ [[package]] name = "wasmer-types" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "cranelift-entity", "serde", @@ -1371,7 +1371,7 @@ dependencies = [ [[package]] name = "wasmer-vm" -version = "1.0.0-beta1" +version = "1.0.0-beta2" dependencies = [ "backtrace", "cc", diff --git a/lib/vm/src/vmcontext.rs b/lib/vm/src/vmcontext.rs index a919c8f49..4e50eb459 100644 --- a/lib/vm/src/vmcontext.rs +++ b/lib/vm/src/vmcontext.rs @@ -95,7 +95,7 @@ mod test_vmfunction_import { /// containing the relevant context for running the function indicated /// in `address`. #[repr(C)] -pub struct VMDynamicFunctionContext { +pub struct VMDynamicFunctionContext { /// The address of the inner dynamic function. /// /// Note: The function must be on the form of @@ -106,7 +106,14 @@ pub struct VMDynamicFunctionContext { pub ctx: T, } -impl Clone for VMDynamicFunctionContext { +// The `ctx` itself must be `Send`, `address` can be passed between +// threads because all usage is `unsafe` and synchronized. +unsafe impl Send for VMDynamicFunctionContext {} +// The `ctx` itself must be `Sync`, `address` can be shared between +// threads because all usage is `unsafe` and synchronized. +unsafe impl Sync for VMDynamicFunctionContext {} + +impl Clone for VMDynamicFunctionContext { fn clone(&self) -> Self { Self { address: self.address,