wasmer/backend/sys/entities/
module.rs1use std::path::Path;
3use std::sync::Arc;
4
5use bytes::Bytes;
6use wasmer_compiler::{Artifact, ArtifactCreate, Engine};
7use wasmer_types::{
8 CompilationProgressCallback, CompileError, DeserializeError, ExportType, ExportsIterator,
9 ImportType, ImportsIterator, ModuleInfo, SerializeError,
10};
11#[cfg(feature = "experimental-host-interrupt")]
12use wasmer_vm::interrupt_registry;
13use wasmer_vm::{Trap, TrapCode};
14
15use crate::{
16 AsStoreMut, AsStoreRef, BackendModule, IntoBytes, StoreContext,
17 backend::sys::entities::engine::NativeEngineExt, engine::AsEngineRef,
18 error::InstantiationError, vm::VMInstance,
19};
20use wasmer_vm::StoreHandle;
21
22#[derive(Clone, PartialEq, Eq)]
23#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
24pub struct Module {
26 artifact: Arc<Artifact>,
41}
42
43impl Module {
44 pub(crate) fn from_binary(
45 engine: &impl AsEngineRef,
46 binary: &[u8],
47 ) -> Result<Self, CompileError> {
48 Self::validate(engine, binary)?;
49 unsafe { Self::from_binary_unchecked(engine, binary) }
50 }
51
52 pub(crate) fn from_binary_with_progress(
53 engine: &impl AsEngineRef,
54 binary: &[u8],
55 callback: CompilationProgressCallback,
56 ) -> Result<Self, CompileError> {
57 Self::validate(engine, binary)?;
58
59 let artifact = engine
60 .as_engine_ref()
61 .engine()
62 .as_sys()
63 .compile_with_progress(binary, Some(callback))?;
64 Ok(Self::from_artifact(artifact))
65 }
66
67 pub(crate) unsafe fn from_binary_unchecked(
68 engine: &impl AsEngineRef,
69 binary: &[u8],
70 ) -> Result<Self, CompileError> {
71 Self::compile(engine, binary)
72 }
73
74 #[cfg(feature = "compiler")]
75 #[tracing::instrument(level = "debug", skip_all)]
76 pub(crate) fn validate(engine: &impl AsEngineRef, binary: &[u8]) -> Result<(), CompileError> {
77 engine.as_engine_ref().engine().as_sys().validate(binary)
78 }
79
80 #[cfg(not(feature = "compiler"))]
81 pub(crate) fn validate(_engine: &impl AsEngineRef, _binary: &[u8]) -> Result<(), CompileError> {
82 Err(CompileError::UnsupportedTarget(
83 "The compiler feature is not enabled, but is required to validate a Module".to_string(),
84 ))
85 }
86
87 #[cfg(feature = "compiler")]
88 fn compile(engine: &impl AsEngineRef, binary: &[u8]) -> Result<Self, CompileError> {
89 let artifact = engine.as_engine_ref().engine().as_sys().compile(binary)?;
90 Ok(Self::from_artifact(artifact))
91 }
92
93 #[cfg(not(feature = "compiler"))]
94 fn compile(_engine: &impl AsEngineRef, _binary: &[u8]) -> Result<Self, CompileError> {
95 Err(CompileError::UnsupportedTarget(
96 "The compiler feature is not enabled, but is required to compile a Module".to_string(),
97 ))
98 }
99
100 pub(crate) fn serialize(&self) -> Result<Bytes, SerializeError> {
101 self.artifact.serialize().map(|bytes| bytes.into())
102 }
103
104 #[tracing::instrument(level = "debug", skip_all)]
105 pub(crate) unsafe fn deserialize_unchecked(
106 engine: &impl AsEngineRef,
107 bytes: impl IntoBytes,
108 ) -> Result<Self, DeserializeError> {
109 let bytes = bytes.into_bytes();
110
111 let artifact = unsafe {
112 engine
113 .as_engine_ref()
114 .engine()
115 .as_sys()
116 .deserialize_unchecked(bytes.into())?
117 };
118 Ok(Self::from_artifact(artifact))
119 }
120
121 #[tracing::instrument(level = "debug", skip_all)]
122 pub(crate) unsafe fn deserialize(
123 engine: &impl AsEngineRef,
124 bytes: impl IntoBytes,
125 ) -> Result<Self, DeserializeError> {
126 let bytes = bytes.into_bytes();
127 let artifact = unsafe {
128 engine
129 .as_engine_ref()
130 .engine()
131 .as_sys()
132 .deserialize(bytes.into())?
133 };
134 Ok(Self::from_artifact(artifact))
135 }
136
137 pub(crate) unsafe fn deserialize_from_file_unchecked(
138 engine: &impl AsEngineRef,
139 path: impl AsRef<Path>,
140 ) -> Result<Self, DeserializeError> {
141 let artifact = unsafe {
142 engine
143 .as_engine_ref()
144 .engine()
145 .as_sys()
146 .deserialize_from_file_unchecked(path.as_ref())?
147 };
148 Ok(Self::from_artifact(artifact))
149 }
150
151 pub(crate) unsafe fn deserialize_from_file(
152 engine: &impl AsEngineRef,
153 path: impl AsRef<Path>,
154 ) -> Result<Self, DeserializeError> {
155 let artifact = unsafe {
156 engine
157 .as_engine_ref()
158 .engine()
159 .as_sys()
160 .deserialize_from_file(path.as_ref())?
161 };
162 Ok(Self::from_artifact(artifact))
163 }
164
165 pub(super) fn from_artifact(artifact: Arc<Artifact>) -> Self {
166 Self { artifact }
167 }
168
169 #[allow(clippy::result_large_err)]
170 pub(crate) fn instantiate(
171 &self,
172 store: &mut impl AsStoreMut,
173 imports: &[crate::Extern],
174 ) -> Result<VMInstance, InstantiationError> {
175 if !self.artifact.allocated() {
176 return Err(InstantiationError::DifferentArchOS);
179 }
180 for import in imports {
182 if !import.is_from_store(store) {
183 return Err(InstantiationError::DifferentStores);
184 }
185 }
186 let signal_handler = store.as_store_ref().signal_handler();
187 let mut store_mut = store.as_store_mut();
188 let store_ptr = store_mut.inner as *mut _;
189 let (engine, objects) = store_mut.engine_and_objects_mut();
190 let config = engine.tunables().vmconfig();
191 unsafe {
192 let mut instance_handle = self.artifact.instantiate(
193 engine.tunables(),
194 &imports
195 .iter()
196 .map(|e| crate::Extern::to_vm_extern(e).unwrap_sys())
197 .collect::<Vec<_>>(),
198 objects.as_sys_mut(),
199 )?;
200
201 let store_id = objects.id();
202 #[cfg(feature = "experimental-host-interrupt")]
203 let interrupt_guard = match interrupt_registry::install(store_id) {
204 Ok(x) => x,
205 Err(interrupt_registry::InstallError::AlreadyInterrupted) => {
206 return Err(InstantiationError::Start(
207 Trap::lib(TrapCode::HostInterrupt).into(),
208 ));
209 }
210 };
211
212 let store_install_guard = StoreContext::ensure_installed(store_ptr);
213
214 if let Err(err) =
220 self.artifact
221 .finish_instantiation(config, signal_handler, &mut instance_handle)
222 {
223 let _ = StoreHandle::new(objects.as_sys_mut(), instance_handle);
226 return Err(err.into());
227 }
228
229 drop(store_install_guard);
230 #[cfg(feature = "experimental-host-interrupt")]
231 drop(interrupt_guard);
232
233 Ok(VMInstance::Sys(instance_handle))
234 }
235 }
236
237 pub(crate) fn name(&self) -> Option<&str> {
238 self.info().name.as_deref()
239 }
240
241 pub(crate) fn set_name(&mut self, name: &str) -> bool {
242 Arc::get_mut(&mut self.artifact)
243 .is_some_and(|artifact| artifact.set_module_info_name(name.to_string()))
244 }
245
246 pub(crate) fn imports(&self) -> ImportsIterator<Box<dyn Iterator<Item = ImportType> + '_>> {
247 self.info().imports()
248 }
249
250 pub(crate) fn exports(&self) -> ExportsIterator<Box<dyn Iterator<Item = ExportType> + '_>> {
251 self.info().exports()
252 }
253
254 pub(crate) fn custom_sections<'a>(
255 &'a self,
256 name: &'a str,
257 ) -> Box<dyn Iterator<Item = Box<[u8]>> + 'a> {
258 self.info().custom_sections(name)
259 }
260
261 pub(crate) fn info(&self) -> &ModuleInfo {
262 self.artifact.module_info()
263 }
264}
265
266impl crate::Module {
267 pub fn into_sys(self) -> crate::backend::sys::module::Module {
269 match self.0 {
270 BackendModule::Sys(s) => s,
271 _ => panic!("Not a `sys` module!"),
272 }
273 }
274
275 pub fn as_sys(&self) -> &crate::backend::sys::module::Module {
277 match self.0 {
278 BackendModule::Sys(ref s) => s,
279 _ => panic!("Not a `sys` module!"),
280 }
281 }
282
283 pub fn as_sys_mut(&mut self) -> &mut crate::backend::sys::module::Module {
285 match self.0 {
286 BackendModule::Sys(ref mut s) => s,
287 _ => panic!("Not a `sys` module!"),
288 }
289 }
290
291 pub fn sys_artifact(&self) -> Option<&Artifact> {
301 match self.0 {
302 BackendModule::Sys(ref s) => Some(&s.artifact),
303 #[allow(unreachable_patterns)]
304 _ => None,
305 }
306 }
307}