Reuse Cranelift codegen contexts across wasmtime compilations (#4181)
This commit is contained in:
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user