style: Track document state dependencies in the invalidation maps.

This commit is contained in:
Emilio Cobos Álvarez 2018-01-11 15:40:37 +01:00
parent 14661e470f
commit 2c1d72ad1a
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C

View file

@ -6,7 +6,7 @@
use {Atom, LocalName, Namespace};
use context::QuirksMode;
use element_state::ElementState;
use element_state::{DocumentState, ElementState};
use fallible::FallibleVec;
use hashglobe::FailedAllocationError;
use selector_map::{MaybeCaseInsensitiveHashMap, SelectorMap, SelectorMapEntry};
@ -133,6 +133,19 @@ impl SelectorMapEntry for StateDependency {
}
}
/// The same, but for document state selectors.
#[derive(Clone, Debug, MallocSizeOf)]
pub struct DocumentStateDependency {
/// The selector that is affected. We don't need to track an offset, since
/// when it changes it changes for the whole document anyway.
#[cfg_attr(feature = "gecko",
ignore_malloc_size_of = "CssRules have primary refs, we measure there")]
#[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")]
pub selector: Selector<SelectorImpl>,
/// The state this dependency is affected by.
pub state: DocumentState,
}
/// A map where we store invalidations.
///
/// This is slightly different to a SelectorMap, in the sense of that the same
@ -151,6 +164,8 @@ pub struct InvalidationMap {
pub id_to_selector: MaybeCaseInsensitiveHashMap<Atom, SmallVec<[Dependency; 1]>>,
/// A map of all the state dependencies.
pub state_affecting_selectors: SelectorMap<StateDependency>,
/// A list of document state dependencies in the rules we represent.
pub document_state_selectors: Vec<DocumentStateDependency>,
/// A map of other attribute affecting selectors.
pub other_attribute_affecting_selectors: SelectorMap<Dependency>,
/// Whether there are attribute rules of the form `[class~="foo"]` that may
@ -172,6 +187,7 @@ impl InvalidationMap {
class_to_selector: MaybeCaseInsensitiveHashMap::new(),
id_to_selector: MaybeCaseInsensitiveHashMap::new(),
state_affecting_selectors: SelectorMap::new(),
document_state_selectors: Vec::new(),
other_attribute_affecting_selectors: SelectorMap::new(),
has_class_attribute_selectors: false,
has_id_attribute_selectors: false,
@ -181,6 +197,7 @@ impl InvalidationMap {
/// Returns the number of dependencies stored in the invalidation map.
pub fn len(&self) -> usize {
self.state_affecting_selectors.len() +
self.document_state_selectors.len() +
self.other_attribute_affecting_selectors.len() +
self.id_to_selector.iter().fold(0, |accum, (_, ref v)| {
accum + v.len()
@ -195,7 +212,7 @@ impl InvalidationMap {
pub fn note_selector(
&mut self,
selector: &Selector<SelectorImpl>,
quirks_mode: QuirksMode
quirks_mode: QuirksMode,
) -> Result<(), FailedAllocationError> {
self.collect_invalidations_for(selector, quirks_mode)
}
@ -205,6 +222,7 @@ impl InvalidationMap {
self.class_to_selector.clear();
self.id_to_selector.clear();
self.state_affecting_selectors.clear();
self.document_state_selectors.clear();
self.other_attribute_affecting_selectors.clear();
self.has_id_attribute_selectors = false;
self.has_class_attribute_selectors = false;
@ -222,6 +240,8 @@ impl InvalidationMap {
let mut combinator;
let mut index = 0;
let mut document_state = DocumentState::empty();
loop {
let sequence_start = index;
@ -229,6 +249,7 @@ impl InvalidationMap {
classes: SmallVec::new(),
ids: SmallVec::new(),
state: ElementState::empty(),
document_state: &mut document_state,
other_attributes: false,
has_id_attribute_selectors: false,
has_class_attribute_selectors: false,
@ -297,15 +318,28 @@ impl InvalidationMap {
index += 1; // Account for the combinator.
}
if !document_state.is_empty() {
self.document_state_selectors.try_push(DocumentStateDependency {
state: document_state,
selector: selector.clone(),
})?;
}
Ok(())
}
}
/// A struct that collects invalidations for a given compound selector.
struct CompoundSelectorDependencyCollector {
struct CompoundSelectorDependencyCollector<'a> {
/// The state this compound selector is affected by.
state: ElementState,
/// The document this _complex_ selector is affected by.
///
/// We don't need to track state per compound selector, since it's global
/// state and it changes for everything.
document_state: &'a mut DocumentState,
/// The classes this compound selector is affected by.
///
/// NB: This will be often a single class, but could be multiple in
@ -330,7 +364,7 @@ struct CompoundSelectorDependencyCollector {
has_class_attribute_selectors: bool,
}
impl SelectorVisitor for CompoundSelectorDependencyCollector {
impl<'a> SelectorVisitor for CompoundSelectorDependencyCollector<'a> {
type Impl = SelectorImpl;
fn visit_simple_selector(&mut self, s: &Component<SelectorImpl>) -> bool {
@ -353,6 +387,7 @@ impl SelectorVisitor for CompoundSelectorDependencyCollector {
}
_ => pc.state_flag(),
};
*self.document_state |= pc.document_state_flag();
}
_ => {}
}