* Move wasm data/debuginfo into the ELF compilation image This commit moves existing allocations of `Box<[u8]>` stored separately from compilation's final ELF image into the ELF image itself. The goal of this commit is to reduce the amount of data which `bincode` will need to process in the future. DWARF debugging information and wasm data segments can be quite large, and they're relatively rarely read, so there's typically no need to copy them around. Instead by moving them into the ELF image this opens up the opportunity in the future to eliminate copies and use data directly as-found in the image itself. For information accessed possibly-multiple times, such as the wasm data ranges, the indexes of the data within the ELF image are computed when a `CompiledModule` is created. These indexes are then used to directly index into the image without having to root around in the ELF file each time they're accessed. One other change located here is that the symbolication context previously cloned the debug information into it to adhere to the `'static` lifetime safely, but this isn't actually ever used in `wasmtime` right now so the unsafety around this has been removed and instead borrowed data is returned (no more clones, yay!). * Fix lightbeam
68 lines
2.1 KiB
Rust
68 lines
2.1 KiB
Rust
use anyhow::{bail, Context as _, Result};
|
|
use std::mem;
|
|
use target_lexicon::Triple;
|
|
use wasmparser::WasmFeatures;
|
|
use wasmtime::Strategy;
|
|
use wasmtime_environ::{ModuleEnvironment, PrimaryMap, Tunables};
|
|
|
|
/// Creates object file from binary wasm data.
|
|
pub fn compile_to_obj(
|
|
wasm: &[u8],
|
|
target: Option<&Triple>,
|
|
strategy: Strategy,
|
|
enable_simd: bool,
|
|
opt_level: wasmtime::OptLevel,
|
|
debug_info: bool,
|
|
) -> Result<Vec<u8>> {
|
|
match strategy {
|
|
Strategy::Cranelift | Strategy::Auto => {}
|
|
other => panic!("unsupported strategy {:?}", other),
|
|
}
|
|
let mut builder = wasmtime_cranelift::builder();
|
|
if let Some(target) = target {
|
|
builder.target(target.clone())?;
|
|
}
|
|
let mut features = WasmFeatures::default();
|
|
|
|
if enable_simd {
|
|
builder.enable("enable_simd").unwrap();
|
|
features.simd = true;
|
|
}
|
|
|
|
match opt_level {
|
|
wasmtime::OptLevel::None => {}
|
|
wasmtime::OptLevel::Speed => {
|
|
builder.set("opt_level", "speed").unwrap();
|
|
}
|
|
wasmtime::OptLevel::SpeedAndSize => {
|
|
builder.set("opt_level", "speed_and_size").unwrap();
|
|
}
|
|
other => bail!("unknown optimization level {:?}", other),
|
|
}
|
|
|
|
// TODO: Expose the tunables as command-line flags.
|
|
let mut tunables = Tunables::default();
|
|
tunables.generate_native_debuginfo = debug_info;
|
|
tunables.parse_wasm_debuginfo = debug_info;
|
|
|
|
let compiler = builder.build();
|
|
let environ = ModuleEnvironment::new(&tunables, &features);
|
|
let (_main_module, mut translation, types) = environ
|
|
.translate(wasm)
|
|
.context("failed to translate module")?;
|
|
assert_eq!(translation.len(), 1);
|
|
let mut funcs = PrimaryMap::default();
|
|
for (index, func) in mem::take(&mut translation[0].function_body_inputs) {
|
|
funcs.push(compiler.compile_function(&translation[0], index, func, &tunables, &types)?);
|
|
}
|
|
let mut obj = compiler.object()?;
|
|
compiler.emit_obj(
|
|
&translation[0],
|
|
&types,
|
|
funcs,
|
|
tunables.generate_native_debuginfo,
|
|
&mut obj,
|
|
)?;
|
|
Ok(obj.write()?)
|
|
}
|