tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }