Skip to content

Commit

Permalink
Store WasmFuncType in FuncType
Browse files Browse the repository at this point in the history
This commit updates `wasmtime::FuncType` to exactly store an internal
`WasmFuncType` from the cranelift crates. This allows us to remove a
translation layer when we are given a `FuncType` and want to get an
internal cranelift type out as a result.

The other major change from this commit was changing the constructor and
accessors of `FuncType` to be iterator-based instead of exposing
implementation details.
  • Loading branch information
alexcrichton committed Nov 5, 2020
1 parent 6b137c2 commit 038294e
Show file tree
Hide file tree
Showing 13 changed files with 116 additions and 148 deletions.
16 changes: 3 additions & 13 deletions crates/c-api/src/types/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,9 @@ pub extern "C" fn wasm_functype_new(
params: &mut wasm_valtype_vec_t,
results: &mut wasm_valtype_vec_t,
) -> Box<wasm_functype_t> {
let params = params
.take()
.into_iter()
.map(|vt| vt.unwrap().ty.clone())
.collect::<Vec<_>>();
let results = results
.take()
.into_iter()
.map(|vt| vt.unwrap().ty.clone())
.collect::<Vec<_>>();
let functype = FuncType::new(params.into_boxed_slice(), results.into_boxed_slice());
let params = params.take().into_iter().map(|vt| vt.unwrap().ty.clone());
let results = results.take().into_iter().map(|vt| vt.unwrap().ty.clone());
let functype = FuncType::new(params, results);
Box::new(wasm_functype_t::new(functype))
}

Expand All @@ -74,7 +66,6 @@ pub extern "C" fn wasm_functype_params(ft: &wasm_functype_t) -> &wasm_valtype_ve
ft.params_cache.get_or_init(|| {
ft.ty
.params()
.iter()
.map(|p| Some(Box::new(wasm_valtype_t { ty: p.clone() })))
.collect::<Vec<_>>()
.into()
Expand All @@ -87,7 +78,6 @@ pub extern "C" fn wasm_functype_results(ft: &wasm_functype_t) -> &wasm_valtype_v
ft.returns_cache.get_or_init(|| {
ft.ty
.results()
.iter()
.map(|p| Some(Box::new(wasm_valtype_t { ty: p.clone() })))
.collect::<Vec<_>>()
.into()
Expand Down
12 changes: 6 additions & 6 deletions crates/fuzzing/src/oracles/dummy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ pub fn dummy_imports<'module>(
/// Construct a dummy function for the given function type
pub fn dummy_func(store: &Store, ty: FuncType) -> Func {
Func::new(store, ty.clone(), move |_, _, results| {
for (ret_ty, result) in ty.results().iter().zip(results) {
for (ret_ty, result) in ty.results().zip(results) {
*result = dummy_value(ret_ty)?;
}
Ok(())
})
}

/// Construct a dummy value for the given value type.
pub fn dummy_value(val_ty: &ValType) -> Result<Val, Trap> {
pub fn dummy_value(val_ty: ValType) -> Result<Val, Trap> {
Ok(match val_ty {
ValType::I32 => Val::I32(0),
ValType::I64 => Val::I64(0),
Expand All @@ -58,19 +58,19 @@ pub fn dummy_value(val_ty: &ValType) -> Result<Val, Trap> {
}

/// Construct a sequence of dummy values for the given types.
pub fn dummy_values(val_tys: &[ValType]) -> Result<Vec<Val>, Trap> {
val_tys.iter().map(dummy_value).collect()
pub fn dummy_values(val_tys: impl IntoIterator<Item = ValType>) -> Result<Vec<Val>, Trap> {
val_tys.into_iter().map(dummy_value).collect()
}

/// Construct a dummy global for the given global type.
pub fn dummy_global(store: &Store, ty: GlobalType) -> Result<Global, Trap> {
let val = dummy_value(ty.content())?;
let val = dummy_value(ty.content().clone())?;
Ok(Global::new(store, ty, val).unwrap())
}

/// Construct a dummy table for the given table type.
pub fn dummy_table(store: &Store, ty: TableType) -> Result<Table, Trap> {
let init_val = dummy_value(&ty.element())?;
let init_val = dummy_value(ty.element().clone())?;
Ok(Table::new(store, ty, init_val).unwrap())
}

Expand Down
74 changes: 38 additions & 36 deletions crates/wasmtime/src/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ macro_rules! getters {
// Verify all the paramers match the expected parameters, and that
// there are no extra parameters...
let ty = self.ty();
let mut params = ty.params().iter().cloned();
let mut params = ty.params();
let n = 0;
$(
let n = n + 1;
Expand All @@ -173,7 +173,7 @@ macro_rules! getters {
ensure!(params.next().is_none(), "Type mismatch: too many arguments (expected {})", n);

// ... then do the same for the results...
let mut results = ty.results().iter().cloned();
let mut results = ty.results();
R::matches(&mut results)
.context("Type mismatch in return type")?;
ensure!(results.next().is_none(), "Type mismatch: too many return values (expected 1)");
Expand Down Expand Up @@ -274,7 +274,7 @@ impl Func {
let mut args: SmallVec<[Val; STACK_ARGS]> =
SmallVec::with_capacity(ty_clone.params().len());
let store = Store::upgrade(&store_weak).unwrap();
for (i, ty) in ty_clone.params().iter().enumerate() {
for (i, ty) in ty_clone.params().enumerate() {
unsafe {
let val = Val::read_value_from(&store, values_vec.add(i), ty);
args.push(val);
Expand All @@ -298,7 +298,7 @@ impl Func {
// produces the wrong number or wrong types of values, and we need
// to catch that here.
for (i, (ret, ty)) in returns.into_iter().zip(ty_clone.results()).enumerate() {
if ret.ty() != *ty {
if ret.ty() != ty {
return Err(Trap::new(
"function attempted to return an incompatible value",
));
Expand Down Expand Up @@ -596,9 +596,9 @@ impl Func {
let mut values_vec = vec![0; max(params.len(), my_ty.results().len())];

// Store the argument values into `values_vec`.
let param_tys = my_ty.params().iter();
let param_tys = my_ty.params();
for ((arg, slot), ty) in params.iter().cloned().zip(&mut values_vec).zip(param_tys) {
if arg.ty() != *ty {
if arg.ty() != ty {
bail!(
"argument type mismatch: found {} but expected {}",
arg.ty(),
Expand Down Expand Up @@ -628,7 +628,7 @@ impl Func {

// Load the return values out of `values_vec`.
let mut results = Vec::with_capacity(my_ty.results().len());
for (index, ty) in my_ty.results().iter().enumerate() {
for (index, ty) in my_ty.results().enumerate() {
unsafe {
let ptr = values_vec.as_ptr().add(index);
results.push(Val::read_value_from(&self.instance.store, ptr, ty));
Expand Down Expand Up @@ -876,7 +876,7 @@ pub unsafe trait WasmTy {

// Add this type to the given vec of expected valtypes.
#[doc(hidden)]
fn push(dst: &mut Vec<ValType>);
fn valtype() -> Option<ValType>;

// Does the next valtype(s) match this type?
#[doc(hidden)]
Expand Down Expand Up @@ -923,7 +923,7 @@ pub unsafe trait WasmRet {

// Same as `WasmTy::push`.
#[doc(hidden)]
fn push(dst: &mut Vec<ValType>);
fn valtype() -> Option<ValType>;

// Same as `WasmTy::matches`.
#[doc(hidden)]
Expand Down Expand Up @@ -952,7 +952,9 @@ unsafe impl WasmTy for () {
#[inline]
unsafe fn from_abi<'a>(_abi: Self::Abi, _store: WeakStore<'a>) -> Self {}

fn push(_dst: &mut Vec<ValType>) {}
fn valtype() -> Option<ValType> {
None
}

fn matches(_tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
Ok(())
Expand Down Expand Up @@ -983,8 +985,8 @@ unsafe impl WasmTy for i32 {
abi
}

fn push(dst: &mut Vec<ValType>) {
dst.push(ValType::I32);
fn valtype() -> Option<ValType> {
Some(ValType::I32)
}

fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
Expand Down Expand Up @@ -1028,8 +1030,8 @@ unsafe impl WasmTy for u32 {
abi as Self
}

fn push(dst: &mut Vec<ValType>) {
<i32 as WasmTy>::push(dst)
fn valtype() -> Option<ValType> {
<i32 as WasmTy>::valtype()
}

fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
Expand Down Expand Up @@ -1065,8 +1067,8 @@ unsafe impl WasmTy for i64 {
abi
}

fn push(dst: &mut Vec<ValType>) {
dst.push(ValType::I64);
fn valtype() -> Option<ValType> {
Some(ValType::I64)
}

fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
Expand Down Expand Up @@ -1110,8 +1112,8 @@ unsafe impl WasmTy for u64 {
abi as Self
}

fn push(dst: &mut Vec<ValType>) {
<i64 as WasmTy>::push(dst)
fn valtype() -> Option<ValType> {
<i64 as WasmTy>::valtype()
}

fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
Expand Down Expand Up @@ -1147,8 +1149,8 @@ unsafe impl WasmTy for f32 {
abi
}

fn push(dst: &mut Vec<ValType>) {
dst.push(ValType::F32);
fn valtype() -> Option<ValType> {
Some(ValType::F32)
}

fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
Expand Down Expand Up @@ -1192,8 +1194,8 @@ unsafe impl WasmTy for f64 {
abi
}

fn push(dst: &mut Vec<ValType>) {
dst.push(ValType::F64);
fn valtype() -> Option<ValType> {
Some(ValType::F64)
}

fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
Expand Down Expand Up @@ -1254,8 +1256,8 @@ unsafe impl WasmTy for Option<ExternRef> {
}
}

fn push(dst: &mut Vec<ValType>) {
dst.push(ValType::ExternRef);
fn valtype() -> Option<ValType> {
Some(ValType::ExternRef)
}

fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
Expand Down Expand Up @@ -1307,8 +1309,8 @@ unsafe impl WasmTy for Option<Func> {
Func::from_caller_checked_anyfunc(&store, abi)
}

fn push(dst: &mut Vec<ValType>) {
dst.push(ValType::FuncRef);
fn valtype() -> Option<ValType> {
Some(ValType::FuncRef)
}

fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
Expand Down Expand Up @@ -1353,9 +1355,8 @@ where
<Self as WasmTy>::from_abi(abi, store)
}

#[inline]
fn push(dst: &mut Vec<ValType>) {
<Self as WasmTy>::push(dst)
fn valtype() -> Option<ValType> {
<Self as WasmTy>::valtype()
}

#[inline]
Expand Down Expand Up @@ -1405,8 +1406,8 @@ where
Ok(<T as WasmTy>::from_abi(abi, store))
}

fn push(dst: &mut Vec<ValType>) {
<T as WasmTy>::push(dst)
fn valtype() -> Option<ValType> {
<T as WasmTy>::valtype()
}

fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
Expand Down Expand Up @@ -1657,11 +1658,12 @@ macro_rules! impl_into_func {
R::store_to_args(ret, args);
}

let mut _args = Vec::new();
$($args::push(&mut _args);)*
let mut ret = Vec::new();
R::push(&mut ret);
let ty = FuncType::new(_args.into(), ret.into());
let ty = FuncType::new(
None::<ValType>.into_iter()
$(.chain($args::valtype()))*
,
R::valtype(),
);

let store_weak = store.weak();
let trampoline = host_trampoline::<$($args,)* R>;
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmtime/src/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,7 @@ impl Linker {
// Otherwise return a no-op function.
Ok(Func::new(
&self.store,
FuncType::new(Vec::new().into_boxed_slice(), Vec::new().into_boxed_slice()),
FuncType::new(None, None),
move |_, _, _| Ok(()),
))
}
Expand Down
8 changes: 4 additions & 4 deletions crates/wasmtime/src/trampoline/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ pub fn create_handle_with_function(

let pointer_type = isa.pointer_type();
let sig = ft.get_wasmtime_signature(pointer_type);
let wft = ft.to_wasm_func_type();
let wft = ft.as_wasm_func_type();

let mut fn_builder_ctx = FunctionBuilderContext::new();
let mut module = Module::new();
Expand All @@ -241,7 +241,7 @@ pub fn create_handle_with_function(
&sig,
mem::size_of::<u128>(),
)?;
store.signatures().borrow_mut().register(&wft, trampoline);
store.signatures().borrow_mut().register(wft, trampoline);

// Next up we wrap everything up into an `InstanceHandle` by publishing our
// code memory (makes it executable) and ensuring all our various bits of
Expand All @@ -265,7 +265,7 @@ pub unsafe fn create_handle_with_raw_function(
store: &Store,
state: Box<dyn Any>,
) -> Result<StoreInstanceHandle> {
let wft = ft.to_wasm_func_type();
let wft = ft.as_wasm_func_type();

let mut module = Module::new();
let mut finished_functions = PrimaryMap::new();
Expand All @@ -276,7 +276,7 @@ pub unsafe fn create_handle_with_raw_function(
.exports
.insert(String::new(), EntityIndex::Function(func_id));
finished_functions.push(func);
store.signatures().borrow_mut().register(&wft, trampoline);
store.signatures().borrow_mut().register(wft, trampoline);

create_handle(module, store, finished_functions, state, &[])
}
Loading

0 comments on commit 038294e

Please sign in to comment.