jugar_probar/coverage/
superblock.rs1use super::{BlockId, FunctionId};
12use std::collections::HashSet;
13use std::hash::{Hash, Hasher};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
17pub struct SuperblockId(u32);
18
19impl SuperblockId {
20 #[inline]
22 #[must_use]
23 pub const fn new(id: u32) -> Self {
24 Self(id)
25 }
26
27 #[inline]
29 #[must_use]
30 pub const fn as_u32(self) -> u32 {
31 self.0
32 }
33}
34
35impl Hash for SuperblockId {
36 fn hash<H: Hasher>(&self, state: &mut H) {
37 self.0.hash(state);
38 }
39}
40
41#[derive(Debug, Clone)]
46pub struct Superblock {
47 id: SuperblockId,
49 blocks: Vec<BlockId>,
51 block_set: HashSet<BlockId>,
53 cost: u64,
55 function: FunctionId,
57}
58
59impl Superblock {
60 #[must_use]
62 pub fn new(id: SuperblockId, blocks: Vec<BlockId>, function: FunctionId) -> Self {
63 let block_set: HashSet<BlockId> = blocks.iter().copied().collect();
64 let cost = blocks.len() as u64;
65 Self {
66 id,
67 blocks,
68 block_set,
69 cost,
70 function,
71 }
72 }
73
74 #[inline]
76 #[must_use]
77 pub fn id(&self) -> SuperblockId {
78 self.id
79 }
80
81 #[inline]
83 #[must_use]
84 pub fn block_count(&self) -> usize {
85 self.blocks.len()
86 }
87
88 #[inline]
90 #[must_use]
91 pub fn contains(&self, block: BlockId) -> bool {
92 self.block_set.contains(&block)
93 }
94
95 #[must_use]
97 pub fn blocks(&self) -> &[BlockId] {
98 &self.blocks
99 }
100
101 #[inline]
103 #[must_use]
104 pub fn cost_estimate(&self) -> u64 {
105 self.cost
106 }
107
108 pub fn set_cost_estimate(&mut self, cost: u64) {
110 self.cost = cost;
111 }
112
113 #[inline]
115 #[must_use]
116 pub fn function(&self) -> FunctionId {
117 self.function
118 }
119
120 pub fn iter(&self) -> impl Iterator<Item = &BlockId> {
122 self.blocks.iter()
123 }
124}
125
126#[derive(Debug, Clone)]
131pub struct SuperblockBuilder {
132 target_size: usize,
134 max_size: usize,
136 next_id: u32,
138}
139
140impl SuperblockBuilder {
141 #[must_use]
145 pub fn new() -> Self {
146 Self {
147 target_size: 64,
148 max_size: 256,
149 next_id: 0,
150 }
151 }
152
153 #[must_use]
155 pub fn with_target_size(mut self, size: usize) -> Self {
156 self.target_size = size;
157 self
158 }
159
160 #[must_use]
162 pub fn with_max_size(mut self, size: usize) -> Self {
163 self.max_size = size;
164 self
165 }
166
167 #[must_use]
171 pub fn build_from_blocks(&self, blocks: &[BlockId], function: FunctionId) -> Vec<Superblock> {
172 if blocks.is_empty() {
173 return Vec::new();
174 }
175
176 let effective_size = self.target_size.min(self.max_size);
177 let mut superblocks = Vec::new();
178 let mut next_id = self.next_id;
179
180 for chunk in blocks.chunks(effective_size) {
181 let id = SuperblockId::new(next_id);
182 next_id += 1;
183 superblocks.push(Superblock::new(id, chunk.to_vec(), function));
184 }
185
186 superblocks
187 }
188
189 #[must_use]
193 pub fn build_from_function_blocks(
194 &self,
195 function_blocks: &[(FunctionId, Vec<BlockId>)],
196 ) -> Vec<Superblock> {
197 let mut all_superblocks = Vec::new();
198
199 for (function, blocks) in function_blocks {
200 let superblocks = self.build_from_blocks(blocks, *function);
201 all_superblocks.extend(superblocks);
202 }
203
204 all_superblocks
205 }
206
207 #[must_use]
209 pub fn next_id(&self) -> u32 {
210 self.next_id
211 }
212}
213
214impl Default for SuperblockBuilder {
215 fn default() -> Self {
216 Self::new()
217 }
218}