Move compilation into Module from Instance. (#822)

* Move compilation into Module from Instance.

* Fix fuzzing

* Use wasmtime::Module in fuzzing crates

Instead of wasmtime_jit.

* Compile eagerly.

* Review fixes.

* Always use the saved name.

* Preserve the former behavior for fuzzing oracle
This commit is contained in:
Sergei Pepyakin
2020-01-16 23:37:10 +01:00
committed by Alex Crichton
parent e474a9e822
commit 5b8be5f262
12 changed files with 378 additions and 413 deletions

View File

@@ -9,6 +9,7 @@ use wasmparser::{
validate, CustomSectionKind, ExternalKind, ImportSectionEntryType, ModuleReader, Name,
OperatorValidatorConfig, SectionCode, ValidatingParserConfig,
};
use wasmtime_jit::CompiledModule;
fn into_memory_type(mt: wasmparser::MemoryType) -> MemoryType {
assert!(!mt.shared);
@@ -56,12 +57,6 @@ fn into_table_type(tt: wasmparser::TableType) -> TableType {
TableType::new(ty, limits)
}
#[derive(Clone)]
pub(crate) enum ModuleCodeSource {
Binary(Box<[u8]>),
Unknown,
}
/// A compiled WebAssembly module, ready to be instantiated.
///
/// A `Module` is a compiled in-memory representation of an input WebAssembly
@@ -84,10 +79,10 @@ pub struct Module {
struct ModuleInner {
store: Store,
source: ModuleCodeSource,
imports: Box<[ImportType]>,
exports: Box<[ExportType]>,
name: Option<String>,
compiled: Option<CompiledModule>,
}
impl Module {
@@ -131,7 +126,7 @@ impl Module {
// Note that the call to `unsafe` here should be ok because we
// previously validated the binary, meaning we're guaranteed to pass a
// valid binary for `store`.
unsafe { Module::new_unchecked(store, binary) }
unsafe { Module::new_internal(store, binary, None) }
}
/// Creates a new WebAssembly `Module` from the given in-memory `binary`
@@ -139,9 +134,11 @@ impl Module {
///
/// See [`Module::new`] for other details.
pub fn new_with_name(store: &Store, binary: &[u8], name: &str) -> Result<Module> {
let mut ret = Module::new(store, binary)?;
Rc::get_mut(&mut ret.inner).unwrap().name = Some(name.to_string());
Ok(ret)
Module::validate(store, binary)?;
// Note that the call to `unsafe` here should be ok because we
// previously validated the binary, meaning we're guaranteed to pass a
// valid binary for `store`.
unsafe { Module::new_internal(store, binary, Some(name)) }
}
/// Creates a new WebAssembly `Module` from the given in-memory `binary`
@@ -171,8 +168,20 @@ impl Module {
/// be somewhat valid for decoding purposes, and the basics of decoding can
/// still fail.
pub unsafe fn new_unchecked(store: &Store, binary: &[u8]) -> Result<Module> {
Module::new_internal(store, binary, None)
}
/// Creates a new `Module` and compiles it without doing any validation.
unsafe fn new_internal(store: &Store, binary: &[u8], name: Option<&str>) -> Result<Module> {
let mut ret = Module::empty(store);
ret.read_imports_and_exports(binary)?;
let inner = Rc::get_mut(&mut ret.inner).unwrap();
if let Some(name) = name {
// Assign or override the module's name if supplied.
inner.name = Some(name.to_string());
}
inner.compiled = Some(compile(store, binary, inner.name.as_deref())?);
Ok(ret)
}
@@ -219,19 +228,16 @@ impl Module {
Module {
inner: Rc::new(ModuleInner {
store: store.clone(),
source: ModuleCodeSource::Unknown,
imports: Box::new([]),
exports: Box::new([]),
name: None,
compiled: None,
}),
}
}
pub(crate) fn binary(&self) -> Option<&[u8]> {
match &self.inner.source {
ModuleCodeSource::Binary(b) => Some(b),
_ => None,
}
pub(crate) fn compiled_module(&self) -> Option<&CompiledModule> {
self.inner.compiled.as_ref()
}
/// Returns identifier/name that this [`Module`] has. This name
@@ -259,7 +265,6 @@ impl Module {
fn read_imports_and_exports(&mut self, binary: &[u8]) -> Result<()> {
let inner = Rc::get_mut(&mut self.inner).unwrap();
inner.source = ModuleCodeSource::Binary(binary.into());
let mut reader = ModuleReader::new(binary)?;
let mut imports = Vec::new();
let mut exports = Vec::new();
@@ -387,3 +392,21 @@ impl Module {
Ok(())
}
}
fn compile(store: &Store, binary: &[u8], module_name: Option<&str>) -> Result<CompiledModule> {
let exports = store.global_exports().clone();
let compiled_module = CompiledModule::new(
&mut store.compiler_mut(),
binary,
module_name,
exports,
store.engine().config().debug_info,
)?;
// Register all module signatures
for signature in compiled_module.module().signatures.values() {
store.register_wasmtime_signature(signature);
}
Ok(compiled_module)
}