Remove some allocations in CodeMemory (#3253)
* Remove some allocations in `CodeMemory` This commit removes the `FinishedFunctions` type as well as allocations associated with trampolines when allocating inside of a `CodeMemory`. The main goal of this commit is to improve the time spent in `CodeMemory` where currently today a good portion of time is spent simply parsing symbol names and trying to extract function indices from them. Instead this commit implements a new strategy (different from #3236) where compilation records offset/length information for all functions/trampolines so this doesn't need to be re-learned from the object file later. A consequence of this commit is that this offset information will be decoded/encoded through `bincode` unconditionally, but we can also optimize that later if necessary as well. Internally this involved quite a bit of refactoring since the previous map for `FinishedFunctions` was relatively heavily relied upon. * comments
This commit is contained in:
@@ -21,13 +21,13 @@ use cranelift_wasm::{
|
||||
use object::write::Object;
|
||||
use std::any::Any;
|
||||
use std::cmp;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::collections::BTreeMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::mem;
|
||||
use std::sync::Mutex;
|
||||
use wasmtime_environ::{
|
||||
AddressMapSection, CompileError, FilePos, FlagValue, FunctionBodyData, FunctionInfo,
|
||||
InstructionAddressMap, Module, ModuleTranslation, StackMapInformation, TrapCode,
|
||||
InstructionAddressMap, Module, ModuleTranslation, StackMapInformation, Trampoline, TrapCode,
|
||||
TrapEncodingBuilder, TrapInformation, Tunables, TypeTables, VMOffsets,
|
||||
};
|
||||
|
||||
@@ -120,12 +120,12 @@ impl wasmtime_environ::Compiler for Compiler {
|
||||
let func_index = module.func_index(func_index);
|
||||
let mut context = Context::new();
|
||||
context.func.name = get_func_name(func_index);
|
||||
context.func.signature = func_signature(isa, module, types, func_index);
|
||||
context.func.signature = func_signature(isa, translation, types, func_index);
|
||||
if tunables.generate_native_debuginfo {
|
||||
context.func.collect_debug_info();
|
||||
}
|
||||
|
||||
let mut func_env = FuncEnvironment::new(isa, module, types, tunables);
|
||||
let mut func_env = FuncEnvironment::new(isa, translation, types, tunables);
|
||||
|
||||
// We use these as constant offsets below in
|
||||
// `stack_limit_from_arguments`, so assert their values here. This
|
||||
@@ -201,6 +201,7 @@ impl wasmtime_environ::Compiler for Compiler {
|
||||
None
|
||||
};
|
||||
|
||||
let length = u32::try_from(code_buf.len()).unwrap();
|
||||
Ok(Box::new(CompiledFunction {
|
||||
body: code_buf,
|
||||
jt_offsets: context.func.jt_offsets,
|
||||
@@ -212,6 +213,8 @@ impl wasmtime_environ::Compiler for Compiler {
|
||||
info: FunctionInfo {
|
||||
start_srcloc: address_transform.start_srcloc,
|
||||
stack_maps: stack_map_sink.finish(),
|
||||
start: 0,
|
||||
length,
|
||||
},
|
||||
address_map: address_transform,
|
||||
}))
|
||||
@@ -224,40 +227,38 @@ impl wasmtime_environ::Compiler for Compiler {
|
||||
funcs: PrimaryMap<DefinedFuncIndex, Box<dyn Any + Send>>,
|
||||
emit_dwarf: bool,
|
||||
obj: &mut Object,
|
||||
) -> Result<PrimaryMap<DefinedFuncIndex, FunctionInfo>> {
|
||||
) -> Result<(PrimaryMap<DefinedFuncIndex, FunctionInfo>, Vec<Trampoline>)> {
|
||||
const CODE_SECTION_ALIGNMENT: u64 = 0x1000;
|
||||
let funcs: crate::CompiledFunctions = funcs
|
||||
.into_iter()
|
||||
.map(|(_i, f)| *f.downcast().unwrap())
|
||||
.collect();
|
||||
|
||||
// Build trampolines for every signature that can be used by this module.
|
||||
let signatures = translation
|
||||
.module
|
||||
.functions
|
||||
.iter()
|
||||
.filter_map(|(i, sig)| match translation.module.defined_func_index(i) {
|
||||
Some(i) if !translation.module.possibly_exported_funcs.contains(&i) => None,
|
||||
_ => Some(*sig),
|
||||
})
|
||||
.collect::<BTreeSet<_>>();
|
||||
let mut trampolines = Vec::with_capacity(signatures.len());
|
||||
for i in signatures {
|
||||
let func = self.host_to_wasm_trampoline(&types.wasm_signatures[i])?;
|
||||
trampolines.push((i, func));
|
||||
}
|
||||
|
||||
let mut builder = ObjectBuilder::new(obj, &translation.module);
|
||||
let mut addrs = AddressMapSection::default();
|
||||
let mut traps = TrapEncodingBuilder::default();
|
||||
let compiled_trampolines = translation
|
||||
.exported_signatures
|
||||
.iter()
|
||||
.map(|i| self.host_to_wasm_trampoline(&types.wasm_signatures[*i]))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
let mut func_starts = Vec::with_capacity(funcs.len());
|
||||
for (i, func) in funcs.iter() {
|
||||
let range = builder.func(i, func);
|
||||
addrs.push(range.clone(), &func.address_map.instructions);
|
||||
traps.push(range, &func.traps);
|
||||
traps.push(range.clone(), &func.traps);
|
||||
func_starts.push(range.start);
|
||||
}
|
||||
for (i, func) in trampolines.iter() {
|
||||
builder.trampoline(*i, func);
|
||||
|
||||
// Build trampolines for every signature that can be used by this module.
|
||||
let mut trampolines = Vec::with_capacity(translation.exported_signatures.len());
|
||||
for (i, func) in translation
|
||||
.exported_signatures
|
||||
.iter()
|
||||
.zip(&compiled_trampolines)
|
||||
{
|
||||
trampolines.push(builder.trampoline(*i, &func));
|
||||
}
|
||||
builder.align_text_to(CODE_SECTION_ALIGNMENT);
|
||||
|
||||
@@ -295,7 +296,17 @@ impl wasmtime_environ::Compiler for Compiler {
|
||||
addrs.append_to(obj);
|
||||
traps.append_to(obj);
|
||||
|
||||
Ok(funcs.into_iter().map(|(_, f)| f.info).collect())
|
||||
Ok((
|
||||
funcs
|
||||
.into_iter()
|
||||
.zip(func_starts)
|
||||
.map(|((_, mut f), start)| {
|
||||
f.info.start = start;
|
||||
f.info
|
||||
})
|
||||
.collect(),
|
||||
trampolines,
|
||||
))
|
||||
}
|
||||
|
||||
fn emit_trampoline_obj(
|
||||
@@ -303,15 +314,15 @@ impl wasmtime_environ::Compiler for Compiler {
|
||||
ty: &WasmFuncType,
|
||||
host_fn: usize,
|
||||
obj: &mut Object,
|
||||
) -> Result<()> {
|
||||
) -> Result<(Trampoline, Trampoline)> {
|
||||
let host_to_wasm = self.host_to_wasm_trampoline(ty)?;
|
||||
let wasm_to_host = self.wasm_to_host_trampoline(ty, host_fn)?;
|
||||
let module = Module::new();
|
||||
let mut builder = ObjectBuilder::new(obj, &module);
|
||||
builder.trampoline(SignatureIndex::new(0), &host_to_wasm);
|
||||
builder.trampoline(SignatureIndex::new(1), &wasm_to_host);
|
||||
let a = builder.trampoline(SignatureIndex::new(0), &host_to_wasm);
|
||||
let b = builder.trampoline(SignatureIndex::new(1), &wasm_to_host);
|
||||
builder.finish(&*self.isa)?;
|
||||
Ok(())
|
||||
Ok((a, b))
|
||||
}
|
||||
|
||||
fn triple(&self) -> &target_lexicon::Triple {
|
||||
|
||||
Reference in New Issue
Block a user