wasmer/entities/memory/mod.rs
1pub use shared::SharedMemory;
2use wasmer_types::{MemoryError, MemoryType, Pages};
3
4use crate::{
5 AsStoreMut, AsStoreRef, ExportError, Exportable, Extern, StoreMut, StoreRef,
6 vm::{VMExtern, VMExternMemory, VMMemory},
7};
8
9pub(crate) mod buffer;
10pub(crate) mod inner;
11pub(crate) mod location;
12pub(crate) mod shared;
13pub(crate) mod view;
14
15pub(crate) use inner::*;
16pub use view::*;
17
18/// A WebAssembly `memory` instance.
19///
20/// A memory instance is the runtime representation of a linear memory.
21/// It consists of a vector of bytes and an optional maximum size.
22///
23/// The length of the vector always is a multiple of the WebAssembly
24/// page size, which is defined to be the constant 65536 – abbreviated 64Ki.
25/// Like in a memory type, the maximum size in a memory instance is
26/// given in units of this page size.
27///
28/// A memory created by the host or in WebAssembly code will be accessible and
29/// mutable from both host and WebAssembly.
30///
31/// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances>
32#[derive(Debug, Clone, PartialEq, Eq, derive_more::From)]
33#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
34pub struct Memory(pub(crate) BackendMemory);
35
36impl Memory {
37 /// Creates a new host [`Memory`] from the provided [`MemoryType`].
38 ///
39 /// This function will construct the `Memory` using the store
40 /// `BaseTunables`.
41 ///
42 /// # Example
43 ///
44 /// ```
45 /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value};
46 /// # let mut store = Store::default();
47 /// #
48 /// let m = Memory::new(&mut store, MemoryType::new(1, None, false)).unwrap();
49 /// ```
50 pub fn new(store: &mut impl AsStoreMut, ty: MemoryType) -> Result<Self, MemoryError> {
51 BackendMemory::new(store, ty).map(Self)
52 }
53
54 /// Create a memory object from an existing memory and attaches it to the store
55 pub fn new_from_existing<IntoVMMemory>(
56 new_store: &mut impl AsStoreMut,
57 memory: IntoVMMemory,
58 ) -> Self
59 where
60 IntoVMMemory: Into<VMMemory>,
61 {
62 Self(BackendMemory::new_from_existing(new_store, memory.into()))
63 }
64
65 /// Returns the [`MemoryType`] of the `Memory`.
66 ///
67 /// # Example
68 ///
69 /// ```
70 /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value};
71 /// # let mut store = Store::default();
72 /// #
73 /// let mt = MemoryType::new(1, None, false);
74 /// let m = Memory::new(&mut store, mt).unwrap();
75 ///
76 /// assert_eq!(m.ty(&mut store), mt);
77 /// ```
78 pub fn ty(&self, store: &impl AsStoreRef) -> MemoryType {
79 self.0.ty(store)
80 }
81
82 /// Creates a view into the memory that then allows for
83 /// read and write
84 pub fn view<'a>(&self, store: &'a (impl AsStoreRef + ?Sized)) -> MemoryView<'a> {
85 MemoryView::new(self, store)
86 }
87
88 /// Retrieve the size of the memory in pages.
89 pub fn size(&self, store: &impl AsStoreRef) -> Pages {
90 self.0.size(store)
91 }
92
93 /// Grow memory by the specified amount of WebAssembly [`Pages`] and return
94 /// the previous memory size.
95 ///
96 /// # Example
97 ///
98 /// ```
99 /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value, WASM_MAX_PAGES};
100 /// # let mut store = Store::default();
101 /// #
102 /// let m = Memory::new(&mut store, MemoryType::new(1, Some(3), false)).unwrap();
103 /// let p = m.grow(&mut store, 2).unwrap();
104 ///
105 /// assert_eq!(p, Pages(1));
106 /// assert_eq!(m.view(&mut store).size(), Pages(3));
107 /// ```
108 ///
109 /// # Errors
110 ///
111 /// Returns an error if memory can't be grown by the specified amount
112 /// of pages.
113 ///
114 /// ```should_panic
115 /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value, WASM_MAX_PAGES};
116 /// # use wasmer::FunctionEnv;
117 /// # let mut store = Store::default();
118 /// # let env = FunctionEnv::new(&mut store, ());
119 /// #
120 /// let m = Memory::new(&mut store, MemoryType::new(1, Some(1), false)).unwrap();
121 ///
122 /// // This results in an error: `MemoryError::CouldNotGrow`.
123 /// let s = m.grow(&mut store, 1).unwrap();
124 /// ```
125 pub fn grow<IntoPages>(
126 &self,
127 store: &mut impl AsStoreMut,
128 delta: IntoPages,
129 ) -> Result<Pages, MemoryError>
130 where
131 IntoPages: Into<Pages>,
132 {
133 self.0.grow(store, delta)
134 }
135
136 /// Grows the memory to at least a minimum size.
137 ///
138 /// # Note
139 ///
140 /// If the memory is already big enough for the min size this function does nothing.
141 pub fn grow_at_least(
142 &self,
143 store: &mut impl AsStoreMut,
144 min_size: u64,
145 ) -> Result<(), MemoryError> {
146 self.0.grow_at_least(store, min_size)
147 }
148
149 /// Resets the memory back to zero length
150 pub fn reset(&self, store: &mut impl AsStoreMut) -> Result<(), MemoryError> {
151 self.0.reset(store)
152 }
153
154 /// Attempts to duplicate this memory (if its clonable) in a new store
155 /// (copied memory)
156 pub fn copy_to_store(
157 &self,
158 store: &impl AsStoreRef,
159 new_store: &mut impl AsStoreMut,
160 ) -> Result<Self, MemoryError> {
161 self.0.copy_to_store(store, new_store).map(Self)
162 }
163
164 pub(crate) fn from_vm_extern(store: &mut impl AsStoreMut, vm_extern: VMExternMemory) -> Self {
165 Self(BackendMemory::from_vm_extern(store, vm_extern))
166 }
167
168 /// Checks whether this `Memory` can be used with the given context.
169 pub fn is_from_store(&self, store: &impl AsStoreRef) -> bool {
170 self.0.is_from_store(store)
171 }
172
173 /// Attempt to create a new reference to the underlying memory; this new reference can then be
174 /// used within a different store (from the same implementer).
175 ///
176 /// # Errors
177 ///
178 /// Fails if the underlying memory is not clonable.
179 pub fn try_clone(&self, store: &impl AsStoreRef) -> Result<VMMemory, MemoryError> {
180 self.0.try_clone(store)
181 }
182
183 /// Attempts to clone this memory (if its clonable) in a new store
184 /// (cloned memory will be shared between those that clone it)
185 pub fn share_in_store(
186 &self,
187 store: &impl AsStoreRef,
188 new_store: &mut impl AsStoreMut,
189 ) -> Result<Self, MemoryError> {
190 self.0.share_in_store(store, new_store).map(Self)
191 }
192
193 /// Get a [`SharedMemory`].
194 ///
195 /// Only returns `Some(_)` if the memory is shared, and if the target
196 /// backend supports shared memory operations.
197 ///
198 /// See [`SharedMemory`] and its methods for more information.
199 pub fn as_shared(&self, store: &impl AsStoreRef) -> Option<SharedMemory> {
200 self.0.as_shared(store)
201 }
202
203 /// Create a [`VMExtern`] from self.
204 pub(crate) fn to_vm_extern(&self) -> VMExtern {
205 self.0.to_vm_extern()
206 }
207}
208
209impl<'a> Exportable<'a> for Memory {
210 fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> {
211 match _extern {
212 Extern::Memory(memory) => Ok(memory),
213 _ => Err(ExportError::IncompatibleType),
214 }
215 }
216}