style: Make the counters non-atomic counters and merge afterwards.

This was consistently faster in the benchmark (even when counters were disabled,
which was slightly suspicious, but...).

Anyway, it's not really much code, most of it is FFI copy-pasta.

Differential Revision: https://phabricator.services.mozilla.com/D3874
This commit is contained in:
Emilio Cobos Álvarez 2018-08-21 12:31:11 +02:00
parent 4f04988c13
commit 86b4b70369
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
3 changed files with 45 additions and 11 deletions

View file

@ -4,10 +4,10 @@
//! Various stuff for CSS property use counters.
#[cfg(feature = "gecko")]
use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
use properties::{NonCustomPropertyId, NON_CUSTOM_PROPERTY_ID_COUNT};
// FIXME(emilio): We need AtomicU32 on stable ASAP...
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use std::cell::Cell;
#[cfg(target_pointer_width = "64")]
const BITS_PER_ENTRY: usize = 64;
@ -18,7 +18,7 @@ const BITS_PER_ENTRY: usize = 32;
/// One bit per each non-custom CSS property.
#[derive(Default)]
pub struct NonCustomPropertyUseCounters {
storage: [AtomicUsize; (NON_CUSTOM_PROPERTY_ID_COUNT - 1 + BITS_PER_ENTRY) / BITS_PER_ENTRY],
storage: [Cell<usize>; (NON_CUSTOM_PROPERTY_ID_COUNT - 1 + BITS_PER_ENTRY) / BITS_PER_ENTRY],
}
impl NonCustomPropertyUseCounters {
@ -36,7 +36,8 @@ impl NonCustomPropertyUseCounters {
#[inline]
pub fn record(&self, id: NonCustomPropertyId) {
let (bucket, pattern) = Self::bucket_and_pattern(id);
self.storage[bucket].fetch_or(pattern, Ordering::Relaxed);
let bucket = &self.storage[bucket];
bucket.set(bucket.get() | pattern)
}
/// Returns whether a given non-custom property ID has been recorded
@ -44,7 +45,15 @@ impl NonCustomPropertyUseCounters {
#[inline]
pub fn recorded(&self, id: NonCustomPropertyId) -> bool {
let (bucket, pattern) = Self::bucket_and_pattern(id);
self.storage[bucket].load(Ordering::Relaxed) & pattern != 0
self.storage[bucket].get() & pattern != 0
}
/// Merge `other` into `self`.
#[inline]
fn merge(&self, other: &Self) {
for (bucket, other_bucket) in self.storage.iter().zip(other.storage.iter()) {
bucket.set(bucket.get() | other_bucket.get())
}
}
}
@ -55,3 +64,24 @@ pub struct UseCounters {
/// document's stylesheets.
pub non_custom_properties: NonCustomPropertyUseCounters,
}
impl UseCounters {
/// Merge the use counters.
///
/// Used for parallel parsing, where we parse off-main-thread.
#[inline]
pub fn merge(&self, other: &Self) {
self.non_custom_properties.merge(&other.non_custom_properties)
}
}
#[cfg(feature = "gecko")]
unsafe impl HasFFI for UseCounters {
type FFIType = ::gecko_bindings::structs::StyleUseCounters;
}
#[cfg(feature = "gecko")]
unsafe impl HasSimpleFFI for UseCounters {}
#[cfg(feature = "gecko")]
unsafe impl HasBoxFFI for UseCounters {}