wasmer_engine_object_file/
engine.rs1use crate::ObjectFileArtifact;
2use std::io::Read;
3use std::path::Path;
4use std::sync::{Arc, Mutex};
5#[cfg(feature = "compiler")]
6use wasmer_compiler::Compiler;
7use wasmer_compiler::{CompileError, Target};
8use wasmer_engine::{Artifact, DeserializeError, Engine, EngineId, Tunables};
9#[cfg(feature = "compiler")]
10use wasmer_types::Features;
11use wasmer_types::FunctionType;
12use wasmer_vm::{SignatureRegistry, VMSharedSignatureIndex};
13
14#[derive(Clone)]
16pub struct ObjectFileEngine {
17 inner: Arc<Mutex<ObjectFileEngineInner>>,
18 target: Arc<Target>,
20 engine_id: EngineId,
21}
22
23impl ObjectFileEngine {
24 #[cfg(feature = "compiler")]
26 pub fn new(compiler: Box<dyn Compiler>, target: Target, features: Features) -> Self {
27 Self {
28 inner: Arc::new(Mutex::new(ObjectFileEngineInner {
29 compiler: Some(compiler),
30 signatures: SignatureRegistry::new(),
31 prefixer: None,
32 features,
33 })),
34 target: Arc::new(target),
35 engine_id: EngineId::default(),
36 }
37 }
38
39 pub fn headless() -> Self {
53 Self {
54 inner: Arc::new(Mutex::new(ObjectFileEngineInner {
55 #[cfg(feature = "compiler")]
56 compiler: None,
57 #[cfg(feature = "compiler")]
58 features: Features::default(),
59 signatures: SignatureRegistry::new(),
60 prefixer: None,
61 })),
62 target: Arc::new(Target::default()),
63 engine_id: EngineId::default(),
64 }
65 }
66
67 pub fn set_deterministic_prefixer<F>(&mut self, prefixer: F)
78 where
79 F: Fn(&[u8]) -> String + Send + 'static,
80 {
81 let mut inner = self.inner_mut();
82 inner.prefixer = Some(Box::new(prefixer));
83 }
84
85 pub(crate) fn inner(&self) -> std::sync::MutexGuard<'_, ObjectFileEngineInner> {
86 self.inner.lock().unwrap()
87 }
88
89 pub(crate) fn inner_mut(&self) -> std::sync::MutexGuard<'_, ObjectFileEngineInner> {
90 self.inner.lock().unwrap()
91 }
92}
93
94impl Engine for ObjectFileEngine {
95 fn target(&self) -> &Target {
97 &self.target
98 }
99
100 fn register_signature(&self, func_type: &FunctionType) -> VMSharedSignatureIndex {
102 let compiler = self.inner();
103 compiler.signatures().register(func_type)
104 }
105
106 fn lookup_signature(&self, sig: VMSharedSignatureIndex) -> Option<FunctionType> {
108 let compiler = self.inner();
109 compiler.signatures().lookup(sig)
110 }
111
112 fn validate(&self, binary: &[u8]) -> Result<(), CompileError> {
114 self.inner().validate(binary)
115 }
116
117 #[cfg(feature = "compiler")]
119 fn compile(
120 &self,
121 binary: &[u8],
122 tunables: &dyn Tunables,
123 ) -> Result<Arc<dyn Artifact>, CompileError> {
124 Ok(Arc::new(ObjectFileArtifact::new(&self, binary, tunables)?))
125 }
126
127 #[cfg(not(feature = "compiler"))]
129 fn compile(
130 &self,
131 _binary: &[u8],
132 _tunables: &dyn Tunables,
133 ) -> Result<Arc<dyn Artifact>, CompileError> {
134 Err(CompileError::Codegen(
135 "The `ObjectFileEngine` is operating in headless mode, so it cannot compile a module."
136 .to_string(),
137 ))
138 }
139
140 unsafe fn deserialize(&self, bytes: &[u8]) -> Result<Arc<dyn Artifact>, DeserializeError> {
142 Ok(Arc::new(ObjectFileArtifact::deserialize(&self, &bytes)?))
143 }
144
145 unsafe fn deserialize_from_file(
148 &self,
149 file_ref: &Path,
150 ) -> Result<Arc<dyn Artifact>, DeserializeError> {
151 let mut f = std::fs::File::open(file_ref)?;
152 let mut vec = vec![];
153 f.read_to_end(&mut vec)?;
154
155 self.deserialize(&vec[..])
156 }
157
158 fn id(&self) -> &EngineId {
159 &self.engine_id
160 }
161
162 fn cloned(&self) -> Arc<dyn Engine + Send + Sync> {
163 Arc::new(self.clone())
164 }
165}
166
167pub struct ObjectFileEngineInner {
169 #[cfg(feature = "compiler")]
171 compiler: Option<Box<dyn Compiler>>,
172 #[cfg(feature = "compiler")]
174 features: Features,
175 signatures: SignatureRegistry,
178 prefixer: Option<Box<dyn Fn(&[u8]) -> String + Send>>,
182}
183
184impl ObjectFileEngineInner {
185 #[cfg(feature = "compiler")]
187 pub fn compiler(&self) -> Result<&dyn Compiler, CompileError> {
188 if self.compiler.is_none() {
189 return Err(CompileError::Codegen("The `ObjectFileEngine` is operating in headless mode, so it can only execute already compiled Modules.".to_string()));
190 }
191 Ok(&**self
192 .compiler
193 .as_ref()
194 .expect("Can't get compiler reference"))
195 }
196
197 #[cfg(feature = "compiler")]
198 pub(crate) fn get_prefix(&self, bytes: &[u8]) -> String {
199 if let Some(prefixer) = &self.prefixer {
200 prefixer(&bytes)
201 } else {
202 "".to_string()
203 }
204 }
205
206 #[cfg(feature = "compiler")]
207 pub(crate) fn features(&self) -> &Features {
208 &self.features
209 }
210
211 #[cfg(feature = "compiler")]
213 pub fn validate<'data>(&self, data: &'data [u8]) -> Result<(), CompileError> {
214 self.compiler()?.validate_module(self.features(), data)
215 }
216
217 #[cfg(not(feature = "compiler"))]
219 pub fn validate<'data>(&self, _data: &'data [u8]) -> Result<(), CompileError> {
220 Err(CompileError::Validate(
221 "The `ObjectFileEngine` is not compiled with compiler support, which is required for validating".to_string(),
222 ))
223 }
224
225 pub fn signatures(&self) -> &SignatureRegistry {
227 &self.signatures
228 }
229}