Add a cranelift compile-time feature to wasmtime (#3206)

* Remove unnecessary into_iter/map

Forgotten from a previous refactoring, this variable was already of the
right type!

* Move `wasmtime_jit::Compiler` into `wasmtime`

This `Compiler` struct is mostly a historical artifact at this point and
wasn't necessarily pulling much weight any more. This organization also
doesn't lend itself super well to compiling out `cranelift` when the
`Compiler` here is used for both parallel iteration configuration
settings as well as compilation.

The movement into `wasmtime` is relatively small, with
`Module::build_artifacts` being the main function added here which is a
merging of the previous functions removed from the `wasmtime-jit` crate.

* Add a `cranelift` compile-time feature to `wasmtime`

This commit concludes the saga of refactoring Wasmtime and making
Cranelift an optional dependency by adding a new Cargo feature to the
`wasmtime` crate called `cranelift`, which is enabled by default.

This feature is implemented by having a new cfg for `wasmtime` itself,
`cfg(compiler)`, which is used wherever compilation is necessary. This
bubbles up to disable APIs such as `Module::new`, `Func::new`,
`Engine::precompile_module`, and a number of `Config` methods affecting
compiler configuration. Checks are added to CI that when built in this
mode Wasmtime continues to successfully build. It's hoped that although
this is effectively "sprinkle `#[cfg]` until things compile" this won't
be too too bad to maintain over time since it's also an use case we're
interested in supporting.

With `cranelift` disabled the only way to create a `Module` is with the
`Module::deserialize` method, which requires some form of precompiled
artifact.

Two consequences of this change are:

* `Module::serialize` is also disabled in this mode. The reason for this
  is that serialized modules contain ISA/shared flags encoded in them
  which were used to produce the compiled code. There's no storage for
  this if compilation is disabled. This could probably be re-enabled in
  the future if necessary, but it may not end up being all that necessary.

* Deserialized modules are not checked to ensure that their ISA/shared
  flags are compatible with the host CPU. This is actually already the
  case, though, with normal modules. We'll likely want to fix this in
  the future using a shared implementation for both these locations.

Documentation should be updated to indicate that `cranelift` can be
disabled, although it's not really the most prominent documentation
because this is expected to be a somewhat niche use case (albeit
important, just not too common).

* Always enable cranelift for the C API

* Fix doc example builds

* Fix check tests on GitHub Actions
This commit is contained in:
Alex Crichton
2021-08-18 16:47:47 -05:00
committed by GitHub
parent 7a19b8fe2c
commit ddfadaeb38
22 changed files with 418 additions and 436 deletions

View File

@@ -4,7 +4,6 @@
//! steps.
use crate::code_memory::CodeMemory;
use crate::compiler::{Compilation, Compiler};
use crate::debug::create_gdbjit_image;
use crate::link::link_module;
use anyhow::Result;
@@ -14,8 +13,8 @@ use std::sync::Arc;
use thiserror::Error;
use wasmtime_environ::{
CompileError, DebugInfoData, DefinedFuncIndex, FunctionInfo, InstanceSignature,
InstanceTypeIndex, Module, ModuleEnvironment, ModuleSignature, ModuleTranslation,
ModuleTypeIndex, PrimaryMap, SignatureIndex, StackMapInformation, WasmFuncType,
InstanceTypeIndex, Module, ModuleSignature, ModuleTranslation, ModuleTypeIndex, PrimaryMap,
SignatureIndex, StackMapInformation, Tunables, WasmFuncType,
};
use wasmtime_profiling::ProfilingAgent;
use wasmtime_runtime::{GdbJitImageRegistration, InstantiationError, VMFunctionBody, VMTrampoline};
@@ -84,70 +83,32 @@ struct DebugInfo {
}
impl CompilationArtifacts {
/// Creates a `CompilationArtifacts` for a singular translated wasm module.
///
/// The `use_paged_init` argument controls whether or not an attempt is made to
/// organize linear memory initialization data as entire pages or to leave
/// the memory initialization data as individual segments.
pub fn build(
compiler: &Compiler,
data: &[u8],
use_paged_mem_init: bool,
) -> Result<(usize, Vec<CompilationArtifacts>, TypeTables), SetupError> {
let (main_module, translations, types) =
ModuleEnvironment::new(compiler.tunables(), compiler.features())
.translate(data)
.map_err(|error| SetupError::Compile(CompileError::Wasm(error)))?;
let list = compiler.run_maybe_parallel::<_, _, SetupError, _>(
translations,
|mut translation| {
let Compilation { obj, funcs } = compiler.compile(&mut translation, &types)?;
let ModuleTranslation {
mut module,
debuginfo,
has_unparsed_debuginfo,
..
} = translation;
if use_paged_mem_init {
if let Some(init) = module.memory_initialization.to_paged(&module) {
module.memory_initialization = init;
}
}
Ok(CompilationArtifacts {
module: Arc::new(module),
obj: obj.into_boxed_slice(),
funcs: funcs
.into_iter()
.map(|(_, func)| FunctionInfo {
stack_maps: func.stack_maps,
traps: func.traps,
address_map: func.address_map,
})
.collect(),
native_debug_info_present: compiler.tunables().generate_native_debuginfo,
debug_info: if compiler.tunables().parse_wasm_debuginfo {
Some(debuginfo.into())
} else {
None
},
has_unparsed_debuginfo,
})
/// Creates a new `CompilationArtifacts` from the final results of
/// compilation.
pub fn new(
translation: ModuleTranslation<'_>,
obj: Vec<u8>,
funcs: PrimaryMap<DefinedFuncIndex, FunctionInfo>,
tunables: &Tunables,
) -> CompilationArtifacts {
let ModuleTranslation {
module,
debuginfo,
has_unparsed_debuginfo,
..
} = translation;
CompilationArtifacts {
module: Arc::new(module),
obj: obj.into_boxed_slice(),
funcs,
native_debug_info_present: tunables.generate_native_debuginfo,
debug_info: if tunables.parse_wasm_debuginfo {
Some(debuginfo.into())
} else {
None
},
)?;
Ok((
main_module,
list,
TypeTables {
wasm_signatures: types.wasm_signatures,
module_signatures: types.module_signatures,
instance_signatures: types.instance_signatures,
},
))
has_unparsed_debuginfo,
}
}
}
@@ -189,16 +150,6 @@ pub struct CompiledModule {
}
impl CompiledModule {
/// Creates a list of compiled modules from the given list of compilation
/// artifacts.
pub fn from_artifacts_list(
artifacts: Vec<CompilationArtifacts>,
profiler: &dyn ProfilingAgent,
compiler: &Compiler,
) -> Result<Vec<Arc<Self>>, SetupError> {
compiler.run_maybe_parallel(artifacts, |a| CompiledModule::from_artifacts(a, profiler))
}
/// Creates `CompiledModule` directly from `CompilationArtifacts`.
pub fn from_artifacts(
artifacts: CompilationArtifacts,