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

Remove duplicated checks during instantiation #812

Closed
wants to merge 11 commits into from
33 changes: 0 additions & 33 deletions crates/wasmi/src/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,6 @@ pub enum GlobalError {
/// The type of the new value that mismatches the type of the global variable.
encountered: ValueType,
},
/// Occurs when a global type does not satisfy the constraints of another.
UnsatisfyingGlobalType {
/// The unsatisfying [`GlobalType`].
unsatisfying: GlobalType,
/// The required [`GlobalType`].
required: GlobalType,
},
}

impl Display for GlobalError {
Expand All @@ -57,16 +50,6 @@ impl Display for GlobalError {
expected {expected:?} but encountered {encountered:?}.",
)
}
Self::UnsatisfyingGlobalType {
unsatisfying,
required,
} => {
write!(
f,
"global type {unsatisfying:?} does not \
satisfy requirements of {required:?}",
)
}
}
}
}
Expand Down Expand Up @@ -119,22 +102,6 @@ impl GlobalType {
pub fn mutability(&self) -> Mutability {
self.mutability
}

/// Checks if `self` satisfies the given `GlobalType`.
///
/// # Errors
///
/// - If the initial limits of the `required` [`GlobalType`] are greater than `self`.
/// - If the maximum limits of the `required` [`GlobalType`] are greater than `self`.
pub(crate) fn satisfies(&self, required: &GlobalType) -> Result<(), GlobalError> {
if self != required {
return Err(GlobalError::UnsatisfyingGlobalType {
unsatisfying: *self,
required: *required,
});
}
Ok(())
}
}

/// A global variable entity.
Expand Down
78 changes: 9 additions & 69 deletions crates/wasmi/src/module/instantiate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ use crate::{
ElementSegment,
Error,
Extern,
ExternType,
FuncRef,
FuncType,
Global,
Instance,
InstanceEntity,
Expand Down Expand Up @@ -61,7 +59,7 @@ impl Module {
let handle = context.as_context_mut().store.inner.alloc_instance();
let mut builder = InstanceEntity::build(self);

self.extract_imports(&context, &mut builder, externals)?;
Self::extract_imports(&mut builder, externals);
self.extract_functions(&mut context, &mut builder, handle);
self.extract_tables(&mut context, &mut builder)?;
self.extract_memories(&mut context, &mut builder)?;
Expand All @@ -77,85 +75,27 @@ impl Module {
Ok(InstancePre::new(handle, builder))
}

/// Extract the Wasm imports from the module and zips them with the given external values.
///
/// This also stores imported references into the [`Instance`] under construction.
///
/// # Errors
///
/// - If too few or too many external values are given for the required module imports.
/// - If the zipped import and given external have mismatching types, e.g. on index `i`
/// the module requires a function import but on index `i` the externals provide a global
/// variable external value.
/// - If the externally provided [`Table`], [`Memory`], [`Func`] or [`Global`] has a type
/// mismatch with the expected module import type.
///
/// [`Func`]: [`crate::Func`]
fn extract_imports<I>(
&self,
context: &impl AsContextMut,
builder: &mut InstanceEntityBuilder,
externals: I,
) -> Result<(), InstantiationError>
/// Extract the Wasm imports from the module.
fn extract_imports<I>(builder: &mut InstanceEntityBuilder, externals: I)
where
I: IntoIterator<Item = Extern>,
{
let mut imports = self.imports();
let mut externals = externals.into_iter();
loop {
// Iterate on module imports and the given external values in lock-step fashion.
//
// Note: We cannot use [`zip`](`core::iter::zip`) here since we require that both
// iterators yield the same amount of elements.
let (import, external) = match (imports.next(), externals.next()) {
(Some(import), Some(external)) => (import, external),
(None, None) => break,
(Some(_), None) | (None, Some(_)) => {
return Err(InstantiationError::ImportsExternalsLenMismatch)
}
};
match (import.ty(), external) {
(ExternType::Func(expected_signature), Extern::Func(func)) => {
let actual_signature = func.ty_dedup(context.as_context());
let actual_signature = self
.engine
.resolve_func_type(actual_signature, FuncType::clone);
// Note: We can compare function signatures without resolving them because
// we deduplicate them before registering. Therefore two equal instances of
// [`SignatureEntity`] will be associated to the same [`Signature`].
if &actual_signature != expected_signature {
// Note: In case of error we could resolve the signatures for better error readability.
return Err(InstantiationError::SignatureMismatch {
actual: actual_signature,
expected: expected_signature.clone(),
});
}
for external in externals {
match external {
Extern::Func(func) => {
builder.push_func(func);
}
(ExternType::Table(required), Extern::Table(table)) => {
let imported = table.dynamic_ty(context.as_context());
imported.is_subtype_or_err(required)?;
Extern::Table(table) => {
builder.push_table(table);
}
(ExternType::Memory(required), Extern::Memory(memory)) => {
let imported = memory.dynamic_ty(context.as_context());
imported.is_subtype_or_err(required)?;
Extern::Memory(memory) => {
builder.push_memory(memory);
}
(ExternType::Global(required), Extern::Global(global)) => {
let imported = global.ty(context.as_context());
required.satisfies(&imported)?;
Extern::Global(global) => {
builder.push_global(global);
}
(expected_import, actual_extern_val) => {
return Err(InstantiationError::ImportsExternalsMismatch {
expected: expected_import.clone(),
actual: actual_extern_val,
});
}
}
}
Ok(())
}

/// Extracts the Wasm functions from the module and stores them into the [`Store`].
Expand Down
Loading