Reuse Cranelift codegen contexts across wasmtime compilations (#4181)

This commit is contained in:
Benjamin Bouvier
2022-05-24 11:03:01 +02:00
committed by GitHub
parent b830c3cf93
commit 3a7910ecb0

View File

@@ -32,10 +32,24 @@ use wasmtime_environ::{
TrapCode, TrapEncodingBuilder, TrapInformation, Tunables, VMOffsets, TrapCode, TrapEncodingBuilder, TrapInformation, Tunables, VMOffsets,
}; };
struct CompilerContext {
func_translator: FuncTranslator,
codegen_context: Context,
}
impl Default for CompilerContext {
fn default() -> Self {
Self {
func_translator: FuncTranslator::new(),
codegen_context: Context::new(),
}
}
}
/// A compiler that compiles a WebAssembly module with Compiler, translating /// A compiler that compiles a WebAssembly module with Compiler, translating
/// the Wasm to Compiler IR, optimizing it and then translating to assembly. /// the Wasm to Compiler IR, optimizing it and then translating to assembly.
pub(crate) struct Compiler { pub(crate) struct Compiler {
translators: Mutex<Vec<FuncTranslator>>, contexts: Mutex<Vec<CompilerContext>>,
isa: Box<dyn TargetIsa>, isa: Box<dyn TargetIsa>,
linkopts: LinkOptions, linkopts: LinkOptions,
} }
@@ -43,19 +57,24 @@ pub(crate) struct Compiler {
impl Compiler { impl Compiler {
pub(crate) fn new(isa: Box<dyn TargetIsa>, linkopts: LinkOptions) -> Compiler { pub(crate) fn new(isa: Box<dyn TargetIsa>, linkopts: LinkOptions) -> Compiler {
Compiler { Compiler {
translators: Default::default(), contexts: Default::default(),
isa, isa,
linkopts, linkopts,
} }
} }
fn take_translator(&self) -> FuncTranslator { fn take_context(&self) -> CompilerContext {
let candidate = self.translators.lock().unwrap().pop(); let candidate = self.contexts.lock().unwrap().pop();
candidate.unwrap_or_else(FuncTranslator::new) candidate
.map(|mut ctx| {
ctx.codegen_context.clear();
ctx
})
.unwrap_or_else(Default::default)
} }
fn save_translator(&self, translator: FuncTranslator) { fn save_context(&self, ctx: CompilerContext) {
self.translators.lock().unwrap().push(translator); self.contexts.lock().unwrap().push(ctx);
} }
fn get_function_address_map( fn get_function_address_map(
@@ -114,7 +133,12 @@ impl wasmtime_environ::Compiler for Compiler {
let isa = &*self.isa; let isa = &*self.isa;
let module = &translation.module; let module = &translation.module;
let func_index = module.func_index(func_index); let func_index = module.func_index(func_index);
let mut context = Context::new();
let CompilerContext {
mut func_translator,
codegen_context: mut context,
} = self.take_context();
context.func.name = get_func_name(func_index); context.func.name = get_func_name(func_index);
context.func.signature = func_signature(isa, translation, types, func_index); context.func.signature = func_signature(isa, translation, types, func_index);
if tunables.generate_native_debuginfo { if tunables.generate_native_debuginfo {
@@ -156,14 +180,12 @@ impl wasmtime_environ::Compiler for Compiler {
readonly: false, readonly: false,
}); });
context.func.stack_limit = Some(stack_limit); context.func.stack_limit = Some(stack_limit);
let mut func_translator = self.take_translator();
func_translator.translate_body( func_translator.translate_body(
&mut input.validator, &mut input.validator,
input.body.clone(), input.body.clone(),
&mut context.func, &mut context.func,
&mut func_env, &mut func_env,
)?; )?;
self.save_translator(func_translator);
let mut code_buf: Vec<u8> = Vec::new(); let mut code_buf: Vec<u8> = Vec::new();
context context
@@ -217,11 +239,19 @@ impl wasmtime_environ::Compiler for Compiler {
log::trace!("{:?} timing info\n{}", func_index, timing); log::trace!("{:?} timing info\n{}", func_index, timing);
let length = u32::try_from(code_buf.len()).unwrap(); let length = u32::try_from(code_buf.len()).unwrap();
let stack_slots = std::mem::take(&mut context.func.stack_slots);
self.save_context(CompilerContext {
func_translator,
codegen_context: context,
});
Ok(Box::new(CompiledFunction { Ok(Box::new(CompiledFunction {
body: code_buf, body: code_buf,
relocations: func_relocs, relocations: func_relocs,
value_labels_ranges: ranges.unwrap_or(Default::default()), value_labels_ranges: ranges.unwrap_or(Default::default()),
stack_slots: context.func.stack_slots, stack_slots,
unwind_info, unwind_info,
traps, traps,
info: FunctionInfo { info: FunctionInfo {
@@ -405,8 +435,11 @@ impl Compiler {
host_signature.params.push(ir::AbiParam::new(pointer_type)); host_signature.params.push(ir::AbiParam::new(pointer_type));
host_signature.params.push(ir::AbiParam::new(pointer_type)); host_signature.params.push(ir::AbiParam::new(pointer_type));
let mut func_translator = self.take_translator(); let CompilerContext {
let mut context = Context::new(); mut func_translator,
codegen_context: mut context,
} = self.take_context();
context.func = ir::Function::with_name_signature(ExternalName::user(0, 0), host_signature); context.func = ir::Function::with_name_signature(ExternalName::user(0, 0), host_signature);
// This trampoline will load all the parameters from the `values_vec` // This trampoline will load all the parameters from the `values_vec`
@@ -467,8 +500,11 @@ impl Compiler {
builder.ins().return_(&[]); builder.ins().return_(&[]);
builder.finalize(); builder.finalize();
let func = self.finish_trampoline(context, isa)?; let func = self.finish_trampoline(&mut context, isa)?;
self.save_translator(func_translator); self.save_context(CompilerContext {
func_translator,
codegen_context: context,
});
Ok(func) Ok(func)
} }
@@ -489,7 +525,11 @@ impl Compiler {
let value_size = mem::size_of::<u128>(); let value_size = mem::size_of::<u128>();
let values_vec_len = (value_size * cmp::max(ty.params().len(), ty.returns().len())) as u32; let values_vec_len = (value_size * cmp::max(ty.params().len(), ty.returns().len())) as u32;
let mut context = Context::new(); let CompilerContext {
mut func_translator,
codegen_context: mut context,
} = self.take_context();
context.func = context.func =
ir::Function::with_name_signature(ir::ExternalName::user(0, 0), wasm_signature); ir::Function::with_name_signature(ir::ExternalName::user(0, 0), wasm_signature);
@@ -498,7 +538,6 @@ impl Compiler {
values_vec_len, values_vec_len,
)); ));
let mut func_translator = self.take_translator();
let mut builder = FunctionBuilder::new(&mut context.func, func_translator.context()); let mut builder = FunctionBuilder::new(&mut context.func, func_translator.context());
let block0 = builder.create_block(); let block0 = builder.create_block();
@@ -542,14 +581,17 @@ impl Compiler {
builder.ins().return_(&results); builder.ins().return_(&results);
builder.finalize(); builder.finalize();
let func = self.finish_trampoline(context, isa)?; let func = self.finish_trampoline(&mut context, isa)?;
self.save_translator(func_translator); self.save_context(CompilerContext {
func_translator,
codegen_context: context,
});
Ok(func) Ok(func)
} }
fn finish_trampoline( fn finish_trampoline(
&self, &self,
mut context: Context, context: &mut Context,
isa: &dyn TargetIsa, isa: &dyn TargetIsa,
) -> Result<CompiledFunction, CompileError> { ) -> Result<CompiledFunction, CompileError> {
let mut code_buf = Vec::new(); let mut code_buf = Vec::new();