Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Internal runtime ↔️ backend abstraction refactor. #348

Merged
merged 15 commits into from
Apr 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ All PRs to the Wasmer repository must add to this file.
Blocks of changes will separated by version increments.

## **[Unreleased]**
- [#348](https://github.com/wasmerio/wasmer/pull/348) Refactor internal runtime ↔️ backend abstraction.
- [#355](https://github.com/wasmerio/wasmer/pull/355) Misc changes to `Cargo.toml`s for publishing
- [#352](https://github.com/wasmerio/wasmer/pull/352) Bump version numbers to 0.3.0
- [#351](https://github.com/wasmerio/wasmer/pull/351) Add hidden option to specify wasm program name (can be used to improve error messages)
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion bors.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ status = [
"ci/circleci: lint",
"ci/circleci: test",
"ci/circleci: test-macos",
"ci/circleci: test-rust-nightly",
"continuous-integration/appveyor/branch"
]
required_approvals = 1
timeout_sec = 900
delete_merged_branches = true
delete_merged_branches = true
14 changes: 6 additions & 8 deletions lib/clif-backend/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,15 @@ impl Module {
handler_data.clone(),
)?;

let protected_caller = Caller::new(&self.info, handler_data, trampolines);

let cache_gen = Box::new(CacheGenerator::new(
backend_cache,
Arc::clone(&func_resolver.memory),
));

let runnable_module = Caller::new(handler_data, trampolines, func_resolver);

Ok(ModuleInner {
func_resolver: Box::new(func_resolver),
protected_caller: Box::new(protected_caller),
runnable_module: Box::new(runnable_module),
cache_gen,

info: self.info,
Expand All @@ -103,16 +102,15 @@ impl Module {
)
.map_err(|e| CacheError::Unknown(format!("{:?}", e)))?;

let protected_caller = Caller::new(&info, handler_data, trampolines);

let cache_gen = Box::new(CacheGenerator::new(
backend_cache,
Arc::clone(&func_resolver.memory),
));

let runnable_module = Caller::new(handler_data, trampolines, func_resolver);

Ok(ModuleInner {
func_resolver: Box::new(func_resolver),
protected_caller: Box::new(protected_caller),
runnable_module: Box::new(runnable_module),
cache_gen,

info,
Expand Down
10 changes: 2 additions & 8 deletions lib/clif-backend/src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use wasmer_runtime_core::cache::Error as CacheError;
use wasmer_runtime_core::{
self,
backend::{
self,
sys::{Memory, Protect},
SigRegistry,
},
Expand Down Expand Up @@ -357,13 +356,8 @@ pub struct FuncResolver {
pub(crate) memory: Arc<Memory>,
}

// Implements FuncResolver trait.
impl backend::FuncResolver for FuncResolver {
fn get(
&self,
_module: &wasmer_runtime_core::module::ModuleInner,
index: LocalFuncIndex,
) -> Option<NonNull<vm::Func>> {
impl FuncResolver {
pub fn lookup(&self, index: LocalFuncIndex) -> Option<NonNull<vm::Func>> {
lookup_func(&self.map, &self.memory, index)
}
}
Expand Down
150 changes: 14 additions & 136 deletions lib/clif-backend/src/signal/mod.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
use crate::relocation::{TrapData, TrapSink};
use crate::resolver::FuncResolver;
use crate::trampoline::Trampolines;
use hashbrown::HashSet;
use libc::c_void;
use std::{any::Any, cell::Cell, ptr::NonNull, sync::Arc};
use wasmer_runtime_core::{
backend::{ProtectedCaller, Token, UserTrapper},
error::RuntimeResult,
export::Context,
module::{ExportIndex, ModuleInfo, ModuleInner},
backend::{RunnableModule, UserTrapper},
module::ModuleInfo,
typed_func::{Wasm, WasmTrapInfo},
types::{FuncIndex, FuncSig, LocalOrImport, SigIndex, Type, Value},
vm::{self, ImportBacking},
types::{LocalFuncIndex, SigIndex},
vm,
};

#[cfg(unix)]
Expand Down Expand Up @@ -39,130 +37,44 @@ impl UserTrapper for Trapper {
}

pub struct Caller {
func_export_set: HashSet<FuncIndex>,
handler_data: HandlerData,
trampolines: Arc<Trampolines>,
resolver: FuncResolver,
}

impl Caller {
pub fn new(
module: &ModuleInfo,
handler_data: HandlerData,
trampolines: Arc<Trampolines>,
resolver: FuncResolver,
) -> Self {
let mut func_export_set = HashSet::new();
for export_index in module.exports.values() {
if let ExportIndex::Func(func_index) = export_index {
func_export_set.insert(*func_index);
}
}
if let Some(start_func_index) = module.start_func {
func_export_set.insert(start_func_index);
}

Self {
func_export_set,
handler_data,
trampolines,
resolver,
}
}
}

impl ProtectedCaller for Caller {
fn call(
&self,
module: &ModuleInner,
func_index: FuncIndex,
params: &[Value],
import_backing: &ImportBacking,
vmctx: *mut vm::Ctx,
_: Token,
) -> RuntimeResult<Vec<Value>> {
let (func_ptr, ctx, signature, sig_index) =
get_func_from_index(&module, import_backing, func_index);

let vmctx_ptr = match ctx {
Context::External(external_vmctx) => external_vmctx,
Context::Internal => vmctx,
};

assert!(self.func_export_set.contains(&func_index));

assert!(
signature.returns().len() <= 1,
"multi-value returns not yet supported"
);

assert!(
signature.check_param_value_types(params),
"incorrect signature"
);

let param_vec: Vec<u64> = params
.iter()
.map(|val| match val {
Value::I32(x) => *x as u64,
Value::I64(x) => *x as u64,
Value::F32(x) => x.to_bits() as u64,
Value::F64(x) => x.to_bits(),
})
.collect();

let mut return_vec = vec![0; signature.returns().len()];

let trampoline = self
.trampolines
.lookup(sig_index)
.expect("that trampoline doesn't exist");

#[cfg(not(target_os = "windows"))]
call_protected(&self.handler_data, || unsafe {
// Leap of faith.
trampoline(
vmctx_ptr,
func_ptr,
param_vec.as_ptr(),
return_vec.as_mut_ptr(),
);
})?;

// the trampoline is called from C on windows
#[cfg(target_os = "windows")]
call_protected(
&self.handler_data,
trampoline,
vmctx_ptr,
func_ptr,
param_vec.as_ptr(),
return_vec.as_mut_ptr(),
)?;

Ok(return_vec
.iter()
.zip(signature.returns().iter())
.map(|(&x, ty)| match ty {
Type::I32 => Value::I32(x as i32),
Type::I64 => Value::I64(x as i64),
Type::F32 => Value::F32(f32::from_bits(x as u32)),
Type::F64 => Value::F64(f64::from_bits(x as u64)),
})
.collect())
impl RunnableModule for Caller {
fn get_func(&self, _: &ModuleInfo, func_index: LocalFuncIndex) -> Option<NonNull<vm::Func>> {
self.resolver.lookup(func_index)
}

fn get_wasm_trampoline(&self, module: &ModuleInner, sig_index: SigIndex) -> Option<Wasm> {
fn get_trampoline(&self, _: &ModuleInfo, sig_index: SigIndex) -> Option<Wasm> {
unsafe extern "C" fn invoke(
trampoline: unsafe extern "C" fn(*mut vm::Ctx, NonNull<vm::Func>, *const u64, *mut u64),
ctx: *mut vm::Ctx,
func: NonNull<vm::Func>,
args: *const u64,
rets: *mut u64,
trap_info: *mut WasmTrapInfo,
_trap_info: *mut WasmTrapInfo,
invoke_env: Option<NonNull<c_void>>,
) -> bool {
let handler_data = &*invoke_env.unwrap().cast().as_ptr();

#[cfg(not(target_os = "windows"))]
let res = call_protected(handler_data, || unsafe {
let res = call_protected(handler_data, || {
// Leap of faith.
trampoline(ctx, func, args, rets);
})
Expand Down Expand Up @@ -194,40 +106,6 @@ impl ProtectedCaller for Caller {
}
}

fn get_func_from_index<'a>(
module: &'a ModuleInner,
import_backing: &ImportBacking,
func_index: FuncIndex,
) -> (NonNull<vm::Func>, Context, &'a FuncSig, SigIndex) {
let sig_index = *module
.info
.func_assoc
.get(func_index)
.expect("broken invariant, incorrect func index");

let (func_ptr, ctx) = match func_index.local_or_import(&module.info) {
LocalOrImport::Local(local_func_index) => (
module
.func_resolver
.get(&module, local_func_index)
.expect("broken invariant, func resolver not synced with module.exports")
.cast(),
Context::Internal,
),
LocalOrImport::Import(imported_func_index) => {
let imported_func = import_backing.imported_func(imported_func_index);
(
NonNull::new(imported_func.func as *mut _).unwrap(),
Context::External(imported_func.vmctx),
)
}
};

let signature = &module.info.signatures[sig_index];

(func_ptr, ctx, signature, sig_index)
}

unsafe impl Send for HandlerData {}
unsafe impl Sync for HandlerData {}

Expand Down
1 change: 0 additions & 1 deletion lib/clif-backend/src/trampoline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use cranelift_codegen::{
isa, Context,
};
use hashbrown::HashMap;
use std::ffi::c_void;
use std::{iter, mem, ptr::NonNull};
use wasmer_runtime_core::{
backend::sys::{Memory, Protect},
Expand Down
Loading