#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[repr(u8)]
#[non_exhaustive]
pub enum UnwindFallbackKind {
NoModule = 0,
NoModuleUnwindData = 1,
EhFrameHdrLookup = 2,
DwarfCfiIndexLookup = 3,
DwarfFdeRead = 4,
DwarfUnwindInfo = 5,
DwarfStackPointerMovedBackwards = 6,
DwarfDidNotAdvance = 7,
DwarfCouldNotRecoverCfa = 8,
DwarfCouldNotRecoverReturnAddress = 9,
DwarfCouldNotRecoverFramePointer = 10,
OtherUnwindFormat = 11,
}
impl UnwindFallbackKind {
pub const ALL: &'static [Self] = &[
Self::NoModule,
Self::NoModuleUnwindData,
Self::EhFrameHdrLookup,
Self::DwarfCfiIndexLookup,
Self::DwarfFdeRead,
Self::DwarfUnwindInfo,
Self::DwarfStackPointerMovedBackwards,
Self::DwarfDidNotAdvance,
Self::DwarfCouldNotRecoverCfa,
Self::DwarfCouldNotRecoverReturnAddress,
Self::DwarfCouldNotRecoverFramePointer,
Self::OtherUnwindFormat,
];
}
const UNWIND_FALLBACK_KIND_COUNT: usize = UnwindFallbackKind::ALL.len();
const _: () = {
let mut index = 0;
while index < UnwindFallbackKind::ALL.len() {
assert!(UnwindFallbackKind::ALL[index] as usize == index);
index += 1;
}
};
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct UnwindFallbackStats {
counts: [u64; UNWIND_FALLBACK_KIND_COUNT],
}
impl UnwindFallbackStats {
pub(crate) fn record(&mut self, kind: UnwindFallbackKind) {
let count = &mut self.counts[kind as usize];
*count = count.saturating_add(1);
}
#[must_use]
pub fn count(&self, kind: UnwindFallbackKind) -> u64 {
self.counts[kind as usize]
}
#[must_use]
pub fn total(&self) -> u64 {
self.counts.iter().sum()
}
pub fn nonzero_counts(&self) -> impl Iterator<Item = (UnwindFallbackKind, u64)> + '_ {
UnwindFallbackKind::ALL.iter().filter_map(|&kind| {
let count = self.count(kind);
(count != 0).then_some((kind, count))
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn keeps_reasons_separate() {
let mut stats = UnwindFallbackStats::default();
stats.record(UnwindFallbackKind::NoModule);
stats.record(UnwindFallbackKind::DwarfCouldNotRecoverCfa);
stats.record(UnwindFallbackKind::DwarfCouldNotRecoverCfa);
assert_eq!(stats.total(), 3);
assert_eq!(stats.count(UnwindFallbackKind::NoModule), 1);
assert_eq!(stats.count(UnwindFallbackKind::DwarfCouldNotRecoverCfa), 2);
assert_eq!(stats.nonzero_counts().count(), 2);
}
}