Skip to content

Commit

Permalink
Improve Wasmtime-like API for wasmi further (#616)
Browse files Browse the repository at this point in the history
* rename signature getters to ty_dedup

* rename Func::func_type to ty

* remove Global::value_type getter

* rename Global::global_type into ty

* add docs to GlobalType::new

* make GlobalType and Mutability more similar to Wasmtime API

GlobalType::content() -> ValueType
Mutability::{Const, Var}

* use GlobalType in GlobalEntity

* remove GlobalType::value_type getter

* remove Global::is_mutable getter

* rename Table::table_type to ty

* rename Memory::memory_type to ty

* rename Value::value_type to ty

* update the changelog for the next release

* update changelog further

* rename Table fields and getters

Now:
- Table::minimum
- Table::maximum

Also improve docs.

* rename TableEntity fields

* rename Table::len -> size

* apply rustfmt

* add changelog link

* update changelog

* make Table and TableType operate on u32 instead of usize

This affects Table::{new, size, get, set, grow} methods and TableType::{new, minimum, maximum} methods and their users.

* update changelog

* apply clippy suggestion
  • Loading branch information
Robbepop authored Jan 17, 2023
1 parent b9168b0 commit 3b89bfd
Show file tree
Hide file tree
Showing 23 changed files with 184 additions and 208 deletions.
19 changes: 18 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Dates in this file are formattes as `YYYY-MM-DD`.

### Changed

- Mirror Wasmtime API more closely:
- Mirror Wasmtime API more closely. (https://github.com/paritytech/wasmi/pull/615, https://github.com/paritytech/wasmi/pull/616)
- Renamed `Caller::host_data` method to `Caller::data`.
- Renamed `Caller::host_data_mut` method to `Caller::data_mut`.
- Add `Extern::ty` method and the `ExternType` type.
Expand All @@ -31,6 +31,23 @@ Dates in this file are formattes as `YYYY-MM-DD`.
- `Instance::get_global`
- `Instance::get_table`
- `Instance::get_memory`
- Rename getters for querying types of runtime objects:
- `Func::func_type` => `Func::ty`
- `Global::global_type` => `Global::ty`
- `Table::table_type` => `Table::ty`
- `Memory::memory_type` => `Memory::ty`
- `Value::value_type` => `Value::ty`
- Remove `Global::value_type` getter.
- Use `global.ty().content()` instead.
- Remove `Global::is_mutable` getter.
- Use `global.ty().mutability().is_mut()` instead.
- Rename `Mutability::Mutable` to `Var`.
- Add `Mutability::is_mut` getter.
- While this API is not included in Wasmtime it is a useful convenience method.
- Rename `TableType::initial` method to `minimum`.
- Rename `Table::len` method to `size`.
- `Table` and `TableType` now operate on `u32` instead of `usize` just like in Wasmtime.
- This affects `Table::{new, size, set, get, grow}` methods and `TableType::{new, minimum, maximum}` methods and their users.

## [`0.22.0`] - 2023-01-16

Expand Down
2 changes: 1 addition & 1 deletion crates/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ fn main() -> Result<()> {
let func_args = args.func_args;

let (func, func_name, mut store) = load_wasm_func(&wasm_file, &module, &func_name)?;
let func_type = func.func_type(&store);
let func_type = func.ty(&store);
let func_args = type_check_arguments(&func_name, &func_type, &func_args)?;
let mut results = prepare_results_buffer(&func_type);

Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ impl Value {

/// Get variable type for this value.
#[inline]
pub fn value_type(&self) -> ValueType {
pub fn ty(&self) -> ValueType {
match *self {
Value::I32(_) => ValueType::I32,
Value::I64(_) => ValueType::I64,
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmi/src/engine/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ impl<'ctx, 'engine, 'func> Executor<'ctx, 'engine, 'func> {
let func = self
.ctx
.resolve_table(table)
.get(func_index as usize)
.get(func_index)
.map_err(|_| TrapCode::TableOutOfBounds)?
.ok_or(TrapCode::IndirectCallToNull)?;
let actual_signature = self.ctx.get_func_type(func);
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmi/src/engine/func_builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,7 @@ impl<'parser> FuncBuilder<'parser> {
self.translate_if_reachable(|builder| {
let global_idx = GlobalIdx(global_idx);
let global_type = builder.res.get_type_of_global(global_idx);
debug_assert_eq!(global_type.mutability(), Mutability::Mutable);
debug_assert_eq!(global_type.mutability(), Mutability::Var);
builder.stack_height.pop1();
let global_idx = global_idx.into_u32().into();
builder
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmi/src/engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ impl<'engine> EngineExecutor<'engine> {
{
self.stack
.values
.drop(host_func.func_type(ctx.as_context()).params().len());
.drop(host_func.ty(ctx.as_context()).params().len());
self.stack.values.extend(params.call_params());
let mut frame = self
.stack
Expand Down
6 changes: 3 additions & 3 deletions crates/wasmi/src/engine/resumable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,11 @@ impl ResumableInvocation {
outputs: &mut [Value],
) -> Result<ResumableCall, Error> {
self.engine
.resolve_func_type(self.host_func().signature(ctx.as_context()), |func_type| {
.resolve_func_type(self.host_func().ty_dedup(ctx.as_context()), |func_type| {
func_type.match_results(inputs, true)
})?;
self.engine
.resolve_func_type(self.func.signature(ctx.as_context()), |func_type| {
.resolve_func_type(self.func.ty_dedup(ctx.as_context()), |func_type| {
func_type.match_results(outputs, false)?;
func_type.prepare_outputs(outputs);
<Result<(), Error>>::Ok(()) // TODO: why do we need types here?
Expand Down Expand Up @@ -249,7 +249,7 @@ impl<Results> TypedResumableInvocation<Results> {
Results: WasmResults,
{
self.engine
.resolve_func_type(self.host_func().signature(ctx.as_context()), |func_type| {
.resolve_func_type(self.host_func().ty_dedup(ctx.as_context()), |func_type| {
func_type.match_results(inputs, true)
})?;
self.engine
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmi/src/engine/stack/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ impl Stack {
// The host function signature is required for properly
// adjusting, inspecting and manipulating the value stack.
let (input_types, output_types) = func_types
.resolve_func_type(host_func.signature())
.resolve_func_type(host_func.ty_dedup())
.params_results();
// In case the host function returns more values than it takes
// we are required to extend the value stack.
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmi/src/engine/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl<'a> CallResults for &'a mut [Value] {
fn call_results(self, results: &[UntypedValue]) -> Self::Results {
assert_eq!(self.len(), results.len());
self.iter_mut().zip(results).for_each(|(dst, src)| {
*dst = src.with_type(dst.value_type());
*dst = src.with_type(dst.ty());
})
}
}
8 changes: 4 additions & 4 deletions crates/wasmi/src/external.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,10 @@ impl Extern {
/// If this item does not belong to the `store` provided.
pub fn ty(&self, ctx: impl AsContext) -> ExternType {
match self {
Extern::Global(global) => global.global_type(ctx).into(),
Extern::Table(table) => table.table_type(ctx).into(),
Extern::Memory(memory) => memory.memory_type(ctx).into(),
Extern::Func(func) => func.func_type(ctx).into(),
Extern::Global(global) => global.ty(ctx).into(),
Extern::Table(table) => table.ty(ctx).into(),
Extern::Memory(memory) => memory.ty(ctx).into(),
Extern::Func(func) => func.ty(ctx).into(),
}
}
}
Expand Down
20 changes: 10 additions & 10 deletions crates/wasmi/src/func/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ impl<T> FuncEntity<T> {
}

/// Returns the signature of the Wasm function.
pub fn signature(&self) -> DedupFuncType {
pub fn ty_dedup(&self) -> DedupFuncType {
match self.as_internal() {
FuncEntityInternal::Wasm(func) => func.signature(),
FuncEntityInternal::Host(func) => func.signature(),
FuncEntityInternal::Wasm(func) => func.ty_dedup(),
FuncEntityInternal::Host(func) => func.ty_dedup(),
}
}
}
Expand Down Expand Up @@ -138,7 +138,7 @@ impl WasmFuncEntity {
}

/// Returns the signature of the Wasm function.
pub fn signature(&self) -> DedupFuncType {
pub fn ty_dedup(&self) -> DedupFuncType {
self.signature
}

Expand Down Expand Up @@ -216,7 +216,7 @@ impl<T> HostFuncEntity<T> {
}

/// Returns the signature of the host function.
pub fn signature(&self) -> DedupFuncType {
pub fn ty_dedup(&self) -> DedupFuncType {
self.signature
}

Expand Down Expand Up @@ -260,15 +260,15 @@ impl Func {
}

/// Returns the signature of the function.
pub(crate) fn signature(&self, ctx: impl AsContext) -> DedupFuncType {
ctx.as_context().store.resolve_func(*self).signature()
pub(crate) fn ty_dedup(&self, ctx: impl AsContext) -> DedupFuncType {
ctx.as_context().store.resolve_func(*self).ty_dedup()
}

/// Returns the function type of the [`Func`].
pub fn func_type(&self, ctx: impl AsContext) -> FuncType {
pub fn ty(&self, ctx: impl AsContext) -> FuncType {
ctx.as_context()
.store
.resolve_func_type(self.signature(&ctx))
.resolve_func_type(self.ty_dedup(&ctx))
}

/// Calls the Wasm or host function with the given inputs.
Expand Down Expand Up @@ -360,7 +360,7 @@ impl Func {
inputs: &[Value],
outputs: &mut [Value],
) -> Result<(), FuncError> {
let fn_type = self.signature(ctx.as_context());
let fn_type = self.ty_dedup(ctx.as_context());
ctx.as_context()
.store
.resolve_func_type_with(fn_type, |func_type| {
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmi/src/func/typed_func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ where
/// If the provided static types `Params` and `Results` for the parameters
/// and result types of `func` mismatch the signature of `func`.
pub(crate) fn new(ctx: impl AsContext, func: Func) -> Result<Self, Error> {
let func_type = func.func_type(&ctx);
let func_type = func.ty(&ctx);
let (actual_params, actual_results) = (
<Params as WasmTypeList>::types(),
<Results as WasmTypeList>::types(),
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmi/src/func_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ impl Ty for ValueType {

impl Ty for Value {
fn ty(&self) -> ValueType {
self.value_type()
self.ty()
}
}

Expand Down
75 changes: 25 additions & 50 deletions crates/wasmi/src/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,36 +77,42 @@ pub enum Mutability {
/// The value of the global variable is a constant.
Const,
/// The value of the global variable is mutable.
Mutable,
Var,
}

impl Mutability {
/// Returns `true` if this mutability is constant.
/// Returns `true` if this mutability is [`Mutability::Const`].
pub fn is_const(&self) -> bool {
matches!(self, Self::Const)
}

/// Returns `true` if this mutability is [`Mutability::Var`].
pub fn is_mut(&self) -> bool {
matches!(self, Self::Var)
}
}

/// The type of a global variable.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct GlobalType {
/// The value type of the global variable.
value_type: ValueType,
content: ValueType,
/// The mutability of the global variable.
mutability: Mutability,
}

impl GlobalType {
pub fn new(value_type: ValueType, mutability: Mutability) -> Self {
/// Creates a new [`GlobalType`] from the given [`ValueType`] and [`Mutability`].
pub fn new(content: ValueType, mutability: Mutability) -> Self {
Self {
value_type,
content,
mutability,
}
}

/// Returns the [`ValueType`] of the global variable.
pub fn value_type(&self) -> ValueType {
self.value_type
pub fn content(&self) -> ValueType {
self.content
}

/// Returns the [`Mutability`] of the global variable.
Expand Down Expand Up @@ -136,35 +142,22 @@ impl GlobalType {
pub struct GlobalEntity {
/// The current value of the global variable.
value: UntypedValue,
/// The value type of the global variable.
value_type: ValueType,
/// The mutability of the global variable.
mutability: Mutability,
/// The type of the global variable.
ty: GlobalType,
}

impl GlobalEntity {
/// Creates a new global entity with the given initial value and mutability.
pub fn new(initial_value: Value, mutability: Mutability) -> Self {
Self {
value: initial_value.into(),
value_type: initial_value.value_type(),
mutability,
ty: GlobalType::new(initial_value.ty(), mutability),
}
}

/// Returns `true` if the global variable is mutable.
pub fn is_mutable(&self) -> bool {
matches!(self.mutability, Mutability::Mutable)
}

/// Returns the type of the global variable value.
pub fn value_type(&self) -> ValueType {
self.value_type
}

/// Returns the [`GlobalType`] of the global variable.
pub fn global_type(&self) -> GlobalType {
GlobalType::new(self.value_type(), self.mutability)
pub fn ty(&self) -> GlobalType {
self.ty
}

/// Sets a new value to the global variable.
Expand All @@ -174,13 +167,13 @@ impl GlobalEntity {
/// - If the global variable is immutable.
/// - If there is a type mismatch between the global variable and the new value.
pub fn set(&mut self, new_value: Value) -> Result<(), GlobalError> {
if !self.is_mutable() {
if !self.ty().mutability().is_mut() {
return Err(GlobalError::ImmutableWrite);
}
if self.value_type() != new_value.value_type() {
if self.ty().content() != new_value.ty() {
return Err(GlobalError::TypeMismatch {
expected: self.value_type(),
encountered: new_value.value_type(),
expected: self.ty().content(),
encountered: new_value.ty(),
});
}
self.set_untyped(new_value.into());
Expand All @@ -201,7 +194,7 @@ impl GlobalEntity {

/// Returns the current value of the global variable.
pub fn get(&self) -> Value {
self.get_untyped().with_type(self.value_type)
self.get_untyped().with_type(self.ty().content())
}

/// Returns the current untyped value of the global variable.
Expand Down Expand Up @@ -244,27 +237,9 @@ impl Global {
.alloc_global(GlobalEntity::new(initial_value, mutability))
}

/// Returns `true` if the global variable is mutable.
///
/// # Panics
///
/// Panics if `ctx` does not own this [`Global`].
pub fn is_mutable(&self, ctx: impl AsContext) -> bool {
ctx.as_context().store.resolve_global(*self).is_mutable()
}

/// Returns the type of the global variable value.
///
/// # Panics
///
/// Panics if `ctx` does not own this [`Global`].
pub fn value_type(&self, ctx: impl AsContext) -> ValueType {
ctx.as_context().store.resolve_global(*self).value_type()
}

/// Returns the [`GlobalType`] of the global variable.
pub fn global_type(&self, ctx: impl AsContext) -> GlobalType {
ctx.as_context().store.resolve_global(*self).global_type()
pub fn ty(&self, ctx: impl AsContext) -> GlobalType {
ctx.as_context().store.resolve_global(*self).ty()
}

/// Sets a new value to the global variable.
Expand Down
8 changes: 4 additions & 4 deletions crates/wasmi/src/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ impl<T> Linker<T> {
match import.ty() {
ExternType::Func(expected_func_type) => {
let func = resolved.and_then(Extern::into_func).ok_or_else(make_err)?;
let actual_func_type = func.signature(&context);
let actual_func_type = func.ty_dedup(&context);
let actual_func_type = context.store.resolve_func_type(actual_func_type);
if &actual_func_type != expected_func_type {
return Err(LinkerError::FuncTypeMismatch {
Expand All @@ -385,23 +385,23 @@ impl<T> Linker<T> {
}
ExternType::Table(expected_table_type) => {
let table = resolved.and_then(Extern::into_table).ok_or_else(make_err)?;
let actual_table_type = table.table_type(context);
let actual_table_type = table.ty(context);
actual_table_type.satisfies(expected_table_type)?;
Ok(Extern::Table(table))
}
ExternType::Memory(expected_memory_type) => {
let memory = resolved
.and_then(Extern::into_memory)
.ok_or_else(make_err)?;
let actual_memory_type = memory.memory_type(context);
let actual_memory_type = memory.ty(context);
actual_memory_type.satisfies(expected_memory_type)?;
Ok(Extern::Memory(memory))
}
ExternType::Global(expected_global_type) => {
let global = resolved
.and_then(Extern::into_global)
.ok_or_else(make_err)?;
let actual_global_type = global.global_type(context);
let actual_global_type = global.ty(context);
if &actual_global_type != expected_global_type {
return Err(LinkerError::GlobalTypeMismatch {
name: import.import_name().clone(),
Expand Down
Loading

0 comments on commit 3b89bfd

Please sign in to comment.