diff --git a/components/script_layout_interface/wrapper_traits.rs b/components/script_layout_interface/wrapper_traits.rs index 05b24bca915..33116058aa9 100644 --- a/components/script_layout_interface/wrapper_traits.rs +++ b/components/script_layout_interface/wrapper_traits.rs @@ -346,7 +346,7 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug + #[inline] fn get_before_pseudo(&self) -> Option { - if self.style_data().styles.pseudos.has(&PseudoElement::Before) { + if self.style_data().styles.pseudos.get(&PseudoElement::Before).is_some() { Some(self.with_pseudo(PseudoElementType::Before(None))) } else { None @@ -355,7 +355,7 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug + #[inline] fn get_after_pseudo(&self) -> Option { - if self.style_data().styles.pseudos.has(&PseudoElement::After) { + if self.style_data().styles.pseudos.get(&PseudoElement::After).is_some() { Some(self.with_pseudo(PseudoElementType::After(None))) } else { None diff --git a/components/style/context.rs b/components/style/context.rs index f36df67a55c..103c3a5a7d3 100644 --- a/components/style/context.rs +++ b/components/style/context.rs @@ -21,7 +21,7 @@ use rule_tree::StrongRuleNode; use selector_parser::{EAGER_PSEUDO_COUNT, SnapshotMap}; use selectors::matching::ElementSelectorFlags; use shared_lock::StylesheetGuards; -use sharing::{ValidationData, StyleSharingCandidateCache}; +use sharing::StyleSharingCandidateCache; use std::fmt; use std::ops::Add; #[cfg(feature = "servo")] use std::sync::Mutex; @@ -269,8 +269,6 @@ pub struct CurrentElementInfo { element: OpaqueNode, /// Whether the element is being styled for the first time. is_initial_style: bool, - /// Lazy cache of the different data used for style sharing. - pub validation_data: ValidationData, /// A Vec of possibly expired animations. Used only by Servo. #[allow(dead_code)] pub possibly_expired_animations: Vec, @@ -575,7 +573,6 @@ impl ThreadLocalStyleContext { self.current_element_info = Some(CurrentElementInfo { element: element.as_node().opaque(), is_initial_style: !data.has_styles(), - validation_data: ValidationData::default(), possibly_expired_animations: Vec::new(), }); } diff --git a/components/style/data.rs b/components/style/data.rs index a62d1359e1a..1116d83d0d2 100644 --- a/components/style/data.rs +++ b/components/style/data.rs @@ -4,7 +4,6 @@ //! Per-node data used in style calculation. -use arrayvec::ArrayVec; use context::SharedStyleContext; use dom::TElement; use invalidation::element::restyle_hints::RestyleHint; @@ -157,20 +156,6 @@ impl EagerPseudoStyles { self.0.as_ref().and_then(|p| p[pseudo.eager_index()].as_ref()) } - /// Returns a mutable reference to the style for a given eager pseudo, if it exists. - pub fn get_mut(&mut self, pseudo: &PseudoElement) -> Option<&mut Arc> { - debug_assert!(pseudo.is_eager()); - match self.0 { - None => return None, - Some(ref mut arc) => Arc::make_mut(arc)[pseudo.eager_index()].as_mut(), - } - } - - /// Returns true if the EagerPseudoStyles has the style for |pseudo|. - pub fn has(&self, pseudo: &PseudoElement) -> bool { - self.get(pseudo).is_some() - } - /// Sets the style for the eager pseudo. pub fn set(&mut self, pseudo: &PseudoElement, value: Arc) { if self.0.is_none() { @@ -179,57 +164,6 @@ impl EagerPseudoStyles { let arr = Arc::make_mut(self.0.as_mut().unwrap()); arr[pseudo.eager_index()] = Some(value); } - - /// Inserts a pseudo-element. The pseudo-element must not already exist. - pub fn insert(&mut self, pseudo: &PseudoElement, value: Arc) { - debug_assert!(!self.has(pseudo)); - self.set(pseudo, value); - } - - /// Removes a pseudo-element style if it exists, and returns it. - pub fn take(&mut self, pseudo: &PseudoElement) -> Option> { - let result = match self.0 { - None => return None, - Some(ref mut arc) => Arc::make_mut(arc)[pseudo.eager_index()].take(), - }; - let empty = self.0.as_ref().unwrap().iter().all(|x| x.is_none()); - if empty { - self.0 = None; - } - result - } - - /// Returns a list of the pseudo-elements. - pub fn keys(&self) -> ArrayVec<[PseudoElement; EAGER_PSEUDO_COUNT]> { - let mut v = ArrayVec::new(); - if let Some(ref arr) = self.0 { - for i in 0..EAGER_PSEUDO_COUNT { - if arr[i].is_some() { - v.push(PseudoElement::from_eager_index(i)); - } - } - } - v - } - - /// Returns whether this map has the same set of pseudos as the given one. - pub fn has_same_pseudos_as(&self, other: &Self) -> bool { - // We could probably just compare self.keys() to other.keys(), but that - // seems like it'll involve a bunch more moving stuff around and - // whatnot. - match (&self.0, &other.0) { - (&Some(ref our_arr), &Some(ref other_arr)) => { - for i in 0..EAGER_PSEUDO_COUNT { - if our_arr[i].is_some() != other_arr[i].is_some() { - return false - } - } - true - }, - (&None, &None) => true, - _ => false, - } - } } /// The styles associated with a node, including the styles for any @@ -248,11 +182,6 @@ impl ElementStyles { self.primary.as_ref() } - /// Returns the mutable primary style. - pub fn get_primary_mut(&mut self) -> Option<&mut Arc> { - self.primary.as_mut() - } - /// Returns the primary style. Panic if no style available. pub fn primary(&self) -> &Arc { self.primary.as_ref().unwrap() diff --git a/components/style/sharing/mod.rs b/components/style/sharing/mod.rs index f330f226090..8aa66d4739e 100644 --- a/components/style/sharing/mod.rs +++ b/components/style/sharing/mod.rs @@ -70,11 +70,10 @@ use bit_vec::BitVec; use bloom::StyleBloom; use cache::{LRUCache, LRUCacheMutIterator}; use context::{SelectorFlagsMap, SharedStyleContext, StyleContext}; -use data::{ElementData, ElementStyles}; +use data::ElementStyles; use dom::{TElement, SendElement}; -use matching::{ChildCascadeRequirement, MatchMethods}; +use matching::MatchMethods; use properties::ComputedValues; -use selector_parser::RestyleDamage; use selectors::matching::{ElementSelectorFlags, VisitedHandlingMode}; use smallvec::SmallVec; use std::mem; @@ -329,11 +328,9 @@ impl StyleSharingTarget { /// Attempts to share a style with another node. pub fn share_style_if_possible( - mut self, + &mut self, context: &mut StyleContext, - data: &mut ElementData) - -> StyleSharingResult - { + ) -> StyleSharingResult { let cache = &mut context.thread_local.style_sharing_candidate_cache; let shared_context = &context.shared; let selector_flags_map = &mut context.thread_local.selector_flags; @@ -347,70 +344,17 @@ impl StyleSharingTarget { debug_assert_eq!(bloom_filter.current_parent(), self.element.traversal_parent()); - let result = cache - .share_style_if_possible(shared_context, - selector_flags_map, - bloom_filter, - &mut self, - data); - - - context.thread_local.current_element_info.as_mut().unwrap().validation_data = - self.validation_data.take(); - result + cache.share_style_if_possible( + shared_context, + selector_flags_map, + bloom_filter, + self + ) } - fn accumulate_damage_when_sharing(&self, - shared_context: &SharedStyleContext, - shared_styles: &ElementStyles, - data: &mut ElementData) -> ChildCascadeRequirement { - // Accumulate restyle damage for the case when our sharing - // target managed to share style. This can come from several - // sources: - // - // 1) We matched a different set of eager pseudos (which - // should cause a reconstruct). - // 2) We have restyle damage from the eager pseudo computed - // styles. - // 3) We have restyle damage from our own computed styles. - if data.has_styles() { - // We used to have pseudos (because we had styles). - // Check for damage from the set of pseudos changing or - // pseudos being restyled. - let (styles, mut restyle_data) = data.styles_and_restyle_mut(); - let old_pseudos = &styles.pseudos; - let new_pseudos = &shared_styles.pseudos; - - if !old_pseudos.has_same_pseudos_as(new_pseudos) { - restyle_data.damage |= RestyleDamage::reconstruct(); - } else { - // It's a bit unfortunate that we have to keep - // mapping PseudoElements back to indices - // here.... - for pseudo in old_pseudos.keys() { - let old_values = - old_pseudos.get(&pseudo).map(|v| &**v); - let new_values = - new_pseudos.get(&pseudo).unwrap(); - self.element.accumulate_damage( - &shared_context, - restyle_data, - old_values, - new_values, - Some(&pseudo) - ); - } - } - } - - let old_values = data.styles.primary.take(); - self.element.accumulate_damage( - &shared_context, - &mut data.restyle, - old_values.as_ref().map(|v| &**v), - shared_styles.primary(), - None - ) + /// Gets the validation data used to match against this target, if any. + pub fn take_validation_data(&mut self) -> ValidationData { + self.validation_data.take() } } @@ -451,10 +395,8 @@ pub enum StyleSharingResult { /// We didn't find anybody to share the style with. CannotShare, /// The node's style can be shared. The integer specifies the index in the - /// LRU cache that was hit and the damage that was done. The - /// `ChildCascadeRequirement` indicates whether style changes due to using - /// the shared style mean we need to recascade to children. - StyleWasShared(usize, ChildCascadeRequirement), + /// LRU cache that was hit and the damage that was done. + StyleWasShared(usize, ElementStyles), } /// An LRU cache of the last few nodes seen, so that we can aggressively try to @@ -553,7 +495,6 @@ impl StyleSharingCandidateCache { selector_flags_map: &mut SelectorFlagsMap, bloom_filter: &StyleBloom, target: &mut StyleSharingTarget, - data: &mut ElementData ) -> StyleSharingResult { if shared_context.options.disable_style_sharing_cache { debug!("{:?} Cannot share style: style sharing cache disabled", @@ -584,14 +525,7 @@ impl StyleSharingCandidateCache { match sharing_result { Ok(shared_styles) => { - // Yay, cache hit. Share the style. - let child_cascade_requirement = - target.accumulate_damage_when_sharing(shared_context, - &shared_styles, - data); - data.styles = shared_styles; - - return StyleSharingResult::StyleWasShared(i, child_cascade_requirement) + return StyleSharingResult::StyleWasShared(i, shared_styles) } Err(miss) => { debug!("Cache miss: {:?}", miss); @@ -605,12 +539,13 @@ impl StyleSharingCandidateCache { StyleSharingResult::CannotShare } - fn test_candidate(target: &mut StyleSharingTarget, - candidate: &mut StyleSharingCandidate, - shared: &SharedStyleContext, - bloom: &StyleBloom, - selector_flags_map: &mut SelectorFlagsMap) - -> Result { + fn test_candidate( + target: &mut StyleSharingTarget, + candidate: &mut StyleSharingCandidate, + shared: &SharedStyleContext, + bloom: &StyleBloom, + selector_flags_map: &mut SelectorFlagsMap + ) -> Result { macro_rules! miss { ($miss: ident) => { return Err(CacheMiss::$miss); diff --git a/components/style/traversal.rs b/components/style/traversal.rs index 70eb8ce5e84..aeac476b720 100644 --- a/components/style/traversal.rs +++ b/components/style/traversal.rs @@ -771,50 +771,38 @@ where context.thread_local.bloom_filter.assert_complete(element); - // Now that our bloom filter is set up, try the style sharing - // cache. If we get a match we can skip the rest of the work. - let target = StyleSharingTarget::new(element); - let sharing_result = target.share_style_if_possible(context, data); - - if let StyleWasShared(index, had_damage) = sharing_result { - context.thread_local.statistics.styles_shared += 1; - context.thread_local.style_sharing_candidate_cache.touch(index); - return had_damage; - } - - context.thread_local.statistics.elements_matched += 1; - + // This is only relevant for animations as of right now. important_rules_changed = true; - // Perform the matching and cascading. - let new_styles = - StyleResolverForElement::new(element, context, RuleInclusion::All) - .resolve_style_with_default_parents(); + let mut target = StyleSharingTarget::new(element); - // If we previously tried to match this element against the cache, - // the revalidation match results will already be cached. Otherwise - // we'll have None, and compute them later on-demand. - // - // If we do have the results, grab them here to satisfy the borrow - // checker. - let validation_data = - context.thread_local - .current_element_info - .as_mut().unwrap() - .validation_data - .take(); + // Now that our bloom filter is set up, try the style sharing + // cache. + match target.share_style_if_possible(context) { + StyleWasShared(index, styles) => { + context.thread_local.statistics.styles_shared += 1; + context.thread_local.style_sharing_candidate_cache.touch(index); + styles + } + CannotShare => { + context.thread_local.statistics.elements_matched += 1; + // Perform the matching and cascading. + let new_styles = + StyleResolverForElement::new(element, context, RuleInclusion::All) + .resolve_style_with_default_parents(); - let dom_depth = context.thread_local.bloom_filter.matching_depth(); - context.thread_local - .style_sharing_candidate_cache - .insert_if_possible( - &element, - new_styles.primary(), - validation_data, - dom_depth - ); + context.thread_local + .style_sharing_candidate_cache + .insert_if_possible( + &element, + new_styles.primary(), + target.take_validation_data(), + context.thread_local.bloom_filter.matching_depth(), + ); - new_styles + new_styles + } + } } CascadeWithReplacements(flags) => { // Skipping full matching, load cascade inputs from previous values.