feat(runtime) Get ready for tiering (#257)

* Add local_function field to context

* Add local call indirection to llvm

* local call indirection

* Fix  vm test

* Fix cranelift local call indirection

* Fix unwinding on nightly
This commit is contained in:
Lachlan Sneff
2019-03-08 15:15:16 -08:00
committed by GitHub
parent a8751b6bbc
commit 17eada53f3
11 changed files with 118 additions and 11 deletions

3
Cargo.lock generated
View File

@ -1,3 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "0.6.10" version = "0.6.10"
@ -1344,6 +1346,7 @@ dependencies = [
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
"nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
"wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -445,6 +445,12 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
pos.ins().symbol_value(ir::types::I64, sig_index_global) pos.ins().symbol_value(ir::types::I64, sig_index_global)
// let dynamic_sigindices_array_ptr = pos.ins().load(
// ptr_type,
// mflags,
// )
// let expected_sig = pos.ins().iconst(ir::types::I32, sig_index.index() as i64); // let expected_sig = pos.ins().iconst(ir::types::I32, sig_index.index() as i64);
// self.env.deduplicated[clif_sig_index] // self.env.deduplicated[clif_sig_index]
@ -477,9 +483,10 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
call_args: &[ir::Value], call_args: &[ir::Value],
) -> cranelift_wasm::WasmResult<ir::Inst> { ) -> cranelift_wasm::WasmResult<ir::Inst> {
let callee_index: FuncIndex = Converter(clif_callee_index).into(); let callee_index: FuncIndex = Converter(clif_callee_index).into();
let ptr_type = self.pointer_type();
match callee_index.local_or_import(&self.env.module.info) { match callee_index.local_or_import(&self.env.module.info) {
LocalOrImport::Local(_) => { LocalOrImport::Local(local_function_index) => {
// this is an internal function // this is an internal function
let vmctx = pos let vmctx = pos
.func .func
@ -490,10 +497,28 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
args.push(vmctx); args.push(vmctx);
args.extend(call_args.iter().cloned()); args.extend(call_args.iter().cloned());
Ok(pos.ins().call(callee, &args)) let sig_ref = pos.func.dfg.ext_funcs[callee].signature;
let function_ptr = {
let mflags = ir::MemFlags::trusted();
let function_array_ptr = pos.ins().load(
ptr_type,
mflags,
vmctx,
vm::Ctx::offset_local_functions() as i32,
);
pos.ins().load(
ptr_type,
mflags,
function_array_ptr,
(local_function_index.index() as i32) * 8,
)
};
Ok(pos.ins().call_indirect(sig_ref, function_ptr, &args))
} }
LocalOrImport::Import(imported_func_index) => { LocalOrImport::Import(imported_func_index) => {
let ptr_type = self.pointer_type();
// this is an imported function // this is an imported function
let vmctx = pos.func.create_global_value(ir::GlobalValueData::VMContext); let vmctx = pos.func.create_global_value(ir::GlobalValueData::VMContext);

View File

@ -20,6 +20,7 @@ cc = "1.0"
lazy_static = "1.2.0" lazy_static = "1.2.0"
regex = "1.1.0" regex = "1.1.0"
semver = "0.9" semver = "0.9"
rustc_version = "0.2.3"
[dev-dependencies] [dev-dependencies]
wabt = "0.7.4" wabt = "0.7.4"

View File

@ -212,4 +212,10 @@ fn main() {
.compile("llvm-backend"); .compile("llvm-backend");
println!("cargo:rustc-link-lib=static=llvm-backend"); println!("cargo:rustc-link-lib=static=llvm-backend");
println!("cargo:rerun-if-changed=build.rs");
// Enable "nightly" cfg if the current compiler is nightly.
if rustc_version::version_meta().unwrap().channel == rustc_version::Channel::Nightly {
println!("cargo:rustc-cfg=nightly");
}
} }

View File

@ -664,14 +664,15 @@ fn parse_function(
let call_site = match func_index.local_or_import(info) { let call_site = match func_index.local_or_import(info) {
LocalOrImport::Local(local_func_index) => { LocalOrImport::Local(local_func_index) => {
let func_value = functions[local_func_index];
let params: Vec<_> = [ctx.basic()] let params: Vec<_> = [ctx.basic()]
.iter() .iter()
.chain(state.peekn(func_sig.params().len())?.iter()) .chain(state.peekn(func_sig.params().len())?.iter())
.map(|v| *v) .map(|v| *v)
.collect(); .collect();
builder.build_call(func_value, &params, &state.var_name()) let func_ptr = ctx.local_func(local_func_index, llvm_sig);
builder.build_call(func_ptr, &params, &state.var_name())
} }
LocalOrImport::Import(import_func_index) => { LocalOrImport::Import(import_func_index) => {
let (func_ptr_untyped, ctx_ptr) = ctx.imported_func(import_func_index); let (func_ptr_untyped, ctx_ptr) = ctx.imported_func(import_func_index);

View File

@ -3,7 +3,7 @@ use inkwell::{
builder::Builder, builder::Builder,
context::Context, context::Context,
module::Module, module::Module,
types::{BasicType, FloatType, IntType, PointerType, StructType, VoidType}, types::{BasicType, FloatType, FunctionType, IntType, PointerType, StructType, VoidType},
values::{ values::{
BasicValue, BasicValueEnum, FloatValue, FunctionValue, InstructionValue, IntValue, BasicValue, BasicValueEnum, FloatValue, FunctionValue, InstructionValue, IntValue,
PointerValue, PointerValue,
@ -16,7 +16,8 @@ use wasmer_runtime_core::{
module::ModuleInfo, module::ModuleInfo,
structures::TypedIndex, structures::TypedIndex,
types::{ types::{
GlobalIndex, ImportedFuncIndex, LocalOrImport, MemoryIndex, SigIndex, TableIndex, Type, GlobalIndex, ImportedFuncIndex, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex,
TableIndex, Type,
}, },
}; };
@ -161,6 +162,7 @@ impl Intrinsics {
let imported_func_ty = let imported_func_ty =
context.struct_type(&[i8_ptr_ty_basic, ctx_ptr_ty.as_basic_type_enum()], false); context.struct_type(&[i8_ptr_ty_basic, ctx_ptr_ty.as_basic_type_enum()], false);
let sigindex_ty = i32_ty; let sigindex_ty = i32_ty;
let local_function_ty = i8_ptr_ty;
let anyfunc_ty = context.struct_type( let anyfunc_ty = context.struct_type(
&[ &[
@ -203,6 +205,9 @@ impl Intrinsics {
sigindex_ty sigindex_ty
.ptr_type(AddressSpace::Generic) .ptr_type(AddressSpace::Generic)
.as_basic_type_enum(), .as_basic_type_enum(),
local_function_ty
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
], ],
false, false,
); );
@ -582,6 +587,36 @@ impl<'a> CtxType<'a> {
) )
} }
pub fn local_func(&mut self, index: LocalFuncIndex, fn_ty: FunctionType) -> PointerValue {
let local_func_array_ptr_ptr = unsafe {
self.builder
.build_struct_gep(self.ctx_ptr_value, 8, "local_func_array_ptr_ptr")
};
let local_func_array_ptr = self
.builder
.build_load(local_func_array_ptr_ptr, "local_func_array_ptr")
.into_pointer_value();
let local_func_ptr_ptr = unsafe {
self.builder.build_in_bounds_gep(
local_func_array_ptr,
&[self
.intrinsics
.i32_ty
.const_int(index.index() as u64, false)],
"local_func_ptr_ptr",
)
};
let local_func_ptr = self
.builder
.build_load(local_func_ptr_ptr, "local_func_ptr")
.into_pointer_value();
self.builder.build_pointer_cast(
local_func_ptr,
fn_ty.ptr_type(AddressSpace::Generic),
"local_func_ptr",
)
}
pub fn dynamic_sigindex(&mut self, index: SigIndex) -> IntValue { pub fn dynamic_sigindex(&mut self, index: SigIndex) -> IntValue {
let (cached_sigindices, builder, info, ctx_ptr_value, intrinsics, cache_builder) = ( let (cached_sigindices, builder, info, ctx_ptr_value, intrinsics, cache_builder) = (
&mut self.cached_sigindices, &mut self.cached_sigindices,

View File

@ -1,3 +1,5 @@
#![cfg_attr(nightly, feature(unwind_attributes))]
use inkwell::{ use inkwell::{
execution_engine::JitFunction, execution_engine::JitFunction,
targets::{CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine}, targets::{CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine},

View File

@ -41,6 +41,7 @@ pub unsafe fn visit_fde(addr: *mut u8, size: usize, visitor: extern "C" fn(*mut
} }
extern "C" { extern "C" {
#[cfg_attr(nightly, unwind(allowed))]
fn throw_trap(ty: i32) -> !; fn throw_trap(ty: i32) -> !;
} }
@ -50,12 +51,13 @@ pub unsafe fn install_signal_handler() {
SaFlags::SA_ONSTACK | SaFlags::SA_SIGINFO, SaFlags::SA_ONSTACK | SaFlags::SA_SIGINFO,
SigSet::empty(), SigSet::empty(),
); );
sigaction(SIGFPE, &sa).unwrap(); // sigaction(SIGFPE, &sa).unwrap();
sigaction(SIGILL, &sa).unwrap(); // sigaction(SIGILL, &sa).unwrap();
sigaction(SIGSEGV, &sa).unwrap(); sigaction(SIGSEGV, &sa).unwrap();
sigaction(SIGBUS, &sa).unwrap(); sigaction(SIGBUS, &sa).unwrap();
} }
#[cfg_attr(nightly, unwind(allowed))]
extern "C" fn signal_trap_handler( extern "C" fn signal_trap_handler(
signum: ::nix::libc::c_int, signum: ::nix::libc::c_int,
siginfo: *mut siginfo_t, siginfo: *mut siginfo_t,

View File

@ -10,8 +10,8 @@ use crate::{
table::Table, table::Table,
types::{ types::{
ImportedFuncIndex, ImportedGlobalIndex, ImportedMemoryIndex, ImportedTableIndex, ImportedFuncIndex, ImportedGlobalIndex, ImportedMemoryIndex, ImportedTableIndex,
Initializer, LocalGlobalIndex, LocalMemoryIndex, LocalOrImport, LocalTableIndex, SigIndex, Initializer, LocalFuncIndex, LocalGlobalIndex, LocalMemoryIndex, LocalOrImport,
Value, LocalTableIndex, SigIndex, Value,
}, },
vm, vm,
}; };
@ -28,6 +28,7 @@ pub struct LocalBacking {
pub(crate) vm_globals: BoxedMap<LocalGlobalIndex, *mut vm::LocalGlobal>, pub(crate) vm_globals: BoxedMap<LocalGlobalIndex, *mut vm::LocalGlobal>,
pub(crate) dynamic_sigindices: BoxedMap<SigIndex, vm::SigId>, pub(crate) dynamic_sigindices: BoxedMap<SigIndex, vm::SigId>,
pub(crate) local_functions: BoxedMap<LocalFuncIndex, *const vm::Func>,
} }
// impl LocalBacking { // impl LocalBacking {
@ -51,6 +52,7 @@ impl LocalBacking {
let vm_globals = Self::finalize_globals(&mut globals); let vm_globals = Self::finalize_globals(&mut globals);
let dynamic_sigindices = Self::generate_sigindices(&module.info); let dynamic_sigindices = Self::generate_sigindices(&module.info);
let local_functions = Self::generate_local_functions(module);
Self { Self {
memories, memories,
@ -62,9 +64,23 @@ impl LocalBacking {
vm_globals, vm_globals,
dynamic_sigindices, dynamic_sigindices,
local_functions,
} }
} }
fn generate_local_functions(module: &ModuleInner) -> BoxedMap<LocalFuncIndex, *const vm::Func> {
(0..module.info.func_assoc.len() - module.info.imported_functions.len())
.map(|index| {
module
.func_resolver
.get(module, LocalFuncIndex::new(index))
.unwrap()
.as_ptr() as *const _
})
.collect::<Map<_, _>>()
.into_boxed_map()
}
fn generate_sigindices(info: &ModuleInfo) -> BoxedMap<SigIndex, vm::SigId> { fn generate_sigindices(info: &ModuleInfo) -> BoxedMap<SigIndex, vm::SigId> {
info.signatures info.signatures
.iter() .iter()

View File

@ -245,6 +245,7 @@ pub enum Protect {
Read, Read,
ReadWrite, ReadWrite,
ReadExec, ReadExec,
ReadWriteExec,
} }
impl Protect { impl Protect {
@ -254,6 +255,7 @@ impl Protect {
Protect::Read => 1, Protect::Read => 1,
Protect::ReadWrite => 1 | 2, Protect::ReadWrite => 1 | 2,
Protect::ReadExec => 1 | 4, Protect::ReadExec => 1 | 4,
Protect::ReadWriteExec => 1 | 2 | 4,
} }
} }

View File

@ -40,6 +40,8 @@ pub struct Ctx {
/// modules safely. /// modules safely.
pub(crate) dynamic_sigindices: *const SigId, pub(crate) dynamic_sigindices: *const SigId,
pub(crate) local_functions: *const *const Func,
local_backing: *mut LocalBacking, local_backing: *mut LocalBacking,
import_backing: *mut ImportBacking, import_backing: *mut ImportBacking,
module: *const ModuleInner, module: *const ModuleInner,
@ -66,6 +68,7 @@ impl Ctx {
imported_funcs: import_backing.vm_functions.as_mut_ptr(), imported_funcs: import_backing.vm_functions.as_mut_ptr(),
dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(), dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(),
local_functions: local_backing.local_functions.as_ptr(),
local_backing, local_backing,
import_backing, import_backing,
@ -95,6 +98,7 @@ impl Ctx {
imported_funcs: import_backing.vm_functions.as_mut_ptr(), imported_funcs: import_backing.vm_functions.as_mut_ptr(),
dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(), dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(),
local_functions: local_backing.local_functions.as_ptr(),
local_backing, local_backing,
import_backing, import_backing,
@ -173,6 +177,10 @@ impl Ctx {
pub fn offset_signatures() -> u8 { pub fn offset_signatures() -> u8 {
7 * (mem::size_of::<usize>() as u8) 7 * (mem::size_of::<usize>() as u8)
} }
pub fn offset_local_functions() -> u8 {
8 * (mem::size_of::<usize>() as u8)
}
} }
enum InnerFunc {} enum InnerFunc {}
@ -363,6 +371,11 @@ mod vm_offset_tests {
Ctx::offset_imported_funcs() as usize, Ctx::offset_imported_funcs() as usize,
offset_of!(Ctx => imported_funcs).get_byte_offset(), offset_of!(Ctx => imported_funcs).get_byte_offset(),
); );
assert_eq!(
Ctx::offset_local_functions() as usize,
offset_of!(Ctx => local_functions).get_byte_offset(),
);
} }
#[test] #[test]
@ -470,6 +483,7 @@ mod vm_ctx_tests {
vm_globals: Map::new().into_boxed_map(), vm_globals: Map::new().into_boxed_map(),
dynamic_sigindices: Map::new().into_boxed_map(), dynamic_sigindices: Map::new().into_boxed_map(),
local_functions: Map::new().into_boxed_map(),
}; };
let mut import_backing = ImportBacking { let mut import_backing = ImportBacking {
memories: Map::new().into_boxed_map(), memories: Map::new().into_boxed_map(),