1 //! Generate instance limits for the pooling allocation strategy.
2 
3 use arbitrary::{Arbitrary, Unstructured};
4 use wasmtime::MpkEnabled;
5 
6 /// Configuration for `wasmtime::PoolingAllocationStrategy`.
7 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
8 #[allow(missing_docs)]
9 pub 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 memory_pages: u64,
17     pub table_elements: u32,
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 max_unused_warm_slots: u32,
31 
32     pub async_stack_zeroing: bool,
33     pub async_stack_keep_resident: usize,
34 
35     pub memory_protection_keys: MpkEnabled,
36     pub max_memory_protection_keys: usize,
37 }
38 
39 impl PoolingAllocationConfig {
40     /// Convert the generated limits to Wasmtime limits.
41     pub fn to_wasmtime(&self) -> wasmtime::PoolingAllocationConfig {
42         let mut cfg = wasmtime::PoolingAllocationConfig::default();
43 
44         cfg.total_component_instances(self.total_component_instances);
45         cfg.total_core_instances(self.total_core_instances);
46         cfg.total_memories(self.total_memories);
47         cfg.total_tables(self.total_tables);
48         cfg.total_stacks(self.total_stacks);
49 
50         cfg.memory_pages(self.memory_pages);
51         cfg.table_elements(self.table_elements);
52 
53         cfg.max_component_instance_size(self.component_instance_size);
54         cfg.max_memories_per_component(self.max_memories_per_component);
55         cfg.max_tables_per_component(self.max_tables_per_component);
56 
57         cfg.max_core_instance_size(self.core_instance_size);
58         cfg.max_memories_per_module(self.max_memories_per_module);
59         cfg.max_tables_per_module(self.max_tables_per_module);
60 
61         cfg.table_keep_resident(self.table_keep_resident);
62         cfg.linear_memory_keep_resident(self.linear_memory_keep_resident);
63 
64         cfg.max_unused_warm_slots(self.max_unused_warm_slots);
65 
66         cfg.async_stack_zeroing(self.async_stack_zeroing);
67         cfg.async_stack_keep_resident(self.async_stack_keep_resident);
68 
69         cfg.memory_protection_keys(self.memory_protection_keys);
70 
71         cfg
72     }
73 }
74 
75 impl<'a> Arbitrary<'a> for PoolingAllocationConfig {
76     fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
77         const MAX_COUNT: u32 = 100;
78         const MAX_TABLES: u32 = 100;
79         const MAX_MEMORIES: u32 = 100;
80         const MAX_ELEMENTS: u32 = 1000;
81         const MAX_MEMORY_PAGES: u64 = 160; // 10 MiB
82         const MAX_SIZE: usize = 1 << 20; // 1 MiB
83         const MAX_INSTANCE_MEMORIES: u32 = 10;
84         const MAX_INSTANCE_TABLES: u32 = 10;
85 
86         let total_memories = u.int_in_range(1..=MAX_MEMORIES)?;
87 
88         Ok(Self {
89             total_component_instances: u.int_in_range(1..=MAX_COUNT)?,
90             total_core_instances: u.int_in_range(1..=MAX_COUNT)?,
91             total_memories,
92             total_tables: u.int_in_range(1..=MAX_TABLES)?,
93             total_stacks: u.int_in_range(1..=MAX_COUNT)?,
94 
95             memory_pages: u.int_in_range(0..=MAX_MEMORY_PAGES)?,
96             table_elements: u.int_in_range(0..=MAX_ELEMENTS)?,
97 
98             component_instance_size: u.int_in_range(0..=MAX_SIZE)?,
99             max_memories_per_component: u.int_in_range(1..=MAX_INSTANCE_MEMORIES)?,
100             max_tables_per_component: u.int_in_range(1..=MAX_INSTANCE_TABLES)?,
101 
102             core_instance_size: u.int_in_range(0..=MAX_SIZE)?,
103             max_memories_per_module: u.int_in_range(1..=MAX_INSTANCE_MEMORIES)?,
104             max_tables_per_module: u.int_in_range(1..=MAX_INSTANCE_TABLES)?,
105 
106             table_keep_resident: u.int_in_range(0..=1 << 20)?,
107             linear_memory_keep_resident: u.int_in_range(0..=1 << 20)?,
108 
109             max_unused_warm_slots: u.int_in_range(0..=total_memories + 10)?,
110 
111             async_stack_zeroing: u.arbitrary()?,
112             async_stack_keep_resident: u.int_in_range(0..=1 << 20)?,
113 
114             memory_protection_keys: u.choose(&[MpkEnabled::Auto, MpkEnabled::Disable])?.clone(),
115             max_memory_protection_keys: u.int_in_range(0..=20)?,
116         })
117     }
118 }
119