Update wasm-tools dependencies (#4970)

* Update wasm-tools dependencies

This update brings in a number of features such as:

* The component model binary format and AST has been slightly adjusted
  in a few locations. Names are dropped from parameters/results now in
  the internal representation since they were not used anyway. At this
  time the ability to bind a multi-return function has not been exposed.

* The `wasmparser` validator pass will now share allocations with prior
  functions, providing what's probably a very minor speedup for Wasmtime
  itself.

* The text format for many component-related tests now requires named
  parameters.

* Some new relaxed-simd instructions are updated to be ignored.

I hope to have a follow-up to expose the multi-return ability to the
embedding API of components.

* Update audit information for new crates
This commit is contained in:
Alex Crichton
2022-09-27 13:12:34 -05:00
committed by GitHub
parent 10deb9b7fe
commit 29c7de7340
31 changed files with 407 additions and 331 deletions

View File

@@ -30,6 +30,7 @@ use std::collections::HashMap;
use std::convert::TryFrom;
use std::mem;
use std::sync::{Arc, Mutex};
use wasmparser::{FuncValidatorAllocations, FunctionBody};
use wasmtime_environ::{
AddressMapSection, CacheStore, CompileError, FilePos, FlagValue, FunctionBodyData,
FunctionInfo, InstructionAddressMap, Module, ModuleTranslation, ModuleTypes, PtrSize,
@@ -51,6 +52,7 @@ struct CompilerContext {
func_translator: FuncTranslator,
codegen_context: Context,
incremental_cache_ctx: Option<IncrementalCacheContext>,
validator_allocations: FuncValidatorAllocations,
}
impl Default for CompilerContext {
@@ -59,6 +61,7 @@ impl Default for CompilerContext {
func_translator: FuncTranslator::new(),
codegen_context: Context::new(),
incremental_cache_ctx: None,
validator_allocations: Default::default(),
}
}
}
@@ -141,13 +144,13 @@ impl Compiler {
fn get_function_address_map(
&self,
context: &Context,
data: &FunctionBodyData<'_>,
body: &FunctionBody<'_>,
body_len: u32,
tunables: &Tunables,
) -> FunctionAddressMap {
// Generate artificial srcloc for function start/end to identify boundary
// within module.
let data = data.body.get_binary_reader();
let data = body.get_binary_reader();
let offset = data.original_position();
let len = data.bytes_remaining();
assert!((offset + len) <= u32::max_value() as usize);
@@ -186,7 +189,7 @@ impl wasmtime_environ::Compiler for Compiler {
&self,
translation: &ModuleTranslation<'_>,
func_index: DefinedFuncIndex,
mut input: FunctionBodyData<'_>,
input: FunctionBodyData<'_>,
tunables: &Tunables,
types: &ModuleTypes,
) -> Result<Box<dyn Any + Send>, CompileError> {
@@ -198,6 +201,7 @@ impl wasmtime_environ::Compiler for Compiler {
mut func_translator,
codegen_context: mut context,
incremental_cache_ctx: mut cache_ctx,
validator_allocations,
} = self.take_context();
context.func.signature = func_signature(isa, translation, types, func_index);
@@ -264,9 +268,11 @@ impl wasmtime_environ::Compiler for Compiler {
readonly: false,
});
context.func.stack_limit = Some(stack_limit);
let FunctionBodyData { validator, body } = input;
let mut validator = validator.into_validator(validator_allocations);
func_translator.translate_body(
&mut input.validator,
input.body.clone(),
&mut validator,
body.clone(),
&mut context.func,
&mut func_env,
)?;
@@ -300,7 +306,7 @@ impl wasmtime_environ::Compiler for Compiler {
};
let address_transform =
self.get_function_address_map(&context, &input, code_buf.len() as u32, tunables);
self.get_function_address_map(&context, &body, code_buf.len() as u32, tunables);
let ranges = if tunables.generate_native_debuginfo {
Some(context.compiled_code().unwrap().value_labels_ranges.clone())
@@ -320,6 +326,7 @@ impl wasmtime_environ::Compiler for Compiler {
func_translator,
codegen_context: context,
incremental_cache_ctx: cache_ctx,
validator_allocations: validator.into_allocations(),
});
Ok(Box::new(CompiledFunction {
@@ -566,6 +573,7 @@ impl Compiler {
mut func_translator,
codegen_context: mut context,
incremental_cache_ctx: mut cache_ctx,
validator_allocations,
} = self.take_context();
// The name doesn't matter here.
@@ -634,6 +642,7 @@ impl Compiler {
func_translator,
codegen_context: context,
incremental_cache_ctx: cache_ctx,
validator_allocations,
});
Ok(func)
}
@@ -679,6 +688,7 @@ impl Compiler {
mut func_translator,
codegen_context: mut context,
incremental_cache_ctx: mut cache_ctx,
validator_allocations,
} = self.take_context();
// The name doesn't matter here.
@@ -713,6 +723,7 @@ impl Compiler {
func_translator,
codegen_context: context,
incremental_cache_ctx: cache_ctx,
validator_allocations,
});
Ok(func)
}

View File

@@ -32,6 +32,7 @@ impl ComponentCompiler for Compiler {
mut func_translator,
codegen_context: mut context,
mut incremental_cache_ctx,
validator_allocations,
} = self.take_context();
context.func = ir::Function::with_name_signature(
@@ -156,6 +157,7 @@ impl ComponentCompiler for Compiler {
func_translator,
codegen_context: context,
incremental_cache_ctx,
validator_allocations,
});
Ok(Box::new(func))
}
@@ -166,6 +168,7 @@ impl ComponentCompiler for Compiler {
mut func_translator,
codegen_context: mut context,
mut incremental_cache_ctx,
validator_allocations,
} = self.take_context();
context.func = ir::Function::with_name_signature(
ir::UserFuncName::user(0, 0),
@@ -187,6 +190,7 @@ impl ComponentCompiler for Compiler {
func_translator,
codegen_context: context,
incremental_cache_ctx,
validator_allocations,
});
Ok(Box::new(func))
}
@@ -205,6 +209,7 @@ impl ComponentCompiler for Compiler {
mut func_translator,
codegen_context: mut context,
mut incremental_cache_ctx,
validator_allocations,
} = self.take_context();
context.func = ir::Function::with_name_signature(
@@ -226,6 +231,7 @@ impl ComponentCompiler for Compiler {
func_translator,
codegen_context: context,
incremental_cache_ctx,
validator_allocations,
});
Ok(Box::new(func))
}

View File

@@ -626,32 +626,6 @@ impl<'a, 'data> Translator<'a, 'data> {
// Aliases of instance exports (either core or component) will be
// recorded as an initializer of the appropriate type with outer
// aliases handled specially via upvars and type processing.
Payload::AliasSection(s) => {
self.validator.alias_section(&s)?;
for alias in s {
let init = match alias? {
wasmparser::Alias::InstanceExport {
kind,
instance_index,
name,
} => {
let instance = ModuleInstanceIndex::from_u32(instance_index);
self.alias_module_instance_export(kind, instance, name)
}
wasmparser::Alias::Outer {
kind: wasmparser::OuterAliasKind::Type,
count,
index,
} => {
let index = TypeIndex::from_u32(index);
let ty = self.types.core_outer_type(count, index);
self.types.push_core_typedef(ty);
continue;
}
};
self.result.initializers.push(init);
}
}
Payload::ComponentAliasSection(s) => {
self.validator.component_alias_section(&s)?;
for alias in s {
@@ -670,6 +644,14 @@ impl<'a, 'data> Translator<'a, 'data> {
self.alias_component_outer(kind, count, index);
continue;
}
wasmparser::ComponentAlias::CoreInstanceExport {
kind,
instance_index,
name,
} => {
let instance = ModuleInstanceIndex::from_u32(instance_index);
self.alias_module_instance_export(kind, instance, name)
}
};
self.result.initializers.push(init);
}

View File

@@ -509,19 +509,14 @@ impl ComponentTypesBuilder {
);
assert!(prev.is_none());
}
wasmparser::ModuleTypeDeclaration::Alias(alias) => match alias {
wasmparser::Alias::Outer {
kind: wasmparser::OuterAliasKind::Type,
count,
index,
} => {
let ty = self.core_outer_type(*count, TypeIndex::from_u32(*index));
self.push_core_typedef(ty);
}
wasmparser::Alias::InstanceExport { .. } => {
unreachable!("invalid alias {alias:?}")
}
},
wasmparser::ModuleTypeDeclaration::OuterAlias {
kind: wasmparser::OuterAliasKind::Type,
count,
index,
} => {
let ty = self.core_outer_type(*count, TypeIndex::from_u32(*index));
self.push_core_typedef(ty);
}
}
}
@@ -640,12 +635,12 @@ impl ComponentTypesBuilder {
params: ty
.params
.iter()
.map(|(name, ty)| (name.map(|s| s.to_string()), self.valtype(ty)))
.map(|(_name, ty)| self.valtype(ty))
.collect(),
results: ty
.results
.iter()
.map(|(name, ty)| (name.map(|s| s.to_string()), self.valtype(ty)))
.map(|(_name, ty)| self.valtype(ty))
.collect(),
};
self.add_func_type(ty)
@@ -998,9 +993,9 @@ pub struct TypeComponentInstance {
pub struct TypeFunc {
/// The list of optionally named parameters for this function, and their
/// types.
pub params: Box<[(Option<String>, InterfaceType)]>,
pub params: Box<[InterfaceType]>,
/// The return values of this function.
pub results: Box<[(Option<String>, InterfaceType)]>,
pub results: Box<[InterfaceType]>,
}
/// All possible interface types that values can have.

View File

@@ -37,7 +37,7 @@ impl ComponentTypesBuilder {
let mut params = match self.flatten_types(
&options.options,
MAX_FLAT_PARAMS,
ty.params.iter().map(|(_, ty)| *ty),
ty.params.iter().copied(),
) {
Some(list) => list,
None => {
@@ -50,7 +50,7 @@ impl ComponentTypesBuilder {
let results = match self.flatten_types(
&options.options,
MAX_FLAT_RESULTS,
ty.results.iter().map(|(_, ty)| *ty),
ty.results.iter().map(|ty| *ty),
) {
Some(list) => list,
None => {

View File

@@ -313,9 +313,9 @@ impl Compiler<'_, '_> {
fn translate_params(&mut self, adapter: &AdapterData, param_locals: &[(u32, ValType)]) {
let src_tys = &self.types[adapter.lower.ty].params;
let src_tys = src_tys.iter().map(|(_, ty)| *ty).collect::<Vec<_>>();
let src_tys = src_tys.iter().copied().collect::<Vec<_>>();
let dst_tys = &self.types[adapter.lift.ty].params;
let dst_tys = dst_tys.iter().map(|(_, ty)| *ty).collect::<Vec<_>>();
let dst_tys = dst_tys.iter().copied().collect::<Vec<_>>();
let lift_opts = &adapter.lift.options;
let lower_opts = &adapter.lower.options;
@@ -389,9 +389,9 @@ impl Compiler<'_, '_> {
result_locals: &[(u32, ValType)],
) {
let src_tys = &self.types[adapter.lift.ty].results;
let src_tys = src_tys.iter().map(|(_, ty)| *ty).collect::<Vec<_>>();
let src_tys = src_tys.iter().map(|ty| *ty).collect::<Vec<_>>();
let dst_tys = &self.types[adapter.lower.ty].results;
let dst_tys = dst_tys.iter().map(|(_, ty)| *ty).collect::<Vec<_>>();
let dst_tys = dst_tys.iter().map(|ty| *ty).collect::<Vec<_>>();
let lift_opts = &adapter.lift.options;
let lower_opts = &adapter.lower.options;

View File

@@ -14,9 +14,9 @@ use std::convert::{TryFrom, TryInto};
use std::path::PathBuf;
use std::sync::Arc;
use wasmparser::{
CustomSectionReader, DataKind, ElementItem, ElementKind, Encoding, ExternalKind, FuncValidator,
FunctionBody, NameSectionReader, Naming, Operator, Parser, Payload, Type, TypeRef, Validator,
ValidatorResources,
CustomSectionReader, DataKind, ElementItem, ElementKind, Encoding, ExternalKind,
FuncToValidate, FunctionBody, NameSectionReader, Naming, Operator, Parser, Payload, Type,
TypeRef, Validator, ValidatorResources,
};
/// Object containing the standalone environment information.
@@ -90,7 +90,7 @@ pub struct FunctionBodyData<'a> {
/// The body of the function, containing code and locals.
pub body: FunctionBody<'a>,
/// Validator for the function body
pub validator: FuncValidator<ValidatorResources>,
pub validator: FuncToValidate<ValidatorResources>,
}
#[derive(Debug, Default)]

View File

@@ -325,7 +325,7 @@ mod tests {
(import "" "make_refs" (func (;2;) (type 3)))
(func (;3;) (type 1) (param externref externref externref externref externref externref externref externref externref externref)
(local externref)
loop ;; label = @1
loop ;; label = @0
call 0
call 2
call 1

View File

@@ -129,15 +129,15 @@ impl TryFrom<wasmparser::FuncType> for WasmFuncType {
type Error = WasmError;
fn try_from(ty: wasmparser::FuncType) -> Result<Self, Self::Error> {
let params = ty
.params
.into_vec()
.into_iter()
.params()
.iter()
.copied()
.map(WasmType::try_from)
.collect::<Result<_, Self::Error>>()?;
let returns = ty
.returns
.into_vec()
.into_iter()
.results()
.iter()
.copied()
.map(WasmType::try_from)
.collect::<Result<_, Self::Error>>()?;
Ok(Self::new(params, returns))

View File

@@ -246,10 +246,8 @@ impl Func {
let data = &store[self.0];
let ty = &data.types[data.ty];
Params::typecheck_named_list(&ty.params, &data.types)
.context("type mismatch with parameters")?;
Return::typecheck_named_list(&ty.results, &data.types)
.context("type mismatch with results")?;
Params::typecheck_list(&ty.params, &data.types).context("type mismatch with parameters")?;
Return::typecheck_list(&ty.results, &data.types).context("type mismatch with results")?;
Ok(())
}
@@ -260,7 +258,7 @@ impl Func {
data.types[data.ty]
.params
.iter()
.map(|(_, ty)| Type::from(ty, &data.types))
.map(|ty| Type::from(ty, &data.types))
.collect()
}
@@ -270,7 +268,7 @@ impl Func {
data.types[data.ty]
.results
.iter()
.map(|(_, ty)| Type::from(ty, &data.types))
.map(|ty| Type::from(ty, &data.types))
.collect()
}

View File

@@ -89,16 +89,8 @@ impl HostFunc {
func: Box::new(DynamicContext {
func,
types: Types {
params: ty
.params
.iter()
.map(|(_, ty)| Type::from(ty, types))
.collect(),
results: ty
.results
.iter()
.map(|(_, ty)| Type::from(ty, types))
.collect(),
params: ty.params.iter().map(|ty| Type::from(ty, types)).collect(),
results: ty.results.iter().map(|ty| Type::from(ty, types)).collect(),
},
}),
})
@@ -123,8 +115,8 @@ where
R: ComponentNamedList + Lower,
{
let ty = &types[ty];
P::typecheck_named_list(&ty.params, types).context("type mismatch with parameters")?;
R::typecheck_named_list(&ty.results, types).context("type mismatch with results")?;
P::typecheck_list(&ty.params, types).context("type mismatch with parameters")?;
R::typecheck_list(&ty.results, types).context("type mismatch with results")?;
Ok(())
}

View File

@@ -308,10 +308,7 @@ pub unsafe trait ComponentNamedList: ComponentType {
/// Performs a typecheck to ensure that this `ComponentNamedList`
/// implementor matches the types of the types in `params`.
#[doc(hidden)]
fn typecheck_named_list(
params: &[(Option<String>, InterfaceType)],
types: &ComponentTypes,
) -> Result<()>;
fn typecheck_list(params: &[InterfaceType], types: &ComponentTypes) -> Result<()>;
}
/// A trait representing types which can be passed to and read from components
@@ -1965,14 +1962,14 @@ macro_rules! impl_component_ty_for_tuples {
unsafe impl<$($t,)*> ComponentNamedList for ($($t,)*)
where $($t: ComponentType),*
{
fn typecheck_named_list(
names: &[(Option<String>, InterfaceType)],
fn typecheck_list(
names: &[InterfaceType],
_types: &ComponentTypes,
) -> Result<()> {
if names.len() != $n {
bail!("expected {} types, found {}", $n, names.len());
}
let mut names = names.iter().map(|i| &i.1);
let mut names = names.iter();
$($t::typecheck(names.next().unwrap(), _types)?;)*
debug_assert!(names.next().is_none());
Ok(())

View File

@@ -590,7 +590,13 @@ impl Module {
}
}
engine.run_maybe_parallel(functions, |(mut validator, body)| validator.validate(&body))?;
engine.run_maybe_parallel(functions, |(validator, body)| {
// FIXME: it would be best here to use a rayon-specific parallel
// iterator that maintains state-per-thread to share the function
// validator allocations (`Default::default` here) across multiple
// functions.
validator.into_validator(Default::default()).validate(&body)
})?;
Ok(())
}