style: Simplify and improve the per origin stylesheet invalidation setup.

MozReview-Commit-ID: adDDRhNnOw
Signed-off-by: Emilio Cobos Álvarez <emilio@crisal.io>
This commit is contained in:
Emilio Cobos Álvarez 2017-08-22 15:07:33 +02:00
parent a98fd5e2b6
commit e1517d62af
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
2 changed files with 25 additions and 62 deletions

View file

@ -9,7 +9,7 @@ use invalidation::stylesheets::StylesheetInvalidationSet;
use media_queries::Device; use media_queries::Device;
use shared_lock::SharedRwLockReadGuard; use shared_lock::SharedRwLockReadGuard;
use std::slice; use std::slice;
use stylesheets::{OriginSet, PerOrigin, StylesheetInDocument}; use stylesheets::{Origin, OriginSet, StylesheetInDocument};
/// Entry for a StylesheetSet. We don't bother creating a constructor, because /// Entry for a StylesheetSet. We don't bother creating a constructor, because
/// there's no sensible defaults for the member variables. /// there's no sensible defaults for the member variables.
@ -51,8 +51,11 @@ where
/// include recursive `@import` rules. /// include recursive `@import` rules.
entries: Vec<StylesheetSetEntry<S>>, entries: Vec<StylesheetSetEntry<S>>,
/// Per-origin stylesheet invalidation data. /// The invalidations for stylesheets added or removed from this document.
invalidation_data: PerOrigin<InvalidationData>, invalidations: StylesheetInvalidationSet,
/// The origins whose stylesheets have changed so far.
origins_dirty: OriginSet,
/// Has author style been disabled? /// Has author style been disabled?
author_style_disabled: bool, author_style_disabled: bool,
@ -66,7 +69,8 @@ where
pub fn new() -> Self { pub fn new() -> Self {
StylesheetSet { StylesheetSet {
entries: vec![], entries: vec![],
invalidation_data: Default::default(), invalidations: StylesheetInvalidationSet::new(),
origins_dirty: OriginSet::empty(),
author_style_disabled: false, author_style_disabled: false,
} }
} }
@ -97,12 +101,10 @@ where
sheet: &S, sheet: &S,
guard: &SharedRwLockReadGuard, guard: &SharedRwLockReadGuard,
) { ) {
let origin = sheet.contents(guard).origin;
let data = self.invalidation_data.borrow_mut_for_origin(&origin);
if let Some(device) = device { if let Some(device) = device {
data.invalidations.collect_invalidations_for(device, sheet, guard); self.invalidations.collect_invalidations_for(device, sheet, guard);
} }
data.dirty = true; self.origins_dirty |= sheet.contents(guard).origin;
} }
/// Appends a new stylesheet to the current set. /// Appends a new stylesheet to the current set.
@ -169,15 +171,13 @@ where
return; return;
} }
self.author_style_disabled = disabled; self.author_style_disabled = disabled;
self.invalidation_data.author.invalidations.invalidate_fully(); self.invalidations.invalidate_fully();
self.invalidation_data.author.dirty = true; self.origins_dirty |= Origin::Author;
} }
/// Returns whether the given set has changed from the last flush. /// Returns whether the given set has changed from the last flush.
pub fn has_changed(&self) -> bool { pub fn has_changed(&self) -> bool {
self.invalidation_data !self.origins_dirty.is_empty()
.iter_origins()
.any(|(d, _)| d.dirty)
} }
/// Flush the current set, unmarking it as dirty, and returns the damaged /// Flush the current set, unmarking it as dirty, and returns the damaged
@ -189,40 +189,25 @@ where
where where
E: TElement, E: TElement,
{ {
use std::mem;
debug!("StylesheetSet::flush"); debug!("StylesheetSet::flush");
let mut origins = OriginSet::empty(); let have_invalidations = self.invalidations.flush(document_element);
let mut have_invalidations = false; let origins = mem::replace(&mut self.origins_dirty, OriginSet::empty());
for (data, origin) in self.invalidation_data.iter_mut_origins() {
if data.dirty {
have_invalidations |= data.invalidations.flush(document_element);
data.dirty = false;
origins |= origin;
}
}
(origins, have_invalidations) (origins, have_invalidations)
} }
/// Flush stylesheets, but without running any of the invalidation passes. /// Flush stylesheets, but without running any of the invalidation passes.
///
/// FIXME(emilio): This should eventually disappear. Please keep this
/// Servo-only.
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
pub fn flush_without_invalidation(&mut self) -> (StylesheetIterator<S>, OriginSet) { pub fn flush_without_invalidation(&mut self) -> OriginSet {
use std::mem;
debug!("StylesheetSet::flush_without_invalidation"); debug!("StylesheetSet::flush_without_invalidation");
let mut origins = OriginSet::empty(); self.invalidations.clear();
for (data, origin) in self.invalidation_data.iter_mut_origins() { mem::replace(&mut self.origins_dirty, OriginSet::empty())
if data.dirty {
data.invalidations.clear();
data.dirty = false;
origins |= origin;
}
}
(self.iter(), origins)
} }
/// Returns an iterator over the current list of stylesheets. /// Returns an iterator over the current list of stylesheets.
@ -233,30 +218,7 @@ where
/// Mark the stylesheets for the specified origin as dirty, because /// Mark the stylesheets for the specified origin as dirty, because
/// something external may have invalidated it. /// something external may have invalidated it.
pub fn force_dirty(&mut self, origins: OriginSet) { pub fn force_dirty(&mut self, origins: OriginSet) {
for origin in origins.iter() { self.invalidations.invalidate_fully();
let data = self.invalidation_data.borrow_mut_for_origin(&origin); self.origins_dirty |= origins;
data.invalidations.invalidate_fully();
data.dirty = true;
}
}
}
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
struct InvalidationData {
/// The stylesheet invalidations for this origin that we still haven't
/// processed.
invalidations: StylesheetInvalidationSet,
/// Whether the sheets for this origin in the `StylesheetSet`'s entry list
/// has changed since the last restyle.
dirty: bool,
}
impl Default for InvalidationData {
fn default() -> Self {
InvalidationData {
invalidations: StylesheetInvalidationSet::new(),
dirty: false,
}
} }
} }

View file

@ -40,6 +40,7 @@ impl Origin {
bitflags! { bitflags! {
/// A set of origins. This is equivalent to Gecko's OriginFlags. /// A set of origins. This is equivalent to Gecko's OriginFlags.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub flags OriginSet: u8 { pub flags OriginSet: u8 {
/// https://drafts.csswg.org/css-cascade/#cascade-origin-user-agent /// https://drafts.csswg.org/css-cascade/#cascade-origin-user-agent
const ORIGIN_USER_AGENT = Origin::UserAgent as u8, const ORIGIN_USER_AGENT = Origin::UserAgent as u8,