diff options
-rw-r--r-- | components/style/sharing/checks.rs | 13 | ||||
-rw-r--r-- | components/style/sharing/mod.rs | 52 |
2 files changed, 46 insertions, 19 deletions
diff --git a/components/style/sharing/checks.rs b/components/style/sharing/checks.rs index 6fad78fcb7e..d773afc2bd4 100644 --- a/components/style/sharing/checks.rs +++ b/components/style/sharing/checks.rs @@ -12,7 +12,6 @@ use element_state::*; use selectors::bloom::BloomFilter; use selectors::matching::StyleRelations; use sharing::{StyleSharingCandidate, StyleSharingTarget}; -use sink::ForgetfulSink; use stylearc::Arc; /// Determines, based on the results of selector matching, whether it's worth to @@ -23,8 +22,7 @@ pub fn relations_are_shareable(relations: &StyleRelations) -> bool { use selectors::matching::*; !relations.intersects(AFFECTED_BY_ID_SELECTOR | AFFECTED_BY_PSEUDO_ELEMENTS | - AFFECTED_BY_STYLE_ATTRIBUTE | - AFFECTED_BY_PRESENTATIONAL_HINTS) + AFFECTED_BY_STYLE_ATTRIBUTE) } /// Whether, given two elements, they have pointer-equal computed values. @@ -51,12 +49,13 @@ pub fn same_computed_values<E>(first: Option<E>, second: Option<E>) -> bool /// We consider not worth to share style with an element that has presentational /// hints, both because implementing the code that compares that the hints are /// equal is somewhat annoying, and also because it'd be expensive enough. -pub fn has_presentational_hints<E>(element: E) -> bool +pub fn have_same_presentational_hints<E>( + target: &mut StyleSharingTarget<E>, + candidate: &mut StyleSharingCandidate<E> +) -> bool where E: TElement, { - let mut hints = ForgetfulSink::new(); - element.synthesize_presentational_hints_for_legacy_attributes(&mut hints); - !hints.is_empty() + target.pres_hints() == candidate.pres_hints() } /// Whether a given element has the same class attribute than a given candidate. diff --git a/components/style/sharing/mod.rs b/components/style/sharing/mod.rs index c850ee24605..c6fe9a078a8 100644 --- a/components/style/sharing/mod.rs +++ b/components/style/sharing/mod.rs @@ -15,10 +15,9 @@ use matching::{ChildCascadeRequirement, MatchMethods}; use properties::ComputedValues; use selectors::bloom::BloomFilter; use selectors::matching::{ElementSelectorFlags, StyleRelations}; -use sink::ForgetfulSink; use smallvec::SmallVec; use std::ops::Deref; -use stylist::Stylist; +use stylist::{ApplicableDeclarationBlock, Stylist}; mod checks; @@ -45,6 +44,9 @@ pub struct CachedStyleSharingData { /// a similar fashion as what Boris is doing for the ID attribute. class_list: Option<SmallVec<[Atom; 5]>>, + /// The list of presentational attributes of the element. + pres_hints: Option<SmallVec<[ApplicableDeclarationBlock; 5]>>, + /// The cached result of matching this entry against the revalidation /// selectors. revalidation_match_results: Option<BitVec>, @@ -56,6 +58,7 @@ impl CachedStyleSharingData { pub fn new() -> Self { Self { class_list: None, + pres_hints: None, revalidation_match_results: None, } } @@ -64,10 +67,24 @@ impl CachedStyleSharingData { pub fn take(&mut self) -> Self { Self { class_list: self.class_list.take(), + pres_hints: self.pres_hints.take(), revalidation_match_results: self.revalidation_match_results.take(), } } + /// Get or compute the list of presentational attributes associated with + /// this element. + pub fn pres_hints<E>(&mut self, element: E) -> &[ApplicableDeclarationBlock] + where E: TElement, + { + if self.pres_hints.is_none() { + let mut pres_hints = SmallVec::new(); + element.synthesize_presentational_hints_for_legacy_attributes(&mut pres_hints); + self.pres_hints = Some(pres_hints); + } + &*self.pres_hints.as_ref().unwrap() + } + /// Get or compute the class-list associated with this element. pub fn class_list<E>(&mut self, element: E) -> &[Atom] where E: TElement, @@ -121,6 +138,11 @@ impl<E: TElement> StyleSharingCandidate<E> { self.cache.class_list(*self.element) } + /// Get the pres hints of this candidate. + fn pres_hints(&mut self) -> &[ApplicableDeclarationBlock] { + self.cache.pres_hints(*self.element) + } + /// Get the classlist of this candidate. fn revalidation_match_results( &mut self, @@ -167,6 +189,11 @@ impl<E: TElement> StyleSharingTarget<E> { self.cache.class_list(self.element) } + /// Get the pres hints of this candidate. + fn pres_hints(&mut self) -> &[ApplicableDeclarationBlock] { + self.cache.pres_hints(self.element) + } + fn revalidation_match_results( &mut self, stylist: &Stylist, @@ -307,7 +334,9 @@ impl<E: TElement> StyleSharingCandidateCache<E> { element: &E, style: &ComputedValues, relations: StyleRelations, - cache: CachedStyleSharingData) { + mut cache: CachedStyleSharingData) { + use selectors::matching::AFFECTED_BY_PRESENTATIONAL_HINTS; + let parent = match element.parent_element() { Some(element) => element, None => { @@ -328,14 +357,6 @@ impl<E: TElement> StyleSharingCandidateCache<E> { return; } - // Make sure we noted any presentational hints in the StyleRelations. - if cfg!(debug_assertions) { - let mut hints = ForgetfulSink::new(); - element.synthesize_presentational_hints_for_legacy_attributes(&mut hints); - debug_assert!(hints.is_empty(), - "Style relations should not be shareable!"); - } - let box_style = style.get_box(); if box_style.specifies_transitions() { debug!("Failing to insert to the cache: transitions"); @@ -347,6 +368,13 @@ impl<E: TElement> StyleSharingCandidateCache<E> { return; } + // Take advantage of the information we've learned during + // selector-matching. + if !relations.intersects(AFFECTED_BY_PRESENTATIONAL_HINTS) { + debug_assert!(cache.pres_hints.as_ref().map_or(true, |v| v.is_empty())); + cache.pres_hints = Some(SmallVec::new()); + } + debug!("Inserting into cache: {:?} with parent {:?}", element, parent); self.cache.insert(StyleSharingCandidate { @@ -532,7 +560,7 @@ impl<E: TElement> StyleSharingCandidateCache<E> { miss!(Class) } - if checks::has_presentational_hints(target.element) { + if !checks::have_same_presentational_hints(target, candidate) { miss!(PresHints) } |