190ac295eSAlex Crichton use crate::Trap;
281a89169SAlex Crichton use crate::prelude::*;
3cc8d04f4SAlex Crichton use crate::runtime::vm::{self, ExportMemory};
4f881ab24SAlex Crichton use crate::store::{StoreInstanceId, StoreOpaque, StoreResourceLimiter};
5d4242001SAdam Bratschi-Kaye use crate::trampoline::generate_memory_export;
6cc8d04f4SAlex Crichton #[cfg(feature = "async")]
7cc8d04f4SAlex Crichton use crate::vm::VMStore;
8d4242001SAdam Bratschi-Kaye use crate::{AsContext, AsContextMut, Engine, MemoryType, StoreContext, StoreContextMut};
981a89169SAlex Crichton use core::cell::UnsafeCell;
1081a89169SAlex Crichton use core::fmt;
1181a89169SAlex Crichton use core::slice;
1281a89169SAlex Crichton use core::time::Duration;
130e9a691dSAlex Crichton use wasmtime_environ::DefinedMemoryIndex;
14d4242001SAdam Bratschi-Kaye 
1572004aadSNick Fitzgerald pub use crate::runtime::vm::WaitResult;
16d4242001SAdam Bratschi-Kaye 
17d4242001SAdam Bratschi-Kaye /// Error for out of bounds [`Memory`] access.
18d4242001SAdam Bratschi-Kaye #[derive(Debug)]
19d4242001SAdam Bratschi-Kaye #[non_exhaustive]
20d4242001SAdam Bratschi-Kaye pub struct MemoryAccessError {
21d4242001SAdam Bratschi-Kaye     // Keep struct internals private for future extensibility.
22d4242001SAdam Bratschi-Kaye     _private: (),
23d4242001SAdam Bratschi-Kaye }
24d4242001SAdam Bratschi-Kaye 
2581a89169SAlex Crichton impl fmt::Display for MemoryAccessError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result2681a89169SAlex Crichton     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27d4242001SAdam Bratschi-Kaye         write!(f, "out of bounds memory access")
28d4242001SAdam Bratschi-Kaye     }
29d4242001SAdam Bratschi-Kaye }
30d4242001SAdam Bratschi-Kaye 
31935097c1SAlex Crichton impl core::error::Error for MemoryAccessError {}
32d4242001SAdam Bratschi-Kaye 
33d4242001SAdam Bratschi-Kaye /// A WebAssembly linear memory.
34d4242001SAdam Bratschi-Kaye ///
35d4242001SAdam Bratschi-Kaye /// WebAssembly memories represent a contiguous array of bytes that have a size
36d4242001SAdam Bratschi-Kaye /// that is always a multiple of the WebAssembly page size, currently 64
37d4242001SAdam Bratschi-Kaye /// kilobytes.
38d4242001SAdam Bratschi-Kaye ///
39d4242001SAdam Bratschi-Kaye /// WebAssembly memory is used for global data (not to be confused with wasm
40d4242001SAdam Bratschi-Kaye /// `global` items), statics in C/C++/Rust, shadow stack memory, etc. Accessing
41d4242001SAdam Bratschi-Kaye /// wasm memory is generally quite fast.
42d4242001SAdam Bratschi-Kaye ///
43d4242001SAdam Bratschi-Kaye /// Memories, like other wasm items, are owned by a [`Store`](crate::Store).
44d4242001SAdam Bratschi-Kaye ///
45d4242001SAdam Bratschi-Kaye /// # `Memory` and Safety
46d4242001SAdam Bratschi-Kaye ///
47d4242001SAdam Bratschi-Kaye /// Linear memory is a lynchpin of safety for WebAssembly. In Wasmtime there are
48d4242001SAdam Bratschi-Kaye /// safe methods of interacting with a [`Memory`]:
49d4242001SAdam Bratschi-Kaye ///
50d4242001SAdam Bratschi-Kaye /// * [`Memory::read`]
51d4242001SAdam Bratschi-Kaye /// * [`Memory::write`]
52d4242001SAdam Bratschi-Kaye /// * [`Memory::data`]
53d4242001SAdam Bratschi-Kaye /// * [`Memory::data_mut`]
54d4242001SAdam Bratschi-Kaye ///
55d4242001SAdam Bratschi-Kaye /// Note that all of these consider the entire store context as borrowed for the
56d4242001SAdam Bratschi-Kaye /// duration of the call or the duration of the returned slice. This largely
57d4242001SAdam Bratschi-Kaye /// means that while the function is running you'll be unable to borrow anything
58d4242001SAdam Bratschi-Kaye /// else from the store. This includes getting access to the `T` on
59d4242001SAdam Bratschi-Kaye /// [`Store<T>`](crate::Store), but it also means that you can't recursively
60d4242001SAdam Bratschi-Kaye /// call into WebAssembly for instance.
61d4242001SAdam Bratschi-Kaye ///
62d4242001SAdam Bratschi-Kaye /// If you'd like to dip your toes into handling [`Memory`] in a more raw
63d4242001SAdam Bratschi-Kaye /// fashion (e.g. by using raw pointers or raw slices), then there's a few
64d4242001SAdam Bratschi-Kaye /// important points to consider when doing so:
65d4242001SAdam Bratschi-Kaye ///
66d4242001SAdam Bratschi-Kaye /// * Any recursive calls into WebAssembly can possibly modify any byte of the
67d4242001SAdam Bratschi-Kaye ///   entire memory. This means that whenever wasm is called Rust can't have any
68d4242001SAdam Bratschi-Kaye ///   long-lived borrows live across the wasm function call. Slices like `&mut
69d4242001SAdam Bratschi-Kaye ///   [u8]` will be violated because they're not actually exclusive at that
70d4242001SAdam Bratschi-Kaye ///   point, and slices like `&[u8]` are also violated because their contents
71d4242001SAdam Bratschi-Kaye ///   may be mutated.
72d4242001SAdam Bratschi-Kaye ///
73d4242001SAdam Bratschi-Kaye /// * WebAssembly memories can grow, and growth may change the base pointer.
74d4242001SAdam Bratschi-Kaye ///   This means that even holding a raw pointer to memory over a wasm function
75d4242001SAdam Bratschi-Kaye ///   call is also incorrect. Anywhere in the function call the base address of
76d4242001SAdam Bratschi-Kaye ///   memory may change. Note that growth can also be requested from the
77d4242001SAdam Bratschi-Kaye ///   embedding API as well.
78d4242001SAdam Bratschi-Kaye ///
79d4242001SAdam Bratschi-Kaye /// As a general rule of thumb it's recommended to stick to the safe methods of
80d4242001SAdam Bratschi-Kaye /// [`Memory`] if you can. It's not advised to use raw pointers or `unsafe`
81d4242001SAdam Bratschi-Kaye /// operations because of how easy it is to accidentally get things wrong.
82d4242001SAdam Bratschi-Kaye ///
83d4242001SAdam Bratschi-Kaye /// Some examples of safely interacting with memory are:
84d4242001SAdam Bratschi-Kaye ///
85d4242001SAdam Bratschi-Kaye /// ```rust
86d4242001SAdam Bratschi-Kaye /// use wasmtime::{Memory, Store, MemoryAccessError};
87d4242001SAdam Bratschi-Kaye ///
88d4242001SAdam Bratschi-Kaye /// // Memory can be read and written safely with the `Memory::read` and
89d4242001SAdam Bratschi-Kaye /// // `Memory::write` methods.
90d4242001SAdam Bratschi-Kaye /// // An error is returned if the copy did not succeed.
91d4242001SAdam Bratschi-Kaye /// fn safe_examples(mem: Memory, store: &mut Store<()>) -> Result<(), MemoryAccessError> {
92d4242001SAdam Bratschi-Kaye ///     let offset = 5;
93d4242001SAdam Bratschi-Kaye ///     mem.write(&mut *store, offset, b"hello")?;
94d4242001SAdam Bratschi-Kaye ///     let mut buffer = [0u8; 5];
95d4242001SAdam Bratschi-Kaye ///     mem.read(&store, offset, &mut buffer)?;
96d4242001SAdam Bratschi-Kaye ///     assert_eq!(b"hello", &buffer);
97d4242001SAdam Bratschi-Kaye ///
98d4242001SAdam Bratschi-Kaye ///     // Note that while this is safe care must be taken because the indexing
99d4242001SAdam Bratschi-Kaye ///     // here may panic if the memory isn't large enough.
100d4242001SAdam Bratschi-Kaye ///     assert_eq!(&mem.data(&store)[offset..offset + 5], b"hello");
101d4242001SAdam Bratschi-Kaye ///     mem.data_mut(&mut *store)[offset..offset + 5].copy_from_slice(b"bye!!");
102d4242001SAdam Bratschi-Kaye ///
103d4242001SAdam Bratschi-Kaye ///     Ok(())
104d4242001SAdam Bratschi-Kaye /// }
105d4242001SAdam Bratschi-Kaye /// ```
106d4242001SAdam Bratschi-Kaye ///
107d4242001SAdam Bratschi-Kaye /// It's worth also, however, covering some examples of **incorrect**,
108d4242001SAdam Bratschi-Kaye /// **unsafe** usages of `Memory`. Do not do these things!
109d4242001SAdam Bratschi-Kaye ///
110d4242001SAdam Bratschi-Kaye /// ```rust
11196e19700SNick Fitzgerald /// use wasmtime::{Memory, Result, Store};
112d4242001SAdam Bratschi-Kaye ///
113d4242001SAdam Bratschi-Kaye /// // NOTE: All code in this function is not safe to execute and may cause
114d4242001SAdam Bratschi-Kaye /// // segfaults/undefined behavior at runtime. Do not copy/paste these examples
115d4242001SAdam Bratschi-Kaye /// // into production code!
116d4242001SAdam Bratschi-Kaye /// unsafe fn unsafe_examples(mem: Memory, store: &mut Store<()>) -> Result<()> {
117d4242001SAdam Bratschi-Kaye ///     // First and foremost, any borrow can be invalidated at any time via the
118d4242001SAdam Bratschi-Kaye ///     // `Memory::grow` function. This can relocate memory which causes any
119d4242001SAdam Bratschi-Kaye ///     // previous pointer to be possibly invalid now.
1209e46e78aSAlex Crichton ///     unsafe {
121d4242001SAdam Bratschi-Kaye ///         let pointer: &u8 = &*mem.data_ptr(&store);
122d4242001SAdam Bratschi-Kaye ///         mem.grow(&mut *store, 1)?; // invalidates `pointer`!
123d4242001SAdam Bratschi-Kaye ///         // println!("{}", *pointer); // FATAL: use-after-free
1249e46e78aSAlex Crichton ///     }
125d4242001SAdam Bratschi-Kaye ///
126d4242001SAdam Bratschi-Kaye ///     // Note that the use-after-free also applies to slices, whether they're
127d4242001SAdam Bratschi-Kaye ///     // slices of bytes or strings.
1289e46e78aSAlex Crichton ///     unsafe {
129d4242001SAdam Bratschi-Kaye ///         let mem_slice = std::slice::from_raw_parts(
130d4242001SAdam Bratschi-Kaye ///             mem.data_ptr(&store),
131d4242001SAdam Bratschi-Kaye ///             mem.data_size(&store),
132d4242001SAdam Bratschi-Kaye ///         );
133d4242001SAdam Bratschi-Kaye ///         let slice: &[u8] = &mem_slice[0x100..0x102];
134d4242001SAdam Bratschi-Kaye ///         mem.grow(&mut *store, 1)?; // invalidates `slice`!
135d4242001SAdam Bratschi-Kaye ///         // println!("{:?}", slice); // FATAL: use-after-free
1369e46e78aSAlex Crichton ///     }
137d4242001SAdam Bratschi-Kaye ///
138d4242001SAdam Bratschi-Kaye ///     // The `Memory` type may be stored in other locations, so if you hand
139d4242001SAdam Bratschi-Kaye ///     // off access to the `Store` then those locations may also call
140d4242001SAdam Bratschi-Kaye ///     // `Memory::grow` or similar, so it's not enough to just audit code for
141d4242001SAdam Bratschi-Kaye ///     // calls to `Memory::grow`.
1429e46e78aSAlex Crichton ///     unsafe {
143d4242001SAdam Bratschi-Kaye ///         let pointer: &u8 = &*mem.data_ptr(&store);
144d4242001SAdam Bratschi-Kaye ///         some_other_function(store); // may invalidate `pointer` through use of `store`
145d4242001SAdam Bratschi-Kaye ///         // println!("{:?}", pointer); // FATAL: maybe a use-after-free
1469e46e78aSAlex Crichton ///     }
147d4242001SAdam Bratschi-Kaye ///
148d4242001SAdam Bratschi-Kaye ///     // An especially subtle aspect of accessing a wasm instance's memory is
149d4242001SAdam Bratschi-Kaye ///     // that you need to be extremely careful about aliasing. Anyone at any
150d4242001SAdam Bratschi-Kaye ///     // time can call `data_unchecked()` or `data_unchecked_mut()`, which
151d4242001SAdam Bratschi-Kaye ///     // means you can easily have aliasing mutable references:
1529e46e78aSAlex Crichton ///     unsafe {
153d4242001SAdam Bratschi-Kaye ///         let ref1: &u8 = &*mem.data_ptr(&store).add(0x100);
154d4242001SAdam Bratschi-Kaye ///         let ref2: &mut u8 = &mut *mem.data_ptr(&store).add(0x100);
155d4242001SAdam Bratschi-Kaye ///         // *ref2 = *ref1; // FATAL: violates Rust's aliasing rules
1569e46e78aSAlex Crichton ///     }
157d4242001SAdam Bratschi-Kaye ///
158d4242001SAdam Bratschi-Kaye ///     Ok(())
159d4242001SAdam Bratschi-Kaye /// }
160d4242001SAdam Bratschi-Kaye /// # fn some_other_function(store: &mut Store<()>) {}
161d4242001SAdam Bratschi-Kaye /// ```
162d4242001SAdam Bratschi-Kaye ///
163d4242001SAdam Bratschi-Kaye /// Overall there's some general rules of thumb when unsafely working with
164d4242001SAdam Bratschi-Kaye /// `Memory` and getting raw pointers inside of it:
165d4242001SAdam Bratschi-Kaye ///
166d4242001SAdam Bratschi-Kaye /// * If you never have a "long lived" pointer into memory, you're likely in the
167d4242001SAdam Bratschi-Kaye ///   clear. Care still needs to be taken in threaded scenarios or when/where
168d4242001SAdam Bratschi-Kaye ///   data is read, but you'll be shielded from many classes of issues.
169d4242001SAdam Bratschi-Kaye /// * Long-lived pointers must always respect Rust'a aliasing rules. It's ok for
170d4242001SAdam Bratschi-Kaye ///   shared borrows to overlap with each other, but mutable borrows must
171d4242001SAdam Bratschi-Kaye ///   overlap with nothing.
172d4242001SAdam Bratschi-Kaye /// * Long-lived pointers are only valid if they're not invalidated for their
173d4242001SAdam Bratschi-Kaye ///   lifetime. This means that [`Store`](crate::Store) isn't used to reenter
174d4242001SAdam Bratschi-Kaye ///   wasm or the memory itself is never grown or otherwise modified/aliased.
175d4242001SAdam Bratschi-Kaye ///
176d4242001SAdam Bratschi-Kaye /// At this point it's worth reiterating again that unsafely working with
177d4242001SAdam Bratschi-Kaye /// `Memory` is pretty tricky and not recommended! It's highly recommended to
178d4242001SAdam Bratschi-Kaye /// use the safe methods to interact with [`Memory`] whenever possible.
179d4242001SAdam Bratschi-Kaye ///
180d4242001SAdam Bratschi-Kaye /// ## `Memory` Safety and Threads
181d4242001SAdam Bratschi-Kaye ///
182d4242001SAdam Bratschi-Kaye /// Currently the `wasmtime` crate does not implement the wasm threads proposal,
183d4242001SAdam Bratschi-Kaye /// but it is planned to do so. It may be interesting to readers to see how this
184d4242001SAdam Bratschi-Kaye /// affects memory safety and what was previously just discussed as well.
185d4242001SAdam Bratschi-Kaye ///
186d4242001SAdam Bratschi-Kaye /// Once threads are added into the mix, all of the above rules still apply.
187d4242001SAdam Bratschi-Kaye /// There's an additional consideration that all reads and writes can happen
188d4242001SAdam Bratschi-Kaye /// concurrently, though. This effectively means that any borrow into wasm
189d4242001SAdam Bratschi-Kaye /// memory are virtually never safe to have.
190d4242001SAdam Bratschi-Kaye ///
191d4242001SAdam Bratschi-Kaye /// Mutable pointers are fundamentally unsafe to have in a concurrent scenario
192d4242001SAdam Bratschi-Kaye /// in the face of arbitrary wasm code. Only if you dynamically know for sure
193d4242001SAdam Bratschi-Kaye /// that wasm won't access a region would it be safe to construct a mutable
194d4242001SAdam Bratschi-Kaye /// pointer. Additionally even shared pointers are largely unsafe because their
195d4242001SAdam Bratschi-Kaye /// underlying contents may change, so unless `UnsafeCell` in one form or
196d4242001SAdam Bratschi-Kaye /// another is used everywhere there's no safety.
197d4242001SAdam Bratschi-Kaye ///
198d4242001SAdam Bratschi-Kaye /// One important point about concurrency is that while [`Memory::grow`] can
199d4242001SAdam Bratschi-Kaye /// happen concurrently it will never relocate the base pointer. Shared
200d4242001SAdam Bratschi-Kaye /// memories must always have a maximum size and they will be preallocated such
201d4242001SAdam Bratschi-Kaye /// that growth will never relocate the base pointer. The current size of the
202d4242001SAdam Bratschi-Kaye /// memory may still change over time though.
203d4242001SAdam Bratschi-Kaye ///
204d4242001SAdam Bratschi-Kaye /// Overall the general rule of thumb for shared memories is that you must
205d4242001SAdam Bratschi-Kaye /// atomically read and write everything. Nothing can be borrowed and everything
206d4242001SAdam Bratschi-Kaye /// must be eagerly copied out. This means that [`Memory::data`] and
207d4242001SAdam Bratschi-Kaye /// [`Memory::data_mut`] won't work in the future (they'll probably return an
208d4242001SAdam Bratschi-Kaye /// error) for shared memories when they're implemented. When possible it's
209d4242001SAdam Bratschi-Kaye /// recommended to use [`Memory::read`] and [`Memory::write`] which will still
210d4242001SAdam Bratschi-Kaye /// be provided.
211d4242001SAdam Bratschi-Kaye #[derive(Copy, Clone, Debug)]
2120e9a691dSAlex Crichton #[repr(C)] // here for the C API
2130e9a691dSAlex Crichton pub struct Memory {
2140e9a691dSAlex Crichton     /// The internal store instance that this memory belongs to.
2150e9a691dSAlex Crichton     instance: StoreInstanceId,
2160e9a691dSAlex Crichton     /// The index of the memory, within `instance` above, that this memory
2170e9a691dSAlex Crichton     /// refers to.
2180e9a691dSAlex Crichton     index: DefinedMemoryIndex,
2190e9a691dSAlex Crichton }
2200e9a691dSAlex Crichton 
2210e9a691dSAlex Crichton // Double-check that the C representation in `extern.h` matches our in-Rust
2220e9a691dSAlex Crichton // representation here in terms of size/alignment/etc.
2230e9a691dSAlex Crichton const _: () = {
2240e9a691dSAlex Crichton     #[repr(C)]
2255603ee7bSAlex Crichton     struct Tmp(u64, u32);
2260e9a691dSAlex Crichton     #[repr(C)]
2270e9a691dSAlex Crichton     struct C(Tmp, u32);
2280e9a691dSAlex Crichton     assert!(core::mem::size_of::<C>() == core::mem::size_of::<Memory>());
2290e9a691dSAlex Crichton     assert!(core::mem::align_of::<C>() == core::mem::align_of::<Memory>());
2300e9a691dSAlex Crichton     assert!(core::mem::offset_of!(Memory, instance) == 0);
2310e9a691dSAlex Crichton };
232d4242001SAdam Bratschi-Kaye 
233d4242001SAdam Bratschi-Kaye impl Memory {
234d4242001SAdam Bratschi-Kaye     /// Creates a new WebAssembly memory given the configuration of `ty`.
235d4242001SAdam Bratschi-Kaye     ///
236d4242001SAdam Bratschi-Kaye     /// The `store` argument will be the owner of the returned [`Memory`]. All
237d4242001SAdam Bratschi-Kaye     /// WebAssembly memory is initialized to zero.
238d4242001SAdam Bratschi-Kaye     ///
239d4242001SAdam Bratschi-Kaye     /// # Panics
240d4242001SAdam Bratschi-Kaye     ///
241d4242001SAdam Bratschi-Kaye     /// This function will panic if the [`Store`](`crate::Store`) has a
242d4242001SAdam Bratschi-Kaye     /// [`ResourceLimiterAsync`](`crate::ResourceLimiterAsync`) (see also:
243d4242001SAdam Bratschi-Kaye     /// [`Store::limiter_async`](`crate::Store::limiter_async`)). When
244d4242001SAdam Bratschi-Kaye     /// using an async resource limiter, use [`Memory::new_async`] instead.
245d4242001SAdam Bratschi-Kaye     ///
246d4242001SAdam Bratschi-Kaye     /// # Examples
247d4242001SAdam Bratschi-Kaye     ///
248d4242001SAdam Bratschi-Kaye     /// ```
249d4242001SAdam Bratschi-Kaye     /// # use wasmtime::*;
25096e19700SNick Fitzgerald     /// # fn main() -> Result<()> {
251d4242001SAdam Bratschi-Kaye     /// let engine = Engine::default();
252d4242001SAdam Bratschi-Kaye     /// let mut store = Store::new(&engine, ());
253d4242001SAdam Bratschi-Kaye     ///
254d4242001SAdam Bratschi-Kaye     /// let memory_ty = MemoryType::new(1, None);
255d4242001SAdam Bratschi-Kaye     /// let memory = Memory::new(&mut store, memory_ty)?;
256d4242001SAdam Bratschi-Kaye     ///
257d4242001SAdam Bratschi-Kaye     /// let module = Module::new(&engine, "(module (memory (import \"\" \"\") 1))")?;
258d4242001SAdam Bratschi-Kaye     /// let instance = Instance::new(&mut store, &module, &[memory.into()])?;
259d4242001SAdam Bratschi-Kaye     /// // ...
260d4242001SAdam Bratschi-Kaye     /// # Ok(())
261d4242001SAdam Bratschi-Kaye     /// # }
262d4242001SAdam Bratschi-Kaye     /// ```
new(mut store: impl AsContextMut, ty: MemoryType) -> Result<Memory>263d4242001SAdam Bratschi-Kaye     pub fn new(mut store: impl AsContextMut, ty: MemoryType) -> Result<Memory> {
264cc8d04f4SAlex Crichton         let (mut limiter, store) = store
265cc8d04f4SAlex Crichton             .as_context_mut()
266cc8d04f4SAlex Crichton             .0
267cc8d04f4SAlex Crichton             .validate_sync_resource_limiter_and_store_opaque()?;
268cc8d04f4SAlex Crichton         vm::assert_ready(Self::_new(store, limiter.as_mut(), ty))
269d4242001SAdam Bratschi-Kaye     }
270d4242001SAdam Bratschi-Kaye 
271d4242001SAdam Bratschi-Kaye     /// Async variant of [`Memory::new`]. You must use this variant with
272d4242001SAdam Bratschi-Kaye     /// [`Store`](`crate::Store`)s which have a
273d4242001SAdam Bratschi-Kaye     /// [`ResourceLimiterAsync`](`crate::ResourceLimiterAsync`).
274d4242001SAdam Bratschi-Kaye     ///
275d4242001SAdam Bratschi-Kaye     /// # Panics
276d4242001SAdam Bratschi-Kaye     ///
277d4242001SAdam Bratschi-Kaye     /// This function will panic when used with a non-async
278d4242001SAdam Bratschi-Kaye     /// [`Store`](`crate::Store`).
279d4242001SAdam Bratschi-Kaye     #[cfg(feature = "async")]
new_async(mut store: impl AsContextMut, ty: MemoryType) -> Result<Memory>280aa91737eSAlex Crichton     pub async fn new_async(mut store: impl AsContextMut, ty: MemoryType) -> Result<Memory> {
281155ea7fcSAlex Crichton         let (mut limiter, store) = store.as_context_mut().0.resource_limiter_and_store_opaque();
282155ea7fcSAlex Crichton         Self::_new(store, limiter.as_mut(), ty).await
283d4242001SAdam Bratschi-Kaye     }
284d4242001SAdam Bratschi-Kaye 
285d4242001SAdam Bratschi-Kaye     /// Helper function for attaching the memory to a "frankenstein" instance
_new( store: &mut StoreOpaque, limiter: Option<&mut StoreResourceLimiter<'_>>, ty: MemoryType, ) -> Result<Memory>286155ea7fcSAlex Crichton     async fn _new(
287155ea7fcSAlex Crichton         store: &mut StoreOpaque,
288155ea7fcSAlex Crichton         limiter: Option<&mut StoreResourceLimiter<'_>>,
289155ea7fcSAlex Crichton         ty: MemoryType,
290155ea7fcSAlex Crichton     ) -> Result<Memory> {
2911fcd0933SAlex Crichton         if ty.is_shared() {
2921fcd0933SAlex Crichton             bail!("shared memories must be created through `SharedMemory`")
2931fcd0933SAlex Crichton         }
2941fcd0933SAlex Crichton         Ok(generate_memory_export(store, limiter, &ty, None)
2951fcd0933SAlex Crichton             .await?
2961fcd0933SAlex Crichton             .unshared()
2971fcd0933SAlex Crichton             .unwrap())
298d4242001SAdam Bratschi-Kaye     }
299d4242001SAdam Bratschi-Kaye 
300d4242001SAdam Bratschi-Kaye     /// Returns the underlying type of this memory.
301d4242001SAdam Bratschi-Kaye     ///
302d4242001SAdam Bratschi-Kaye     /// # Panics
303d4242001SAdam Bratschi-Kaye     ///
304d4242001SAdam Bratschi-Kaye     /// Panics if this memory doesn't belong to `store`.
305d4242001SAdam Bratschi-Kaye     ///
306d4242001SAdam Bratschi-Kaye     /// # Examples
307d4242001SAdam Bratschi-Kaye     ///
308d4242001SAdam Bratschi-Kaye     /// ```
309d4242001SAdam Bratschi-Kaye     /// # use wasmtime::*;
31096e19700SNick Fitzgerald     /// # fn main() -> Result<()> {
311d4242001SAdam Bratschi-Kaye     /// let engine = Engine::default();
312d4242001SAdam Bratschi-Kaye     /// let mut store = Store::new(&engine, ());
313d4242001SAdam Bratschi-Kaye     /// let module = Module::new(&engine, "(module (memory (export \"mem\") 1))")?;
314d4242001SAdam Bratschi-Kaye     /// let instance = Instance::new(&mut store, &module, &[])?;
315d4242001SAdam Bratschi-Kaye     /// let memory = instance.get_memory(&mut store, "mem").unwrap();
316d4242001SAdam Bratschi-Kaye     /// let ty = memory.ty(&store);
317d4242001SAdam Bratschi-Kaye     /// assert_eq!(ty.minimum(), 1);
318d4242001SAdam Bratschi-Kaye     /// # Ok(())
319d4242001SAdam Bratschi-Kaye     /// # }
320d4242001SAdam Bratschi-Kaye     /// ```
ty(&self, store: impl AsContext) -> MemoryType321d4242001SAdam Bratschi-Kaye     pub fn ty(&self, store: impl AsContext) -> MemoryType {
322d4242001SAdam Bratschi-Kaye         let store = store.as_context();
3230e9a691dSAlex Crichton         MemoryType::from_wasmtime_memory(self.wasmtime_ty(store.0))
324d4242001SAdam Bratschi-Kaye     }
325d4242001SAdam Bratschi-Kaye 
326d4242001SAdam Bratschi-Kaye     /// Safely reads memory contents at the given offset into a buffer.
327d4242001SAdam Bratschi-Kaye     ///
328d4242001SAdam Bratschi-Kaye     /// The entire buffer will be filled.
329d4242001SAdam Bratschi-Kaye     ///
330d4242001SAdam Bratschi-Kaye     /// If `offset + buffer.len()` exceed the current memory capacity, then the
331d4242001SAdam Bratschi-Kaye     /// buffer is left untouched and a [`MemoryAccessError`] is returned.
332d4242001SAdam Bratschi-Kaye     ///
333d4242001SAdam Bratschi-Kaye     /// # Panics
334d4242001SAdam Bratschi-Kaye     ///
335d4242001SAdam Bratschi-Kaye     /// Panics if this memory doesn't belong to `store`.
read( &self, store: impl AsContext, offset: usize, buffer: &mut [u8], ) -> Result<(), MemoryAccessError>336d4242001SAdam Bratschi-Kaye     pub fn read(
337d4242001SAdam Bratschi-Kaye         &self,
338d4242001SAdam Bratschi-Kaye         store: impl AsContext,
339d4242001SAdam Bratschi-Kaye         offset: usize,
340d4242001SAdam Bratschi-Kaye         buffer: &mut [u8],
341d4242001SAdam Bratschi-Kaye     ) -> Result<(), MemoryAccessError> {
342d4242001SAdam Bratschi-Kaye         let store = store.as_context();
343d4242001SAdam Bratschi-Kaye         let slice = self
344d4242001SAdam Bratschi-Kaye             .data(&store)
345d4242001SAdam Bratschi-Kaye             .get(offset..)
346d4242001SAdam Bratschi-Kaye             .and_then(|s| s.get(..buffer.len()))
347d4242001SAdam Bratschi-Kaye             .ok_or(MemoryAccessError { _private: () })?;
348d4242001SAdam Bratschi-Kaye         buffer.copy_from_slice(slice);
349d4242001SAdam Bratschi-Kaye         Ok(())
350d4242001SAdam Bratschi-Kaye     }
351d4242001SAdam Bratschi-Kaye 
352d4242001SAdam Bratschi-Kaye     /// Safely writes contents of a buffer to this memory at the given offset.
353d4242001SAdam Bratschi-Kaye     ///
354d4242001SAdam Bratschi-Kaye     /// If the `offset + buffer.len()` exceeds the current memory capacity, then
355d4242001SAdam Bratschi-Kaye     /// none of the buffer is written to memory and a [`MemoryAccessError`] is
356d4242001SAdam Bratschi-Kaye     /// returned.
357d4242001SAdam Bratschi-Kaye     ///
358d4242001SAdam Bratschi-Kaye     /// # Panics
359d4242001SAdam Bratschi-Kaye     ///
360d4242001SAdam Bratschi-Kaye     /// Panics if this memory doesn't belong to `store`.
write( &self, mut store: impl AsContextMut, offset: usize, buffer: &[u8], ) -> Result<(), MemoryAccessError>361d4242001SAdam Bratschi-Kaye     pub fn write(
362d4242001SAdam Bratschi-Kaye         &self,
363d4242001SAdam Bratschi-Kaye         mut store: impl AsContextMut,
364d4242001SAdam Bratschi-Kaye         offset: usize,
365d4242001SAdam Bratschi-Kaye         buffer: &[u8],
366d4242001SAdam Bratschi-Kaye     ) -> Result<(), MemoryAccessError> {
367d4242001SAdam Bratschi-Kaye         let mut context = store.as_context_mut();
368d4242001SAdam Bratschi-Kaye         self.data_mut(&mut context)
369d4242001SAdam Bratschi-Kaye             .get_mut(offset..)
370d4242001SAdam Bratschi-Kaye             .and_then(|s| s.get_mut(..buffer.len()))
371d4242001SAdam Bratschi-Kaye             .ok_or(MemoryAccessError { _private: () })?
372d4242001SAdam Bratschi-Kaye             .copy_from_slice(buffer);
373d4242001SAdam Bratschi-Kaye         Ok(())
374d4242001SAdam Bratschi-Kaye     }
375d4242001SAdam Bratschi-Kaye 
376d4242001SAdam Bratschi-Kaye     /// Returns this memory as a native Rust slice.
377d4242001SAdam Bratschi-Kaye     ///
378d4242001SAdam Bratschi-Kaye     /// Note that this method will consider the entire store context provided as
379d4242001SAdam Bratschi-Kaye     /// borrowed for the duration of the lifetime of the returned slice.
380d4242001SAdam Bratschi-Kaye     ///
381d4242001SAdam Bratschi-Kaye     /// # Panics
382d4242001SAdam Bratschi-Kaye     ///
383d4242001SAdam Bratschi-Kaye     /// Panics if this memory doesn't belong to `store`.
data<'a, T: 'static>(&self, store: impl Into<StoreContext<'a, T>>) -> &'a [u8]384f81c0dc0SAlex Crichton     pub fn data<'a, T: 'static>(&self, store: impl Into<StoreContext<'a, T>>) -> &'a [u8] {
385d4242001SAdam Bratschi-Kaye         unsafe {
386d4242001SAdam Bratschi-Kaye             let store = store.into();
3870e9a691dSAlex Crichton             let definition = store[self.instance].memory(self.index);
388d4242001SAdam Bratschi-Kaye             debug_assert!(!self.ty(store).is_shared());
389b86b9682SAlex Crichton             slice::from_raw_parts(definition.base.as_ptr(), definition.current_length())
390d4242001SAdam Bratschi-Kaye         }
391d4242001SAdam Bratschi-Kaye     }
392d4242001SAdam Bratschi-Kaye 
393d4242001SAdam Bratschi-Kaye     /// Returns this memory as a native Rust mutable slice.
394d4242001SAdam Bratschi-Kaye     ///
395d4242001SAdam Bratschi-Kaye     /// Note that this method will consider the entire store context provided as
396d4242001SAdam Bratschi-Kaye     /// borrowed for the duration of the lifetime of the returned slice.
397d4242001SAdam Bratschi-Kaye     ///
398d4242001SAdam Bratschi-Kaye     /// # Panics
399d4242001SAdam Bratschi-Kaye     ///
400d4242001SAdam Bratschi-Kaye     /// Panics if this memory doesn't belong to `store`.
data_mut<'a, T: 'static>( &self, store: impl Into<StoreContextMut<'a, T>>, ) -> &'a mut [u8]401f81c0dc0SAlex Crichton     pub fn data_mut<'a, T: 'static>(
402f81c0dc0SAlex Crichton         &self,
403f81c0dc0SAlex Crichton         store: impl Into<StoreContextMut<'a, T>>,
404f81c0dc0SAlex Crichton     ) -> &'a mut [u8] {
405d4242001SAdam Bratschi-Kaye         unsafe {
406d4242001SAdam Bratschi-Kaye             let store = store.into();
4070e9a691dSAlex Crichton             let definition = store[self.instance].memory(self.index);
408d4242001SAdam Bratschi-Kaye             debug_assert!(!self.ty(store).is_shared());
409b86b9682SAlex Crichton             slice::from_raw_parts_mut(definition.base.as_ptr(), definition.current_length())
410d4242001SAdam Bratschi-Kaye         }
411d4242001SAdam Bratschi-Kaye     }
412d4242001SAdam Bratschi-Kaye 
413d4242001SAdam Bratschi-Kaye     /// Same as [`Memory::data_mut`], but also returns the `T` from the
414d4242001SAdam Bratschi-Kaye     /// [`StoreContextMut`].
415d4242001SAdam Bratschi-Kaye     ///
416d4242001SAdam Bratschi-Kaye     /// This method can be used when you want to simultaneously work with the
417d4242001SAdam Bratschi-Kaye     /// `T` in the store as well as the memory behind this [`Memory`]. Using
418d4242001SAdam Bratschi-Kaye     /// [`Memory::data_mut`] would consider the entire store borrowed, whereas
419d4242001SAdam Bratschi-Kaye     /// this method allows the Rust compiler to see that the borrow of this
420d4242001SAdam Bratschi-Kaye     /// memory and the borrow of `T` are disjoint.
421d4242001SAdam Bratschi-Kaye     ///
422d4242001SAdam Bratschi-Kaye     /// # Panics
423d4242001SAdam Bratschi-Kaye     ///
424d4242001SAdam Bratschi-Kaye     /// Panics if this memory doesn't belong to `store`.
data_and_store_mut<'a, T: 'static>( &self, store: impl Into<StoreContextMut<'a, T>>, ) -> (&'a mut [u8], &'a mut T)425f81c0dc0SAlex Crichton     pub fn data_and_store_mut<'a, T: 'static>(
426d4242001SAdam Bratschi-Kaye         &self,
427d4242001SAdam Bratschi-Kaye         store: impl Into<StoreContextMut<'a, T>>,
428d4242001SAdam Bratschi-Kaye     ) -> (&'a mut [u8], &'a mut T) {
429d4242001SAdam Bratschi-Kaye         // Note the unsafety here. Our goal is to simultaneously borrow the
430d4242001SAdam Bratschi-Kaye         // memory and custom data from `store`, and the store it's connected
431d4242001SAdam Bratschi-Kaye         // to. Rust will not let us do that, however, because we must call two
432d4242001SAdam Bratschi-Kaye         // separate methods (both of which borrow the whole `store`) and one of
433d4242001SAdam Bratschi-Kaye         // our borrows is mutable (the custom data).
434d4242001SAdam Bratschi-Kaye         //
435d4242001SAdam Bratschi-Kaye         // This operation, however, is safe because these borrows do not overlap
436d4242001SAdam Bratschi-Kaye         // and in the process of borrowing them mutability doesn't actually
437d4242001SAdam Bratschi-Kaye         // touch anything. This is akin to mutably borrowing two indices in an
438d4242001SAdam Bratschi-Kaye         // array, which is safe so long as the indices are separate.
439d4242001SAdam Bratschi-Kaye         unsafe {
440d4242001SAdam Bratschi-Kaye             let mut store = store.into();
441d4242001SAdam Bratschi-Kaye             let data = &mut *(store.data_mut() as *mut T);
442d4242001SAdam Bratschi-Kaye             (self.data_mut(store), data)
443d4242001SAdam Bratschi-Kaye         }
444d4242001SAdam Bratschi-Kaye     }
445d4242001SAdam Bratschi-Kaye 
446d4242001SAdam Bratschi-Kaye     /// Returns the base pointer, in the host's address space, that the memory
447d4242001SAdam Bratschi-Kaye     /// is located at.
448d4242001SAdam Bratschi-Kaye     ///
449d4242001SAdam Bratschi-Kaye     /// For more information and examples see the documentation on the
450d4242001SAdam Bratschi-Kaye     /// [`Memory`] type.
451d4242001SAdam Bratschi-Kaye     ///
452d4242001SAdam Bratschi-Kaye     /// # Panics
453d4242001SAdam Bratschi-Kaye     ///
454d4242001SAdam Bratschi-Kaye     /// Panics if this memory doesn't belong to `store`.
data_ptr(&self, store: impl AsContext) -> *mut u8455d4242001SAdam Bratschi-Kaye     pub fn data_ptr(&self, store: impl AsContext) -> *mut u8 {
4560e9a691dSAlex Crichton         store.as_context()[self.instance]
4570e9a691dSAlex Crichton             .memory(self.index)
4580e9a691dSAlex Crichton             .base
4590e9a691dSAlex Crichton             .as_ptr()
460d4242001SAdam Bratschi-Kaye     }
461d4242001SAdam Bratschi-Kaye 
462d4242001SAdam Bratschi-Kaye     /// Returns the byte length of this memory.
463d4242001SAdam Bratschi-Kaye     ///
464bdd78422SNick Fitzgerald     /// WebAssembly memories are made up of a whole number of pages, so the byte
465bdd78422SNick Fitzgerald     /// size returned will always be a multiple of this memory's page size. Note
466bdd78422SNick Fitzgerald     /// that different Wasm memories may have different page sizes. You can get
467bdd78422SNick Fitzgerald     /// a memory's page size via the [`Memory::page_size`] method.
468bdd78422SNick Fitzgerald     ///
469bdd78422SNick Fitzgerald     /// By default the page size is 64KiB (aka `0x10000`, `2**16`, `1<<16`, or
470bdd78422SNick Fitzgerald     /// `65536`) but [the custom-page-sizes proposal] allows a memory to opt
471bdd78422SNick Fitzgerald     /// into a page size of `1`. Future extensions might allow any power of two
472bdd78422SNick Fitzgerald     /// as a page size.
473bdd78422SNick Fitzgerald     ///
474bdd78422SNick Fitzgerald     /// [the custom-page-sizes proposal]: https://github.com/WebAssembly/custom-page-sizes
475d4242001SAdam Bratschi-Kaye     ///
476d4242001SAdam Bratschi-Kaye     /// For more information and examples see the documentation on the
477d4242001SAdam Bratschi-Kaye     /// [`Memory`] type.
478d4242001SAdam Bratschi-Kaye     ///
479d4242001SAdam Bratschi-Kaye     /// # Panics
480d4242001SAdam Bratschi-Kaye     ///
481d4242001SAdam Bratschi-Kaye     /// Panics if this memory doesn't belong to `store`.
data_size(&self, store: impl AsContext) -> usize482d4242001SAdam Bratschi-Kaye     pub fn data_size(&self, store: impl AsContext) -> usize {
483d4242001SAdam Bratschi-Kaye         self.internal_data_size(store.as_context().0)
484d4242001SAdam Bratschi-Kaye     }
485d4242001SAdam Bratschi-Kaye 
internal_data_size(&self, store: &StoreOpaque) -> usize486d4242001SAdam Bratschi-Kaye     pub(crate) fn internal_data_size(&self, store: &StoreOpaque) -> usize {
4870e9a691dSAlex Crichton         store[self.instance].memory(self.index).current_length()
488d4242001SAdam Bratschi-Kaye     }
489d4242001SAdam Bratschi-Kaye 
490bdd78422SNick Fitzgerald     /// Returns the size, in units of pages, of this Wasm memory.
491bdd78422SNick Fitzgerald     ///
492bdd78422SNick Fitzgerald     /// WebAssembly memories are made up of a whole number of pages, so the byte
493bdd78422SNick Fitzgerald     /// size returned will always be a multiple of this memory's page size. Note
494bdd78422SNick Fitzgerald     /// that different Wasm memories may have different page sizes. You can get
495bdd78422SNick Fitzgerald     /// a memory's page size via the [`Memory::page_size`] method.
496bdd78422SNick Fitzgerald     ///
497bdd78422SNick Fitzgerald     /// By default the page size is 64KiB (aka `0x10000`, `2**16`, `1<<16`, or
498bdd78422SNick Fitzgerald     /// `65536`) but [the custom-page-sizes proposal] allows a memory to opt
499bdd78422SNick Fitzgerald     /// into a page size of `1`. Future extensions might allow any power of two
500bdd78422SNick Fitzgerald     /// as a page size.
501bdd78422SNick Fitzgerald     ///
502bdd78422SNick Fitzgerald     /// [the custom-page-sizes proposal]: https://github.com/WebAssembly/custom-page-sizes
503d4242001SAdam Bratschi-Kaye     ///
504d4242001SAdam Bratschi-Kaye     /// # Panics
505d4242001SAdam Bratschi-Kaye     ///
506d4242001SAdam Bratschi-Kaye     /// Panics if this memory doesn't belong to `store`.
size(&self, store: impl AsContext) -> u64507d4242001SAdam Bratschi-Kaye     pub fn size(&self, store: impl AsContext) -> u64 {
508d4242001SAdam Bratschi-Kaye         self.internal_size(store.as_context().0)
509d4242001SAdam Bratschi-Kaye     }
510d4242001SAdam Bratschi-Kaye 
internal_size(&self, store: &StoreOpaque) -> u64511d4242001SAdam Bratschi-Kaye     pub(crate) fn internal_size(&self, store: &StoreOpaque) -> u64 {
512bdd78422SNick Fitzgerald         let byte_size = self.internal_data_size(store);
513bdd78422SNick Fitzgerald         let page_size = usize::try_from(self._page_size(store)).unwrap();
514bdd78422SNick Fitzgerald         u64::try_from(byte_size / page_size).unwrap()
515bdd78422SNick Fitzgerald     }
516bdd78422SNick Fitzgerald 
517bdd78422SNick Fitzgerald     /// Returns the size of a page, in bytes, for this memory.
518bdd78422SNick Fitzgerald     ///
519bdd78422SNick Fitzgerald     /// WebAssembly memories are made up of a whole number of pages, so the byte
520bdd78422SNick Fitzgerald     /// size (as returned by [`Memory::data_size`]) will always be a multiple of
521bdd78422SNick Fitzgerald     /// their page size. Different Wasm memories may have different page sizes.
522bdd78422SNick Fitzgerald     ///
523bdd78422SNick Fitzgerald     /// By default this is 64KiB (aka `0x10000`, `2**16`, `1<<16`, or `65536`)
524bdd78422SNick Fitzgerald     /// but [the custom-page-sizes proposal] allows opting into a page size of
525bdd78422SNick Fitzgerald     /// `1`. Future extensions might allow any power of two as a page size.
526bdd78422SNick Fitzgerald     ///
527bdd78422SNick Fitzgerald     /// [the custom-page-sizes proposal]: https://github.com/WebAssembly/custom-page-sizes
page_size(&self, store: impl AsContext) -> u64528bdd78422SNick Fitzgerald     pub fn page_size(&self, store: impl AsContext) -> u64 {
529bdd78422SNick Fitzgerald         self._page_size(store.as_context().0)
530bdd78422SNick Fitzgerald     }
531bdd78422SNick Fitzgerald 
_page_size(&self, store: &StoreOpaque) -> u64532bdd78422SNick Fitzgerald     pub(crate) fn _page_size(&self, store: &StoreOpaque) -> u64 {
5330e9a691dSAlex Crichton         self.wasmtime_ty(store).page_size()
534bdd78422SNick Fitzgerald     }
535bdd78422SNick Fitzgerald 
536bdd78422SNick Fitzgerald     /// Returns the log2 of this memory's page size, in bytes.
537bdd78422SNick Fitzgerald     ///
538bdd78422SNick Fitzgerald     /// WebAssembly memories are made up of a whole number of pages, so the byte
539bdd78422SNick Fitzgerald     /// size (as returned by [`Memory::data_size`]) will always be a multiple of
540bdd78422SNick Fitzgerald     /// their page size. Different Wasm memories may have different page sizes.
541bdd78422SNick Fitzgerald     ///
542bdd78422SNick Fitzgerald     /// By default the page size is 64KiB (aka `0x10000`, `2**16`, `1<<16`, or
543bdd78422SNick Fitzgerald     /// `65536`) but [the custom-page-sizes proposal] allows opting into a page
544bdd78422SNick Fitzgerald     /// size of `1`. Future extensions might allow any power of two as a page
545bdd78422SNick Fitzgerald     /// size.
546bdd78422SNick Fitzgerald     ///
547bdd78422SNick Fitzgerald     /// [the custom-page-sizes proposal]: https://github.com/WebAssembly/custom-page-sizes
page_size_log2(&self, store: impl AsContext) -> u8548bdd78422SNick Fitzgerald     pub fn page_size_log2(&self, store: impl AsContext) -> u8 {
549bdd78422SNick Fitzgerald         self._page_size_log2(store.as_context().0)
550bdd78422SNick Fitzgerald     }
551bdd78422SNick Fitzgerald 
_page_size_log2(&self, store: &StoreOpaque) -> u8552bdd78422SNick Fitzgerald     pub(crate) fn _page_size_log2(&self, store: &StoreOpaque) -> u8 {
5530e9a691dSAlex Crichton         self.wasmtime_ty(store).page_size_log2
554d4242001SAdam Bratschi-Kaye     }
555d4242001SAdam Bratschi-Kaye 
556d4242001SAdam Bratschi-Kaye     /// Grows this WebAssembly memory by `delta` pages.
557d4242001SAdam Bratschi-Kaye     ///
558d4242001SAdam Bratschi-Kaye     /// This will attempt to add `delta` more pages of memory on to the end of
559d4242001SAdam Bratschi-Kaye     /// this `Memory` instance. If successful this may relocate the memory and
560d4242001SAdam Bratschi-Kaye     /// cause [`Memory::data_ptr`] to return a new value. Additionally any
561d4242001SAdam Bratschi-Kaye     /// unsafely constructed slices into this memory may no longer be valid.
562d4242001SAdam Bratschi-Kaye     ///
563d4242001SAdam Bratschi-Kaye     /// On success returns the number of pages this memory previously had
564d4242001SAdam Bratschi-Kaye     /// before the growth succeeded.
565d4242001SAdam Bratschi-Kaye     ///
566bdd78422SNick Fitzgerald     /// Note that, by default, a WebAssembly memory's page size is 64KiB (aka
567bdd78422SNick Fitzgerald     /// 65536 or 2<sup>16</sup>). The [custom-page-sizes proposal] allows Wasm
568bdd78422SNick Fitzgerald     /// memories to opt into a page size of one byte (and this may be further
569bdd78422SNick Fitzgerald     /// relaxed to any power of two in a future extension).
570bdd78422SNick Fitzgerald     ///
571bdd78422SNick Fitzgerald     /// [custom-page-sizes proposal]: https://github.com/WebAssembly/custom-page-sizes
572bdd78422SNick Fitzgerald     ///
573d4242001SAdam Bratschi-Kaye     /// # Errors
574d4242001SAdam Bratschi-Kaye     ///
575d4242001SAdam Bratschi-Kaye     /// Returns an error if memory could not be grown, for example if it exceeds
576d4242001SAdam Bratschi-Kaye     /// the maximum limits of this memory. A
577d4242001SAdam Bratschi-Kaye     /// [`ResourceLimiter`](crate::ResourceLimiter) is another example of
578d4242001SAdam Bratschi-Kaye     /// preventing a memory to grow.
579d4242001SAdam Bratschi-Kaye     ///
580cc8d04f4SAlex Crichton     /// This function will return an error if the [`Store`](`crate::Store`) has
581cc8d04f4SAlex Crichton     /// a [`ResourceLimiterAsync`](`crate::ResourceLimiterAsync`) (see also:
582cc8d04f4SAlex Crichton     /// [`Store::limiter_async`](`crate::Store::limiter_async`). When using an
583cc8d04f4SAlex Crichton     /// async resource limiter, use [`Memory::grow_async`] instead.
584cc8d04f4SAlex Crichton     ///
585d4242001SAdam Bratschi-Kaye     /// # Panics
586d4242001SAdam Bratschi-Kaye     ///
587d4242001SAdam Bratschi-Kaye     /// Panics if this memory doesn't belong to `store`.
588d4242001SAdam Bratschi-Kaye     ///
589d4242001SAdam Bratschi-Kaye     /// # Examples
590d4242001SAdam Bratschi-Kaye     ///
591d4242001SAdam Bratschi-Kaye     /// ```
592d4242001SAdam Bratschi-Kaye     /// # use wasmtime::*;
59396e19700SNick Fitzgerald     /// # fn main() -> Result<()> {
594d4242001SAdam Bratschi-Kaye     /// let engine = Engine::default();
595d4242001SAdam Bratschi-Kaye     /// let mut store = Store::new(&engine, ());
596d4242001SAdam Bratschi-Kaye     /// let module = Module::new(&engine, "(module (memory (export \"mem\") 1 2))")?;
597d4242001SAdam Bratschi-Kaye     /// let instance = Instance::new(&mut store, &module, &[])?;
598d4242001SAdam Bratschi-Kaye     /// let memory = instance.get_memory(&mut store, "mem").unwrap();
599d4242001SAdam Bratschi-Kaye     ///
600d4242001SAdam Bratschi-Kaye     /// assert_eq!(memory.size(&store), 1);
601d4242001SAdam Bratschi-Kaye     /// assert_eq!(memory.grow(&mut store, 1)?, 1);
602d4242001SAdam Bratschi-Kaye     /// assert_eq!(memory.size(&store), 2);
603d4242001SAdam Bratschi-Kaye     /// assert!(memory.grow(&mut store, 1).is_err());
604d4242001SAdam Bratschi-Kaye     /// assert_eq!(memory.size(&store), 2);
605d4242001SAdam Bratschi-Kaye     /// assert_eq!(memory.grow(&mut store, 0)?, 2);
606d4242001SAdam Bratschi-Kaye     /// # Ok(())
607d4242001SAdam Bratschi-Kaye     /// # }
608d4242001SAdam Bratschi-Kaye     /// ```
grow(&self, mut store: impl AsContextMut, delta: u64) -> Result<u64>609d4242001SAdam Bratschi-Kaye     pub fn grow(&self, mut store: impl AsContextMut, delta: u64) -> Result<u64> {
610d4242001SAdam Bratschi-Kaye         let store = store.as_context_mut().0;
611cc8d04f4SAlex Crichton         let (mut limiter, store) = store.validate_sync_resource_limiter_and_store_opaque()?;
612cc8d04f4SAlex Crichton         vm::assert_ready(self._grow(store, limiter.as_mut(), delta))
613d4242001SAdam Bratschi-Kaye     }
614d4242001SAdam Bratschi-Kaye 
615d4242001SAdam Bratschi-Kaye     /// Async variant of [`Memory::grow`]. Required when using a
616d4242001SAdam Bratschi-Kaye     /// [`ResourceLimiterAsync`](`crate::ResourceLimiterAsync`).
617d4242001SAdam Bratschi-Kaye     ///
618d4242001SAdam Bratschi-Kaye     /// # Panics
619d4242001SAdam Bratschi-Kaye     ///
620d4242001SAdam Bratschi-Kaye     /// This function will panic when used with a non-async
621d4242001SAdam Bratschi-Kaye     /// [`Store`](`crate::Store`).
622d4242001SAdam Bratschi-Kaye     #[cfg(feature = "async")]
grow_async(&self, mut store: impl AsContextMut, delta: u64) -> Result<u64>623aa91737eSAlex Crichton     pub async fn grow_async(&self, mut store: impl AsContextMut, delta: u64) -> Result<u64> {
624f881ab24SAlex Crichton         let store = store.as_context_mut();
625f881ab24SAlex Crichton         let (mut limiter, store) = store.0.resource_limiter_and_store_opaque();
626f881ab24SAlex Crichton         self._grow(store, limiter.as_mut(), delta).await
627d4242001SAdam Bratschi-Kaye     }
628d4242001SAdam Bratschi-Kaye 
_grow( &self, store: &mut StoreOpaque, limiter: Option<&mut StoreResourceLimiter<'_>>, delta: u64, ) -> Result<u64>629f881ab24SAlex Crichton     async fn _grow(
630ab76f64bSAlex Crichton         &self,
631f881ab24SAlex Crichton         store: &mut StoreOpaque,
632f881ab24SAlex Crichton         limiter: Option<&mut StoreResourceLimiter<'_>>,
633f881ab24SAlex Crichton         delta: u64,
634f881ab24SAlex Crichton     ) -> Result<u64> {
635f881ab24SAlex Crichton         let result = self
636f881ab24SAlex Crichton             .instance
6372b832281SAlex Crichton             .get_mut(store)
638f881ab24SAlex Crichton             .memory_grow(limiter, self.index, delta)
639f881ab24SAlex Crichton             .await?;
640f881ab24SAlex Crichton         match result {
641f881ab24SAlex Crichton             Some(size) => {
642f881ab24SAlex Crichton                 let page_size = self.wasmtime_ty(store).page_size();
643f881ab24SAlex Crichton                 Ok(u64::try_from(size).unwrap() / page_size)
644f881ab24SAlex Crichton             }
645557cc2d6SAlex Crichton             None => bail!("failed to grow memory by `{delta}`"),
646f881ab24SAlex Crichton         }
647d4242001SAdam Bratschi-Kaye     }
648d4242001SAdam Bratschi-Kaye 
6491fcd0933SAlex Crichton     /// Creates a new memory from its raw component parts.
6501fcd0933SAlex Crichton     ///
6511fcd0933SAlex Crichton     /// # Safety
6521fcd0933SAlex Crichton     ///
6531fcd0933SAlex Crichton     /// The caller must ensure that the memory pointed to by `instance` and
6541fcd0933SAlex Crichton     /// `index` is not a shared memory. For that `SharedMemory` must be used
6551fcd0933SAlex Crichton     /// instead.
from_raw(instance: StoreInstanceId, index: DefinedMemoryIndex) -> Memory6561fcd0933SAlex Crichton     pub(crate) unsafe fn from_raw(instance: StoreInstanceId, index: DefinedMemoryIndex) -> Memory {
6572b832281SAlex Crichton         Memory { instance, index }
658d4242001SAdam Bratschi-Kaye     }
659d4242001SAdam Bratschi-Kaye 
wasmtime_ty<'a>(&self, store: &'a StoreOpaque) -> &'a wasmtime_environ::Memory6600e9a691dSAlex Crichton     pub(crate) fn wasmtime_ty<'a>(&self, store: &'a StoreOpaque) -> &'a wasmtime_environ::Memory {
6610e9a691dSAlex Crichton         let module = store[self.instance].env_module();
6620e9a691dSAlex Crichton         let index = module.memory_index(self.index);
6630e9a691dSAlex Crichton         &module.memories[index]
664d4242001SAdam Bratschi-Kaye     }
665d4242001SAdam Bratschi-Kaye 
vmimport(&self, store: &StoreOpaque) -> crate::runtime::vm::VMMemoryImport66672004aadSNick Fitzgerald     pub(crate) fn vmimport(&self, store: &StoreOpaque) -> crate::runtime::vm::VMMemoryImport {
6671fcd0933SAlex Crichton         store[self.instance].get_defined_memory_vmimport(self.index)
668d4242001SAdam Bratschi-Kaye     }
669d4242001SAdam Bratschi-Kaye 
comes_from_same_store(&self, store: &StoreOpaque) -> bool670d4242001SAdam Bratschi-Kaye     pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool {
6710e9a691dSAlex Crichton         store.id() == self.instance.store_id()
672d4242001SAdam Bratschi-Kaye     }
673d4242001SAdam Bratschi-Kaye 
674*7051ab30SChris Fallin     /// Returns a stable identifier for this memory within its store.
675*7051ab30SChris Fallin     ///
676*7051ab30SChris Fallin     /// This allows distinguishing memories when introspecting them
677*7051ab30SChris Fallin     /// e.g. via debug APIs.
678*7051ab30SChris Fallin     #[cfg(feature = "debug")]
debug_index_in_store(&self) -> u64679*7051ab30SChris Fallin     pub fn debug_index_in_store(&self) -> u64 {
680*7051ab30SChris Fallin         u64::from(self.instance.instance().as_u32()) << 32 | u64::from(self.index.as_u32())
681*7051ab30SChris Fallin     }
682*7051ab30SChris Fallin 
683d4242001SAdam Bratschi-Kaye     /// Get a stable hash key for this memory.
684d4242001SAdam Bratschi-Kaye     ///
685d4242001SAdam Bratschi-Kaye     /// Even if the same underlying memory definition is added to the
686d4242001SAdam Bratschi-Kaye     /// `StoreData` multiple times and becomes multiple `wasmtime::Memory`s,
687d4242001SAdam Bratschi-Kaye     /// this hash key will be consistent across all of these memories.
68894f21bc9SAlex Crichton     #[cfg(feature = "coredump")]
hash_key(&self, store: &StoreOpaque) -> impl core::hash::Hash + Eq + use<>689de1ad347SAlex Crichton     pub(crate) fn hash_key(&self, store: &StoreOpaque) -> impl core::hash::Hash + Eq + use<> {
690132a1a53SAlex Crichton         store[self.instance].memory_ptr(self.index).as_ptr().addr()
691d4242001SAdam Bratschi-Kaye     }
692d4242001SAdam Bratschi-Kaye }
693d4242001SAdam Bratschi-Kaye 
694d4242001SAdam Bratschi-Kaye /// A linear memory. This trait provides an interface for raw memory buffers
695d4242001SAdam Bratschi-Kaye /// which are used by wasmtime, e.g. inside ['Memory']. Such buffers are in
696d4242001SAdam Bratschi-Kaye /// principle not thread safe. By implementing this trait together with
697d4242001SAdam Bratschi-Kaye /// MemoryCreator, one can supply wasmtime with custom allocated host managed
698d4242001SAdam Bratschi-Kaye /// memory.
699d4242001SAdam Bratschi-Kaye ///
700d4242001SAdam Bratschi-Kaye /// # Safety
701d4242001SAdam Bratschi-Kaye ///
702d4242001SAdam Bratschi-Kaye /// The memory should be page aligned and a multiple of page size.
703d4242001SAdam Bratschi-Kaye /// To prevent possible silent overflows, the memory should be protected by a
704d4242001SAdam Bratschi-Kaye /// guard page.  Additionally the safety concerns explained in ['Memory'], for
705d4242001SAdam Bratschi-Kaye /// accessing the memory apply here as well.
706d4242001SAdam Bratschi-Kaye ///
707f2ab725eSNick Fitzgerald /// Note that this is a relatively advanced feature and it is recommended to be
708f2ab725eSNick Fitzgerald /// familiar with wasmtime runtime code to use it.
709d4242001SAdam Bratschi-Kaye pub unsafe trait LinearMemory: Send + Sync + 'static {
710d4242001SAdam Bratschi-Kaye     /// Returns the number of allocated bytes which are accessible at this time.
byte_size(&self) -> usize711d4242001SAdam Bratschi-Kaye     fn byte_size(&self) -> usize;
712d4242001SAdam Bratschi-Kaye 
713f50d8d93SAlex Crichton     /// Returns byte capacity of this linear memory's current allocation.
714d4242001SAdam Bratschi-Kaye     ///
715f50d8d93SAlex Crichton     /// Growth up to this value should not relocate the linear memory base
716f50d8d93SAlex Crichton     /// pointer.
byte_capacity(&self) -> usize717f50d8d93SAlex Crichton     fn byte_capacity(&self) -> usize;
718d4242001SAdam Bratschi-Kaye 
719d4242001SAdam Bratschi-Kaye     /// Grows this memory to have the `new_size`, in bytes, specified.
720d4242001SAdam Bratschi-Kaye     ///
721d4242001SAdam Bratschi-Kaye     /// Returns `Err` if memory can't be grown by the specified amount
722d4242001SAdam Bratschi-Kaye     /// of bytes. The error may be downcastable to `std::io::Error`.
723d4242001SAdam Bratschi-Kaye     /// Returns `Ok` if memory was grown successfully.
grow_to(&mut self, new_size: usize) -> Result<()>724d4242001SAdam Bratschi-Kaye     fn grow_to(&mut self, new_size: usize) -> Result<()>;
725d4242001SAdam Bratschi-Kaye 
726d4242001SAdam Bratschi-Kaye     /// Return the allocated memory as a mutable pointer to u8.
as_ptr(&self) -> *mut u8727d4242001SAdam Bratschi-Kaye     fn as_ptr(&self) -> *mut u8;
728d4242001SAdam Bratschi-Kaye }
729d4242001SAdam Bratschi-Kaye 
730d4242001SAdam Bratschi-Kaye /// A memory creator. Can be used to provide a memory creator
731d4242001SAdam Bratschi-Kaye /// to wasmtime which supplies host managed memory.
732d4242001SAdam Bratschi-Kaye ///
733d4242001SAdam Bratschi-Kaye /// # Safety
734d4242001SAdam Bratschi-Kaye ///
735d4242001SAdam Bratschi-Kaye /// This trait is unsafe, as the memory safety depends on proper implementation
736d4242001SAdam Bratschi-Kaye /// of memory management. Memories created by the MemoryCreator should always be
737d4242001SAdam Bratschi-Kaye /// treated as owned by wasmtime instance, and any modification of them outside
738d4242001SAdam Bratschi-Kaye /// of wasmtime invoked routines is unsafe and may lead to corruption.
739d4242001SAdam Bratschi-Kaye ///
740f2ab725eSNick Fitzgerald /// Note that this is a relatively advanced feature and it is recommended to be
741f2ab725eSNick Fitzgerald /// familiar with Wasmtime runtime code to use it.
742d4242001SAdam Bratschi-Kaye pub unsafe trait MemoryCreator: Send + Sync {
743d4242001SAdam Bratschi-Kaye     /// Create a new `LinearMemory` object from the specified parameters.
744d4242001SAdam Bratschi-Kaye     ///
745d4242001SAdam Bratschi-Kaye     /// The type of memory being created is specified by `ty` which indicates
746d4242001SAdam Bratschi-Kaye     /// both the minimum and maximum size, in wasm pages. The minimum and
747d4242001SAdam Bratschi-Kaye     /// maximum sizes, in bytes, are also specified as parameters to avoid
748d4242001SAdam Bratschi-Kaye     /// integer conversion if desired.
749d4242001SAdam Bratschi-Kaye     ///
750d4242001SAdam Bratschi-Kaye     /// The `reserved_size_in_bytes` value indicates the expected size of the
751d4242001SAdam Bratschi-Kaye     /// reservation that is to be made for this memory. If this value is `None`
752d4242001SAdam Bratschi-Kaye     /// than the implementation is free to allocate memory as it sees fit. If
753d4242001SAdam Bratschi-Kaye     /// the value is `Some`, however, then the implementation is expected to
754d4242001SAdam Bratschi-Kaye     /// reserve that many bytes for the memory's allocation, plus the guard
755d4242001SAdam Bratschi-Kaye     /// size at the end. Note that this reservation need only be a virtual
756d4242001SAdam Bratschi-Kaye     /// memory reservation, physical memory does not need to be allocated
757d4242001SAdam Bratschi-Kaye     /// immediately. In this case `grow` should never move the base pointer and
758d4242001SAdam Bratschi-Kaye     /// the maximum size of `ty` is guaranteed to fit within
759d4242001SAdam Bratschi-Kaye     /// `reserved_size_in_bytes`.
760d4242001SAdam Bratschi-Kaye     ///
761d4242001SAdam Bratschi-Kaye     /// The `guard_size_in_bytes` parameter indicates how many bytes of space,
762d4242001SAdam Bratschi-Kaye     /// after the memory allocation, is expected to be unmapped. JIT code will
763d4242001SAdam Bratschi-Kaye     /// elide bounds checks based on the `guard_size_in_bytes` provided, so for
764d4242001SAdam Bratschi-Kaye     /// JIT code to work correctly the memory returned will need to be properly
765d4242001SAdam Bratschi-Kaye     /// guarded with `guard_size_in_bytes` bytes left unmapped after the base
766d4242001SAdam Bratschi-Kaye     /// allocation.
767d4242001SAdam Bratschi-Kaye     ///
768d4242001SAdam Bratschi-Kaye     /// Note that the `reserved_size_in_bytes` and `guard_size_in_bytes` options
769d4242001SAdam Bratschi-Kaye     /// are tuned from the various [`Config`](crate::Config) methods about
770d4242001SAdam Bratschi-Kaye     /// memory sizes/guards. Additionally these two values are guaranteed to be
771d4242001SAdam Bratschi-Kaye     /// multiples of the system page size.
772d4242001SAdam Bratschi-Kaye     ///
773d4242001SAdam Bratschi-Kaye     /// Memory created from this method should be zero filled.
new_memory( &self, ty: MemoryType, minimum: usize, maximum: Option<usize>, reserved_size_in_bytes: Option<usize>, guard_size_in_bytes: usize, ) -> Result<Box<dyn LinearMemory>, String>774d4242001SAdam Bratschi-Kaye     fn new_memory(
775d4242001SAdam Bratschi-Kaye         &self,
776d4242001SAdam Bratschi-Kaye         ty: MemoryType,
777d4242001SAdam Bratschi-Kaye         minimum: usize,
778d4242001SAdam Bratschi-Kaye         maximum: Option<usize>,
779d4242001SAdam Bratschi-Kaye         reserved_size_in_bytes: Option<usize>,
780d4242001SAdam Bratschi-Kaye         guard_size_in_bytes: usize,
781d4242001SAdam Bratschi-Kaye     ) -> Result<Box<dyn LinearMemory>, String>;
782d4242001SAdam Bratschi-Kaye }
783d4242001SAdam Bratschi-Kaye 
784d4242001SAdam Bratschi-Kaye /// A constructor for externally-created shared memory.
785d4242001SAdam Bratschi-Kaye ///
786d4242001SAdam Bratschi-Kaye /// The [threads proposal] adds the concept of "shared memory" to WebAssembly.
787d4242001SAdam Bratschi-Kaye /// This is much the same as a Wasm linear memory (i.e., [`Memory`]), but can be
788d4242001SAdam Bratschi-Kaye /// used concurrently by multiple agents. Because these agents may execute in
789d4242001SAdam Bratschi-Kaye /// different threads, [`SharedMemory`] must be thread-safe.
790d4242001SAdam Bratschi-Kaye ///
7910a55f804SAlex Crichton /// When the [threads proposal is enabled](crate::Config::wasm_threads) and the
7920a55f804SAlex Crichton /// [the creation of shared memories is enabled](crate::Config::shared_memory),
7930a55f804SAlex Crichton /// there are multiple ways to construct shared memory:
794d4242001SAdam Bratschi-Kaye ///  1. for imported shared memory, e.g., `(import "env" "memory" (memory 1 1
795d4242001SAdam Bratschi-Kaye ///     shared))`, the user must supply a [`SharedMemory`] with the
796d4242001SAdam Bratschi-Kaye ///     externally-created memory as an import to the instance--e.g.,
797d4242001SAdam Bratschi-Kaye ///     `shared_memory.into()`.
798d4242001SAdam Bratschi-Kaye ///  2. for private or exported shared memory, e.g., `(export "env" "memory"
799d4242001SAdam Bratschi-Kaye ///     (memory 1 1 shared))`, Wasmtime will create the memory internally during
800d4242001SAdam Bratschi-Kaye ///     instantiation--access using `Instance::get_shared_memory()`.
801d4242001SAdam Bratschi-Kaye ///
802d4242001SAdam Bratschi-Kaye /// [threads proposal]:
803d4242001SAdam Bratschi-Kaye ///     https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md
804d4242001SAdam Bratschi-Kaye ///
805d4242001SAdam Bratschi-Kaye /// # Examples
806d4242001SAdam Bratschi-Kaye ///
807d4242001SAdam Bratschi-Kaye /// ```
808d4242001SAdam Bratschi-Kaye /// # use wasmtime::*;
80996e19700SNick Fitzgerald /// # fn main() -> Result<()> {
810d4242001SAdam Bratschi-Kaye /// let mut config = Config::new();
811d4242001SAdam Bratschi-Kaye /// config.wasm_threads(true);
8120a55f804SAlex Crichton /// config.shared_memory(true);
81369b4acbfSAlex Crichton /// # if Engine::new(&config).is_err() { return Ok(()); }
814d4242001SAdam Bratschi-Kaye /// let engine = Engine::new(&config)?;
815d4242001SAdam Bratschi-Kaye /// let mut store = Store::new(&engine, ());
816d4242001SAdam Bratschi-Kaye ///
817d4242001SAdam Bratschi-Kaye /// let shared_memory = SharedMemory::new(&engine, MemoryType::shared(1, 2))?;
818d4242001SAdam Bratschi-Kaye /// let module = Module::new(&engine, r#"(module (memory (import "" "") 1 2 shared))"#)?;
819d4242001SAdam Bratschi-Kaye /// let instance = Instance::new(&mut store, &module, &[shared_memory.into()])?;
820d4242001SAdam Bratschi-Kaye /// // ...
821d4242001SAdam Bratschi-Kaye /// # Ok(())
822d4242001SAdam Bratschi-Kaye /// # }
823d4242001SAdam Bratschi-Kaye /// ```
824d4242001SAdam Bratschi-Kaye #[derive(Clone)]
825bdd78422SNick Fitzgerald pub struct SharedMemory {
826bdd78422SNick Fitzgerald     vm: crate::runtime::vm::SharedMemory,
827bdd78422SNick Fitzgerald     engine: Engine,
828bdd78422SNick Fitzgerald }
829d4242001SAdam Bratschi-Kaye 
830d4242001SAdam Bratschi-Kaye impl SharedMemory {
831d4242001SAdam Bratschi-Kaye     /// Construct a [`SharedMemory`] by providing both the `minimum` and
832d4242001SAdam Bratschi-Kaye     /// `maximum` number of 64K-sized pages. This call allocates the necessary
833d4242001SAdam Bratschi-Kaye     /// pages on the system.
83483b859e5SAlex Crichton     #[cfg(feature = "threads")]
new(engine: &Engine, ty: MemoryType) -> Result<Self>835d4242001SAdam Bratschi-Kaye     pub fn new(engine: &Engine, ty: MemoryType) -> Result<Self> {
836d4242001SAdam Bratschi-Kaye         if !ty.is_shared() {
837d4242001SAdam Bratschi-Kaye             bail!("shared memory must have the `shared` flag enabled on its memory type")
838d4242001SAdam Bratschi-Kaye         }
839d4242001SAdam Bratschi-Kaye         debug_assert!(ty.maximum().is_some());
840d4242001SAdam Bratschi-Kaye 
8412a7f0653SAlex Crichton         let ty = ty.wasmtime_memory();
8420a55f804SAlex Crichton         let memory = crate::runtime::vm::SharedMemory::new(engine, ty)?;
843bdd78422SNick Fitzgerald 
844bdd78422SNick Fitzgerald         Ok(Self {
845bdd78422SNick Fitzgerald             vm: memory,
846bdd78422SNick Fitzgerald             engine: engine.clone(),
847bdd78422SNick Fitzgerald         })
848d4242001SAdam Bratschi-Kaye     }
849d4242001SAdam Bratschi-Kaye 
850d4242001SAdam Bratschi-Kaye     /// Return the type of the shared memory.
ty(&self) -> MemoryType851d4242001SAdam Bratschi-Kaye     pub fn ty(&self) -> MemoryType {
852bdd78422SNick Fitzgerald         MemoryType::from_wasmtime_memory(&self.vm.ty())
853d4242001SAdam Bratschi-Kaye     }
854d4242001SAdam Bratschi-Kaye 
855d4242001SAdam Bratschi-Kaye     /// Returns the size, in WebAssembly pages, of this wasm memory.
size(&self) -> u64856d4242001SAdam Bratschi-Kaye     pub fn size(&self) -> u64 {
857bdd78422SNick Fitzgerald         let byte_size = u64::try_from(self.data_size()).unwrap();
8581fcd0933SAlex Crichton         let page_size = self.page_size();
859bdd78422SNick Fitzgerald         byte_size / page_size
860bdd78422SNick Fitzgerald     }
861bdd78422SNick Fitzgerald 
862bdd78422SNick Fitzgerald     /// Returns the size of a page, in bytes, for this memory.
863bdd78422SNick Fitzgerald     ///
864bdd78422SNick Fitzgerald     /// By default this is 64KiB (aka `0x10000`, `2**16`, `1<<16`, or `65536`)
865bdd78422SNick Fitzgerald     /// but [the custom-page-sizes proposal] allows opting into a page size of
866bdd78422SNick Fitzgerald     /// `1`. Future extensions might allow any power of two as a page size.
867bdd78422SNick Fitzgerald     ///
868bdd78422SNick Fitzgerald     /// [the custom-page-sizes proposal]: https://github.com/WebAssembly/custom-page-sizes
page_size(&self) -> u648691fcd0933SAlex Crichton     pub fn page_size(&self) -> u64 {
8701fcd0933SAlex Crichton         self.ty().page_size()
871d4242001SAdam Bratschi-Kaye     }
872d4242001SAdam Bratschi-Kaye 
873d4242001SAdam Bratschi-Kaye     /// Returns the byte length of this memory.
874d4242001SAdam Bratschi-Kaye     ///
875d4242001SAdam Bratschi-Kaye     /// The returned value will be a multiple of the wasm page size, 64k.
876d4242001SAdam Bratschi-Kaye     ///
877d4242001SAdam Bratschi-Kaye     /// For more information and examples see the documentation on the
878d4242001SAdam Bratschi-Kaye     /// [`Memory`] type.
data_size(&self) -> usize879d4242001SAdam Bratschi-Kaye     pub fn data_size(&self) -> usize {
880bdd78422SNick Fitzgerald         self.vm.byte_size()
881d4242001SAdam Bratschi-Kaye     }
882d4242001SAdam Bratschi-Kaye 
883d4242001SAdam Bratschi-Kaye     /// Return access to the available portion of the shared memory.
884d4242001SAdam Bratschi-Kaye     ///
885d4242001SAdam Bratschi-Kaye     /// The slice returned represents the region of accessible memory at the
886d4242001SAdam Bratschi-Kaye     /// time that this function was called. The contents of the returned slice
887d4242001SAdam Bratschi-Kaye     /// will reflect concurrent modifications happening on other threads.
888d4242001SAdam Bratschi-Kaye     ///
889d4242001SAdam Bratschi-Kaye     /// # Safety
890d4242001SAdam Bratschi-Kaye     ///
891d4242001SAdam Bratschi-Kaye     /// The returned slice is valid for the entire duration of the lifetime of
892d4242001SAdam Bratschi-Kaye     /// this instance of [`SharedMemory`]. The base pointer of a shared memory
893d4242001SAdam Bratschi-Kaye     /// does not change. This [`SharedMemory`] may grow further after this
894d4242001SAdam Bratschi-Kaye     /// function has been called, but the slice returned will not grow.
895d4242001SAdam Bratschi-Kaye     ///
896d4242001SAdam Bratschi-Kaye     /// Concurrent modifications may be happening to the data returned on other
897d4242001SAdam Bratschi-Kaye     /// threads. The `UnsafeCell<u8>` represents that safe access to the
898d4242001SAdam Bratschi-Kaye     /// contents of the slice is not possible through normal loads and stores.
899d4242001SAdam Bratschi-Kaye     ///
900d4242001SAdam Bratschi-Kaye     /// The memory returned must be accessed safely through the `Atomic*` types
901d4242001SAdam Bratschi-Kaye     /// in the [`std::sync::atomic`] module. Casting to those types must
902d4242001SAdam Bratschi-Kaye     /// currently be done unsafely.
data(&self) -> &[UnsafeCell<u8>]903d4242001SAdam Bratschi-Kaye     pub fn data(&self) -> &[UnsafeCell<u8>] {
904d4242001SAdam Bratschi-Kaye         unsafe {
905b86b9682SAlex Crichton             let definition = self.vm.vmmemory_ptr().as_ref();
906b86b9682SAlex Crichton             slice::from_raw_parts(definition.base.as_ptr().cast(), definition.current_length())
907d4242001SAdam Bratschi-Kaye         }
908d4242001SAdam Bratschi-Kaye     }
909d4242001SAdam Bratschi-Kaye 
910d4242001SAdam Bratschi-Kaye     /// Grows this WebAssembly memory by `delta` pages.
911d4242001SAdam Bratschi-Kaye     ///
912d4242001SAdam Bratschi-Kaye     /// This will attempt to add `delta` more pages of memory on to the end of
913d4242001SAdam Bratschi-Kaye     /// this `Memory` instance. If successful this may relocate the memory and
914d4242001SAdam Bratschi-Kaye     /// cause [`Memory::data_ptr`] to return a new value. Additionally any
915d4242001SAdam Bratschi-Kaye     /// unsafely constructed slices into this memory may no longer be valid.
916d4242001SAdam Bratschi-Kaye     ///
917d4242001SAdam Bratschi-Kaye     /// On success returns the number of pages this memory previously had
918d4242001SAdam Bratschi-Kaye     /// before the growth succeeded.
919d4242001SAdam Bratschi-Kaye     ///
920d4242001SAdam Bratschi-Kaye     /// # Errors
921d4242001SAdam Bratschi-Kaye     ///
922d4242001SAdam Bratschi-Kaye     /// Returns an error if memory could not be grown, for example if it exceeds
923d4242001SAdam Bratschi-Kaye     /// the maximum limits of this memory. A
924d4242001SAdam Bratschi-Kaye     /// [`ResourceLimiter`](crate::ResourceLimiter) is another example of
925d4242001SAdam Bratschi-Kaye     /// preventing a memory to grow.
grow(&self, delta: u64) -> Result<u64>926d4242001SAdam Bratschi-Kaye     pub fn grow(&self, delta: u64) -> Result<u64> {
927f881ab24SAlex Crichton         match self.vm.grow(delta)? {
928d4242001SAdam Bratschi-Kaye             Some((old_size, _new_size)) => {
929d4242001SAdam Bratschi-Kaye                 // For shared memory, the `VMMemoryDefinition` is updated inside
930d4242001SAdam Bratschi-Kaye                 // the locked region.
9311fcd0933SAlex Crichton                 Ok(u64::try_from(old_size).unwrap() / self.page_size())
932d4242001SAdam Bratschi-Kaye             }
933557cc2d6SAlex Crichton             None => bail!("failed to grow memory by `{delta}`"),
934d4242001SAdam Bratschi-Kaye         }
935d4242001SAdam Bratschi-Kaye     }
936d4242001SAdam Bratschi-Kaye 
937d4242001SAdam Bratschi-Kaye     /// Equivalent of the WebAssembly `memory.atomic.notify` instruction for
938d4242001SAdam Bratschi-Kaye     /// this shared memory.
939d4242001SAdam Bratschi-Kaye     ///
940d4242001SAdam Bratschi-Kaye     /// This method allows embedders to notify threads blocked on the specified
941d4242001SAdam Bratschi-Kaye     /// `addr`, an index into wasm linear memory. Threads could include
942d4242001SAdam Bratschi-Kaye     /// wasm threads blocked on a `memory.atomic.wait*` instruction or embedder
943d4242001SAdam Bratschi-Kaye     /// threads blocked on [`SharedMemory::atomic_wait32`], for example.
944d4242001SAdam Bratschi-Kaye     ///
945d4242001SAdam Bratschi-Kaye     /// The `count` argument is the number of threads to wake up.
946d4242001SAdam Bratschi-Kaye     ///
947d4242001SAdam Bratschi-Kaye     /// This function returns the number of threads awoken.
948d4242001SAdam Bratschi-Kaye     ///
949d4242001SAdam Bratschi-Kaye     /// # Errors
950d4242001SAdam Bratschi-Kaye     ///
951d4242001SAdam Bratschi-Kaye     /// This function will return an error if `addr` is not within bounds or
952d4242001SAdam Bratschi-Kaye     /// not aligned to a 4-byte boundary.
atomic_notify(&self, addr: u64, count: u32) -> Result<u32, Trap>953d4242001SAdam Bratschi-Kaye     pub fn atomic_notify(&self, addr: u64, count: u32) -> Result<u32, Trap> {
954bdd78422SNick Fitzgerald         self.vm.atomic_notify(addr, count)
955d4242001SAdam Bratschi-Kaye     }
956d4242001SAdam Bratschi-Kaye 
957d4242001SAdam Bratschi-Kaye     /// Equivalent of the WebAssembly `memory.atomic.wait32` instruction for
958d4242001SAdam Bratschi-Kaye     /// this shared memory.
959d4242001SAdam Bratschi-Kaye     ///
960d4242001SAdam Bratschi-Kaye     /// This method allows embedders to block the current thread until notified
961d4242001SAdam Bratschi-Kaye     /// via the `memory.atomic.notify` instruction or the
962d4242001SAdam Bratschi-Kaye     /// [`SharedMemory::atomic_notify`] method, enabling synchronization with
963d4242001SAdam Bratschi-Kaye     /// the wasm guest as desired.
964d4242001SAdam Bratschi-Kaye     ///
965d4242001SAdam Bratschi-Kaye     /// The `expected` argument is the expected 32-bit value to be stored at
966d4242001SAdam Bratschi-Kaye     /// the byte address `addr` specified. The `addr` specified is an index
967d4242001SAdam Bratschi-Kaye     /// into this linear memory.
968d4242001SAdam Bratschi-Kaye     ///
96981a89169SAlex Crichton     /// The optional `timeout` argument is the maximum amount of time to block
97081a89169SAlex Crichton     /// the current thread. If not specified the thread may sleep indefinitely.
971d4242001SAdam Bratschi-Kaye     ///
972d4242001SAdam Bratschi-Kaye     /// This function returns one of three possible values:
973d4242001SAdam Bratschi-Kaye     ///
974d4242001SAdam Bratschi-Kaye     /// * `WaitResult::Ok` - this function, loaded the value at `addr`, found
975d4242001SAdam Bratschi-Kaye     ///   it was equal to `expected`, and then blocked (all as one atomic
976d4242001SAdam Bratschi-Kaye     ///   operation). The thread was then awoken with a `memory.atomic.notify`
977d4242001SAdam Bratschi-Kaye     ///   instruction or the [`SharedMemory::atomic_notify`] method.
978d4242001SAdam Bratschi-Kaye     /// * `WaitResult::Mismatch` - the value at `addr` was loaded but was not
979d4242001SAdam Bratschi-Kaye     ///   equal to `expected` so the thread did not block and immediately
980d4242001SAdam Bratschi-Kaye     ///   returned.
981d4242001SAdam Bratschi-Kaye     /// * `WaitResult::TimedOut` - all the steps of `Ok` happened, except this
982d4242001SAdam Bratschi-Kaye     ///   thread was woken up due to a timeout.
983d4242001SAdam Bratschi-Kaye     ///
984d4242001SAdam Bratschi-Kaye     /// This function will not return due to spurious wakeups.
985d4242001SAdam Bratschi-Kaye     ///
986d4242001SAdam Bratschi-Kaye     /// # Errors
987d4242001SAdam Bratschi-Kaye     ///
988d4242001SAdam Bratschi-Kaye     /// This function will return an error if `addr` is not within bounds or
989d4242001SAdam Bratschi-Kaye     /// not aligned to a 4-byte boundary.
atomic_wait32( &self, addr: u64, expected: u32, timeout: Option<Duration>, ) -> Result<WaitResult, Trap>990d4242001SAdam Bratschi-Kaye     pub fn atomic_wait32(
991d4242001SAdam Bratschi-Kaye         &self,
992d4242001SAdam Bratschi-Kaye         addr: u64,
993d4242001SAdam Bratschi-Kaye         expected: u32,
99481a89169SAlex Crichton         timeout: Option<Duration>,
995d4242001SAdam Bratschi-Kaye     ) -> Result<WaitResult, Trap> {
996bdd78422SNick Fitzgerald         self.vm.atomic_wait32(addr, expected, timeout)
997d4242001SAdam Bratschi-Kaye     }
998d4242001SAdam Bratschi-Kaye 
999d4242001SAdam Bratschi-Kaye     /// Equivalent of the WebAssembly `memory.atomic.wait64` instruction for
1000d4242001SAdam Bratschi-Kaye     /// this shared memory.
1001d4242001SAdam Bratschi-Kaye     ///
1002d4242001SAdam Bratschi-Kaye     /// For more information see [`SharedMemory::atomic_wait32`].
1003d4242001SAdam Bratschi-Kaye     ///
1004d4242001SAdam Bratschi-Kaye     /// # Errors
1005d4242001SAdam Bratschi-Kaye     ///
1006d4242001SAdam Bratschi-Kaye     /// Returns the same error as [`SharedMemory::atomic_wait32`] except that
1007d4242001SAdam Bratschi-Kaye     /// the specified address must be 8-byte aligned instead of 4-byte aligned.
atomic_wait64( &self, addr: u64, expected: u64, timeout: Option<Duration>, ) -> Result<WaitResult, Trap>1008d4242001SAdam Bratschi-Kaye     pub fn atomic_wait64(
1009d4242001SAdam Bratschi-Kaye         &self,
1010d4242001SAdam Bratschi-Kaye         addr: u64,
1011d4242001SAdam Bratschi-Kaye         expected: u64,
101281a89169SAlex Crichton         timeout: Option<Duration>,
1013d4242001SAdam Bratschi-Kaye     ) -> Result<WaitResult, Trap> {
1014bdd78422SNick Fitzgerald         self.vm.atomic_wait64(addr, expected, timeout)
1015d4242001SAdam Bratschi-Kaye     }
1016d4242001SAdam Bratschi-Kaye 
1017d4242001SAdam Bratschi-Kaye     /// Return a reference to the [`Engine`] used to configure the shared
1018d4242001SAdam Bratschi-Kaye     /// memory.
engine(&self) -> &Engine1019d4242001SAdam Bratschi-Kaye     pub(crate) fn engine(&self) -> &Engine {
1020bdd78422SNick Fitzgerald         &self.engine
1021d4242001SAdam Bratschi-Kaye     }
1022d4242001SAdam Bratschi-Kaye 
1023d4242001SAdam Bratschi-Kaye     /// Construct a single-memory instance to provide a way to import
1024d4242001SAdam Bratschi-Kaye     /// [`SharedMemory`] into other modules.
vmimport(&self, store: &mut StoreOpaque) -> crate::runtime::vm::VMMemoryImport102572004aadSNick Fitzgerald     pub(crate) fn vmimport(&self, store: &mut StoreOpaque) -> crate::runtime::vm::VMMemoryImport {
1026e1f50aadSAlex Crichton         // Note `vm::assert_ready` shouldn't panic here because this isn't
1027155ea7fcSAlex Crichton         // actually allocating any new memory (also no limiter), so resource
1028155ea7fcSAlex Crichton         // limiting shouldn't kick in.
10291fcd0933SAlex Crichton         let memory = vm::assert_ready(generate_memory_export(
1030155ea7fcSAlex Crichton             store,
1031155ea7fcSAlex Crichton             None,
1032155ea7fcSAlex Crichton             &self.ty(),
1033155ea7fcSAlex Crichton             Some(&self.vm),
1034155ea7fcSAlex Crichton         ))
10351fcd0933SAlex Crichton         .unwrap();
10361fcd0933SAlex Crichton         match memory {
10371fcd0933SAlex Crichton             ExportMemory::Unshared(_) => unreachable!(),
10381fcd0933SAlex Crichton             ExportMemory::Shared(_shared, vmimport) => vmimport,
10391fcd0933SAlex Crichton         }
1040d4242001SAdam Bratschi-Kaye     }
1041d4242001SAdam Bratschi-Kaye 
10421fcd0933SAlex Crichton     /// Creates a [`SharedMemory`] from its constituent parts.
from_raw(vm: crate::runtime::vm::SharedMemory, engine: Engine) -> Self10431fcd0933SAlex Crichton     pub(crate) fn from_raw(vm: crate::runtime::vm::SharedMemory, engine: Engine) -> Self {
10441fcd0933SAlex Crichton         SharedMemory { vm, engine }
1045d4242001SAdam Bratschi-Kaye     }
1046d4242001SAdam Bratschi-Kaye }
1047d4242001SAdam Bratschi-Kaye 
104881a89169SAlex Crichton impl fmt::Debug for SharedMemory {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result104981a89169SAlex Crichton     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1050d4242001SAdam Bratschi-Kaye         f.debug_struct("SharedMemory").finish_non_exhaustive()
1051d4242001SAdam Bratschi-Kaye     }
1052d4242001SAdam Bratschi-Kaye }
1053d4242001SAdam Bratschi-Kaye 
1054d4242001SAdam Bratschi-Kaye #[cfg(test)]
1055d4242001SAdam Bratschi-Kaye mod tests {
1056d4242001SAdam Bratschi-Kaye     use crate::*;
1057d4242001SAdam Bratschi-Kaye 
1058d4242001SAdam Bratschi-Kaye     // Assert that creating a memory via `Memory::new` respects the limits/tunables
1059d4242001SAdam Bratschi-Kaye     // in `Config`.
1060d4242001SAdam Bratschi-Kaye     #[test]
respect_tunables()1061d4242001SAdam Bratschi-Kaye     fn respect_tunables() {
1062d4242001SAdam Bratschi-Kaye         let mut cfg = Config::new();
10637a28a5b9SAlex Crichton         cfg.memory_reservation(0).memory_guard_size(0);
1064d4242001SAdam Bratschi-Kaye         let mut store = Store::new(&Engine::new(&cfg).unwrap(), ());
1065d4242001SAdam Bratschi-Kaye         let ty = MemoryType::new(1, None);
1066d4242001SAdam Bratschi-Kaye         let mem = Memory::new(&mut store, ty).unwrap();
1067d4242001SAdam Bratschi-Kaye         let store = store.as_context();
106881d7de0aSAlex Crichton         let tunables = store.engine().tunables();
106981d7de0aSAlex Crichton         assert_eq!(tunables.memory_guard_size, 0);
10700e9a691dSAlex Crichton         assert!(
10710e9a691dSAlex Crichton             !mem.wasmtime_ty(store.0)
10720e9a691dSAlex Crichton                 .can_elide_bounds_check(tunables, 12)
10730e9a691dSAlex Crichton         );
1074d4242001SAdam Bratschi-Kaye     }
1075d4242001SAdam Bratschi-Kaye 
1076d4242001SAdam Bratschi-Kaye     #[test]
hash_key_is_stable_across_duplicate_store_data_entries() -> Result<()>1077d4242001SAdam Bratschi-Kaye     fn hash_key_is_stable_across_duplicate_store_data_entries() -> Result<()> {
1078d4242001SAdam Bratschi-Kaye         let mut store = Store::<()>::default();
1079d4242001SAdam Bratschi-Kaye         let module = Module::new(
1080d4242001SAdam Bratschi-Kaye             store.engine(),
1081d4242001SAdam Bratschi-Kaye             r#"
1082d4242001SAdam Bratschi-Kaye                 (module
1083d4242001SAdam Bratschi-Kaye                     (memory (export "m") 1 1)
1084d4242001SAdam Bratschi-Kaye                 )
1085d4242001SAdam Bratschi-Kaye             "#,
1086d4242001SAdam Bratschi-Kaye         )?;
1087d4242001SAdam Bratschi-Kaye         let instance = Instance::new(&mut store, &module, &[])?;
1088d4242001SAdam Bratschi-Kaye 
1089d4242001SAdam Bratschi-Kaye         // Each time we `get_memory`, we call `Memory::from_wasmtime` which adds
1090d4242001SAdam Bratschi-Kaye         // a new entry to `StoreData`, so `g1` and `g2` will have different
1091d4242001SAdam Bratschi-Kaye         // indices into `StoreData`.
1092d4242001SAdam Bratschi-Kaye         let m1 = instance.get_memory(&mut store, "m").unwrap();
1093d4242001SAdam Bratschi-Kaye         let m2 = instance.get_memory(&mut store, "m").unwrap();
1094d4242001SAdam Bratschi-Kaye 
1095d4242001SAdam Bratschi-Kaye         // That said, they really point to the same memory.
1096d4242001SAdam Bratschi-Kaye         assert_eq!(m1.data(&store)[0], 0);
1097d4242001SAdam Bratschi-Kaye         assert_eq!(m2.data(&store)[0], 0);
1098d4242001SAdam Bratschi-Kaye         m1.data_mut(&mut store)[0] = 42;
1099d4242001SAdam Bratschi-Kaye         assert_eq!(m1.data(&mut store)[0], 42);
1100d4242001SAdam Bratschi-Kaye         assert_eq!(m2.data(&mut store)[0], 42);
1101d4242001SAdam Bratschi-Kaye 
1102d4242001SAdam Bratschi-Kaye         // And therefore their hash keys are the same.
1103d4242001SAdam Bratschi-Kaye         assert!(m1.hash_key(&store.as_context().0) == m2.hash_key(&store.as_context().0));
1104d4242001SAdam Bratschi-Kaye 
1105d4242001SAdam Bratschi-Kaye         // But the hash keys are different from different memories.
1106d4242001SAdam Bratschi-Kaye         let instance2 = Instance::new(&mut store, &module, &[])?;
1107d4242001SAdam Bratschi-Kaye         let m3 = instance2.get_memory(&mut store, "m").unwrap();
1108d4242001SAdam Bratschi-Kaye         assert!(m1.hash_key(&store.as_context().0) != m3.hash_key(&store.as_context().0));
1109d4242001SAdam Bratschi-Kaye 
1110d4242001SAdam Bratschi-Kaye         Ok(())
1111d4242001SAdam Bratschi-Kaye     }
1112d4242001SAdam Bratschi-Kaye }
1113