linera_wasmer/sys/
engine.rs

1use std::{path::Path, sync::Arc};
2
3use shared_buffer::OwnedBuffer;
4pub use wasmer_compiler::{
5    Artifact, BaseTunables, CompilerConfig, Engine, EngineBuilder, Tunables,
6};
7#[cfg(feature = "compiler")]
8use wasmer_types::Features;
9use wasmer_types::{DeserializeError, HashAlgorithm, Target};
10
11/// Get the default config for the sys Engine
12#[allow(unreachable_code)]
13pub fn get_default_compiler_config() -> Option<Box<dyn wasmer_compiler::CompilerConfig>> {
14    cfg_if::cfg_if! {
15        if #[cfg(feature = "cranelift")] {
16            Some(Box::<wasmer_compiler_cranelift::Cranelift>::default())
17        } else if #[cfg(feature = "llvm")] {
18            Some(Box::<wasmer_compiler_llvm::LLVM>::default())
19        } else if #[cfg(feature = "singlepass")] {
20            Some(Box::<wasmer_compiler_singlepass::Singlepass>::default())
21        }
22        else {
23            None
24        }
25    }
26}
27
28/// Returns the default engine for the Sys engine
29pub(crate) fn default_engine() -> Engine {
30    #[allow(unreachable_code, unused_mut)]
31    fn get_engine() -> Engine {
32        cfg_if::cfg_if! {
33            if #[cfg(feature = "compiler")] {
34                if let Some(config) = get_default_compiler_config() {
35                    EngineBuilder::new(config)
36                        .engine()
37                } else {
38                    EngineBuilder::headless()
39                        .engine()
40                }
41            } else {
42                EngineBuilder::headless().engine()
43            }
44        }
45    }
46
47    let mut engine = get_engine();
48    let tunables = BaseTunables::for_target(engine.target());
49    engine.set_tunables(tunables);
50    engine
51}
52
53/// The custom trait to access to all the `sys` function in the common
54/// engine.
55pub trait NativeEngineExt {
56    /// Create a new `Engine` with the given config
57    #[cfg(feature = "compiler")]
58    fn new(compiler_config: Box<dyn CompilerConfig>, target: Target, features: Features) -> Self;
59
60    /// Sets the hash algorithm
61    fn set_hash_algorithm(&mut self, hash_algorithm: Option<HashAlgorithm>);
62
63    /// Create a headless `Engine`
64    ///
65    /// A headless engine is an engine without any compiler attached.
66    /// This is useful for assuring a minimal runtime for running
67    /// WebAssembly modules.
68    ///
69    /// For example, for running in IoT devices where compilers are very
70    /// expensive, or also to optimize startup speed.
71    ///
72    /// # Important
73    ///
74    /// Headless engines can't compile or validate any modules,
75    /// they just take already processed Modules (via `Module::serialize`).
76    fn headless() -> Self;
77
78    /// Gets the target
79    fn target(&self) -> &Target;
80
81    /// Attach a Tunable to this engine
82    fn set_tunables(&mut self, tunables: impl Tunables + Send + Sync + 'static);
83
84    /// Get a reference to attached Tunable of this engine
85    fn tunables(&self) -> &dyn Tunables;
86
87    /// Load a serialized WebAssembly module from a memory mapped file and deserialize it.
88    ///
89    /// NOTE: you should almost always prefer [`Self::deserialize_from_mmapped_file`].
90    ///
91    /// # Safety
92    /// See [`Artifact::deserialize_unchecked`].
93    unsafe fn deserialize_from_mmapped_file_unchecked(
94        &self,
95        file_ref: &Path,
96    ) -> Result<crate::Module, DeserializeError>;
97
98    /// Load a serialized WebAssembly module from a memory mapped file and deserialize it.
99    ///
100    /// # Safety
101    /// See [`Artifact::deserialize`].
102    unsafe fn deserialize_from_mmapped_file(
103        &self,
104        file_ref: &Path,
105    ) -> Result<crate::Module, DeserializeError>;
106}
107
108impl NativeEngineExt for crate::engine::Engine {
109    #[cfg(feature = "compiler")]
110    fn new(compiler_config: Box<dyn CompilerConfig>, target: Target, features: Features) -> Self {
111        Self(Engine::new(compiler_config, target, features))
112    }
113
114    fn headless() -> Self {
115        Self(Engine::headless())
116    }
117
118    fn target(&self) -> &Target {
119        self.0.target()
120    }
121
122    fn set_tunables(&mut self, tunables: impl Tunables + Send + Sync + 'static) {
123        self.0.set_tunables(tunables)
124    }
125
126    fn tunables(&self) -> &dyn Tunables {
127        self.0.tunables()
128    }
129
130    unsafe fn deserialize_from_mmapped_file_unchecked(
131        &self,
132        file_ref: &Path,
133    ) -> Result<crate::Module, DeserializeError> {
134        let file = std::fs::File::open(file_ref)?;
135        let artifact = Arc::new(Artifact::deserialize_unchecked(
136            &self.0,
137            OwnedBuffer::from_file(&file)
138                .map_err(|e| DeserializeError::Generic(format!("{e:?}")))?,
139        )?);
140        Ok(crate::Module(super::module::Module::from_artifact(
141            artifact,
142        )))
143    }
144
145    unsafe fn deserialize_from_mmapped_file(
146        &self,
147        file_ref: &Path,
148    ) -> Result<crate::Module, DeserializeError> {
149        let file = std::fs::File::open(file_ref)?;
150        let artifact = Arc::new(Artifact::deserialize(
151            &self.0,
152            OwnedBuffer::from_file(&file)
153                .map_err(|e| DeserializeError::Generic(format!("{e:?}")))?,
154        )?);
155        Ok(crate::Module(super::module::Module::from_artifact(
156            artifact,
157        )))
158    }
159
160    fn set_hash_algorithm(&mut self, hash_algorithm: Option<HashAlgorithm>) {
161        self.0.set_hash_algorithm(hash_algorithm)
162    }
163}