style/use_counters/
mod.rs1use crate::properties::{property_counts, CountedUnknownProperty, NonCustomPropertyId};
8use std::sync::atomic::{AtomicUsize, Ordering};
9
10#[cfg(target_pointer_width = "64")]
11const BITS_PER_ENTRY: usize = 64;
12
13#[cfg(target_pointer_width = "32")]
14const BITS_PER_ENTRY: usize = 32;
15
16#[derive(Debug, Default)]
18pub struct CountedUnknownPropertyUseCounters {
19 storage: [AtomicUsize; property_counts::COUNTED_UNKNOWN.div_ceil(BITS_PER_ENTRY)],
20}
21
22#[derive(Debug, Default)]
24pub struct NonCustomPropertyUseCounters {
25 storage: [AtomicUsize; property_counts::NON_CUSTOM.div_ceil(BITS_PER_ENTRY)],
26}
27
28#[derive(Copy, Clone, Debug)]
30#[repr(u32)]
31pub enum CustomUseCounter {
32 HasNonLocalUriDependency = 0,
34 MaybeHasPathBaseUriDependency,
36 MaybeHasFullBaseUriDependency,
38 Last,
40}
41
42impl CustomUseCounter {
43 #[inline]
44 fn bit(self) -> usize {
45 self as usize
46 }
47}
48
49#[derive(Debug, Default)]
51pub struct CustomUseCounters {
52 storage: [AtomicUsize; (CustomUseCounter::Last as usize).div_ceil(BITS_PER_ENTRY)],
53}
54
55macro_rules! use_counters_methods {
56 ($id: ident) => {
57 #[inline(always)]
60 fn bucket_and_pattern(id: $id) -> (usize, usize) {
61 let bit = id.bit();
62 let bucket = bit / BITS_PER_ENTRY;
63 let bit_in_bucket = bit % BITS_PER_ENTRY;
64 (bucket, 1 << bit_in_bucket)
65 }
66
67 #[inline]
69 pub fn record(&self, id: $id) {
70 let (bucket, pattern) = Self::bucket_and_pattern(id);
71 let bucket = &self.storage[bucket];
72 bucket.fetch_or(pattern, Ordering::Relaxed);
73 }
74
75 #[inline]
78 pub fn recorded(&self, id: $id) -> bool {
79 let (bucket, pattern) = Self::bucket_and_pattern(id);
80 self.storage[bucket].load(Ordering::Relaxed) & pattern != 0
81 }
82
83 #[inline]
85 fn merge(&self, other: &Self) {
86 for (bucket, other_bucket) in self.storage.iter().zip(other.storage.iter()) {
87 bucket.fetch_or(other_bucket.load(Ordering::Relaxed), Ordering::Relaxed);
88 }
89 }
90 };
91}
92
93impl CountedUnknownPropertyUseCounters {
94 use_counters_methods!(CountedUnknownProperty);
95}
96
97impl NonCustomPropertyUseCounters {
98 use_counters_methods!(NonCustomPropertyId);
99}
100
101impl CustomUseCounters {
102 use_counters_methods!(CustomUseCounter);
103}
104
105#[derive(Debug, Default)]
107pub struct UseCounters {
108 pub non_custom_properties: NonCustomPropertyUseCounters,
111 pub counted_unknown_properties: CountedUnknownPropertyUseCounters,
113 pub custom: CustomUseCounters,
115}
116
117impl UseCounters {
118 #[inline]
122 pub fn merge(&self, other: &Self) {
123 self.non_custom_properties
124 .merge(&other.non_custom_properties);
125 self.counted_unknown_properties
126 .merge(&other.counted_unknown_properties);
127 self.custom.merge(&other.custom);
128 }
129}
130
131impl Clone for UseCounters {
132 fn clone(&self) -> Self {
133 let result = Self::default();
134 result.merge(self);
135 result
136 }
137}