|
1 | 1 | use crate::HashMap; |
2 | 2 | use crate::instrumentation::BBCoveragePass; |
3 | 3 | use crate::ir::debuginfo_helper::resolve_source_location; |
4 | | -use std::collections::BTreeSet; |
| 4 | +use std::collections::{BTreeMap, BTreeSet}; |
5 | 5 | use std::fmt::Write; |
6 | 6 | use std::path::PathBuf; |
7 | 7 | use std::sync::Arc; |
@@ -149,6 +149,12 @@ pub(crate) struct ReportInfo { |
149 | 149 | mod_spec: Arc<ModuleSpec>, |
150 | 150 | pub(crate) files: Vec<FileInfo>, |
151 | 151 | path_to_fileid: HashMap<String, FileId>, |
| 152 | + online_cache: Option<OnlineCache>, |
| 153 | +} |
| 154 | + |
| 155 | +struct OnlineCache { |
| 156 | + covered_keys: crate::HashSet<Location>, |
| 157 | + offset_lookup: BTreeMap<u64, Box<[(FileId, u32)]>>, |
152 | 158 | } |
153 | 159 |
|
154 | 160 | impl ReportInfo { |
@@ -185,9 +191,83 @@ impl ReportInfo { |
185 | 191 | mod_spec, |
186 | 192 | files, |
187 | 193 | path_to_fileid, |
| 194 | + online_cache: None, |
188 | 195 | }) |
189 | 196 | } |
190 | 197 |
|
| 198 | + pub(crate) fn process_line_coverage_online(&mut self, sess: &JitFuzzingSession) { |
| 199 | + tracy_full::zone!("process_line_coverage_online"); |
| 200 | + let first = self.online_cache.is_none(); |
| 201 | + let cache = self.online_cache.get_or_insert_with(|| { |
| 202 | + tracy_full::zone!("process_line_coverage_online: compute cache"); |
| 203 | + let offset_lookup = self |
| 204 | + .mod_spec |
| 205 | + .functions |
| 206 | + .iter() |
| 207 | + .flat_map(|func| { |
| 208 | + func.operator_offset_rel.iter().map(|rel| { |
| 209 | + let addr = func.operators_wasm_bin_offset_base as u64 + *rel as u64; |
| 210 | + let mut locs = Vec::new(); |
| 211 | + resolve_source_location(&self.mod_spec, addr, |x| { |
| 212 | + for x in x { |
| 213 | + if x.line() == 0 { |
| 214 | + continue; |
| 215 | + } |
| 216 | + if let Some(file) = x.file() { |
| 217 | + let file_id = self.path_to_fileid[&file.full_path()]; |
| 218 | + locs.push((file_id, x.line() - 1)) |
| 219 | + } |
| 220 | + } |
| 221 | + }); |
| 222 | + |
| 223 | + (addr, locs.into_boxed_slice()) |
| 224 | + }) |
| 225 | + }) |
| 226 | + .collect(); |
| 227 | + OnlineCache { |
| 228 | + covered_keys: crate::HashSet::default(), |
| 229 | + offset_lookup, |
| 230 | + } |
| 231 | + }); |
| 232 | + if first { |
| 233 | + tracy_full::zone!("process_line_coverage_online: mark instrumented"); |
| 234 | + for locs in cache.offset_lookup.values() { |
| 235 | + for (file_id, line) in locs { |
| 236 | + self.files[file_id.0 as usize] |
| 237 | + .line_coverage |
| 238 | + .set_instrumented(*line as usize); |
| 239 | + } |
| 240 | + } |
| 241 | + } |
| 242 | + let mut new_coverage = Vec::new(); |
| 243 | + { |
| 244 | + tracy_full::zone!("process_line_coverage_online: scan coverage"); |
| 245 | + for loc in sess |
| 246 | + .get_pass::<BBCoveragePass>() |
| 247 | + .coverage |
| 248 | + .iter_covered_keys() |
| 249 | + { |
| 250 | + if cache.covered_keys.insert(loc) { |
| 251 | + new_coverage.push(loc); |
| 252 | + } |
| 253 | + } |
| 254 | + } |
| 255 | + |
| 256 | + { |
| 257 | + tracy_full::zone!("process_line_coverage_online: mark covered"); |
| 258 | + for loc in new_coverage { |
| 259 | + let func = &self.mod_spec.functions[loc.function as usize]; |
| 260 | + let base = func.operators_wasm_bin_offset_base as u64; |
| 261 | + let offset = func.operator_offset_rel[loc.index as usize] as u64; |
| 262 | + for (file_id, line) in &cache.offset_lookup[&(base + offset)] { |
| 263 | + self.files[file_id.0 as usize] |
| 264 | + .line_coverage |
| 265 | + .set_covered(*line as usize); |
| 266 | + } |
| 267 | + } |
| 268 | + } |
| 269 | + } |
| 270 | + |
191 | 271 | pub(crate) fn process_line_coverage(&mut self, sess: &JitFuzzingSession) { |
192 | 272 | tracy_full::zone!("ReportInfo::process_line_coverage"); |
193 | 273 | let mod_spec = self.mod_spec.clone(); |
|
0 commit comments