Skip to content

Commit

Permalink
Add Engine::precompile_compatibility_hash (#5826)
Browse files Browse the repository at this point in the history
This method returns a Hash, the output of which can be used to index
precompiled binaries from one Engine instance that can be deserialized
by another Engine instance.
  • Loading branch information
lann authored Apr 18, 2023
1 parent a486aa3 commit 51ed20a
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 3 deletions.
33 changes: 33 additions & 0 deletions crates/wasmtime/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,18 @@ impl Engine {
Ok(mmap.to_vec())
}

/// Returns a [`std::hash::Hash`] that can be used to check precompiled WebAssembly compatibility.
///
/// The outputs of [`Engine::precompile_module`] and [`Engine::precompile_component`]
/// are compatible with a different [`Engine`] instance only if the two engines use
/// compatible [`Config`]s. If this Hash matches between two [`Engine`]s then binaries
/// from one are guaranteed to deserialize in the other.
#[cfg(compiler)]
#[cfg_attr(nightlydoc, doc(cfg(feature = "cranelift")))] // see build.rs
pub fn precompile_compatibility_hash(&self) -> impl std::hash::Hash + '_ {
crate::module::HashedEngineCompileEnv(self)
}

pub(crate) fn run_maybe_parallel<
A: Send,
B: Send,
Expand Down Expand Up @@ -628,6 +640,11 @@ impl Default for Engine {

#[cfg(test)]
mod tests {
use std::{
collections::hash_map::DefaultHasher,
hash::{Hash, Hasher},
};

use crate::{Config, Engine, Module, OptLevel};

use anyhow::Result;
Expand Down Expand Up @@ -693,4 +710,20 @@ mod tests {

Ok(())
}

#[test]
fn precompile_compatibility_key_accounts_for_opt_level() {
fn hash_for_config(cfg: &Config) -> u64 {
let engine = Engine::new(cfg).expect("Config should be valid");
let mut hasher = DefaultHasher::new();
engine.precompile_compatibility_hash().hash(&mut hasher);
hasher.finish()
}
let mut cfg = Config::new();
cfg.cranelift_opt_level(OptLevel::None);
let opt_none_hash = hash_for_config(&cfg);
cfg.cranelift_opt_level(OptLevel::Speed);
let opt_speed_hash = hash_for_config(&cfg);
assert_ne!(opt_none_hash, opt_speed_hash)
}
}
6 changes: 3 additions & 3 deletions crates/wasmtime/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1144,10 +1144,10 @@ fn _assert_send_sync() {
/// The hash computed for this structure is used to key the global wasmtime
/// cache and dictates whether artifacts are reused. Consequently the contents
/// of this hash dictate when artifacts are or aren't re-used.
#[cfg(all(feature = "cache", compiler))]
struct HashedEngineCompileEnv<'a>(&'a Engine);
#[cfg(compiler)]
pub(crate) struct HashedEngineCompileEnv<'a>(pub &'a Engine);

#[cfg(all(feature = "cache", compiler))]
#[cfg(compiler)]
impl std::hash::Hash for HashedEngineCompileEnv<'_> {
fn hash<H: std::hash::Hasher>(&self, hasher: &mut H) {
// Hash the compiler's state based on its target and configuration.
Expand Down

0 comments on commit 51ed20a

Please sign in to comment.