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 unsafe {
84 for i in 0..COVERAGE_MAP_SIZE {
85 *self.ptr.add(i) |= *other.as_ptr().add(i);
86 }
87 }
88 }
89
90 #[must_use]
95 pub fn count_bits_set(&self) -> u32 {
96 let mut count: u32 = 0;
97 unsafe {
100 for i in 0..COVERAGE_MAP_SIZE {
101 count += (*self.ptr.add(i)).count_ones();
102 }
103 }
104 count
105 }
106
107 #[must_use]
109 pub fn has_new_bits(&self, other: &CoverageBitmap) -> bool {
110 unsafe {
114 for i in 0..COVERAGE_MAP_SIZE {
115 let explored = *self.ptr.add(i);
116 let child = *other.as_ptr().add(i);
117 if (child & !explored) != 0 {
119 return true;
120 }
121 }
122 }
123 false
124 }
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130 use crate::shared_mem;
131
132 #[test]
133 fn test_set_bit_and_check() {
134 let ptr = shared_mem::alloc_shared(COVERAGE_MAP_SIZE).expect("alloc failed");
135 let explored_ptr = shared_mem::alloc_shared(COVERAGE_MAP_SIZE).expect("alloc failed");
136 let bm = unsafe { CoverageBitmap::new(ptr) };
137 let vm = unsafe { ExploredMap::new(explored_ptr) };
138
139 assert!(!vm.has_new_bits(&bm));
141
142 bm.set_bit(42);
144 assert!(vm.has_new_bits(&bm));
145
146 vm.merge_from(&bm);
148 assert!(!vm.has_new_bits(&bm));
150
151 unsafe {
152 shared_mem::free_shared(ptr, COVERAGE_MAP_SIZE);
153 shared_mem::free_shared(explored_ptr, COVERAGE_MAP_SIZE);
154 }
155 }
156
157 #[test]
158 fn test_clear() {
159 let ptr = shared_mem::alloc_shared(COVERAGE_MAP_SIZE).expect("alloc failed");
160 let bm = unsafe { CoverageBitmap::new(ptr) };
161
162 bm.set_bit(0);
163 bm.set_bit(100);
164 bm.set_bit(8000);
165
166 bm.clear();
167
168 unsafe {
170 for i in 0..COVERAGE_MAP_SIZE {
171 assert_eq!(*ptr.add(i), 0);
172 }
173 shared_mem::free_shared(ptr, COVERAGE_MAP_SIZE);
174 }
175 }
176
177 #[test]
178 fn test_merge_accumulates() {
179 let bm1_ptr = shared_mem::alloc_shared(COVERAGE_MAP_SIZE).expect("alloc failed");
180 let bm2_ptr = shared_mem::alloc_shared(COVERAGE_MAP_SIZE).expect("alloc failed");
181 let vm_ptr = shared_mem::alloc_shared(COVERAGE_MAP_SIZE).expect("alloc failed");
182
183 let bm1 = unsafe { CoverageBitmap::new(bm1_ptr) };
184 let bm2 = unsafe { CoverageBitmap::new(bm2_ptr) };
185 let vm = unsafe { ExploredMap::new(vm_ptr) };
186
187 bm1.set_bit(10);
188 bm2.set_bit(20);
189
190 vm.merge_from(&bm1);
191 assert!(vm.has_new_bits(&bm2));
193
194 vm.merge_from(&bm2);
195 assert!(!vm.has_new_bits(&bm1));
197 assert!(!vm.has_new_bits(&bm2));
198
199 unsafe {
200 shared_mem::free_shared(bm1_ptr, COVERAGE_MAP_SIZE);
201 shared_mem::free_shared(bm2_ptr, COVERAGE_MAP_SIZE);
202 shared_mem::free_shared(vm_ptr, COVERAGE_MAP_SIZE);
203 }
204 }
205
206 #[test]
207 fn test_count_bits_set() {
208 let vm_ptr = shared_mem::alloc_shared(COVERAGE_MAP_SIZE).expect("alloc failed");
209 let bm_ptr = shared_mem::alloc_shared(COVERAGE_MAP_SIZE).expect("alloc failed");
210 let vm = unsafe { ExploredMap::new(vm_ptr) };
211 let bm = unsafe { CoverageBitmap::new(bm_ptr) };
212
213 assert_eq!(vm.count_bits_set(), 0);
214
215 bm.set_bit(0);
216 bm.set_bit(42);
217 bm.set_bit(8000);
218 vm.merge_from(&bm);
219
220 assert_eq!(vm.count_bits_set(), 3);
221
222 unsafe {
223 shared_mem::free_shared(vm_ptr, COVERAGE_MAP_SIZE);
224 shared_mem::free_shared(bm_ptr, COVERAGE_MAP_SIZE);
225 }
226 }
227}