Move wasm data/debuginfo into the ELF compilation image (#3235)
* 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
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use crate::debug::ModuleMemoryOffset;
|
||||
use crate::func_environ::{get_func_name, FuncEnvironment};
|
||||
use crate::obj::{ObjectBuilder, ObjectBuilderTarget};
|
||||
use crate::obj::ObjectBuilder;
|
||||
use crate::{
|
||||
blank_sig, func_signature, indirect_signature, value_type, wasmtime_call_conv,
|
||||
CompiledFunction, Relocation, RelocationTarget,
|
||||
@@ -18,6 +18,7 @@ use cranelift_wasm::{
|
||||
DefinedFuncIndex, DefinedMemoryIndex, FuncIndex, FuncTranslator, MemoryIndex, SignatureIndex,
|
||||
WasmFuncType,
|
||||
};
|
||||
use object::write::Object;
|
||||
use std::any::Any;
|
||||
use std::cmp;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
@@ -221,7 +222,8 @@ impl wasmtime_environ::Compiler for Compiler {
|
||||
types: &TypeTables,
|
||||
funcs: PrimaryMap<DefinedFuncIndex, Box<dyn Any + Send>>,
|
||||
emit_dwarf: bool,
|
||||
) -> Result<(Vec<u8>, PrimaryMap<DefinedFuncIndex, FunctionInfo>)> {
|
||||
obj: &mut Object,
|
||||
) -> Result<PrimaryMap<DefinedFuncIndex, FunctionInfo>> {
|
||||
const CODE_SECTION_ALIGNMENT: u64 = 0x1000;
|
||||
let funcs: crate::CompiledFunctions = funcs
|
||||
.into_iter()
|
||||
@@ -244,8 +246,7 @@ impl wasmtime_environ::Compiler for Compiler {
|
||||
trampolines.push((i, func));
|
||||
}
|
||||
|
||||
let target = ObjectBuilderTarget::elf(self.isa.triple().architecture)?;
|
||||
let mut builder = ObjectBuilder::new(target, &translation.module);
|
||||
let mut builder = ObjectBuilder::new(obj, &translation.module);
|
||||
|
||||
for (i, func) in funcs.iter() {
|
||||
builder.func(i, func);
|
||||
@@ -285,21 +286,24 @@ impl wasmtime_environ::Compiler for Compiler {
|
||||
builder.dwarf_sections(&dwarf_sections)?;
|
||||
}
|
||||
|
||||
Ok((
|
||||
builder.finish(&*self.isa)?,
|
||||
funcs.into_iter().map(|(_, f)| f.info).collect(),
|
||||
))
|
||||
builder.finish(&*self.isa)?;
|
||||
Ok(funcs.into_iter().map(|(_, f)| f.info).collect())
|
||||
}
|
||||
|
||||
fn emit_trampoline_obj(&self, ty: &WasmFuncType, host_fn: usize) -> Result<Vec<u8>> {
|
||||
fn emit_trampoline_obj(
|
||||
&self,
|
||||
ty: &WasmFuncType,
|
||||
host_fn: usize,
|
||||
obj: &mut Object,
|
||||
) -> Result<()> {
|
||||
let host_to_wasm = self.host_to_wasm_trampoline(ty)?;
|
||||
let wasm_to_host = self.wasm_to_host_trampoline(ty, host_fn)?;
|
||||
let target = ObjectBuilderTarget::elf(self.isa.triple().architecture)?;
|
||||
let module = Module::new();
|
||||
let mut builder = ObjectBuilder::new(target, &module);
|
||||
let mut builder = ObjectBuilder::new(obj, &module);
|
||||
builder.trampoline(SignatureIndex::new(0), &host_to_wasm);
|
||||
builder.trampoline(SignatureIndex::new(1), &wasm_to_host);
|
||||
Ok(builder.finish(&*self.isa)?)
|
||||
builder.finish(&*self.isa)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn triple(&self) -> &target_lexicon::Triple {
|
||||
|
||||
@@ -29,8 +29,8 @@ use object::write::{
|
||||
SymbolSection,
|
||||
};
|
||||
use object::{
|
||||
elf, Architecture, BinaryFormat, Endianness, RelocationEncoding, RelocationKind, SectionKind,
|
||||
SymbolFlags, SymbolKind, SymbolScope,
|
||||
elf, Architecture, RelocationEncoding, RelocationKind, SectionKind, SymbolFlags, SymbolKind,
|
||||
SymbolScope,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
@@ -39,22 +39,6 @@ use wasmtime_environ::{
|
||||
DefinedFuncIndex, EntityRef, FuncIndex, Module, PrimaryMap, SignatureIndex,
|
||||
};
|
||||
|
||||
fn to_object_architecture(
|
||||
arch: target_lexicon::Architecture,
|
||||
) -> Result<Architecture, anyhow::Error> {
|
||||
use target_lexicon::Architecture::*;
|
||||
Ok(match arch {
|
||||
X86_32(_) => Architecture::I386,
|
||||
X86_64 => Architecture::X86_64,
|
||||
Arm(_) => Architecture::Arm,
|
||||
Aarch64(_) => Architecture::Aarch64,
|
||||
S390x => Architecture::S390x,
|
||||
architecture => {
|
||||
anyhow::bail!("target architecture {:?} is unsupported", architecture,);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const TEXT_SECTION_NAME: &[u8] = b".text";
|
||||
|
||||
/// Iterates through all `LibCall` members and all runtime exported functions.
|
||||
@@ -106,27 +90,8 @@ fn write_libcall_symbols(obj: &mut Object) -> HashMap<LibCall, SymbolId> {
|
||||
libcalls
|
||||
}
|
||||
|
||||
pub struct ObjectBuilderTarget {
|
||||
pub(crate) binary_format: BinaryFormat,
|
||||
pub(crate) architecture: Architecture,
|
||||
pub(crate) endianness: Endianness,
|
||||
}
|
||||
|
||||
impl ObjectBuilderTarget {
|
||||
pub fn elf(arch: target_lexicon::Architecture) -> Result<Self> {
|
||||
Ok(Self {
|
||||
binary_format: BinaryFormat::Elf,
|
||||
architecture: to_object_architecture(arch)?,
|
||||
endianness: match arch.endianness().unwrap() {
|
||||
target_lexicon::Endianness::Little => object::Endianness::Little,
|
||||
target_lexicon::Endianness::Big => object::Endianness::Big,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ObjectBuilder<'a> {
|
||||
obj: Object,
|
||||
obj: &'a mut Object,
|
||||
module: &'a Module,
|
||||
text_section: SectionId,
|
||||
func_symbols: PrimaryMap<FuncIndex, SymbolId>,
|
||||
@@ -150,9 +115,7 @@ struct RUNTIME_FUNCTION {
|
||||
}
|
||||
|
||||
impl<'a> ObjectBuilder<'a> {
|
||||
pub fn new(target: ObjectBuilderTarget, module: &'a Module) -> Self {
|
||||
let mut obj = Object::new(target.binary_format, target.architecture, target.endianness);
|
||||
|
||||
pub fn new(obj: &'a mut Object, module: &'a Module) -> Self {
|
||||
// Entire code (functions and trampolines) will be placed
|
||||
// in the ".text" section.
|
||||
let text_section = obj.add_section(
|
||||
@@ -179,7 +142,7 @@ impl<'a> ObjectBuilder<'a> {
|
||||
func_symbols.push(symbol_id);
|
||||
}
|
||||
|
||||
let libcalls = write_libcall_symbols(&mut obj);
|
||||
let libcalls = write_libcall_symbols(obj);
|
||||
|
||||
Self {
|
||||
obj,
|
||||
@@ -309,7 +272,7 @@ impl<'a> ObjectBuilder<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn finish(&mut self, isa: &dyn TargetIsa) -> Result<Vec<u8>> {
|
||||
pub fn finish(&mut self, isa: &dyn TargetIsa) -> Result<()> {
|
||||
self.append_relocations()?;
|
||||
if self.windows_unwind_info.len() > 0 {
|
||||
self.append_windows_unwind_info();
|
||||
@@ -317,7 +280,7 @@ impl<'a> ObjectBuilder<'a> {
|
||||
if self.systemv_unwind_info.len() > 0 {
|
||||
self.append_systemv_unwind_info(isa);
|
||||
}
|
||||
Ok(self.obj.write()?)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn append_relocations(&mut self) -> Result<()> {
|
||||
|
||||
Reference in New Issue
Block a user