1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
use crate::store::{Store, StoreInner, StoreInnermost};
use std::ops::{Deref, DerefMut};

/// A temporary handle to a [`&Store<T>`][`Store`].
///
/// This type is sutable for [`AsContext`] trait bounds on methods if desired.
/// For more information, see [`Store`].
// NB the repr(transparent) here is for the C API and it's important that the
// representation of this `struct` is a pointer for now. If the representation
// changes then the C API will need to be updated
#[repr(transparent)]
pub struct StoreContext<'a, T>(pub(crate) &'a StoreInner<T>);

/// A temporary handle to a [`&mut Store<T>`][`Store`].
///
/// This type is sutable for [`AsContextMut`] or [`AsContext`] trait bounds on
/// methods if desired.  For more information, see [`Store`].
// NB the repr(transparent) here is for the same reason as above.
#[repr(transparent)]
pub struct StoreContextMut<'a, T>(pub(crate) &'a mut StoreInner<T>);

impl<'a, T> StoreContextMut<'a, T> {
    /// One of the unsafe lynchpins of Wasmtime.
    ///
    /// This method is called from one location, `Caller::with`, and is where we
    /// load the raw unsafe trait object pointer from a `*mut VMContext` and
    /// then cast it back to a `StoreContextMut`. This is naturally unsafe due
    /// to the raw pointer usage, but it's also unsafe because `T` here needs to
    /// line up with the `T` used to define the trait object itself.
    ///
    /// This should generally be achieved with various trait bounds throughout
    /// Wasmtime that might give access to the `Caller<'_, T>` type.
    /// Unfortunately there's not a ton of debug asserts we can add here, so we
    /// rely on testing to largely help show that this is correctly used.
    pub(crate) unsafe fn from_raw(
        store: *mut dyn wasmtime_runtime::Store,
    ) -> StoreContextMut<'a, T> {
        StoreContextMut(&mut *(store as *mut StoreInner<T>))
    }

    /// 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.
///
/// This trait is used as a bound on the first argument of many methods within
/// Wasmtime. This trait is implemented for types like [`Store`],
/// [`Caller`](crate::Caller), and [`StoreContext`] itself. Implementors of this
/// trait provide access to a [`StoreContext`] via some means, allowing the
/// method in question to get access to the store's internal information.
///
/// Note that this is only used in contexts where the store's information is
/// read, but not written. For example methods that return type information will
/// use this trait as a bound. More commonly, though, mutation is required and
/// [`AsContextMut`] is needed.
pub trait AsContext {
    /// The host information associated with the [`Store`], aka the `T` in
    /// [`Store<T>`].
    type Data;

    /// Returns the store context that this type provides access to.
    fn as_context(&self) -> StoreContext<'_, Self::Data>;
}

/// A trait used to get exclusive mutable access to a [`Store`] in Wasmtime.
///
/// This trait is used as a bound on the first argument of many methods within
/// Wasmtime. This trait is implemented for types like [`Store`],
/// [`Caller`](crate::Caller), and [`StoreContextMut`] itself. Implementors of
/// this trait provide access to a [`StoreContextMut`] via some means, allowing
/// the method in question to get access to the store's internal information.
///
/// This is notably used for methods that may require some mutation of the
/// [`Store`] itself. For example calling a wasm function can mutate linear
/// memory or globals. Creation of a [`Func`](crate::Func) will update internal
/// data structures. This ends up being quite a common bound in Wasmtime, but
/// typically you can simply pass `&mut store` or `&mut caller` to satisfy it.
///
/// # Calling multiple methods that take `&mut impl AsContextMut`
///
/// As of Rust 1.53.0, [generic methods that take a generic `&mut T` do not get
/// "automatic reborrowing"][reborrowing] and therefore you cannot call multiple
/// generic methods with the same `&mut T` without manually inserting
/// reborrows. This affects the many `wasmtime` API methods that take `&mut impl
/// AsContextMut`.
///
/// For example, this fails to compile because the context is moved into the
/// first call:
///
/// ```compile_fail
/// use wasmtime::{AsContextMut, Instance};
///
/// fn foo(cx: &mut impl AsContextMut, instance: Instance) {
///     // `cx` is not reborrowed, but moved into this call.
///     let my_export = instance.get_export(cx, "my_export");
///
///     // Therefore, this use of `cx` is a use-after-move and prohibited by the
///     // borrow checker.
///     let other_export = instance.get_export(cx, "other_export");
/// #   drop((my_export, other_export));
/// }
/// ```
///
/// To fix this, manually insert reborrows like `&mut *cx` that would otherwise
/// normally be inserted automatically by the Rust compiler for non-generic
/// methods:
///
/// ```
/// use wasmtime::{AsContextMut, Instance};
///
/// fn foo(cx: &mut impl AsContextMut, instance: Instance) {
///     let my_export = instance.get_export(&mut *cx, "my_export");
///
///     // This works now, since `cx` was reborrowed above, rather than moved!
///     let other_export = instance.get_export(&mut *cx, "other_export");
/// #   drop((my_export, other_export));
/// }
/// ```
///
/// [reborrowing]: https://github.com/rust-lang/rust/issues/85161
pub trait AsContextMut: AsContext {
    /// Returns the store context that this type provides access to.
    fn as_context_mut(&mut self) -> StoreContextMut<'_, Self::Data>;
}

impl<T> AsContext for Store<T> {
    type Data = T;

    #[inline]
    fn as_context(&self) -> StoreContext<'_, T> {
        StoreContext(&self.inner)
    }
}

impl<T> AsContextMut for Store<T> {
    #[inline]
    fn as_context_mut(&mut self) -> StoreContextMut<'_, T> {
        StoreContextMut(&mut self.inner)
    }
}

impl<T> AsContext for StoreContext<'_, T> {
    type Data = T;

    #[inline]
    fn as_context(&self) -> StoreContext<'_, T> {
        StoreContext(&*self.0)
    }
}

impl<T> AsContext for StoreContextMut<'_, T> {
    type Data = T;

    #[inline]
    fn as_context(&self) -> StoreContext<'_, T> {
        StoreContext(&*self.0)
    }
}

impl<T> AsContextMut for StoreContextMut<'_, T> {
    #[inline]
    fn as_context_mut(&mut self) -> StoreContextMut<'_, T> {
        StoreContextMut(&mut *self.0)
    }
}

// forward AsContext for &T
impl<T: AsContext> AsContext for &'_ T {
    type Data = T::Data;

    #[inline]
    fn as_context(&self) -> StoreContext<'_, T::Data> {
        T::as_context(*self)
    }
}

// forward AsContext for &mut T
impl<T: AsContext> AsContext for &'_ mut T {
    type Data = T::Data;

    #[inline]
    fn as_context(&self) -> StoreContext<'_, T::Data> {
        T::as_context(*self)
    }
}

// forward AsContextMut for &mut T
impl<T: AsContextMut> AsContextMut for &'_ mut T {
    #[inline]
    fn as_context_mut(&mut self) -> StoreContextMut<'_, T::Data> {
        T::as_context_mut(*self)
    }
}

//
impl<'a, T: AsContext> From<&'a T> for StoreContext<'a, T::Data> {
    fn from(t: &'a T) -> StoreContext<'a, T::Data> {
        t.as_context()
    }
}

impl<'a, T: AsContext> From<&'a mut T> for StoreContext<'a, T::Data> {
    fn from(t: &'a mut T) -> StoreContext<'a, T::Data> {
        T::as_context(t)
    }
}

impl<'a, T: AsContextMut> From<&'a mut T> for StoreContextMut<'a, T::Data> {
    fn from(t: &'a mut T) -> 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
    }
}