From 2c1d72ad1a2e788daf8db0014602ee9640fa4d1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 11 Jan 2018 15:40:37 +0100 Subject: [PATCH] style: Track document state dependencies in the invalidation maps. --- .../invalidation/element/invalidation_map.rs | 43 +++++++++++++++++-- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/components/style/invalidation/element/invalidation_map.rs b/components/style/invalidation/element/invalidation_map.rs index 809d3eb4a78..9cbfcb77e8b 100644 --- a/components/style/invalidation/element/invalidation_map.rs +++ b/components/style/invalidation/element/invalidation_map.rs @@ -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, + /// 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>, /// A map of all the state dependencies. pub state_affecting_selectors: SelectorMap, + /// A list of document state dependencies in the rules we represent. + pub document_state_selectors: Vec, /// A map of other attribute affecting selectors. pub other_attribute_affecting_selectors: SelectorMap, /// 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, - 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) -> bool { @@ -353,6 +387,7 @@ impl SelectorVisitor for CompoundSelectorDependencyCollector { } _ => pc.state_flag(), }; + *self.document_state |= pc.document_state_flag(); } _ => {} }