Merge branch 'master' into feature/benchmarks

This commit is contained in:
Lachlan Sneff
2019-02-22 13:32:09 -08:00
committed by GitHub
7 changed files with 100 additions and 21 deletions

View File

@ -130,7 +130,7 @@ wasmer_link() {
printf "$cyan> Adding to bash profile...$reset\n" printf "$cyan> Adding to bash profile...$reset\n"
WASMER_PROFILE="$(wasmer_detect_profile)" WASMER_PROFILE="$(wasmer_detect_profile)"
LOAD_STR="\n# Wasmer\nexport WASMER_DIR=\"\$HOME/.wasmer\"\n[ -s \"\$WASMER_DIR/wasmer.sh\" ] && source \"\$WASMER_DIR/wasmer.sh\" # This loads wasmer\n" LOAD_STR="\n# Wasmer\nexport WASMER_DIR=\"\$HOME/.wasmer\"\n[ -s \"\$WASMER_DIR/wasmer.sh\" ] && source \"\$WASMER_DIR/wasmer.sh\" # This loads wasmer\n"
SOURCE_STR="# Wasmer config\nexport WASMER_DIR=\"\$HOME/.wasmer\"\nexport PATH=\"\$HOME/.wasmer/bin:\$PATH\"\n" SOURCE_STR="# Wasmer config\nexport WASMER_DIR=\"\$HOME/.wasmer\"\nexport WASMER_CACHE_DIR=\"\$WASMER_DIR/cache\"\nexport PATH=\"\$HOME/.wasmer/bin:\$PATH\"\n"
# We create the wasmer.sh file # We create the wasmer.sh file
echo "$SOURCE_STR" > "$HOME/.wasmer/wasmer.sh" echo "$SOURCE_STR" > "$HOME/.wasmer/wasmer.sh"

View File

@ -50,8 +50,6 @@ impl Module {
namespace_table: StringTable::new(), namespace_table: StringTable::new(),
name_table: StringTable::new(), name_table: StringTable::new(),
wasm_hash: WasmHash::generate(wasm),
}, },
} }
} }

View File

@ -178,7 +178,6 @@ impl Artifact {
magic: WASMER_CACHE_MAGIC, magic: WASMER_CACHE_MAGIC,
version: CURRENT_CACHE_VERSION, version: CURRENT_CACHE_VERSION,
data_len: 0, data_len: 0,
wasm_hash: self.inner.info.wasm_hash.into_array(),
}; };
let mut buffer = cache_header.as_slice().to_vec(); let mut buffer = cache_header.as_slice().to_vec();
@ -203,5 +202,5 @@ pub trait Cache {
type StoreError: fmt::Debug; type StoreError: fmt::Debug;
fn load(&self, key: WasmHash) -> Result<Module, Self::LoadError>; fn load(&self, key: WasmHash) -> Result<Module, Self::LoadError>;
fn store(&mut self, module: Module) -> Result<WasmHash, Self::StoreError>; fn store(&mut self, key: WasmHash, module: Module) -> Result<(), Self::StoreError>;
} }

View File

@ -56,8 +56,6 @@ pub struct ModuleInfo {
pub namespace_table: StringTable<NamespaceIndex>, pub namespace_table: StringTable<NamespaceIndex>,
pub name_table: StringTable<NameIndex>, pub name_table: StringTable<NameIndex>,
pub wasm_hash: WasmHash,
} }
/// A compiled WebAssembly module. /// A compiled WebAssembly module.
@ -116,6 +114,14 @@ impl Module {
} }
} }
impl Clone for Module {
fn clone(&self) -> Self {
Self {
inner: Arc::clone(&self.inner),
}
}
}
impl ModuleInner {} impl ModuleInner {}
#[doc(hidden)] #[doc(hidden)]

View File

@ -565,8 +565,6 @@ mod vm_ctx_tests {
namespace_table: StringTable::new(), namespace_table: StringTable::new(),
name_table: StringTable::new(), name_table: StringTable::new(),
wasm_hash: WasmHash::generate(&[]),
}, },
} }
} }

View File

@ -19,19 +19,19 @@ pub use wasmer_runtime_core::cache::{Artifact, Cache, WasmHash};
/// # Usage: /// # Usage:
/// ///
/// ```rust /// ```rust
/// use wasmer_runtime::cache::{Cache, FileSystemCache}; /// use wasmer_runtime::cache::{Cache, FileSystemCache, WasmHash};
/// ///
/// # use wasmer_runtime::{Module, error::CacheError}; /// # use wasmer_runtime::{Module, error::CacheError};
/// fn store_and_load_module(module: Module) -> Result<Module, CacheError> { /// fn store_module(module: Module) -> Result<Module, CacheError> {
/// // Create a new file system cache. /// // Create a new file system cache.
/// // This is unsafe because we can't ensure that the artifact wasn't /// // This is unsafe because we can't ensure that the artifact wasn't
/// // corrupted or tampered with. /// // corrupted or tampered with.
/// let mut fs_cache = unsafe { FileSystemCache::new("some/directory/goes/here")? }; /// let mut fs_cache = unsafe { FileSystemCache::new("some/directory/goes/here")? };
/// // Store a module into the cache. /// // Compute a key for a given WebAssembly binary
/// // The returned `key` is equivalent to `module.info().wasm_hash`. /// let key = WasmHash::generate(&[]);
/// let key = fs_cache.store(module)?; /// // Store a module into the cache given a key
/// // Load the module back from the cache with the `key`. /// fs_cache.store(key, module.clone())?;
/// fs_cache.load(key) /// Ok(module)
/// } /// }
/// ``` /// ```
pub struct FileSystemCache { pub struct FileSystemCache {
@ -92,8 +92,7 @@ impl Cache for FileSystemCache {
unsafe { wasmer_runtime_core::load_cache_with(serialized_cache, super::default_compiler()) } unsafe { wasmer_runtime_core::load_cache_with(serialized_cache, super::default_compiler()) }
} }
fn store(&mut self, module: Module) -> Result<WasmHash, CacheError> { fn store(&mut self, key: WasmHash, module: Module) -> Result<(), CacheError> {
let key = module.info().wasm_hash;
let filename = key.encode(); let filename = key.encode();
let mut new_path_buf = self.path.clone(); let mut new_path_buf = self.path.clone();
new_path_buf.push(filename); new_path_buf.push(filename);
@ -104,6 +103,6 @@ impl Cache for FileSystemCache {
let mut file = File::create(new_path_buf)?; let mut file = File::create(new_path_buf)?;
file.write_all(&buffer)?; file.write_all(&buffer)?;
Ok(key) Ok(())
} }
} }

View File

@ -1,5 +1,7 @@
extern crate structopt; extern crate structopt;
use std::env;
use std::fs;
use std::fs::File; use std::fs::File;
use std::io; use std::io;
use std::io::Read; use std::io::Read;
@ -11,6 +13,8 @@ use structopt::StructOpt;
use wasmer::webassembly::InstanceABI; use wasmer::webassembly::InstanceABI;
use wasmer::*; use wasmer::*;
use wasmer_emscripten; use wasmer_emscripten;
use wasmer_runtime::cache::{Cache as BaseCache, FileSystemCache, WasmHash};
use wasmer_runtime::error::CacheError;
#[derive(Debug, StructOpt)] #[derive(Debug, StructOpt)]
#[structopt(name = "wasmer", about = "Wasm execution runtime.")] #[structopt(name = "wasmer", about = "Wasm execution runtime.")]
@ -20,6 +24,10 @@ enum CLIOptions {
#[structopt(name = "run")] #[structopt(name = "run")]
Run(Run), Run(Run),
/// Wasmer cache
#[structopt(name = "cache")]
Cache(Cache),
/// Update wasmer to the latest version /// Update wasmer to the latest version
#[structopt(name = "self-update")] #[structopt(name = "self-update")]
SelfUpdate, SelfUpdate,
@ -30,6 +38,10 @@ struct Run {
#[structopt(short = "d", long = "debug")] #[structopt(short = "d", long = "debug")]
debug: bool, debug: bool,
// Disable the cache
#[structopt(long = "disable-cache")]
disable_cache: bool,
/// Input file /// Input file
#[structopt(parse(from_os_str))] #[structopt(parse(from_os_str))]
path: PathBuf, path: PathBuf,
@ -39,6 +51,15 @@ struct Run {
args: Vec<String>, args: Vec<String>,
} }
#[derive(Debug, StructOpt)]
enum Cache {
#[structopt(name = "clean")]
Clean,
#[structopt(name = "dir")]
Dir,
}
/// Read the contents of a file /// Read the contents of a file
fn read_file_contents(path: &PathBuf) -> Result<Vec<u8>, io::Error> { fn read_file_contents(path: &PathBuf) -> Result<Vec<u8>, io::Error> {
let mut buffer: Vec<u8> = Vec::new(); let mut buffer: Vec<u8> = Vec::new();
@ -49,6 +70,18 @@ fn read_file_contents(path: &PathBuf) -> Result<Vec<u8>, io::Error> {
Ok(buffer) Ok(buffer)
} }
fn get_cache_dir() -> PathBuf {
match env::var("WASMER_CACHE_DIR") {
Ok(dir) => PathBuf::from(dir),
Err(_) => {
// We use a temporal directory for saving cache files
let mut temp_dir = env::temp_dir();
temp_dir.push("wasmer");
temp_dir
}
}
}
/// Execute a wasm/wat file /// Execute a wasm/wat file
fn execute_wasm(options: &Run) -> Result<(), String> { fn execute_wasm(options: &Run) -> Result<(), String> {
let wasm_path = &options.path; let wasm_path = &options.path;
@ -66,9 +99,45 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
.map_err(|e| format!("Can't convert from wast to wasm: {:?}", e))?; .map_err(|e| format!("Can't convert from wast to wasm: {:?}", e))?;
} }
let module = if !options.disable_cache {
// If we have cache enabled
// We generate a hash for the given binary, so we can use it as key
// for the Filesystem cache
let hash = WasmHash::generate(&wasm_binary);
let wasmer_cache_dir = get_cache_dir();
// We create a new cache instance.
// It could be possible to use any other kinds of caching, as long as they
// implement the Cache trait (with save and load functions)
let mut cache = unsafe {
FileSystemCache::new(wasmer_cache_dir).map_err(|e| format!("Cache error: {:?}", e))?
};
// cache.load will return the Module if it's able to deserialize it properly, and an error if:
// * The file is not found
// * The file exists, but it's corrupted or can't be converted to a module
let module = match cache.load(hash) {
Ok(module) => {
// We are able to load the module from cache
module
}
Err(_) => {
let module = webassembly::compile(&wasm_binary[..]) let module = webassembly::compile(&wasm_binary[..])
.map_err(|e| format!("Can't compile module: {:?}", e))?; .map_err(|e| format!("Can't compile module: {:?}", e))?;
// We save the module into a cache file
cache.store(hash, module.clone()).unwrap();
module
}
};
module
} else {
webassembly::compile(&wasm_binary[..])
.map_err(|e| format!("Can't compile module: {:?}", e))?
};
let (_abi, import_object, _em_globals) = if wasmer_emscripten::is_emscripten_module(&module) { let (_abi, import_object, _em_globals) = if wasmer_emscripten::is_emscripten_module(&module) {
let mut emscripten_globals = wasmer_emscripten::EmscriptenGlobals::new(&module); let mut emscripten_globals = wasmer_emscripten::EmscriptenGlobals::new(&module);
( (
@ -119,5 +188,15 @@ fn main() {
CLIOptions::SelfUpdate => { CLIOptions::SelfUpdate => {
println!("Self update is not supported on Windows. Use install instructions on the Wasmer homepage: https://wasmer.io"); println!("Self update is not supported on Windows. Use install instructions on the Wasmer homepage: https://wasmer.io");
} }
CLIOptions::Cache(cache) => match cache {
Cache::Clean => {
let cache_dir = get_cache_dir();
fs::remove_dir_all(cache_dir.clone()).expect("Can't remove cache dir");
fs::create_dir(cache_dir.clone()).expect("Can't create cache dir");
}
Cache::Dir => {
println!("{}", get_cache_dir().to_string_lossy());
}
},
} }
} }