coverage: Encode function mappings without re-sorting them
The main change here is that `VirtualFileMapping` now uses an internal hashmap to de-duplicate incoming global file IDs. That removes the need for `encode_mappings_for_function` to re-sort its mappings by filename in order to de-duplicate them. (We still de-duplicate runs of identical filenames to save work, but this is not load-bearing for correctness, so a sort is not necessary.)
This commit is contained in:
parent
88159cafa7
commit
de4cfbca2e
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
use itertools::Itertools as _;
|
use itertools::Itertools as _;
|
||||||
use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods};
|
use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods};
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
@ -205,11 +205,15 @@ struct LocalFileId {}
|
|||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct VirtualFileMapping {
|
struct VirtualFileMapping {
|
||||||
local_to_global: IndexVec<LocalFileId, u32>,
|
local_to_global: IndexVec<LocalFileId, u32>,
|
||||||
|
global_to_local: FxIndexMap<u32, LocalFileId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtualFileMapping {
|
impl VirtualFileMapping {
|
||||||
fn push_global_id(&mut self, global_file_id: u32) -> LocalFileId {
|
fn local_id_for_global(&mut self, global_file_id: u32) -> LocalFileId {
|
||||||
self.local_to_global.push(global_file_id)
|
*self
|
||||||
|
.global_to_local
|
||||||
|
.entry(global_file_id)
|
||||||
|
.or_insert_with(|| self.local_to_global.push(global_file_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_vec(self) -> Vec<u32> {
|
fn into_vec(self) -> Vec<u32> {
|
||||||
@ -226,7 +230,7 @@ fn encode_mappings_for_function(
|
|||||||
global_file_table: &GlobalFileTable,
|
global_file_table: &GlobalFileTable,
|
||||||
function_coverage: &FunctionCoverage<'_>,
|
function_coverage: &FunctionCoverage<'_>,
|
||||||
) -> Vec<u8> {
|
) -> Vec<u8> {
|
||||||
let mut counter_regions = function_coverage.counter_regions().collect::<Vec<_>>();
|
let counter_regions = function_coverage.counter_regions();
|
||||||
if counter_regions.is_empty() {
|
if counter_regions.is_empty() {
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
}
|
}
|
||||||
@ -236,25 +240,23 @@ fn encode_mappings_for_function(
|
|||||||
let mut virtual_file_mapping = VirtualFileMapping::default();
|
let mut virtual_file_mapping = VirtualFileMapping::default();
|
||||||
let mut mapping_regions = Vec::with_capacity(counter_regions.len());
|
let mut mapping_regions = Vec::with_capacity(counter_regions.len());
|
||||||
|
|
||||||
// Sort and group the list of (counter, region) mapping pairs by filename.
|
// Group mappings into runs with the same filename, preserving the order
|
||||||
// (Preserve any further ordering imposed by `FunctionCoverage`.)
|
// yielded by `FunctionCoverage`.
|
||||||
// Prepare file IDs for each filename, and prepare the mapping data so that
|
// Prepare file IDs for each filename, and prepare the mapping data so that
|
||||||
// we can pass it through FFI to LLVM.
|
// we can pass it through FFI to LLVM.
|
||||||
counter_regions.sort_by_key(|(_counter, region)| region.file_name);
|
for (file_name, counter_regions_for_file) in
|
||||||
for counter_regions_for_file in
|
&counter_regions.group_by(|(_counter, region)| region.file_name)
|
||||||
counter_regions.group_by(|(_, a), (_, b)| a.file_name == b.file_name)
|
|
||||||
{
|
{
|
||||||
// Look up the global file ID for this filename.
|
// Look up the global file ID for this filename.
|
||||||
let file_name = counter_regions_for_file[0].1.file_name;
|
|
||||||
let global_file_id = global_file_table.global_file_id_for_file_name(file_name);
|
let global_file_id = global_file_table.global_file_id_for_file_name(file_name);
|
||||||
|
|
||||||
// Associate that global file ID with a local file ID for this function.
|
// Associate that global file ID with a local file ID for this function.
|
||||||
let local_file_id = virtual_file_mapping.push_global_id(global_file_id);
|
let local_file_id = virtual_file_mapping.local_id_for_global(global_file_id);
|
||||||
debug!(" file id: {local_file_id:?} => global {global_file_id} = '{file_name:?}'");
|
debug!(" file id: {local_file_id:?} => global {global_file_id} = '{file_name:?}'");
|
||||||
|
|
||||||
// For each counter/region pair in this function+file, convert it to a
|
// For each counter/region pair in this function+file, convert it to a
|
||||||
// form suitable for FFI.
|
// form suitable for FFI.
|
||||||
for &(counter, region) in counter_regions_for_file {
|
for (counter, region) in counter_regions_for_file {
|
||||||
let CodeRegion { file_name: _, start_line, start_col, end_line, end_col } = *region;
|
let CodeRegion { file_name: _, start_line, start_col, end_line, end_col } = *region;
|
||||||
|
|
||||||
debug!("Adding counter {counter:?} to map for {region:?}");
|
debug!("Adding counter {counter:?} to map for {region:?}");
|
||||||
|
@ -8,13 +8,13 @@
|
|||||||
#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
|
#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
|
||||||
#![cfg_attr(not(bootstrap), doc(rust_logo))]
|
#![cfg_attr(not(bootstrap), doc(rust_logo))]
|
||||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||||
|
#![feature(exact_size_is_empty)]
|
||||||
#![feature(extern_types)]
|
#![feature(extern_types)]
|
||||||
#![feature(hash_raw_entry)]
|
#![feature(hash_raw_entry)]
|
||||||
#![feature(iter_intersperse)]
|
#![feature(iter_intersperse)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(slice_group_by)]
|
|
||||||
#![feature(impl_trait_in_assoc_type)]
|
#![feature(impl_trait_in_assoc_type)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
#![allow(rustc::potential_query_instability)]
|
#![allow(rustc::potential_query_instability)]
|
||||||
|
Loading…
Reference in New Issue
Block a user