diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-06-15 20:28:56 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-15 20:28:56 -0700 |
commit | 33766b2714443399808c950e5bb74b1f124f2bc4 (patch) | |
tree | e55725db70e6f70b0d8d139097ca42646f021c14 | |
parent | e3a52536b650f4aeb951b474936a0b67821f112e (diff) | |
parent | ffc45e9aaa59d5540c5f0480fbe13f48658ec593 (diff) | |
download | servo-33766b2714443399808c950e5bb74b1f124f2bc4.tar.gz servo-33766b2714443399808c950e5bb74b1f124f2bc4.zip |
Auto merge of #17348 - emilio:bup, r=bholley
style: Inline RestyleData.
Bug: 1368236
MozReview-Commit-ID: 49s3SO0PMHf
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/17348)
<!-- Reviewable:end -->
-rw-r--r-- | components/layout/wrapper.rs | 11 | ||||
-rw-r--r-- | components/layout_thread/lib.rs | 11 | ||||
-rw-r--r-- | components/style/data.rs | 141 | ||||
-rw-r--r-- | components/style/dom.rs | 3 | ||||
-rw-r--r-- | components/style/invalidation/element/invalidator.rs | 12 | ||||
-rw-r--r-- | components/style/invalidation/stylesheets.rs | 14 | ||||
-rw-r--r-- | components/style/matching.rs | 20 | ||||
-rw-r--r-- | components/style/sharing/mod.rs | 55 | ||||
-rw-r--r-- | components/style/traversal.rs | 94 | ||||
-rw-r--r-- | ports/geckolib/glue.rs | 21 | ||||
-rw-r--r-- | tests/unit/stylo/size_of.rs | 3 |
11 files changed, 183 insertions, 202 deletions
diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs index 4ae7c403e37..87fe65bb3b9 100644 --- a/components/layout/wrapper.rs +++ b/components/layout/wrapper.rs @@ -171,19 +171,14 @@ impl<T: ThreadSafeLayoutNode> ThreadSafeLayoutNodeHelpers for T { let damage = { let data = node.get_raw_data().unwrap(); - if let Some(r) = data.style_data.element_data.borrow().get_restyle() { - // We're reflowing a node that just got a restyle, and so the - // damage has been computed and stored in the RestyleData. - r.damage - } else if !data.layout_data.borrow().flags.contains(::data::HAS_BEEN_TRAVERSED) { + + if !data.layout_data.borrow().flags.contains(::data::HAS_BEEN_TRAVERSED) { // We're reflowing a node that was styled for the first time and // has never been visited by layout. Return rebuild_and_reflow, // because that's what the code expects. RestyleDamage::rebuild_and_reflow() } else { - // We're reflowing a node whose style data didn't change, but whose - // layout may change due to changes in ancestors or descendants. - RestyleDamage::empty() + data.style_data.element_data.borrow().restyle.damage } }; diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 7c7b5fd89ed..d53fa05a37f 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -1116,7 +1116,7 @@ impl LayoutThread { let el = node.as_element().unwrap(); if let Some(mut d) = element.mutate_data() { if d.has_styles() { - d.ensure_restyle().hint.insert(RestyleHint::restyle_subtree()); + d.restyle.hint.insert(RestyleHint::restyle_subtree()); } } if let Some(p) = el.parent_element() { @@ -1152,7 +1152,7 @@ impl LayoutThread { if needs_dirtying { if let Some(mut d) = element.mutate_data() { if d.has_styles() { - d.ensure_restyle().hint.insert(RestyleHint::restyle_subtree()); + d.restyle.hint.insert(RestyleHint::restyle_subtree()); } } } @@ -1197,12 +1197,11 @@ impl LayoutThread { } let mut style_data = style_data.borrow_mut(); - let mut restyle_data = style_data.ensure_restyle(); // Stash the data on the element for processing by the style system. - restyle_data.hint.insert(restyle.hint.into()); - restyle_data.damage = restyle.damage; - debug!("Noting restyle for {:?}: {:?}", el, restyle_data); + style_data.restyle.hint.insert(restyle.hint.into()); + style_data.restyle.damage = restyle.damage; + debug!("Noting restyle for {:?}: {:?}", el, style_data.restyle); } // Create a layout context for use throughout the following passes. diff --git a/components/style/data.rs b/components/style/data.rs index 46d9fe8afe0..0363d397d74 100644 --- a/components/style/data.rs +++ b/components/style/data.rs @@ -348,17 +348,26 @@ impl ElementStyles { } } +bitflags! { + flags RestyleFlags: u8 { + /// Whether the styles changed for this restyle. + const WAS_RESTYLED = 1 << 0, + /// Whether we reframed/reconstructed any ancestor or self. + const ANCESTOR_WAS_RECONSTRUCTED = 1 << 1, + } +} + /// Transient data used by the restyle algorithm. This structure is instantiated /// either before or during restyle traversal, and is cleared at the end of node /// processing. -#[derive(Debug, Default)] +#[derive(Debug)] pub struct RestyleData { /// The restyle hint, which indicates whether selectors need to be rematched /// for this element, its children, and its descendants. pub hint: RestyleHint, - /// Whether we reframed/reconstructed any ancestor or self. - pub reconstructed_ancestor: bool, + /// A few flags to have in mind. + flags: RestyleFlags, /// The restyle damage, indicating what kind of layout changes are required /// afte restyling. @@ -366,9 +375,53 @@ pub struct RestyleData { } impl RestyleData { - /// Returns true if this RestyleData might invalidate the current style. - pub fn has_invalidations(&self) -> bool { - self.hint.has_self_invalidations() + fn new() -> Self { + Self { + hint: RestyleHint::empty(), + flags: RestyleFlags::empty(), + damage: RestyleDamage::empty(), + } + } + + /// Clear all the restyle state associated with this element. + fn clear(&mut self) { + *self = Self::new(); + } + + /// Returns whether this element or any ancestor is going to be + /// reconstructed. + pub fn reconstructed_self_or_ancestor(&self) -> bool { + self.reconstructed_ancestor() || + self.damage.contains(RestyleDamage::reconstruct()) + } + + /// Returns whether any ancestor of this element was restyled. + fn reconstructed_ancestor(&self) -> bool { + self.flags.contains(ANCESTOR_WAS_RECONSTRUCTED) + } + + /// Sets the flag that tells us whether we've reconstructed an ancestor. + pub fn set_reconstructed_ancestor(&mut self) { + // If it weren't for animation-only traversals, we could assert + // `!self.reconstructed_ancestor()` here. + self.flags.insert(ANCESTOR_WAS_RECONSTRUCTED); + } + + /// Mark this element as restyled, which is useful to know whether we need + /// to do a post-traversal. + pub fn set_restyled(&mut self) { + self.flags.insert(WAS_RESTYLED); + } + + /// Mark this element as restyled, which is useful to know whether we need + /// to do a post-traversal. + pub fn is_restyle(&self) -> bool { + self.flags.contains(WAS_RESTYLED) + } + + /// Returns whether this element has been part of a restyle. + pub fn contains_restyle_data(&self) -> bool { + self.is_restyle() || !self.hint.is_empty() || !self.damage.is_empty() } } @@ -382,9 +435,8 @@ pub struct ElementData { /// The computed styles for the element and its pseudo-elements. styles: Option<ElementStyles>, - /// Restyle tracking. We separate this into a separate allocation so that - /// we can drop it when no restyles are pending on the elemnt. - restyle: Option<Box<RestyleData>>, + /// Restyle state. + pub restyle: RestyleData, } /// The kind of restyle that a single element should do. @@ -402,6 +454,14 @@ pub enum RestyleKind { } impl ElementData { + /// Borrows both styles and restyle mutably at the same time. + pub fn styles_and_restyle_mut( + &mut self + ) -> (&mut ElementStyles, &mut RestyleData) { + (self.styles.as_mut().unwrap(), + &mut self.restyle) + } + /// Invalidates style for this element, its descendants, and later siblings, /// based on the snapshot of the element that we took when attributes or /// state changed. @@ -437,7 +497,7 @@ impl ElementData { pub fn new(existing: Option<ElementStyles>) -> Self { ElementData { styles: existing, - restyle: None, + restyle: RestyleData::new(), } } @@ -448,7 +508,7 @@ impl ElementData { /// Returns whether we have any outstanding style invalidation. pub fn has_invalidations(&self) -> bool { - self.restyle.as_ref().map_or(false, |r| r.has_invalidations()) + self.restyle.hint.has_self_invalidations() } /// Returns the kind of restyling that we're going to need to do on this @@ -465,10 +525,7 @@ impl ElementData { return RestyleKind::MatchAndCascade; } - debug_assert!(self.restyle.is_some()); - let restyle_data = self.restyle.as_ref().unwrap(); - - let hint = restyle_data.hint; + let hint = self.restyle.hint; if shared_context.traversal_flags.for_animation_only() { // return either CascadeWithReplacements or CascadeOnly in case of // animation-only restyle. @@ -488,7 +545,8 @@ impl ElementData { return RestyleKind::CascadeWithReplacements(hint & RestyleHint::replacements()); } - debug_assert!(hint.has_recascade_self(), "We definitely need to do something!"); + debug_assert!(hint.has_recascade_self(), + "We definitely need to do something!"); return RestyleKind::CascadeOnly; } @@ -513,13 +571,6 @@ impl ElementData { self.styles.as_mut().expect("Calling styles_mut() on unstyled ElementData") } - /// Borrows both styles and restyle mutably at the same time. - pub fn styles_and_restyle_mut(&mut self) -> (&mut ElementStyles, - Option<&mut RestyleData>) { - (self.styles.as_mut().unwrap(), - self.restyle.as_mut().map(|r| &mut **r)) - } - /// Sets the computed element styles. pub fn set_styles(&mut self, styles: ElementStyles) { self.styles = Some(styles); @@ -558,47 +609,9 @@ impl ElementData { important_rules != other_important_rules } - /// Returns true if the Element has a RestyleData. - pub fn has_restyle(&self) -> bool { - self.restyle.is_some() - } - - /// Drops any RestyleData. - pub fn clear_restyle(&mut self) { - self.restyle = None; - } - - /// Creates a RestyleData if one doesn't exist. - /// - /// Asserts that the Element has been styled. - pub fn ensure_restyle(&mut self) -> &mut RestyleData { - debug_assert!(self.styles.is_some(), "restyling unstyled element"); - if self.restyle.is_none() { - self.restyle = Some(Box::new(RestyleData::default())); - } - self.restyle.as_mut().unwrap() - } - - /// Gets a reference to the restyle data, if any. - pub fn get_restyle(&self) -> Option<&RestyleData> { - self.restyle.as_ref().map(|r| &**r) - } - - /// Gets a reference to the restyle data. Panic if the element does not - /// have restyle data. - pub fn restyle(&self) -> &RestyleData { - self.get_restyle().expect("Calling restyle without RestyleData") - } - - /// Gets a mutable reference to the restyle data, if any. - pub fn get_restyle_mut(&mut self) -> Option<&mut RestyleData> { - self.restyle.as_mut().map(|r| &mut **r) - } - - /// Gets a mutable reference to the restyle data. Panic if the element does - /// not have restyle data. - pub fn restyle_mut(&mut self) -> &mut RestyleData { - self.get_restyle_mut().expect("Calling restyle_mut without RestyleData") + /// Drops any restyle state from the element. + pub fn clear_restyle_state(&mut self) { + self.restyle.clear(); } /// Returns SMIL overriden value if exists. diff --git a/components/style/dom.rs b/components/style/dom.rs index 795eb51c247..769cedfda28 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -567,8 +567,7 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone + Some(d) => d, None => return false, }; - return data.get_restyle() - .map_or(false, |r| r.hint.has_animation_hint()); + return data.restyle.hint.has_animation_hint() } /// Gets declarations from XBL bindings from the element. Only gecko element could have this. diff --git a/components/style/invalidation/element/invalidator.rs b/components/style/invalidation/element/invalidator.rs index df92a4f3a8d..ed759076e23 100644 --- a/components/style/invalidation/element/invalidator.rs +++ b/components/style/invalidation/element/invalidator.rs @@ -114,7 +114,7 @@ impl<'a, 'b: 'a, E> TreeStyleInvalidator<'a, 'b, E> // We can't just return here because there may also be attribute // changes as well that imply additional hints. let mut data = self.data.as_mut().unwrap(); - data.ensure_restyle().hint.insert(RestyleHint::restyle_subtree().into()); + data.restyle.hint.insert(RestyleHint::restyle_subtree()); } let mut classes_removed = SmallVec::<[Atom; 8]>::new(); @@ -211,7 +211,7 @@ impl<'a, 'b: 'a, E> TreeStyleInvalidator<'a, 'b, E> if invalidated_self { if let Some(ref mut data) = self.data { - data.ensure_restyle().hint.insert(RESTYLE_SELF.into()); + data.restyle.hint.insert(RESTYLE_SELF); } } @@ -287,10 +287,8 @@ impl<'a, 'b: 'a, E> TreeStyleInvalidator<'a, 'b, E> match self.data { None => return false, Some(ref data) => { - if let Some(restyle) = data.get_restyle() { - if restyle.hint.contains_subtree() { - return false; - } + if data.restyle.hint.contains_subtree() { + return false; } } } @@ -494,7 +492,7 @@ impl<'a, 'b: 'a, E> TreeStyleInvalidator<'a, 'b, E> if invalidated_self { if let Some(ref mut data) = self.data { - data.ensure_restyle().hint.insert(RESTYLE_SELF.into()); + data.restyle.hint.insert(RESTYLE_SELF); } } diff --git a/components/style/invalidation/stylesheets.rs b/components/style/invalidation/stylesheets.rs index c72a733467c..b28ae6fed87 100644 --- a/components/style/invalidation/stylesheets.rs +++ b/components/style/invalidation/stylesheets.rs @@ -134,7 +134,7 @@ impl StylesheetInvalidationSet { if self.fully_invalid { debug!("process_invalidations: fully_invalid({:?})", element); - data.ensure_restyle().hint.insert(RestyleHint::restyle_subtree()); + data.restyle.hint.insert(RestyleHint::restyle_subtree()); return true; } } @@ -165,19 +165,17 @@ impl StylesheetInvalidationSet { return false; } - if let Some(ref r) = data.get_restyle() { - if r.hint.contains_subtree() { - debug!("process_invalidations_in_subtree: {:?} was already invalid", - element); - return false; - } + if data.restyle.hint.contains_subtree() { + debug!("process_invalidations_in_subtree: {:?} was already invalid", + element); + return false; } for scope in &self.invalid_scopes { if scope.matches(element) { debug!("process_invalidations_in_subtree: {:?} matched {:?}", element, scope); - data.ensure_restyle().hint.insert(RestyleHint::restyle_subtree()); + data.restyle.hint.insert(RestyleHint::restyle_subtree()); return true; } } diff --git a/components/style/matching.rs b/components/style/matching.rs index 320546147bf..a1cde2f85d5 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -707,8 +707,7 @@ trait PrivateMatchMethods: TElement { // for followup work to make the optimization here more optimal by considering // each bit individually. let skip_applying_damage = - restyle.damage.contains(RestyleDamage::reconstruct()) || - restyle.reconstructed_ancestor; + restyle.reconstructed_self_or_ancestor(); let difference = self.compute_style_difference(&old_values, &new_values, @@ -1187,12 +1186,10 @@ pub trait MatchMethods : TElement { } }); - if matches_different_pseudos { - if let Some(r) = data.get_restyle_mut() { - // Any changes to the matched pseudo-elements trigger - // reconstruction. - r.damage |= RestyleDamage::reconstruct(); - } + if matches_different_pseudos && data.restyle.is_restyle() { + // Any changes to the matched pseudo-elements trigger + // reconstruction. + data.restyle.damage |= RestyleDamage::reconstruct(); } } @@ -1257,16 +1254,11 @@ pub trait MatchMethods : TElement { /// Computes and applies restyle damage. fn accumulate_damage(&self, shared_context: &SharedStyleContext, - restyle: Option<&mut RestyleData>, + restyle: &mut RestyleData, old_values: Option<&ComputedValues>, new_values: &Arc<ComputedValues>, pseudo: Option<&PseudoElement>) -> ChildCascadeRequirement { - let restyle = match restyle { - Some(r) => r, - None => return ChildCascadeRequirement::MustCascadeChildren, - }; - let old_values = match old_values { Some(v) => v, None => return ChildCascadeRequirement::MustCascadeChildren, diff --git a/components/style/sharing/mod.rs b/components/style/sharing/mod.rs index 5971eb34367..a1cedbd4b73 100644 --- a/components/style/sharing/mod.rs +++ b/components/style/sharing/mod.rs @@ -377,38 +377,38 @@ impl<E: TElement> StyleSharingTarget<E> { // We used to have pseudos (because we had styles). // Check for damage from the set of pseudos changing or // pseudos being restyled. - let (styles, restyle_data) = data.styles_and_restyle_mut(); - if let Some(restyle_data) = restyle_data { - let old_pseudos = &styles.pseudos; - let new_pseudos = &shared_style.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).unwrap().values.as_ref().map(|v| &**v); - let new_values = - new_pseudos.get(&pseudo).unwrap().values(); - self.element.accumulate_damage( - &shared_context, - Some(restyle_data), - old_values, - new_values, - Some(&pseudo) - ); - } + let (styles, mut restyle_data) = data.styles_and_restyle_mut(); + let old_pseudos = &styles.pseudos; + let new_pseudos = &shared_style.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).unwrap().values.as_ref().map(|v| &**v); + let new_values = + new_pseudos.get(&pseudo).unwrap().values(); + self.element.accumulate_damage( + &shared_context, + restyle_data, + old_values, + new_values, + Some(&pseudo) + ); } } } - let old_values = data.get_styles_mut() - .and_then(|s| s.primary.values.take()); + let old_values = + data.get_styles_mut().and_then(|s| s.primary.values.take()); + self.element.accumulate_damage( &shared_context, - data.get_restyle_mut(), + &mut data.restyle, old_values.as_ref().map(|v| &**v), shared_style.primary.values(), None @@ -597,9 +597,6 @@ impl<E: TElement> StyleSharingCandidateCache<E> { match sharing_result { Ok(shared_style) => { // Yay, cache hit. Share the style. - - debug_assert_eq!(data.has_styles(), data.has_restyle()); - let child_cascade_requirement = target.accumulate_damage_when_sharing(shared_context, &shared_style, diff --git a/components/style/traversal.rs b/components/style/traversal.rs index 9f085cfe374..004c2485afd 100644 --- a/components/style/traversal.rs +++ b/components/style/traversal.rs @@ -10,7 +10,6 @@ use data::{ElementData, ElementStyles}; use dom::{DirtyDescendants, NodeInfo, OpaqueNode, TElement, TNode}; use invalidation::element::restyle_hints::{RECASCADE_SELF, RECASCADE_DESCENDANTS, RestyleHint}; use matching::{ChildCascadeRequirement, MatchMethods}; -use selector_parser::RestyleDamage; use sharing::{StyleSharingBehavior, StyleSharingTarget}; #[cfg(feature = "servo")] use servo_config::opts; use smallvec::SmallVec; @@ -296,10 +295,8 @@ pub trait DomTraversal<E: TElement> : Sync { if el.is_native_anonymous() { if let Some(parent) = el.traversal_parent() { let parent_data = parent.borrow_data().unwrap(); - let going_to_reframe = parent_data.get_restyle().map_or(false, |r| { - r.reconstructed_ancestor || - r.damage.contains(RestyleDamage::reconstruct()) - }); + let going_to_reframe = + parent_data.restyle.reconstructed_self_or_ancestor(); let mut is_before_or_after_pseudo = false; if let Some(pseudo) = el.implemented_pseudo_element() { @@ -337,9 +334,8 @@ pub trait DomTraversal<E: TElement> : Sync { Some(d) => d, None => return false, }; - return data.get_restyle() - .map_or(false, |r| r.hint.has_animation_hint() || - r.hint.has_recascade_self()); + return data.restyle.hint.has_animation_hint() || + data.restyle.hint.has_recascade_self(); } // If the dirty descendants bit is set, we need to traverse no @@ -360,18 +356,15 @@ pub trait DomTraversal<E: TElement> : Sync { return true; } - // Check the restyle data. - if let Some(r) = data.get_restyle() { - // If we have a restyle hint or need to recascade, we need to - // visit the element. - // - // Note that this is different than checking has_current_styles(), - // since that can return true even if we have a restyle hint - // indicating that the element's descendants (but not necessarily - // the element) need restyling. - if !r.hint.is_empty() { - return true; - } + // If we have a restyle hint or need to recascade, we need to + // visit the element. + // + // Note that this is different than checking has_current_styles(), + // since that can return true even if we have a restyle hint + // indicating that the element's descendants (but not necessarily + // the element) need restyling. + if !data.restyle.hint.is_empty() { + return true; } // Servo uses the post-order traversal for flow construction, so @@ -381,7 +374,7 @@ pub trait DomTraversal<E: TElement> : Sync { // We also need to traverse nodes with explicit damage and no other // restyle data, so that this damage can be cleared. if (cfg!(feature = "servo") || traversal_flags.for_reconstruct()) && - data.get_restyle().map_or(false, |r| !r.damage.is_empty()) { + !data.restyle.damage.is_empty() { return true; } @@ -690,20 +683,17 @@ pub fn recalc_style_at<E, D>(traversal: &D, // Now that matching and cascading is done, clear the bits corresponding to // those operations and compute the propagated restyle hint. - let mut propagated_hint = match data.get_restyle_mut() { - None => RestyleHint::empty(), - Some(r) => { - debug_assert!(context.shared.traversal_flags.for_animation_only() || - !r.hint.has_animation_hint(), - "animation restyle hint should be handled during \ - animation-only restyles"); - r.hint.propagate(&context.shared.traversal_flags) - }, + let mut propagated_hint = { + debug_assert!(context.shared.traversal_flags.for_animation_only() || + !data.restyle.hint.has_animation_hint(), + "animation restyle hint should be handled during \ + animation-only restyles"); + data.restyle.hint.propagate(&context.shared.traversal_flags) }; // FIXME(bholley): Need to handle explicitly-inherited reset properties // somewhere. - propagated_hint.insert(hint.into()); + propagated_hint.insert(hint); trace!("propagated_hint={:?} \ is_display_none={:?}, implementing_pseudo={:?}", @@ -730,10 +720,9 @@ pub fn recalc_style_at<E, D>(traversal: &D, DontLog) && (has_dirty_descendants_for_this_restyle || !propagated_hint.is_empty()) { - let reconstructed_ancestor = data.get_restyle().map_or(false, |r| { - r.reconstructed_ancestor || - r.damage.contains(RestyleDamage::reconstruct()) - }); + let reconstructed_ancestor = + data.restyle.reconstructed_self_or_ancestor(); + preprocess_children::<E, D>( context, element, @@ -746,7 +735,7 @@ pub fn recalc_style_at<E, D>(traversal: &D, // data here, since we won't need to perform a post-traversal to pick up // any change hints. if context.shared.traversal_flags.for_reconstruct() { - data.clear_restyle(); + data.clear_restyle_state(); } if context.shared.traversal_flags.for_animation_only() { @@ -792,6 +781,10 @@ fn compute_style<E, D>(_traversal: &D, debug!("compute_style: {:?} (kind={:?})", element, kind); + if data.has_styles() { + data.restyle.set_restyled(); + } + match kind { MatchAndCascade => { debug_assert!(!context.shared.traversal_flags.for_animation_only(), @@ -870,31 +863,24 @@ where continue; } - // Handle element snapshots and invalidation of descendants and siblings - // as needed. - // - // NB: This will be a no-op if there's no restyle data and no snapshot. - child_data.invalidate_style_if_needed(child, &context.shared); - trace!(" > {:?} -> {:?} + {:?}, pseudo: {:?}", child, - child_data.get_restyle().map(|r| &r.hint), + child_data.restyle.hint, propagated_hint, child.implemented_pseudo_element()); - // If the child doesn't have pre-existing RestyleData and we don't have - // any reason to create one, avoid the useless allocation and move on to - // the next child. - if !reconstructed_ancestor && propagated_hint.is_empty() && !child_data.has_restyle() { - continue; - } - - let mut restyle_data = child_data.ensure_restyle(); - // Propagate the parent restyle hint, that may make us restyle the whole // subtree. - restyle_data.reconstructed_ancestor = reconstructed_ancestor; - restyle_data.hint.insert(propagated_hint); + if reconstructed_ancestor { + child_data.restyle.set_reconstructed_ancestor(); + } + child_data.restyle.hint.insert(propagated_hint); + + // Handle element snapshots and invalidation of descendants and siblings + // as needed. + // + // NB: This will be a no-op if there's no snapshot. + child_data.invalidate_style_if_needed(child, &context.shared); } } diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 19950db47cf..9d8f068be35 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -301,7 +301,7 @@ pub extern "C" fn Servo_TraverseSubtree(root: RawGeckoElementBorrowed, return false; } - element.has_dirty_descendants() || element.borrow_data().unwrap().has_restyle() + element.has_dirty_descendants() || element.borrow_data().unwrap().restyle.contains_restyle_data() } #[no_mangle] @@ -2461,7 +2461,7 @@ unsafe fn maybe_restyle<'a>(data: &'a mut AtomicRefMut<ElementData>, bindings::Gecko_SetOwnerDocumentNeedsStyleFlush(element.0); // Ensure and return the RestyleData. - Some(data.ensure_restyle()) + Some(&mut data.restyle) } #[no_mangle] @@ -2518,13 +2518,16 @@ pub extern "C" fn Servo_NoteExplicitHints(element: RawGeckoElementBorrowed, pub extern "C" fn Servo_TakeChangeHint(element: RawGeckoElementBorrowed) -> nsChangeHint { let element = GeckoElement(element); - let damage = if let Some(mut data) = element.mutate_data() { - let d = data.get_restyle().map_or(GeckoRestyleDamage::empty(), |r| r.damage); - data.clear_restyle(); - d - } else { - warn!("Trying to get change hint from unstyled element"); - GeckoRestyleDamage::empty() + let damage = match element.mutate_data() { + Some(mut data) => { + let damage = data.restyle.damage; + data.clear_restyle_state(); + damage + } + None => { + warn!("Trying to get change hint from unstyled element"); + GeckoRestyleDamage::empty() + } }; debug!("Servo_TakeChangeHint: {:?}, damage={:?}", element, damage); diff --git a/tests/unit/stylo/size_of.rs b/tests/unit/stylo/size_of.rs index d863cb816a8..633180d3289 100644 --- a/tests/unit/stylo/size_of.rs +++ b/tests/unit/stylo/size_of.rs @@ -7,7 +7,7 @@ use servo_arc::Arc; use std::mem::{size_of, align_of}; use style; use style::applicable_declarations::ApplicableDeclarationBlock; -use style::data::{ComputedStyle, ElementData, ElementStyles}; +use style::data::{ComputedStyle, ElementData, ElementStyles, RestyleData}; use style::gecko::selector_parser as real; use style::properties::ComputedValues; use style::rule_tree::{RuleNode, StrongRuleNode}; @@ -34,6 +34,7 @@ size_of_test!(test_size_of_option_rule_node, Option<StrongRuleNode>, 8); size_of_test!(test_size_of_computed_style, ComputedStyle, 32); size_of_test!(test_size_of_element_styles, ElementStyles, 48); size_of_test!(test_size_of_element_data, ElementData, 56); +size_of_test!(test_size_of_restyle_data, RestyleData, 8); size_of_test!(test_size_of_property_declaration, style::properties::PropertyDeclaration, 32); |