components: Improve heuristic for splitting adapters (#4827)
This commit is a (second?) attempt at improving the generation of adapter modules to avoid excessively large functions for fuzz-generated inputs. The first iteration of adapters simply translated an entire type inline per-function. This proved problematic however since the size of the adapter function was on the order of the overall size of a type, which can be exponential for a type that is otherwise defined in linear size. The second iteration of adapters performed a split where memory-based types would always be translated with individual functions. The theory here was that once a type was memory-based it was large enough to not warrant inline translation in the original function and a separate outlined function could be shared and otherwise used to deduplicate portions of the original giant function. This again proved problematic, however, since the splitting heuristic was quite naive and didn't take into account large stack-based types. This third iteration in this commit replaces the previous system with a similar but slightly more general one. Each adapter function now has a concept of fuel which is decremented each time a layer of a type is translated. When fuel runs out further translations are deferred to outlined functions. The fuel counter should hopefully provide a sort of reasonable upper bound on the size of a function and the outlined functions should ideally provide the ability to be called from multiple places and therefore deduplicate what would otherwise be a massive function. This final iteration is another attempt at guaranteeing that an adapter module is linear in size with respect to the input type section of the original module. Additionally this iteration uniformly handles stack and memory-based translations which means that stack-based translations can't go wild in their function size and memory-based translations may benefit slightly from having at least a little bit of inlining internally. The immediate impact of this is that the `component_api` fuzzer seems to be running at a faster rate than before. Otherwise #4825 is sufficient to invalidate preexisting fuzz-bugs and this PR is hopefully the final nail in the coffin to prevent further timeouts for small inputs cropping up. Closes #4816
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
//! Size, align, and flattening information about component model types.
|
||||
|
||||
use crate::component::{
|
||||
ComponentTypesBuilder, FlatType, InterfaceType, MAX_FLAT_PARAMS, MAX_FLAT_RESULTS,
|
||||
};
|
||||
use crate::component::{ComponentTypesBuilder, InterfaceType, MAX_FLAT_PARAMS, MAX_FLAT_RESULTS};
|
||||
use crate::fact::{AdapterOptions, Context, Options};
|
||||
use wasm_encoder::ValType;
|
||||
|
||||
@@ -90,23 +88,11 @@ impl ComponentTypesBuilder {
|
||||
) -> Option<Vec<ValType>> {
|
||||
let mut dst = Vec::new();
|
||||
for ty in tys {
|
||||
let flat = self.flat_types(&ty)?;
|
||||
let types = if opts.memory64 {
|
||||
flat.memory64
|
||||
} else {
|
||||
flat.memory32
|
||||
};
|
||||
for ty in types {
|
||||
let ty = match ty {
|
||||
FlatType::I32 => ValType::I32,
|
||||
FlatType::I64 => ValType::I64,
|
||||
FlatType::F32 => ValType::F32,
|
||||
FlatType::F64 => ValType::F64,
|
||||
};
|
||||
for ty in opts.flat_types(&ty, self)? {
|
||||
if dst.len() == max {
|
||||
return None;
|
||||
}
|
||||
dst.push(ty);
|
||||
dst.push((*ty).into());
|
||||
}
|
||||
}
|
||||
Some(dst)
|
||||
|
||||
Reference in New Issue
Block a user