fxprof_processed_profile/
global_lib_table.rs

1use std::sync::Arc;
2
3use serde::ser::{Serialize, Serializer};
4
5use crate::fast_hash_map::FastHashMap;
6use crate::{LibraryInfo, SymbolTable};
7
8#[derive(Debug)]
9pub struct GlobalLibTable {
10    /// All libraries added via `Profile::add_lib`. May or may not be used.
11    /// Indexed by `LibraryHandle.0`.
12    all_libs: Vec<LibraryInfo>, // append-only for stable LibraryHandles
13    /// Indexed by `GlobalLibIndex.0`.
14    used_libs: Vec<LibraryHandle>, // append-only for stable GlobalLibIndexes
15    lib_map: FastHashMap<LibraryInfo, LibraryHandle>,
16    used_lib_map: FastHashMap<LibraryHandle, GlobalLibIndex>,
17}
18
19impl GlobalLibTable {
20    pub fn new() -> Self {
21        Self {
22            all_libs: Vec::new(),
23            used_libs: Vec::new(),
24            lib_map: FastHashMap::default(),
25            used_lib_map: FastHashMap::default(),
26        }
27    }
28
29    pub fn handle_for_lib(&mut self, lib: LibraryInfo) -> LibraryHandle {
30        let all_libs = &mut self.all_libs;
31        *self.lib_map.entry(lib.clone()).or_insert_with(|| {
32            let handle = LibraryHandle(all_libs.len());
33            all_libs.push(lib);
34            handle
35        })
36    }
37
38    pub fn set_lib_symbol_table(&mut self, library: LibraryHandle, symbol_table: Arc<SymbolTable>) {
39        self.all_libs[library.0].symbol_table = Some(symbol_table);
40    }
41
42    pub fn index_for_used_lib(&mut self, lib_handle: LibraryHandle) -> GlobalLibIndex {
43        let used_libs = &mut self.used_libs;
44        *self.used_lib_map.entry(lib_handle).or_insert_with(|| {
45            let index = GlobalLibIndex(used_libs.len());
46            used_libs.push(lib_handle);
47            index
48        })
49    }
50
51    pub fn get_lib(&self, index: GlobalLibIndex) -> Option<&LibraryInfo> {
52        let handle = self.used_libs.get(index.0)?;
53        self.all_libs.get(handle.0)
54    }
55}
56
57impl Serialize for GlobalLibTable {
58    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
59        serializer.collect_seq(self.used_libs.iter().map(|handle| &self.all_libs[handle.0]))
60    }
61}
62
63/// An index for a *used* library, i.e. a library for which there exists at
64/// least one frame in any process's frame table which refers to this lib.
65#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
66pub struct GlobalLibIndex(usize);
67
68impl Serialize for GlobalLibIndex {
69    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
70        serializer.serialize_u32(self.0 as u32)
71    }
72}
73
74/// The handle for a library, obtained from [`Profile::add_lib`](crate::Profile::add_lib).
75#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
76pub struct LibraryHandle(usize);