Implement function lookups using the table

This commit is contained in:
Mark McCaskey
2019-09-18 16:06:46 -07:00
parent b35a522d28
commit 5741a2cf70
4 changed files with 71 additions and 44 deletions

View File

@ -518,7 +518,7 @@ impl LikeNamespace for Rc<Instance> {
} }
#[must_use] #[must_use]
pub(crate) fn call_func_with_index( fn call_func_with_index(
info: &ModuleInfo, info: &ModuleInfo,
runnable: &dyn RunnableModule, runnable: &dyn RunnableModule,
import_backing: &ImportBacking, import_backing: &ImportBacking,
@ -527,29 +527,12 @@ pub(crate) fn call_func_with_index(
args: &[Value], args: &[Value],
rets: &mut Vec<Value>, rets: &mut Vec<Value>,
) -> CallResult<()> { ) -> CallResult<()> {
rets.clear();
let sig_index = *info let sig_index = *info
.func_assoc .func_assoc
.get(func_index) .get(func_index)
.expect("broken invariant, incorrect func index"); .expect("broken invariant, incorrect func index");
let signature = &info.signatures[sig_index]; let signature = &info.signatures[sig_index];
let num_results = signature.returns().len();
let num_results = num_results
+ signature
.returns()
.iter()
.filter(|&&ty| ty == Type::V128)
.count();
rets.reserve(num_results);
if !signature.check_param_value_types(args) {
Err(ResolveError::Signature {
expected: signature.clone(),
found: args.iter().map(|val| val.ty()).collect(),
})?
}
let func_ptr = match func_index.local_or_import(info) { let func_ptr = match func_index.local_or_import(info) {
LocalOrImport::Local(local_func_index) => { LocalOrImport::Local(local_func_index) => {
@ -567,6 +550,39 @@ pub(crate) fn call_func_with_index(
} }
}; };
let wasm = runnable
.get_trampoline(info, sig_index)
.expect("wasm trampoline");
call_func_with_index_inner(ctx_ptr, func_ptr, signature, wasm, args, rets)
}
pub(crate) fn call_func_with_index_inner(
ctx_ptr: *mut vm::Ctx,
func_ptr: NonNull<vm::Func>,
signature: &FuncSig,
wasm: Wasm,
args: &[Value],
rets: &mut Vec<Value>,
) -> CallResult<()> {
rets.clear();
let num_results = signature.returns().len();
let num_results = num_results
+ signature
.returns()
.iter()
.filter(|&&ty| ty == Type::V128)
.count();
rets.reserve(num_results);
if !signature.check_param_value_types(args) {
Err(ResolveError::Signature {
expected: signature.clone(),
found: args.iter().map(|val| val.ty()).collect(),
})?
}
let mut raw_args: SmallVec<[u64; 8]> = SmallVec::new(); let mut raw_args: SmallVec<[u64; 8]> = SmallVec::new();
for v in args { for v in args {
match v { match v {
@ -598,9 +614,7 @@ pub(crate) fn call_func_with_index(
trampoline, trampoline,
invoke, invoke,
invoke_env, invoke_env,
} = runnable } = wasm;
.get_trampoline(info, sig_index)
.expect("wasm trampoline");
let run_wasm = |result_space: *mut u64| unsafe { let run_wasm = |result_space: *mut u64| unsafe {
let mut trap_info = WasmTrapInfo::Unknown; let mut trap_info = WasmTrapInfo::Unknown;

View File

@ -44,7 +44,7 @@ impl<'a> From<DynFunc<'a>> for Anyfunc<'a> {
} }
pub struct AnyfuncTable { pub struct AnyfuncTable {
backing: Vec<vm::Anyfunc>, pub backing: Vec<vm::Anyfunc>,
max: Option<u32>, max: Option<u32>,
} }

View File

@ -9,8 +9,7 @@ use std::{cell::RefCell, fmt, ptr, rc::Rc};
mod anyfunc; mod anyfunc;
pub use self::anyfunc::Anyfunc; pub use self::anyfunc::{Anyfunc, AnyfuncTable};
use self::anyfunc::AnyfuncTable;
use crate::error::GrowError; use crate::error::GrowError;
pub enum Element<'a> { pub enum Element<'a> {

View File

@ -1,17 +1,19 @@
pub use crate::backing::{ImportBacking, LocalBacking, INTERNALS_SIZE}; pub use crate::backing::{ImportBacking, LocalBacking, INTERNALS_SIZE};
use crate::{ use crate::{
error::{CallError, CallResult, RuntimeError}, error::CallResult,
instance::call_func_with_index, instance::call_func_with_index_inner,
memory::{Memory, MemoryType}, memory::{Memory, MemoryType},
module::{ModuleInfo, ModuleInner}, module::{ModuleInfo, ModuleInner},
sig_registry::SigRegistry,
structures::TypedIndex, structures::TypedIndex,
types::{FuncIndex, LocalOrImport, MemoryIndex, Value}, types::{LocalOrImport, MemoryIndex, TableIndex, Value},
vmcalls, vmcalls,
}; };
use std::{ use std::{
cell::UnsafeCell, cell::UnsafeCell,
ffi::c_void, ffi::c_void,
mem, ptr, mem,
ptr::{self, NonNull},
sync::atomic::{AtomicUsize, Ordering}, sync::atomic::{AtomicUsize, Ordering},
sync::Once, sync::Once,
}; };
@ -397,24 +399,36 @@ impl Ctx {
} }
/// Calls a host or Wasm function at the given index /// Calls a host or Wasm function at the given index
pub fn call_with_index(&mut self, index: FuncIndex, args: &[Value]) -> CallResult<Vec<Value>> { pub fn call_with_index(&mut self, index: TableIndex, args: &[Value]) -> CallResult<Vec<Value>> {
let module = unsafe { &(*self.module) }; let anyfunc_table =
if module.info.func_assoc.get(index).is_none() { unsafe { &*((**self.internal.tables).table as *mut crate::table::AnyfuncTable) };
return Err(CallError::Runtime(RuntimeError::Trap { let entry = anyfunc_table.backing[index.index()];
msg: format!("Index out of bounds: {}", index.index()).into_boxed_str(),
})); let fn_ptr = entry.func;
} let sig_id = entry.sig_id;
let mut output = vec![]; let signature = SigRegistry.lookup_signature(unsafe { std::mem::transmute(sig_id.0) });
call_func_with_index( let mut rets = vec![];
&module.info,
module.runnable_module.as_ref(), let wasm = {
unsafe { &*self.import_backing }, let module = unsafe { &*self.module };
self as *mut Ctx, let runnable = &module.runnable_module;
index,
let sig_index = SigRegistry.lookup_sig_index(signature.clone());
runnable
.get_trampoline(&module.info, sig_index)
.expect("wasm trampoline")
};
call_func_with_index_inner(
self as *mut Ctx, /* doesn't handle all cases */
NonNull::new(fn_ptr as *mut _).unwrap(),
&signature,
wasm,
args, args,
&mut output, &mut rets,
)?; )?;
Ok(output)
Ok(rets)
} }
} }