wasmer_engine_staticlib/
engine.rs1use crate::StaticlibArtifact;
2use loupe::MemoryUsage;
3use std::io::Read;
4use std::path::Path;
5use std::sync::{Arc, Mutex};
6#[cfg(feature = "compiler")]
7use wasmer_compiler::Compiler;
8use wasmer_compiler::{CompileError, Target};
9use wasmer_engine::{Artifact, DeserializeError, Engine, EngineId, Tunables};
10#[cfg(feature = "compiler")]
11use wasmer_types::Features;
12use wasmer_types::FunctionType;
13use wasmer_vm::{
14 FuncDataRegistry, SignatureRegistry, VMCallerCheckedAnyfunc, VMFuncRef, VMSharedSignatureIndex,
15};
16
17#[derive(Clone, MemoryUsage)]
19pub struct StaticlibEngine {
20 inner: Arc<Mutex<StaticlibEngineInner>>,
21 target: Arc<Target>,
23 engine_id: EngineId,
24}
25
26impl StaticlibEngine {
27 #[cfg(feature = "compiler")]
29 pub fn new(compiler: Box<dyn Compiler>, target: Target, features: Features) -> Self {
30 Self {
31 inner: Arc::new(Mutex::new(StaticlibEngineInner {
32 compiler: Some(compiler),
33 signatures: SignatureRegistry::new(),
34 func_data: Arc::new(FuncDataRegistry::new()),
35 prefixer: None,
36 features,
37 })),
38 target: Arc::new(target),
39 engine_id: EngineId::default(),
40 }
41 }
42
43 pub fn headless() -> Self {
57 Self {
58 inner: Arc::new(Mutex::new(StaticlibEngineInner {
59 #[cfg(feature = "compiler")]
60 compiler: None,
61 #[cfg(feature = "compiler")]
62 features: Features::default(),
63 signatures: SignatureRegistry::new(),
64 func_data: Arc::new(FuncDataRegistry::new()),
65 prefixer: None,
66 })),
67 target: Arc::new(Target::default()),
68 engine_id: EngineId::default(),
69 }
70 }
71
72 pub fn set_deterministic_prefixer<F>(&mut self, prefixer: F)
84 where
85 F: Fn(&[u8]) -> String + Send + 'static,
86 {
87 let mut inner = self.inner_mut();
88 inner.prefixer = Some(Box::new(prefixer));
89 }
90
91 pub(crate) fn inner(&self) -> std::sync::MutexGuard<'_, StaticlibEngineInner> {
92 self.inner.lock().unwrap()
93 }
94
95 pub(crate) fn inner_mut(&self) -> std::sync::MutexGuard<'_, StaticlibEngineInner> {
96 self.inner.lock().unwrap()
97 }
98}
99
100impl Engine for StaticlibEngine {
101 fn target(&self) -> &Target {
103 &self.target
104 }
105
106 fn register_signature(&self, func_type: &FunctionType) -> VMSharedSignatureIndex {
108 let compiler = self.inner();
109 compiler.signatures().register(func_type)
110 }
111
112 fn register_function_metadata(&self, func_data: VMCallerCheckedAnyfunc) -> VMFuncRef {
113 let compiler = self.inner();
114 compiler.func_data().register(func_data)
115 }
116
117 fn lookup_signature(&self, sig: VMSharedSignatureIndex) -> Option<FunctionType> {
119 let compiler = self.inner();
120 compiler.signatures().lookup(sig)
121 }
122
123 fn validate(&self, binary: &[u8]) -> Result<(), CompileError> {
125 self.inner().validate(binary)
126 }
127
128 #[cfg(feature = "compiler")]
130 fn compile(
131 &self,
132 binary: &[u8],
133 tunables: &dyn Tunables,
134 ) -> Result<Arc<dyn Artifact>, CompileError> {
135 Ok(Arc::new(StaticlibArtifact::new(&self, binary, tunables)?))
136 }
137
138 #[cfg(not(feature = "compiler"))]
140 fn compile(
141 &self,
142 _binary: &[u8],
143 _tunables: &dyn Tunables,
144 ) -> Result<Arc<dyn Artifact>, CompileError> {
145 Err(CompileError::Codegen(
146 "The `StaticlibEngine` is operating in headless mode, so it cannot compile a module."
147 .to_string(),
148 ))
149 }
150
151 unsafe fn deserialize(&self, bytes: &[u8]) -> Result<Arc<dyn Artifact>, DeserializeError> {
153 Ok(Arc::new(StaticlibArtifact::deserialize(&self, &bytes)?))
154 }
155
156 unsafe fn deserialize_from_file(
161 &self,
162 file_ref: &Path,
163 ) -> Result<Arc<dyn Artifact>, DeserializeError> {
164 let mut f = std::fs::File::open(file_ref)?;
165 let mut vec = vec![];
166 f.read_to_end(&mut vec)?;
167
168 self.deserialize(&vec[..])
169 }
170
171 fn id(&self) -> &EngineId {
172 &self.engine_id
173 }
174
175 fn cloned(&self) -> Arc<dyn Engine + Send + Sync> {
176 Arc::new(self.clone())
177 }
178}
179
180#[derive(MemoryUsage)]
182pub struct StaticlibEngineInner {
183 #[cfg(feature = "compiler")]
185 compiler: Option<Box<dyn Compiler>>,
186
187 #[cfg(feature = "compiler")]
189 features: Features,
190
191 signatures: SignatureRegistry,
194
195 func_data: Arc<FuncDataRegistry>,
199
200 #[loupe(skip)]
204 prefixer: Option<Box<dyn Fn(&[u8]) -> String + Send>>,
205}
206
207impl StaticlibEngineInner {
208 #[cfg(feature = "compiler")]
210 pub fn compiler(&self) -> Result<&dyn Compiler, CompileError> {
211 if self.compiler.is_none() {
212 return Err(CompileError::Codegen("The `StaticlibEngine` is operating in headless mode, so it can only execute already compiled Modules.".to_string()));
213 }
214 Ok(&**self
215 .compiler
216 .as_ref()
217 .expect("Can't get compiler reference"))
218 }
219
220 #[cfg(feature = "compiler")]
221 pub(crate) fn get_prefix(&self, bytes: &[u8]) -> String {
222 if let Some(prefixer) = &self.prefixer {
223 prefixer(&bytes)
224 } else {
225 "".to_string()
226 }
227 }
228
229 #[cfg(feature = "compiler")]
230 pub(crate) fn features(&self) -> &Features {
231 &self.features
232 }
233
234 #[cfg(feature = "compiler")]
236 pub fn validate<'data>(&self, data: &'data [u8]) -> Result<(), CompileError> {
237 self.compiler()?.validate_module(self.features(), data)
238 }
239
240 #[cfg(not(feature = "compiler"))]
242 pub fn validate<'data>(&self, _data: &'data [u8]) -> Result<(), CompileError> {
243 Err(CompileError::Validate(
244 "The `StaticlibEngine` is not compiled with compiler support, which is required for validating".to_string(),
245 ))
246 }
247
248 pub fn signatures(&self) -> &SignatureRegistry {
250 &self.signatures
251 }
252
253 pub(crate) fn func_data(&self) -> &Arc<FuncDataRegistry> {
255 &self.func_data
256 }
257}