Serialize and deserialize compilation artifacts. (#2020)
* Serialize and deserialize Module * Use bincode to serialize * Add wasm_module_serialize; docs * Simple tests
This commit is contained in:
@@ -26,6 +26,8 @@ lazy_static = "1.4"
|
||||
log = "0.4.8"
|
||||
wat = { version = "1.0.18", optional = true }
|
||||
smallvec = "1.4.0"
|
||||
serde = { version = "1.0.94", features = ["derive"] }
|
||||
bincode = "1.2.1"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
winapi = "0.3.7"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use crate::frame_info::GlobalFrameInfoRegistration;
|
||||
use crate::runtime::Engine;
|
||||
use crate::runtime::{Config, Engine};
|
||||
use crate::types::{EntityType, ExportType, ExternType, ImportType};
|
||||
use anyhow::Result;
|
||||
use anyhow::{bail, Context, Result};
|
||||
use std::path::Path;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use wasmtime_jit::CompiledModule;
|
||||
use wasmtime_jit::{CompilationArtifacts, CompiledModule};
|
||||
|
||||
/// A compiled WebAssembly module, ready to be instantiated.
|
||||
///
|
||||
@@ -309,6 +309,51 @@ impl Module {
|
||||
})
|
||||
}
|
||||
|
||||
/// Serialize compilation artifacts to the buffer. See also `deseriaize`.
|
||||
pub fn serialize(&self) -> Result<Vec<u8>> {
|
||||
let artifacts = (
|
||||
compiler_fingerprint(self.engine.config()),
|
||||
self.compiled.to_compilation_artifacts(),
|
||||
);
|
||||
|
||||
let mut buffer = Vec::new();
|
||||
bincode::serialize_into(&mut buffer, &artifacts)?;
|
||||
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
/// Deserializes and creates a module from the compilatio nartifacts.
|
||||
/// The `serialize` saves the compilation artifacts along with the host
|
||||
/// fingerprint, which consists of target, compiler flags, and wasmtime
|
||||
/// package version.
|
||||
///
|
||||
/// The method will fail if fingerprints of current host and serialized
|
||||
/// one are different. The method does not verify the serialized artifacts
|
||||
/// for modifications or curruptions. All responsibily of signing and its
|
||||
/// verification falls on the embedder.
|
||||
pub fn deserialize(engine: &Engine, serialized: &[u8]) -> Result<Module> {
|
||||
let expected_fingerprint = compiler_fingerprint(engine.config());
|
||||
|
||||
let (fingerprint, artifacts) =
|
||||
bincode::deserialize_from::<_, (u64, CompilationArtifacts)>(serialized)
|
||||
.context("Deserialize compilation artifacts")?;
|
||||
if fingerprint != expected_fingerprint {
|
||||
bail!("Incompatible compilation artifact");
|
||||
}
|
||||
|
||||
let compiled = CompiledModule::from_artifacts(
|
||||
artifacts,
|
||||
engine.compiler().isa(),
|
||||
&*engine.config().profiler,
|
||||
)?;
|
||||
|
||||
Ok(Module {
|
||||
engine: engine.clone(),
|
||||
compiled: Arc::new(compiled),
|
||||
frame_info_registration: Arc::new(Mutex::new(None)),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn compiled_module(&self) -> &CompiledModule {
|
||||
&self.compiled
|
||||
}
|
||||
@@ -535,6 +580,13 @@ impl Module {
|
||||
}
|
||||
}
|
||||
|
||||
fn compiler_fingerprint(config: &Config) -> u64 {
|
||||
use std::hash::Hasher;
|
||||
let mut hasher = std::collections::hash_map::DefaultHasher::new();
|
||||
config.compiler_fingerprint(&mut hasher);
|
||||
hasher.finish()
|
||||
}
|
||||
|
||||
fn _assert_send_sync() {
|
||||
fn _assert<T: Send + Sync>() {}
|
||||
_assert::<Module>();
|
||||
|
||||
@@ -10,6 +10,7 @@ use std::hash::{Hash, Hasher};
|
||||
use std::path::Path;
|
||||
use std::rc::{Rc, Weak};
|
||||
use std::sync::Arc;
|
||||
use target_lexicon::Triple;
|
||||
use wasmparser::Validator;
|
||||
use wasmtime_environ::settings::{self, Configurable, SetError};
|
||||
use wasmtime_environ::{ir, isa, isa::TargetIsa, wasm, CacheConfig, Tunables};
|
||||
@@ -634,6 +635,22 @@ impl Config {
|
||||
self.tunables.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Hashes/fingerprints compiler setting to ensure that compatible
|
||||
/// compilation artifacts are used.
|
||||
pub(crate) fn compiler_fingerprint<H>(&self, state: &mut H)
|
||||
where
|
||||
H: Hasher,
|
||||
{
|
||||
self.flags.hash(state);
|
||||
self.tunables.hash(state);
|
||||
|
||||
let triple = Triple::host();
|
||||
triple.hash(state);
|
||||
|
||||
// Catch accidental bugs of reusing across wasmtime versions.
|
||||
env!("CARGO_PKG_VERSION").hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
fn round_up_to_pages(val: u64) -> u64 {
|
||||
|
||||
Reference in New Issue
Block a user