fxprof_processed_profile/
global_lib_table.rsuse std::collections::BTreeSet;
use std::sync::Arc;
use serde::ser::{Serialize, Serializer};
use crate::fast_hash_map::FastHashMap;
use crate::{LibraryInfo, SymbolTable};
#[derive(Debug)]
pub struct GlobalLibTable {
all_libs: Vec<LibraryInfo>, used_libs: Vec<LibraryHandle>, lib_map: FastHashMap<LibraryInfo, LibraryHandle>,
used_lib_map: FastHashMap<LibraryHandle, GlobalLibIndex>,
used_libs_seen_rvas: Vec<BTreeSet<u32>>,
}
impl GlobalLibTable {
pub fn new() -> Self {
Self {
all_libs: Vec::new(),
used_libs: Vec::new(),
lib_map: FastHashMap::default(),
used_lib_map: FastHashMap::default(),
used_libs_seen_rvas: Vec::new(),
}
}
pub fn handle_for_lib(&mut self, lib: LibraryInfo) -> LibraryHandle {
let all_libs = &mut self.all_libs;
*self.lib_map.entry(lib.clone()).or_insert_with(|| {
let handle = LibraryHandle(all_libs.len());
all_libs.push(lib);
handle
})
}
pub fn set_lib_symbol_table(&mut self, library: LibraryHandle, symbol_table: Arc<SymbolTable>) {
self.all_libs[library.0].symbol_table = Some(symbol_table);
}
pub fn index_for_used_lib(&mut self, lib_handle: LibraryHandle) -> GlobalLibIndex {
let used_libs = &mut self.used_libs;
*self.used_lib_map.entry(lib_handle).or_insert_with(|| {
let index = GlobalLibIndex(used_libs.len());
used_libs.push(lib_handle);
self.used_libs_seen_rvas.push(BTreeSet::new());
index
})
}
pub fn get_lib(&self, index: GlobalLibIndex) -> Option<&LibraryInfo> {
let handle = self.used_libs.get(index.0)?;
self.all_libs.get(handle.0)
}
pub fn add_lib_used_rva(&mut self, index: GlobalLibIndex, address: u32) {
self.used_libs_seen_rvas[index.0].insert(address);
}
pub fn lib_used_rva_iter(&self) -> UsedLibraryAddressesIterator {
UsedLibraryAddressesIterator {
next_used_lib_index: 0,
global_lib_table: self,
}
}
}
impl Serialize for GlobalLibTable {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.collect_seq(self.used_libs.iter().map(|handle| &self.all_libs[handle.0]))
}
}
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct GlobalLibIndex(usize);
impl Serialize for GlobalLibIndex {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_u32(self.0 as u32)
}
}
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct LibraryHandle(usize);
pub struct UsedLibraryAddressesIterator<'a> {
next_used_lib_index: usize,
global_lib_table: &'a GlobalLibTable,
}
impl<'a> Iterator for UsedLibraryAddressesIterator<'a> {
type Item = (&'a LibraryInfo, &'a BTreeSet<u32>);
fn next(&mut self) -> Option<Self::Item> {
let rvas = self
.global_lib_table
.used_libs_seen_rvas
.get(self.next_used_lib_index)?;
let lib_handle = self.global_lib_table.used_libs[self.next_used_lib_index];
let info = &self.global_lib_table.all_libs[lib_handle.0];
self.next_used_lib_index += 1;
Some((info, rvas))
}
}