mod.rs (4505B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ 4 5 //! Various stuff for CSS property use counters. 6 7 use crate::properties::{property_counts, CountedUnknownProperty, NonCustomPropertyId}; 8 use std::sync::atomic::{AtomicUsize, Ordering}; 9 10 #[cfg(target_pointer_width = "64")] 11 const BITS_PER_ENTRY: usize = 64; 12 13 #[cfg(target_pointer_width = "32")] 14 const BITS_PER_ENTRY: usize = 32; 15 16 /// One bit per each non-custom CSS property. 17 #[derive(Debug, Default)] 18 pub struct CountedUnknownPropertyUseCounters { 19 storage: 20 [AtomicUsize; (property_counts::COUNTED_UNKNOWN + BITS_PER_ENTRY - 1) / BITS_PER_ENTRY], 21 } 22 23 /// One bit per each non-custom CSS property. 24 #[derive(Debug, Default)] 25 pub struct NonCustomPropertyUseCounters { 26 storage: [AtomicUsize; (property_counts::NON_CUSTOM + BITS_PER_ENTRY - 1) / BITS_PER_ENTRY], 27 } 28 29 /// A custom style use counter that we may want to record. 30 #[derive(Copy, Clone, Debug)] 31 #[repr(u32)] 32 pub enum CustomUseCounter { 33 /// Whether we reference a non-local uri at all. 34 HasNonLocalUriDependency = 0, 35 /// Whether we are likely to be using relative URIs that depend on our path depth. 36 MaybeHasPathBaseUriDependency, 37 /// Whether we are likely to be using relative URIs that depend on our full URI. 38 MaybeHasFullBaseUriDependency, 39 /// Dummy value, used for indexing purposes. 40 Last, 41 } 42 43 impl CustomUseCounter { 44 #[inline] 45 fn bit(self) -> usize { 46 self as usize 47 } 48 } 49 50 /// One bit for each custom use counter. 51 #[derive(Debug, Default)] 52 pub struct CustomUseCounters { 53 storage: 54 [AtomicUsize; ((CustomUseCounter::Last as usize) + BITS_PER_ENTRY - 1) / BITS_PER_ENTRY], 55 } 56 57 macro_rules! use_counters_methods { 58 ($id: ident) => { 59 /// Returns the bucket a given property belongs in, and the bitmask for that 60 /// property. 61 #[inline(always)] 62 fn bucket_and_pattern(id: $id) -> (usize, usize) { 63 let bit = id.bit(); 64 let bucket = bit / BITS_PER_ENTRY; 65 let bit_in_bucket = bit % BITS_PER_ENTRY; 66 (bucket, 1 << bit_in_bucket) 67 } 68 69 /// Record that a given property ID has been parsed. 70 #[inline] 71 pub fn record(&self, id: $id) { 72 let (bucket, pattern) = Self::bucket_and_pattern(id); 73 let bucket = &self.storage[bucket]; 74 bucket.fetch_or(pattern, Ordering::Relaxed); 75 } 76 77 /// Returns whether a given property ID has been recorded 78 /// earlier. 79 #[inline] 80 pub fn recorded(&self, id: $id) -> bool { 81 let (bucket, pattern) = Self::bucket_and_pattern(id); 82 self.storage[bucket].load(Ordering::Relaxed) & pattern != 0 83 } 84 85 /// Merge `other` into `self`. 86 #[inline] 87 fn merge(&self, other: &Self) { 88 for (bucket, other_bucket) in self.storage.iter().zip(other.storage.iter()) { 89 bucket.fetch_or(other_bucket.load(Ordering::Relaxed), Ordering::Relaxed); 90 } 91 } 92 }; 93 } 94 95 impl CountedUnknownPropertyUseCounters { 96 use_counters_methods!(CountedUnknownProperty); 97 } 98 99 impl NonCustomPropertyUseCounters { 100 use_counters_methods!(NonCustomPropertyId); 101 } 102 103 impl CustomUseCounters { 104 use_counters_methods!(CustomUseCounter); 105 } 106 107 /// The use-counter data related to a given document we want to store. 108 #[derive(Debug, Default)] 109 pub struct UseCounters { 110 /// The counters for non-custom properties that have been parsed in the 111 /// document's stylesheets. 112 pub non_custom_properties: NonCustomPropertyUseCounters, 113 /// The counters for css properties which we haven't implemented yet. 114 pub counted_unknown_properties: CountedUnknownPropertyUseCounters, 115 /// Custom counters for virtually everything else. 116 pub custom: CustomUseCounters, 117 } 118 119 impl UseCounters { 120 /// Merge the use counters. 121 /// 122 /// Used for parallel parsing, where we parse off-main-thread. 123 #[inline] 124 pub fn merge(&self, other: &Self) { 125 self.non_custom_properties 126 .merge(&other.non_custom_properties); 127 self.counted_unknown_properties 128 .merge(&other.counted_unknown_properties); 129 self.custom.merge(&other.custom); 130 } 131 } 132 133 impl Clone for UseCounters { 134 fn clone(&self) -> Self { 135 let result = Self::default(); 136 result.merge(self); 137 result 138 } 139 }