wasmtime_fuzzing/generators/
pooling_config.rs

1//! Generate instance limits for the pooling allocation strategy.
2
3use arbitrary::{Arbitrary, Unstructured};
4use wasmtime::MpkEnabled;
5
6/// Configuration for `wasmtime::PoolingAllocationStrategy`.
7#[derive(Debug, Clone, Eq, PartialEq, Hash)]
8#[expect(missing_docs, reason = "self-describing field names")]
9pub struct PoolingAllocationConfig {
10    pub total_component_instances: u32,
11    pub total_core_instances: u32,
12    pub total_memories: u32,
13    pub total_tables: u32,
14    pub total_stacks: u32,
15
16    pub max_memory_size: usize,
17    pub table_elements: usize,
18
19    pub component_instance_size: usize,
20    pub max_memories_per_component: u32,
21    pub max_tables_per_component: u32,
22
23    pub core_instance_size: usize,
24    pub max_memories_per_module: u32,
25    pub max_tables_per_module: u32,
26
27    pub table_keep_resident: usize,
28    pub linear_memory_keep_resident: usize,
29
30    pub decommit_batch_size: usize,
31    pub max_unused_warm_slots: u32,
32
33    pub async_stack_keep_resident: usize,
34
35    pub memory_protection_keys: MpkEnabled,
36    pub max_memory_protection_keys: usize,
37}
38
39impl PoolingAllocationConfig {
40    /// Convert the generated limits to Wasmtime limits.
41    pub fn configure(&self, cfg: &mut wasmtime_cli_flags::CommonOptions) {
42        cfg.opts.pooling_total_component_instances = Some(self.total_component_instances);
43        cfg.opts.pooling_total_core_instances = Some(self.total_core_instances);
44        cfg.opts.pooling_total_memories = Some(self.total_memories);
45        cfg.opts.pooling_total_tables = Some(self.total_tables);
46        cfg.opts.pooling_total_stacks = Some(self.total_stacks);
47
48        cfg.opts.pooling_max_memory_size = Some(self.max_memory_size);
49        cfg.opts.pooling_table_elements = Some(self.table_elements);
50
51        cfg.opts.pooling_max_component_instance_size = Some(self.component_instance_size);
52        cfg.opts.pooling_max_memories_per_component = Some(self.max_memories_per_component);
53        cfg.opts.pooling_max_tables_per_component = Some(self.max_tables_per_component);
54
55        cfg.opts.pooling_max_core_instance_size = Some(self.core_instance_size);
56        cfg.opts.pooling_max_memories_per_module = Some(self.max_memories_per_module);
57        cfg.opts.pooling_max_tables_per_module = Some(self.max_tables_per_module);
58
59        cfg.opts.pooling_table_keep_resident = Some(self.table_keep_resident);
60        cfg.opts.pooling_memory_keep_resident = Some(self.linear_memory_keep_resident);
61
62        cfg.opts.pooling_decommit_batch_size = Some(self.decommit_batch_size);
63        cfg.opts.pooling_max_unused_warm_slots = Some(self.max_unused_warm_slots);
64
65        cfg.opts.pooling_async_stack_keep_resident = Some(self.async_stack_keep_resident);
66
67        cfg.opts.pooling_memory_protection_keys = Some(self.memory_protection_keys);
68        cfg.opts.pooling_max_memory_protection_keys = Some(self.max_memory_protection_keys);
69    }
70}
71
72impl<'a> Arbitrary<'a> for PoolingAllocationConfig {
73    fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
74        const MAX_COUNT: u32 = 100;
75        const MAX_TABLES: u32 = 100;
76        const MAX_MEMORIES: u32 = 100;
77        const MAX_ELEMENTS: usize = 1000;
78        const MAX_MEMORY_SIZE: usize = 10 * (1 << 20); // 10 MiB
79        const MAX_SIZE: usize = 1 << 20; // 1 MiB
80        const MAX_INSTANCE_MEMORIES: u32 = 10;
81        const MAX_INSTANCE_TABLES: u32 = 10;
82
83        let total_memories = u.int_in_range(1..=MAX_MEMORIES)?;
84
85        Ok(Self {
86            total_component_instances: u.int_in_range(1..=MAX_COUNT)?,
87            total_core_instances: u.int_in_range(1..=MAX_COUNT)?,
88            total_memories,
89            total_tables: u.int_in_range(1..=MAX_TABLES)?,
90            total_stacks: u.int_in_range(1..=MAX_COUNT)?,
91
92            max_memory_size: u.int_in_range(0..=MAX_MEMORY_SIZE)?,
93            table_elements: u.int_in_range(0..=MAX_ELEMENTS)?,
94
95            component_instance_size: u.int_in_range(0..=MAX_SIZE)?,
96            max_memories_per_component: u.int_in_range(1..=MAX_INSTANCE_MEMORIES)?,
97            max_tables_per_component: u.int_in_range(1..=MAX_INSTANCE_TABLES)?,
98
99            core_instance_size: u.int_in_range(0..=MAX_SIZE)?,
100            max_memories_per_module: u.int_in_range(1..=MAX_INSTANCE_MEMORIES)?,
101            max_tables_per_module: u.int_in_range(1..=MAX_INSTANCE_TABLES)?,
102
103            table_keep_resident: u.int_in_range(0..=1 << 20)?,
104            linear_memory_keep_resident: u.int_in_range(0..=1 << 20)?,
105
106            decommit_batch_size: u.int_in_range(1..=1000)?,
107            max_unused_warm_slots: u.int_in_range(0..=total_memories + 10)?,
108
109            async_stack_keep_resident: u.int_in_range(0..=1 << 20)?,
110
111            memory_protection_keys: *u.choose(&[MpkEnabled::Auto, MpkEnabled::Disable])?,
112            max_memory_protection_keys: u.int_in_range(1..=20)?,
113        })
114    }
115}