moonpool_explorer/
coverage.rs1pub const COVERAGE_MAP_SIZE: usize = 1024;
10
11pub struct CoverageBitmap {
16 ptr: *mut u8,
17}
18
19impl CoverageBitmap {
20 pub unsafe fn new(ptr: *mut u8) -> Self {
27 Self { ptr }
28 }
29
30 pub fn set_bit(&self, index: usize) {
32 let bit_index = index % (COVERAGE_MAP_SIZE * 8);
33 let byte = bit_index / 8;
34 let bit = bit_index % 8;
35 unsafe {
39 *self.ptr.add(byte) |= 1 << bit;
40 }
41 }
42
43 pub fn clear(&self) {
45 unsafe {
48 std::ptr::write_bytes(self.ptr, 0, COVERAGE_MAP_SIZE);
49 }
50 }
51
52 #[must_use]
54 pub fn as_ptr(&self) -> *const u8 {
55 self.ptr
56 }
57}
58
59pub struct ExploredMap {
64 ptr: *mut u8,
65}
66
67impl ExploredMap {
68 pub unsafe fn new(ptr: *mut u8) -> Self {
75 Self { ptr }
76 }
77
78 pub fn merge_from(&self, other: &CoverageBitmap) {
80 let explored = unsafe { std::slice::from_raw_parts_mut(self.ptr, COVERAGE_MAP_SIZE) };
83 let child = unsafe { std::slice::from_raw_parts(other.as_ptr(), COVERAGE_MAP_SIZE) };
84 for (e, c) in explored.iter_mut().zip(child) {
85 *e |= *c;
86 }
87 }
88
89 #[must_use]
94 pub fn count_bits_set(&self) -> u32 {
95 let explored = unsafe { std::slice::from_raw_parts(self.ptr, COVERAGE_MAP_SIZE) };
97 explored.iter().map(|b| b.count_ones()).sum()
98 }
99
100 #[must_use]
102 pub fn has_new_bits(&self, other: &CoverageBitmap) -> bool {
103 let explored = unsafe { std::slice::from_raw_parts(self.ptr, COVERAGE_MAP_SIZE) };
106 let child = unsafe { std::slice::from_raw_parts(other.as_ptr(), COVERAGE_MAP_SIZE) };
107 explored.iter().zip(child).any(|(e, c)| (c & !e) != 0)
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114 use crate::shared_mem;
115
116 #[test]
117 fn test_set_bit_and_check() {
118 let ptr = shared_mem::alloc_shared(COVERAGE_MAP_SIZE).expect("alloc failed");
119 let explored_ptr = shared_mem::alloc_shared(COVERAGE_MAP_SIZE).expect("alloc failed");
120 let bm = unsafe { CoverageBitmap::new(ptr) };
121 let vm = unsafe { ExploredMap::new(explored_ptr) };
122
123 assert!(!vm.has_new_bits(&bm));
125
126 bm.set_bit(42);
128 assert!(vm.has_new_bits(&bm));
129
130 vm.merge_from(&bm);
132 assert!(!vm.has_new_bits(&bm));
134
135 unsafe {
136 shared_mem::free_shared(ptr, COVERAGE_MAP_SIZE);
137 shared_mem::free_shared(explored_ptr, COVERAGE_MAP_SIZE);
138 }
139 }
140
141 #[test]
142 fn test_clear() {
143 let ptr = shared_mem::alloc_shared(COVERAGE_MAP_SIZE).expect("alloc failed");
144 let bm = unsafe { CoverageBitmap::new(ptr) };
145
146 bm.set_bit(0);
147 bm.set_bit(100);
148 bm.set_bit(8000);
149
150 bm.clear();
151
152 unsafe {
154 for i in 0..COVERAGE_MAP_SIZE {
155 assert_eq!(*ptr.add(i), 0);
156 }
157 shared_mem::free_shared(ptr, COVERAGE_MAP_SIZE);
158 }
159 }
160
161 #[test]
162 fn test_merge_accumulates() {
163 let bm1_ptr = shared_mem::alloc_shared(COVERAGE_MAP_SIZE).expect("alloc failed");
164 let bm2_ptr = shared_mem::alloc_shared(COVERAGE_MAP_SIZE).expect("alloc failed");
165 let vm_ptr = shared_mem::alloc_shared(COVERAGE_MAP_SIZE).expect("alloc failed");
166
167 let bm1 = unsafe { CoverageBitmap::new(bm1_ptr) };
168 let bm2 = unsafe { CoverageBitmap::new(bm2_ptr) };
169 let vm = unsafe { ExploredMap::new(vm_ptr) };
170
171 bm1.set_bit(10);
172 bm2.set_bit(20);
173
174 vm.merge_from(&bm1);
175 assert!(vm.has_new_bits(&bm2));
177
178 vm.merge_from(&bm2);
179 assert!(!vm.has_new_bits(&bm1));
181 assert!(!vm.has_new_bits(&bm2));
182
183 unsafe {
184 shared_mem::free_shared(bm1_ptr, COVERAGE_MAP_SIZE);
185 shared_mem::free_shared(bm2_ptr, COVERAGE_MAP_SIZE);
186 shared_mem::free_shared(vm_ptr, COVERAGE_MAP_SIZE);
187 }
188 }
189
190 #[test]
191 fn test_count_bits_set() {
192 let vm_ptr = shared_mem::alloc_shared(COVERAGE_MAP_SIZE).expect("alloc failed");
193 let bm_ptr = shared_mem::alloc_shared(COVERAGE_MAP_SIZE).expect("alloc failed");
194 let vm = unsafe { ExploredMap::new(vm_ptr) };
195 let bm = unsafe { CoverageBitmap::new(bm_ptr) };
196
197 assert_eq!(vm.count_bits_set(), 0);
198
199 bm.set_bit(0);
200 bm.set_bit(42);
201 bm.set_bit(8000);
202 vm.merge_from(&bm);
203
204 assert_eq!(vm.count_bits_set(), 3);
205
206 unsafe {
207 shared_mem::free_shared(vm_ptr, COVERAGE_MAP_SIZE);
208 shared_mem::free_shared(bm_ptr, COVERAGE_MAP_SIZE);
209 }
210 }
211}