diff --git a/crates/wasmtime/src/externals.rs b/crates/wasmtime/src/externals.rs index 7971f34dcb..b20a00b9e8 100644 --- a/crates/wasmtime/src/externals.rs +++ b/crates/wasmtime/src/externals.rs @@ -119,7 +119,7 @@ impl Extern { pub(crate) unsafe fn from_wasmtime_export( wasmtime_export: wasmtime_runtime::Export, - store: &mut StoreOpaque<'_>, + store: &mut StoreOpaque, ) -> Extern { match wasmtime_export { wasmtime_runtime::Export::Function(f) => { @@ -137,7 +137,7 @@ impl Extern { } } - pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque<'_>) -> bool { + pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool { match self { Extern::Func(f) => f.comes_from_same_store(store), Extern::Global(g) => store.store_data().contains(g.0), @@ -259,10 +259,10 @@ impl Global { /// # } /// ``` pub fn new(mut store: impl AsContextMut, ty: GlobalType, val: Val) -> Result { - Global::_new(&mut store.as_context_mut().opaque(), ty, val) + Global::_new(store.as_context_mut().0, ty, val) } - fn _new(store: &mut StoreOpaque<'_>, ty: GlobalType, val: Val) -> Result { + fn _new(store: &mut StoreOpaque, ty: GlobalType, val: Val) -> Result { if !val.comes_from_same_store(store) { bail!("cross-`Store` globals are not supported"); } @@ -307,7 +307,7 @@ impl Global { .map(|inner| ExternRef { inner }), ), ValType::FuncRef => { - from_checked_anyfunc(definition.as_anyfunc() as *mut _, &mut store.opaque()) + from_checked_anyfunc(definition.as_anyfunc() as *mut _, store.0) } ValType::V128 => Val::V128(*definition.as_u128()), } @@ -326,7 +326,7 @@ impl Global { /// /// Panics if `store` does not own this global. pub fn set(&self, mut store: impl AsContextMut, val: Val) -> Result<()> { - let store = store.as_context_mut(); + let store = store.as_context_mut().0; let ty = self.ty(&store); if ty.mutability() != Mutability::Var { bail!("immutable global cannot be set"); @@ -335,8 +335,7 @@ impl Global { if val.ty() != *ty { bail!("global of type {:?} cannot be set to {:?}", ty, val.ty()); } - let mut store = store.opaque(); - if !val.comes_from_same_store(&store) { + if !val.comes_from_same_store(store) { bail!("cross-`Store` values are not supported"); } unsafe { @@ -348,7 +347,7 @@ impl Global { Val::F64(f) => *definition.as_u64_mut() = f, Val::FuncRef(f) => { *definition.as_anyfunc_mut() = f.map_or(ptr::null(), |f| { - f.caller_checked_anyfunc(&mut store).as_ptr() as *const _ + f.caller_checked_anyfunc(store).as_ptr() as *const _ }); } Val::ExternRef(x) => { @@ -363,7 +362,7 @@ impl Global { pub(crate) unsafe fn from_wasmtime_global( wasmtime_export: wasmtime_runtime::ExportGlobal, - store: &mut StoreOpaque<'_>, + store: &mut StoreOpaque, ) -> Global { Global(store.store_data_mut().insert(wasmtime_export)) } @@ -372,7 +371,7 @@ impl Global { &data[self.0].global } - pub(crate) fn vmimport(&self, store: &StoreOpaque<'_>) -> wasmtime_runtime::VMGlobalImport { + pub(crate) fn vmimport(&self, store: &StoreOpaque) -> wasmtime_runtime::VMGlobalImport { wasmtime_runtime::VMGlobalImport { from: store[self.0].definition, } @@ -435,7 +434,7 @@ impl Table { /// # } /// ``` pub fn new(mut store: impl AsContextMut, ty: TableType, init: Val) -> Result { - Table::_new(&mut store.as_context_mut().opaque(), ty, init) + Table::_new(store.as_context_mut().0, ty, init) } fn _new(store: &mut StoreOpaque, ty: TableType, init: Val) -> Result
{ @@ -483,7 +482,7 @@ impl Table { TableType::from_wasmtime_table(ty) } - fn wasmtime_table(&self, store: &mut StoreOpaque<'_>) -> *mut runtime::Table { + fn wasmtime_table(&self, store: &mut StoreOpaque) -> *mut runtime::Table { unsafe { let export = &store[self.0]; let mut handle = InstanceHandle::from_vmctx(export.vmctx); @@ -500,11 +499,11 @@ impl Table { /// /// Panics if `store` does not own this table. pub fn get(&self, mut store: impl AsContextMut, index: u32) -> Option { - let mut store = store.as_context_mut().opaque(); - let table = self.wasmtime_table(&mut store); + let store = store.as_context_mut().0; + let table = self.wasmtime_table(store); unsafe { match (*table).get(index)? { - runtime::TableElement::FuncRef(f) => Some(from_checked_anyfunc(f, &mut store)), + runtime::TableElement::FuncRef(f) => Some(from_checked_anyfunc(f, store)), runtime::TableElement::ExternRef(None) => Some(Val::ExternRef(None)), runtime::TableElement::ExternRef(Some(x)) => { Some(Val::ExternRef(Some(ExternRef { inner: x }))) @@ -525,10 +524,10 @@ impl Table { /// /// Panics if `store` does not own this table. pub fn set(&self, mut store: impl AsContextMut, index: u32, val: Val) -> Result<()> { + let store = store.as_context_mut().0; let ty = self.ty(&store).element().clone(); - let mut store = store.as_context_mut().opaque(); - let val = val.into_table_element(&mut store, ty)?; - let table = self.wasmtime_table(&mut store); + let val = val.into_table_element(store, ty)?; + let table = self.wasmtime_table(store); unsafe { (*table) .set(index, val) @@ -562,12 +561,12 @@ impl Table { /// /// Panics if `store` does not own this table. pub fn grow(&self, mut store: impl AsContextMut, delta: u32, init: Val) -> Result { + let store = store.as_context_mut().0; let ty = self.ty(&store).element().clone(); - let init = init.into_table_element(&mut store.as_context_mut().opaque(), ty)?; - let table = self.wasmtime_table(&mut store.as_context_mut().opaque()); - let store = store.as_context_mut(); + let init = init.into_table_element(store, ty)?; + let table = self.wasmtime_table(store); unsafe { - match (*table).grow(delta, init, store.0.limiter()) { + match (*table).grow(delta, init, store.limiter()) { Some(size) => { let vm = (*table).vmtable(); *store[self.0].definition = vm; @@ -597,14 +596,13 @@ impl Table { src_index: u32, len: u32, ) -> Result<()> { + let store = store.as_context_mut().0; if dst_table.ty(&store).element() != src_table.ty(&store).element() { bail!("tables do not have the same element type"); } - let mut store = store.as_context_mut().opaque(); - - let dst = dst_table.wasmtime_table(&mut store); - let src = src_table.wasmtime_table(&mut store); + let dst = dst_table.wasmtime_table(store); + let src = src_table.wasmtime_table(store); unsafe { runtime::Table::copy(dst, src, dst_index, src_index, len) .map_err(Trap::from_runtime)?; @@ -629,11 +627,11 @@ impl Table { /// /// Panics if `store` does not own either `dst_table` or `src_table`. pub fn fill(&self, mut store: impl AsContextMut, dst: u32, val: Val, len: u32) -> Result<()> { + let store = store.as_context_mut().0; let ty = self.ty(&store).element().clone(); - let mut store = store.as_context_mut().opaque(); - let val = val.into_table_element(&mut store, ty)?; + let val = val.into_table_element(store, ty)?; - let table = self.wasmtime_table(&mut store); + let table = self.wasmtime_table(store); unsafe { (*table).fill(dst, val, len).map_err(Trap::from_runtime)?; } @@ -643,7 +641,7 @@ impl Table { pub(crate) unsafe fn from_wasmtime_table( wasmtime_export: wasmtime_runtime::ExportTable, - store: &mut StoreOpaque<'_>, + store: &mut StoreOpaque, ) -> Table { Table(store.store_data_mut().insert(wasmtime_export)) } @@ -652,7 +650,7 @@ impl Table { &data[self.0].table.table } - pub(crate) fn vmimport(&self, store: &StoreOpaque<'_>) -> wasmtime_runtime::VMTableImport { + pub(crate) fn vmimport(&self, store: &StoreOpaque) -> wasmtime_runtime::VMTableImport { let export = &store[self.0]; wasmtime_runtime::VMTableImport { from: export.definition, diff --git a/crates/wasmtime/src/func.rs b/crates/wasmtime/src/func.rs index 08ce16efd1..2e7c823a8f 100644 --- a/crates/wasmtime/src/func.rs +++ b/crates/wasmtime/src/func.rs @@ -1,4 +1,4 @@ -use crate::store::{StoreData, StoreInnermost, StoreOpaque, Stored}; +use crate::store::{StoreData, StoreOpaque, Stored}; use crate::{ AsContext, AsContextMut, Engine, Extern, FuncType, Instance, InterruptHandle, StoreContext, StoreContextMut, Trap, Val, ValType, @@ -259,7 +259,7 @@ macro_rules! generate_wrap_async_func { { assert!(store.as_context().async_support(), concat!("cannot use `wrap", $num, "_async` without enabling async support on the config")); Func::wrap(store, move |mut caller: Caller<'_, T>, $($args: $args),*| { - let async_cx = caller.store.as_context_mut().opaque().async_cx(); + let async_cx = caller.store.as_context_mut().0.async_cx(); let mut future = Pin::from(func(caller, $($args),*)); match unsafe { async_cx.block_on(future.as_mut()) } { Ok(ret) => ret.into_fallible(), @@ -307,13 +307,13 @@ impl Func { ty: FuncType, func: impl Fn(Caller<'_, T>, &[Val], &mut [Val]) -> Result<(), Trap> + Send + Sync + 'static, ) -> Self { - let mut store = store.as_context_mut().opaque(); + let store = store.as_context_mut().0; // part of this unsafety is about matching the `T` to a `Store`, // which is done through the `AsContextMut` bound above. unsafe { let host = HostFunc::new(store.engine(), ty, func); - host.into_func(&mut store) + host.into_func(store) } } @@ -398,7 +398,7 @@ impl Func { "cannot use `new_async` without enabling async support in the config" ); Func::new(store, ty, move |mut caller, params, results| { - let async_cx = caller.store.as_context_mut().opaque().async_cx(); + let async_cx = caller.store.as_context_mut().0.async_cx(); let mut future = Pin::from(func(caller, params, results)); match unsafe { async_cx.block_on(future.as_mut()) } { Ok(Ok(())) => Ok(()), @@ -631,12 +631,12 @@ impl Func { mut store: impl AsContextMut, func: impl IntoFunc, ) -> Func { - let mut store = store.as_context_mut().opaque(); + let store = store.as_context_mut().0; // part of this unsafety is about matching the `T` to a `Store`, // which is done through the `AsContextMut` bound above. unsafe { let host = HostFunc::wrap(store.engine(), func); - host.into_func(&mut store) + host.into_func(store) } } @@ -736,7 +736,7 @@ impl Func { my_ty: FuncType, params: &[Val], ) -> Result> { - let mut values_vec = write_params(&mut store.as_context_mut().opaque(), &my_ty, params)?; + let mut values_vec = write_params(store.0, &my_ty, params)?; // Call the trampoline. unsafe { @@ -753,14 +753,10 @@ impl Func { })?; } - return Ok(read_results( - &mut store.as_context_mut().opaque(), - &my_ty, - &values_vec, - )); + return Ok(read_results(store.0, &my_ty, &values_vec)); fn write_params( - store: &mut StoreOpaque<'_>, + store: &mut StoreOpaque, ty: &FuncType, params: &[Val], ) -> Result> { @@ -800,11 +796,7 @@ impl Func { Ok(values_vec) } - fn read_results( - store: &mut StoreOpaque<'_>, - ty: &FuncType, - values_vec: &[u128], - ) -> Box<[Val]> { + fn read_results(store: &mut StoreOpaque, ty: &FuncType, values_vec: &[u128]) -> Box<[Val]> { let mut results = Vec::with_capacity(ty.results().len()); for (index, ty) in ty.results().enumerate() { unsafe { @@ -819,7 +811,7 @@ impl Func { #[inline] pub(crate) fn caller_checked_anyfunc( &self, - store: &StoreInnermost, + store: &StoreOpaque, ) -> NonNull { store.store_data()[self.0].export().anyfunc } @@ -834,7 +826,7 @@ impl Func { Func(store.store_data_mut().insert(data)) } - pub(crate) fn vmimport(&self, store: &mut StoreOpaque<'_>) -> VMFunctionImport { + pub(crate) fn vmimport(&self, store: &mut StoreOpaque) -> VMFunctionImport { unsafe { let f = self.caller_checked_anyfunc(store); VMFunctionImport { @@ -861,10 +853,9 @@ impl Func { const STACK_ARGS: usize = 4; const STACK_RETURNS: usize = 2; let mut args: SmallVec<[Val; STACK_ARGS]> = SmallVec::with_capacity(ty.params().len()); - let mut store = caller.store.as_context_mut().opaque(); for (i, ty) in ty.params().enumerate() { unsafe { - let val = Val::read_value_from(&mut store, values_vec.add(i), ty); + let val = Val::read_value_from(caller.store.0, values_vec.add(i), ty); args.push(val); } } @@ -878,20 +869,19 @@ impl Func { // values produced are correct. There could be a bug in `func` that // produces the wrong number, wrong types, or wrong stores of // values, and we need to catch that here. - let mut store = caller.store.as_context_mut().opaque(); for (i, (ret, ty)) in returns.into_iter().zip(ty.results()).enumerate() { if ret.ty() != ty { return Err(Trap::new( "function attempted to return an incompatible value", )); } - if !ret.comes_from_same_store(&store) { + if !ret.comes_from_same_store(&caller.store.0) { return Err(Trap::new( "cross-`Store` values are not currently supported", )); } unsafe { - ret.write_value_to(&mut store, values_vec.add(i)); + ret.write_value_to(caller.store.0, values_vec.add(i)); } } @@ -1744,8 +1734,7 @@ macro_rules! impl_into_func { if let Err(trap) = caller.store.0.entering_native_hook() { return R::fallible_from_trap(trap); } - let mut _store = caller.sub_caller().store.opaque(); - $(let $args = $args::from_abi($args, &mut _store);)* + $(let $args = $args::from_abi($args, caller.store.0);)* let r = func( caller.sub_caller(), $( $args, )* @@ -1770,11 +1759,10 @@ macro_rules! impl_into_func { // Because the wrapped function is not `unsafe`, we // can't assume it returned a value that is // compatible with this store. - let mut store = caller.store.opaque(); - if !ret.compatible_with_store(&store) { + if !ret.compatible_with_store(caller.store.0) { CallResult::Trap(cross_store_trap()) } else { - match ret.into_abi_for_ret(&mut store, retptr) { + match ret.into_abi_for_ret(caller.store.0, retptr) { Ok(val) => CallResult::Ok(val), Err(trap) => CallResult::Trap(trap.into()), } @@ -1938,19 +1926,19 @@ impl HostFunc { /// /// Can only be inserted into stores with a matching `T` relative to when /// this `HostFunc` was first created. - pub unsafe fn to_func(self: &Arc, store: &mut StoreOpaque<'_>) -> Func { + pub unsafe fn to_func(self: &Arc, store: &mut StoreOpaque) -> Func { self.register_trampoline(store); let me = self.clone(); Func(store.store_data_mut().insert(FuncData::SharedHost(me))) } /// Same as [`HostFunc::to_func`], different ownership. - unsafe fn into_func(self, store: &mut StoreOpaque<'_>) -> Func { + unsafe fn into_func(self, store: &mut StoreOpaque) -> Func { self.register_trampoline(store); Func(store.store_data_mut().insert(FuncData::Host(self))) } - unsafe fn register_trampoline(&self, store: &mut StoreOpaque<'_>) { + unsafe fn register_trampoline(&self, store: &mut StoreOpaque) { let idx = self.export.anyfunc.as_ref().type_index; store.register_host_trampoline(idx, self.trampoline); } diff --git a/crates/wasmtime/src/func/typed.rs b/crates/wasmtime/src/func/typed.rs index 7085b84eab..ad1ad67c0f 100644 --- a/crates/wasmtime/src/func/typed.rs +++ b/crates/wasmtime/src/func/typed.rs @@ -118,7 +118,7 @@ where // Validate that all runtime values flowing into this store indeed // belong within this store, otherwise it would be unsafe for store // values to cross each other. - let params = match params.into_abi(&mut store.as_context_mut().opaque()) { + let params = match params.into_abi(store.0) { Some(abi) => abi, None => { return Err(Trap::new( @@ -154,10 +154,7 @@ where let (_, ret, _, returned) = captures; debug_assert_eq!(result.is_ok(), returned); result?; - Ok(Results::from_abi( - &mut store.as_context_mut().opaque(), - ret.assume_init(), - )) + Ok(Results::from_abi(store.0, ret.assume_init())) } } diff --git a/crates/wasmtime/src/instance.rs b/crates/wasmtime/src/instance.rs index a41045b408..76b0ecce95 100644 --- a/crates/wasmtime/src/instance.rs +++ b/crates/wasmtime/src/instance.rs @@ -121,12 +121,12 @@ impl Instance { ) -> Result { // This unsafety comes from `Instantiator::new` where we must typecheck // first, which we are sure to do here. + let mut store = store.as_context_mut(); let mut i = unsafe { - let mut cx = store.as_context_mut().opaque(); - typecheck_externs(&mut cx, module, imports)?; - Instantiator::new(&mut cx, module, ImportSource::Externs(imports))? + typecheck_externs(store.0, module, imports)?; + Instantiator::new(store.0, module, ImportSource::Externs(imports))? }; - i.run(&mut store.as_context_mut()) + i.run(&mut store) } /// Same as [`Instance::new`], except for usage in [asynchronous stores]. @@ -157,12 +157,12 @@ impl Instance { T: Send, { // See `new` for unsafety comments + let mut store = store.as_context_mut(); let mut i = unsafe { - let mut cx = store.as_context_mut().opaque(); - typecheck_externs(&mut cx, module, imports)?; - Instantiator::new(&mut cx, module, ImportSource::Externs(imports))? + typecheck_externs(store.0, module, imports)?; + Instantiator::new(store.0, module, ImportSource::Externs(imports))? }; - i.run_async(&mut store.as_context_mut()).await + i.run_async(&mut store).await } pub(crate) fn from_wasmtime(handle: InstanceData, store: &mut StoreOpaque) -> Instance { @@ -211,12 +211,12 @@ impl Instance { &'a self, store: impl Into>, ) -> impl ExactSizeIterator> + 'a { - self._exports(store.into().opaque()) + self._exports(store.into().0) } fn _exports<'a>( &'a self, - mut store: StoreOpaque<'a>, + store: &'a mut StoreOpaque, ) -> impl ExactSizeIterator> + 'a { // If this is an `Instantiated` instance then all the `exports` may not // be filled in. Fill them all in now if that's the case. @@ -224,18 +224,17 @@ impl Instance { if exports.iter().any(|e| e.is_none()) { let module = Arc::clone(store.instance(*id).module()); for name in module.exports.keys() { - self._get_export(&mut store, name); + self._get_export(store, name); } } } - let inner = store.into_inner(); - return match &inner.store_data()[self.0] { + return match &store.store_data()[self.0] { InstanceData::Synthetic(names) => { Either::A(names.iter().map(|(k, v)| Export::new(k, v.clone()))) } InstanceData::Instantiated { exports, id, .. } => { - let module = inner.instance(*id).module(); + let module = store.instance(*id).module(); Either::B( module .exports @@ -305,10 +304,10 @@ impl Instance { /// instantiating a module faster, but also means this method requires a /// mutable context. pub fn get_export(&self, mut store: impl AsContextMut, name: &str) -> Option { - self._get_export(&mut store.as_context_mut().opaque(), name) + self._get_export(store.as_context_mut().0, name) } - fn _get_export(&self, store: &mut StoreOpaque<'_>, name: &str) -> Option { + fn _get_export(&self, store: &mut StoreOpaque, name: &str) -> Option { match &store[self.0] { // Synthetic instances always have their entire list of exports // already specified. @@ -458,7 +457,7 @@ impl<'a> Instantiator<'a> { /// /// * The `imports` must all come from the `store` specified. unsafe fn new( - store: &mut StoreOpaque<'_>, + store: &StoreOpaque, module: &Module, imports: ImportSource<'a>, ) -> Result> { @@ -481,9 +480,7 @@ impl<'a> Instantiator<'a> { // NB: this is the same code as `run_async`. It's intentionally // small but should be kept in sync (modulo the async bits). loop { - if let Some((instance, start, toplevel)) = - self.step(&mut store.as_context_mut().opaque())? - { + if let Some((instance, start, toplevel)) = self.step(store.0)? { if let Some(start) = start { Instantiator::start_raw(store, instance, start)?; } @@ -507,7 +504,7 @@ impl<'a> Instantiator<'a> { // NB: this is the same code as `run`. It's intentionally // small but should be kept in sync (modulo the async bits). loop { - let step = self.step(&mut store.as_context_mut().opaque())?; + let step = self.step(store.0)?; if let Some((instance, start, toplevel)) = step { if let Some(start) = start { store @@ -543,7 +540,7 @@ impl<'a> Instantiator<'a> { /// defined here. fn step( &mut self, - store: &mut StoreOpaque<'_>, + store: &mut StoreOpaque, ) -> Result, bool)>> { if self.cur.initializer == 0 { store.bump_resource_counts(&self.cur.module)?; @@ -707,7 +704,7 @@ impl<'a> Instantiator<'a> { fn instantiate_raw( &mut self, - store: &mut StoreOpaque<'_>, + store: &mut StoreOpaque, ) -> Result<(Instance, Option)> { let compiled_module = self.cur.module.compiled_module(); @@ -737,7 +734,7 @@ impl<'a> Instantiator<'a> { imports: self.cur.build(), shared_signatures: self.cur.module.signatures().as_module_map().into(), host_state: Box::new(Instance(instance_to_be)), - store: Some(store.traitobj), + store: Some(store.traitobj()), wasm_data: compiled_module.wasm_data(), })?; @@ -877,7 +874,7 @@ impl<'a> ImportsBuilder<'a> { } } - fn push(&mut self, item: Extern, store: &mut StoreOpaque<'_>) { + fn push(&mut self, item: Extern, store: &mut StoreOpaque) { match item { Extern::Func(i) => { self.functions.push(i.vmimport(store)); @@ -962,16 +959,16 @@ impl InstancePre { // structure and then othrewise the `T` of `InstancePre` connects any // host functions we have in our definition list to the `store` that was // passed in. + let mut store = store.as_context_mut(); let mut instantiator = unsafe { - let mut store = store.as_context_mut().opaque(); - self.ensure_comes_from_same_store(&store)?; + self.ensure_comes_from_same_store(&store.0)?; Instantiator::new( - &mut store, + store.0, &self.module, ImportSource::Definitions(&self.items), )? }; - instantiator.run(&mut store.as_context_mut()) + instantiator.run(&mut store) } /// Creates a new instance, running the start function asynchronously @@ -994,11 +991,11 @@ impl InstancePre { T: Send, { // For the unsafety here see above + let mut store = store.as_context_mut(); let mut i = unsafe { - let mut store = store.as_context_mut().opaque(); - self.ensure_comes_from_same_store(&store)?; + self.ensure_comes_from_same_store(&store.0)?; Instantiator::new( - &mut store, + store.0, &self.module, ImportSource::Definitions(&self.items), )? @@ -1006,7 +1003,7 @@ impl InstancePre { i.run_async(&mut store.as_context_mut()).await } - fn ensure_comes_from_same_store(&self, store: &StoreOpaque<'_>) -> Result<()> { + fn ensure_comes_from_same_store(&self, store: &StoreOpaque) -> Result<()> { for import in self.items.iter() { if !import.comes_from_same_store(store) { bail!("cross-`Store` instantiation is not currently supported"); diff --git a/crates/wasmtime/src/linker.rs b/crates/wasmtime/src/linker.rs index 2f99c7004b..bb49ca09b5 100644 --- a/crates/wasmtime/src/linker.rs +++ b/crates/wasmtime/src/linker.rs @@ -137,7 +137,7 @@ macro_rules! generate_wrap_async_func { ), ); self.func_wrap(module, name, move |mut caller: Caller<'_, T>, $($args: $args),*| { - let async_cx = caller.store.as_context_mut().opaque().async_cx(); + let async_cx = caller.store.as_context_mut().0.async_cx(); let mut future = Pin::from(func(caller, $($args),*)); match unsafe { async_cx.block_on(future.as_mut()) } { Ok(ret) => ret.into_fallible(), @@ -331,7 +331,7 @@ impl Linker { "cannot use `func_new_async` without enabling async support in the config" ); self.func_new(module, name, ty, move |mut caller, params, results| { - let async_cx = caller.store.as_context_mut().opaque().async_cx(); + let async_cx = caller.store.as_context_mut().0.async_cx(); let mut future = Pin::from(func(caller, params, results)); match unsafe { async_cx.block_on(future.as_mut()) } { Ok(Ok(())) => Ok(()), @@ -999,6 +999,7 @@ impl Linker { mut store: impl AsContextMut, module: &Module, ) -> Result> { + let store = store.as_context_mut().0; let imports = module .imports() .map(|import| { @@ -1006,7 +1007,7 @@ impl Linker { .ok_or_else(|| self.link_error(&import)) }) .collect::>()?; - unsafe { InstancePre::new(&mut store.as_context_mut().opaque(), module, imports) } + unsafe { InstancePre::new(store, module, imports) } } fn link_error(&self, import: &ImportType) -> Error { @@ -1031,12 +1032,12 @@ impl Linker { mut store: impl AsContextMut + 'p, ) -> impl Iterator + 'p { self.map.iter().map(move |(key, item)| { - let mut store = store.as_context_mut().opaque(); + let store = store.as_context_mut(); ( &*self.strings[key.module], &*self.strings[key.name], // Should be safe since `T` is connecting the linker and store - unsafe { item.to_extern(&mut store) }, + unsafe { item.to_extern(store.0) }, ) }) } @@ -1052,9 +1053,9 @@ impl Linker { module: &str, name: Option<&str>, ) -> Option { - let mut store = store.as_context_mut().opaque(); + let store = store.as_context_mut().0; // Should be safe since `T` is connecting the linker and store - Some(unsafe { self._get(module, name)?.to_extern(&mut store) }) + Some(unsafe { self._get(module, name)?.to_extern(store) }) } fn _get(&self, module: &str, name: Option<&str>) -> Option<&Definition> { @@ -1077,9 +1078,9 @@ impl Linker { mut store: impl AsContextMut, import: &ImportType, ) -> Option { - let mut store = store.as_context_mut().opaque(); + let store = store.as_context_mut().0; // Should be safe since `T` is connecting the linker and store - Some(unsafe { self._get_by_import(import)?.to_extern(&mut store) }) + Some(unsafe { self._get_by_import(import)?.to_extern(store) }) } fn _get_by_import(&self, import: &ImportType) -> Option { diff --git a/crates/wasmtime/src/memory.rs b/crates/wasmtime/src/memory.rs index b1dbfc7f49..8cfd900645 100644 --- a/crates/wasmtime/src/memory.rs +++ b/crates/wasmtime/src/memory.rs @@ -220,10 +220,10 @@ impl Memory { /// # } /// ``` pub fn new(mut store: impl AsContextMut, ty: MemoryType) -> Result { - Memory::_new(&mut store.as_context_mut().opaque(), ty) + Memory::_new(store.as_context_mut().0, ty) } - fn _new(store: &mut StoreOpaque<'_>, ty: MemoryType) -> Result { + fn _new(store: &mut StoreOpaque, ty: MemoryType) -> Result { unsafe { let export = generate_memory_export(store, &ty)?; Ok(Memory::from_wasmtime_memory(export, store)) @@ -450,10 +450,10 @@ impl Memory { /// # } /// ``` pub fn grow(&self, mut store: impl AsContextMut, delta: u64) -> Result { - let mem = self.wasmtime_memory(&mut store.as_context_mut().opaque()); - let store = store.as_context_mut(); + let store = store.as_context_mut().0; + let mem = self.wasmtime_memory(store); unsafe { - match (*mem).grow(delta, store.0.limiter()) { + match (*mem).grow(delta, store.limiter()) { Some(size) => { let vm = (*mem).vmmemory(); *store[self.0].definition = vm; @@ -464,7 +464,7 @@ impl Memory { } } - fn wasmtime_memory(&self, store: &mut StoreOpaque<'_>) -> *mut wasmtime_runtime::Memory { + fn wasmtime_memory(&self, store: &mut StoreOpaque) -> *mut wasmtime_runtime::Memory { unsafe { let export = &store[self.0]; let mut handle = wasmtime_runtime::InstanceHandle::from_vmctx(export.vmctx); @@ -484,7 +484,7 @@ impl Memory { &store[self.0].memory.memory } - pub(crate) fn vmimport(&self, store: &StoreOpaque<'_>) -> wasmtime_runtime::VMMemoryImport { + pub(crate) fn vmimport(&self, store: &StoreOpaque) -> wasmtime_runtime::VMMemoryImport { let export = &store[self.0]; wasmtime_runtime::VMMemoryImport { from: export.definition, diff --git a/crates/wasmtime/src/store.rs b/crates/wasmtime/src/store.rs index 8b19cfcbc5..a00b5c760d 100644 --- a/crates/wasmtime/src/store.rs +++ b/crates/wasmtime/src/store.rs @@ -1,3 +1,81 @@ +//! Wasmtime's "store" type +//! +//! This module, and its submodules, contain the `Store` type and various types +//! used to interact with it. At first glance this is a pretty confusing module +//! where you need to know the difference between: +//! +//! * `Store` +//! * `StoreContext` +//! * `StoreContextMut` +//! * `AsContext` +//! * `AsContextMut` +//! * `StoreInner` +//! * `StoreOpaque` +//! * `StoreData` +//! +//! There's... quite a lot going on here, and it's easy to be confused. This +//! comment is ideally going to serve the purpose of clarifying what all these +//! types are for and why they're motivated. +//! +//! First it's important to know what's "internal" and what's "external". Almost +//! everything above is defined as `pub`, but only some of the items are +//! reexported to the outside world to be usable from this crate. Otherwise all +//! items are `pub` within this `store` module, and the `store` module is +//! private to the `wasmtime` crate. Notably `Store`, `StoreContext`, +//! `StoreContextMut`, `AsContext`, and `AsContextMut` are all public +//! interfaces to the `wasmtime` crate. You can think of these as: +//! +//! * `Store` - an owned reference to a store, the "root of everything" +//! * `StoreContext` - basically `&StoreInner` +//! * `StoreContextMut` - more-or-less `&mut StoreInner` with caveats. +//! Explained later. +//! * `AsContext` - similar to `AsRef`, but produces `StoreContext` +//! * `AsContextMut` - similar to `AsMut`, but produces `StoreContextMut` +//! +//! Next comes the internal structure of the `Store` itself. This looks like: +//! +//! * `Store` - this type is just a pointer large. It's primarily just +//! intended to be consumed by the outside world. Note that the "just a +//! pointer large" is a load-bearing implementation detail in Wasmtime. This +//! enables it to store a pointer to its own trait object which doesn't need +//! to change over time. +//! +//! * `StoreInner` - the first layer of the contents of a `Store`, what's +//! stored inside the `Box`. This is the general Rust pattern when one struct +//! is a layer over another. The surprising part, though, is that this is +//! further subdivided. This structure only contains things which actually +//! need `T` itself. The downside of this structure is that it's always +//! generic and means that code is monomorphized into consumer crates. We +//! strive to have things be as monomorphic as possible in `wasmtime` so this +//! type is not heavily used. +//! +//! * `StoreOpaque` - this is the primary contents of the `StoreInner` type. +//! Stored inline in the outer type the "opaque" here means that it's a +//! "store" but it doesn't have access to the `T`. This is the primary +//! "internal" reference that Wasmtime uses since `T` is rarely needed by the +//! internals of Wasmtime. +//! +//! * `StoreData` - this is a final helper struct stored within `StoreOpaque`. +//! All references of Wasm items into a `Store` are actually indices into a +//! table in this structure, and the `StoreData` being separate makes it a bit +//! easier to manage/define/work with. There's no real fundamental reason this +//! is split out, although sometimes it's useful to have separate borrows into +//! these tables than the `StoreOpaque`. +//! +//! A major caveat with these representations is that the internal `&mut +//! StoreInner` is never handed out publicly to consumers of this crate, only +//! through a wrapper of `StoreContextMut<'_, T>`. The reason for this is that +//! we want to provide mutable, but not destructive, access to the contents of a +//! `Store`. For example if a `StoreInner` were replaced with some other +//! `StoreInner` then that would drop live instances, possibly those +//! currently executing beneath the current stack frame. This would not be a +//! safe operation. +//! +//! This means, though, that the `wasmtime` crate, which liberally uses `&mut +//! StoreOpaque` internally, has to be careful to never actually destroy the +//! contents of `StoreOpaque`. This is an invariant that we, as the authors of +//! `wasmtime`, must uphold for the public interface to be safe. + use crate::{module::ModuleRegistry, Engine, Module, Trap}; use anyhow::{bail, Result}; use std::cell::UnsafeCell; @@ -79,14 +157,50 @@ pub struct Store { inner: ManuallyDrop>>, } +/// Internal contents of a `Store` that live on the heap. +/// +/// The members of this struct are those that need to be generic over `T`, the +/// store's internal type storage. Otherwise all things that don't rely on `T` +/// should go into `StoreOpaque`. pub struct StoreInner { - // This `StoreInner` structure has references to itself. These aren't + /// Generic metadata about the store that doesn't need access to `T`. + inner: StoreOpaque, + + limiter: Option &mut (dyn crate::ResourceLimiter) + Send + Sync>>, + entering_native_hook: Option Result<(), crate::Trap> + Send + Sync>>, + exiting_native_hook: Option Result<(), crate::Trap> + Send + Sync>>, + // for comments about `ManuallyDrop`, see `Store::into_data` + data: ManuallyDrop, +} + +// Forward methods on `StoreOpaque` to also being on `StoreInner` +impl Deref for StoreInner { + type Target = StoreOpaque; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl DerefMut for StoreInner { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} + +/// Monomorphic storage for a `Store`. +/// +/// This structure contains the bulk of the metadata about a `Store`. This is +/// used internally in Wasmtime when dependence on the `T` of `Store` isn't +/// necessary, allowing code to be monomorphic and compiled into the `wasmtime` +/// crate itself. +pub struct StoreOpaque { + // This `StoreOpaque` structure has references to itself. These aren't // immediately evident, however, so we need to tell the compiler that it // contains self-references. This notably suppresses `noalias` annotations // when this shows up in compiled code because types of this structure do - // indeed alias itself. The best example of this is `StoreOpaque` which - // contains a `&mut StoreInner` and a `*mut dyn Store` which are actually - // the same pointer, indeed aliasing! + // indeed alias itself. An example of this is `default_callee` holds a + // `*mut dyn Store` to the address of this `StoreOpaque` itself, indeed + // aliasing! // // It's somewhat unclear to me at this time if this is 100% sufficient to // get all the right codegen in all the right places. For example does @@ -102,30 +216,7 @@ pub struct StoreInner { // least telling the compiler something about all the aliasing happening // within a `Store`. _marker: marker::PhantomPinned, - inner: StoreInnermost, - limiter: Option &mut (dyn crate::ResourceLimiter) + Send + Sync>>, - entering_native_hook: Option Result<(), crate::Trap> + Send + Sync>>, - exiting_native_hook: Option Result<(), crate::Trap> + Send + Sync>>, - // for comments about `ManuallyDrop`, see `Store::into_data` - data: ManuallyDrop, -} -impl Deref for StoreInner { - type Target = StoreInnermost; - fn deref(&self) -> &Self::Target { - &self.inner - } -} -impl DerefMut for StoreInner { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.inner - } -} - -// I apologize for the convoluted structure and the terrible naming of this struct. -// This exists so that most of wasmtime can be monomorphic on StoreInnermost, without -// having to care about the generic in StoreInner. -pub struct StoreInnermost { engine: Engine, interrupts: Arc, instances: Vec, @@ -217,8 +308,8 @@ impl Store { .expect("failed to allocate default callee") }; let mut inner = Box::new(StoreInner { - _marker: marker::PhantomPinned, - inner: StoreInnermost { + inner: StoreOpaque { + _marker: marker::PhantomPinned, engine: engine.clone(), interrupts: Default::default(), instances: Vec::new(), @@ -249,11 +340,18 @@ impl Store { }); // Once we've actually allocated the store itself we can configure the - // trait object pointer of the default callee. - let store = StoreContextMut(&mut *inner).opaque().traitobj; + // trait object pointer of the default callee. Note the erasure of the + // lifetime here into `'static`, so in general usage of this trait + // object must be strictly bounded to the `Store` itself, and is a + // variant that we have to maintain throughout Wasmtime. unsafe { - inner.default_callee.set_store(store); + let traitobj = std::mem::transmute::< + *mut (dyn wasmtime_runtime::Store + '_), + *mut (dyn wasmtime_runtime::Store + 'static), + >(&mut *inner); + inner.default_callee.set_store(traitobj); } + Self { inner: ManuallyDrop::new(inner), } @@ -696,7 +794,7 @@ impl StoreInner { } } -impl StoreInnermost { +impl StoreOpaque { pub fn bump_resource_counts(&mut self, module: &Module) -> Result<()> { fn bump(slot: &mut usize, max: usize, amt: usize, desc: &str) -> Result<()> { let new = slot.saturating_add(amt); @@ -954,6 +1052,10 @@ impl StoreInnermost { pub fn default_callee(&self) -> *mut VMContext { self.default_callee.vmctx_ptr() } + + pub fn traitobj(&self) -> *mut dyn wasmtime_runtime::Store { + self.default_callee.store() + } } impl StoreContextMut<'_, T> { @@ -1243,7 +1345,7 @@ impl AsyncCx { unsafe impl wasmtime_runtime::Store for StoreInner { fn vminterrupts(&self) -> *mut VMInterrupts { - ::vminterrupts(self) + ::vminterrupts(self) } fn externref_activations_table( @@ -1273,7 +1375,7 @@ unsafe impl wasmtime_runtime::Store for StoreInner { } *injection_count -= 1; let fuel = *fuel_to_inject; - StoreContextMut(self).opaque().out_of_gas_yield(fuel)?; + self.out_of_gas_yield(fuel)?; Ok(()) } #[cfg(not(feature = "async"))] @@ -1319,7 +1421,7 @@ impl Drop for Store { } } -impl Drop for StoreInnermost { +impl Drop for StoreOpaque { fn drop(&mut self) { // NB it's important that this destructor does not access `self.data`. // That is deallocated by `Drop for Store` above. diff --git a/crates/wasmtime/src/store/context.rs b/crates/wasmtime/src/store/context.rs index caf89ee18d..f50557f9dc 100644 --- a/crates/wasmtime/src/store/context.rs +++ b/crates/wasmtime/src/store/context.rs @@ -1,5 +1,4 @@ -use crate::store::{Store, StoreInner, StoreInnermost}; -use std::ops::{Deref, DerefMut}; +use crate::store::{Store, StoreInner}; /// A temporary handle to a [`&Store`][`Store`]. /// @@ -37,27 +36,6 @@ impl<'a, T> StoreContextMut<'a, T> { ) -> StoreContextMut<'a, T> { StoreContextMut(&mut *(store as *mut StoreInner)) } - - /// A helper method to erase the `T` on `Self` so the returned type has no - /// generics. For some more information see [`StoreOpaque`] itself. - /// - /// The primary purpose of this is to help improve compile times where - /// non-generic code can be compiled into libwasmtime.rlib. - pub(crate) fn opaque(mut self) -> StoreOpaque<'a> { - StoreOpaque { - traitobj: self.traitobj(), - inner: self.0, - } - } - - fn traitobj(&mut self) -> *mut dyn wasmtime_runtime::Store { - unsafe { - std::mem::transmute::< - *mut (dyn wasmtime_runtime::Store + '_), - *mut (dyn wasmtime_runtime::Store + 'static), - >(self.0) - } - } } /// A trait used to get shared access to a [`Store`] in Wasmtime. @@ -183,6 +161,33 @@ impl AsContextMut for StoreContextMut<'_, T> { } } +// Implementations for internal consumers, but these aren't public types so +// they're not publicly accessible for crate consumers. +impl AsContext for &'_ StoreInner { + type Data = T; + + #[inline] + fn as_context(&self) -> StoreContext<'_, T> { + StoreContext(self) + } +} + +impl AsContext for &'_ mut StoreInner { + type Data = T; + + #[inline] + fn as_context(&self) -> StoreContext<'_, T> { + StoreContext(self) + } +} + +impl AsContextMut for &'_ mut StoreInner { + #[inline] + fn as_context_mut(&mut self) -> StoreContextMut<'_, T> { + StoreContextMut(&mut **self) + } +} + // forward AsContext for &T impl AsContext for &'_ T { type Data = T::Data; @@ -229,46 +234,3 @@ impl<'a, T: AsContextMut> From<&'a mut T> for StoreContextMut<'a, T::Data> { t.as_context_mut() } } - -/// This structure is akin to a `StoreContextMut` except that the `T` is -/// "erased" to an opaque type. -/// -/// This structure is used pervasively through wasmtime whenever the `T` isn't -/// needed (quite common!). This allows the compiler to erase generics and -/// compile more code in the wasmtime crate itself instead of monomorphizing -/// everything into consumer crates. The primary purpose of this is to help -/// compile times. -#[doc(hidden)] // this is part of `WasmTy`, but a hidden part, so hide this -pub struct StoreOpaque<'a> { - /// The actual pointer to the `StoreInner` internals. - inner: &'a mut StoreInnermost, - - /// A raw trait object that can be used to invoke functions with. Note that - /// this is a pointer which aliases with `inner` above, so extreme care - /// needs to be used when using this (the above `inner` cannot be actively - /// borrowed). - pub traitobj: *mut dyn wasmtime_runtime::Store, -} - -impl<'a> StoreOpaque<'a> { - pub fn into_inner(self) -> &'a StoreInnermost { - self.inner - } -} - -// Deref impls to forward all methods on `StoreOpaque` to `StoreInner`. -impl<'a> Deref for StoreOpaque<'a> { - type Target = StoreInnermost; - - #[inline] - fn deref(&self) -> &Self::Target { - &*self.inner - } -} - -impl<'a> DerefMut for StoreOpaque<'a> { - #[inline] - fn deref_mut(&mut self) -> &mut Self::Target { - &mut *self.inner - } -} diff --git a/crates/wasmtime/src/store/data.rs b/crates/wasmtime/src/store/data.rs index 757599f075..ebcc7627e6 100644 --- a/crates/wasmtime/src/store/data.rs +++ b/crates/wasmtime/src/store/data.rs @@ -158,7 +158,7 @@ where } // forward StoreOpaque => StoreData -impl Index for StoreOpaque<'_> +impl Index for StoreOpaque where StoreData: Index, { @@ -169,7 +169,7 @@ where self.store_data().index(index) } } -impl IndexMut for StoreOpaque<'_> +impl IndexMut for StoreOpaque where StoreData: IndexMut, { diff --git a/crates/wasmtime/src/trampoline.rs b/crates/wasmtime/src/trampoline.rs index 052b99cb85..4452d7b42a 100644 --- a/crates/wasmtime/src/trampoline.rs +++ b/crates/wasmtime/src/trampoline.rs @@ -24,7 +24,7 @@ use wasmtime_runtime::{ fn create_handle( module: Module, - store: &mut StoreOpaque<'_>, + store: &mut StoreOpaque, host_state: Box, func_imports: &[VMFunctionImport], shared_signature_id: Option, @@ -46,7 +46,7 @@ fn create_handle( imports, shared_signatures: shared_signature_id.into(), host_state, - store: Some(store.traitobj), + store: Some(store.traitobj()), wasm_data: &[], }, )?; @@ -56,7 +56,7 @@ fn create_handle( } pub fn generate_global_export( - store: &mut StoreOpaque<'_>, + store: &mut StoreOpaque, gt: &GlobalType, val: Val, ) -> Result { @@ -69,7 +69,7 @@ pub fn generate_global_export( } pub fn generate_memory_export( - store: &mut StoreOpaque<'_>, + store: &mut StoreOpaque, m: &MemoryType, ) -> Result { let instance = create_memory(store, m)?; @@ -81,7 +81,7 @@ pub fn generate_memory_export( } pub fn generate_table_export( - store: &mut StoreOpaque<'_>, + store: &mut StoreOpaque, t: &TableType, ) -> Result { let instance = create_table(store, t)?; diff --git a/crates/wasmtime/src/trampoline/global.rs b/crates/wasmtime/src/trampoline/global.rs index 2efd54ebfb..3feb599b26 100644 --- a/crates/wasmtime/src/trampoline/global.rs +++ b/crates/wasmtime/src/trampoline/global.rs @@ -5,7 +5,7 @@ use anyhow::Result; use wasmtime_environ::{EntityIndex, Global, GlobalInit, Module, ModuleType, SignatureIndex}; use wasmtime_runtime::VMFunctionImport; -pub fn create_global(store: &mut StoreOpaque<'_>, gt: &GlobalType, val: Val) -> Result { +pub fn create_global(store: &mut StoreOpaque, gt: &GlobalType, val: Val) -> Result { let mut module = Module::new(); let mut func_imports = Vec::new(); let mut externref_init = None; diff --git a/crates/wasmtime/src/trampoline/memory.rs b/crates/wasmtime/src/trampoline/memory.rs index a5e016fd5f..d3507504ec 100644 --- a/crates/wasmtime/src/trampoline/memory.rs +++ b/crates/wasmtime/src/trampoline/memory.rs @@ -8,7 +8,7 @@ use std::sync::Arc; use wasmtime_environ::{EntityIndex, MemoryPlan, MemoryStyle, Module, WASM_PAGE_SIZE}; use wasmtime_runtime::{RuntimeLinearMemory, RuntimeMemoryCreator, VMMemoryDefinition}; -pub fn create_memory(store: &mut StoreOpaque<'_>, memory: &MemoryType) -> Result { +pub fn create_memory(store: &mut StoreOpaque, memory: &MemoryType) -> Result { let mut module = Module::new(); let memory_plan = wasmtime_environ::MemoryPlan::for_memory( diff --git a/crates/wasmtime/src/trampoline/table.rs b/crates/wasmtime/src/trampoline/table.rs index 1cf840dd13..f351a26096 100644 --- a/crates/wasmtime/src/trampoline/table.rs +++ b/crates/wasmtime/src/trampoline/table.rs @@ -4,7 +4,7 @@ use crate::TableType; use anyhow::Result; use wasmtime_environ::{EntityIndex, Module}; -pub fn create_table(store: &mut StoreOpaque<'_>, table: &TableType) -> Result { +pub fn create_table(store: &mut StoreOpaque, table: &TableType) -> Result { let mut module = Module::new(); let table_plan = wasmtime_environ::TablePlan::for_table( table.wasmtime_table().clone(), diff --git a/crates/wasmtime/src/types/matching.rs b/crates/wasmtime/src/types/matching.rs index 45b49564a2..c0ded9ee70 100644 --- a/crates/wasmtime/src/types/matching.rs +++ b/crates/wasmtime/src/types/matching.rs @@ -1,6 +1,6 @@ use crate::instance::InstanceData; use crate::linker::Definition; -use crate::store::StoreInnermost; +use crate::store::StoreOpaque; use crate::{signatures::SignatureCollection, Engine, Extern}; use anyhow::{bail, Context, Result}; use wasmtime_environ::{ @@ -12,7 +12,7 @@ use wasmtime_runtime::VMSharedSignatureIndex; pub struct MatchCx<'a> { pub signatures: &'a SignatureCollection, pub types: &'a TypeTables, - pub store: &'a StoreInnermost, + pub store: &'a StoreOpaque, pub engine: &'a Engine, } diff --git a/crates/wasmtime/src/unix.rs b/crates/wasmtime/src/unix.rs index 40c2a57cdd..f52895bea3 100644 --- a/crates/wasmtime/src/unix.rs +++ b/crates/wasmtime/src/unix.rs @@ -33,7 +33,7 @@ impl StoreExt for Store { + Sync, { self.as_context_mut() - .opaque() + .0 .set_signal_handler(Some(Box::new(handler))); } } diff --git a/crates/wasmtime/src/values.rs b/crates/wasmtime/src/values.rs index 344ffa0385..2bfa42200f 100644 --- a/crates/wasmtime/src/values.rs +++ b/crates/wasmtime/src/values.rs @@ -187,7 +187,7 @@ impl Val { pub(crate) fn into_table_element( self, - store: &mut StoreOpaque<'_>, + store: &mut StoreOpaque, ty: ValType, ) -> Result { match (self, ty) { @@ -213,7 +213,7 @@ impl Val { } #[inline] - pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque<'_>) -> bool { + pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool { match self { Val::FuncRef(Some(f)) => f.comes_from_same_store(store), Val::FuncRef(None) => true, diff --git a/crates/wasmtime/src/windows.rs b/crates/wasmtime/src/windows.rs index c8f534b691..c401726eae 100644 --- a/crates/wasmtime/src/windows.rs +++ b/crates/wasmtime/src/windows.rs @@ -27,7 +27,7 @@ impl StoreExt for Store { H: 'static + Fn(winapi::um::winnt::PEXCEPTION_POINTERS) -> bool + Send + Sync, { self.as_context_mut() - .opaque() + .0 .set_signal_handler(Some(Box::new(handler))); } }