Eliminate RestyleData entirely.

Without this change, the previous commit increases the size of ElementData.

MozReview-Commit-ID: 87BZuXINiT9
This commit is contained in:
Bobby Holley 2017-09-11 17:44:46 -07:00
parent 61cad869d9
commit 50cee3e133
12 changed files with 66 additions and 94 deletions

View file

@ -77,7 +77,7 @@ impl<'a, E> DomTraversal<E> for RecalcStyleAndConstructFlows<'a>
// (1) They child doesn't yet have layout data (preorder traversal initializes it).
// (2) The parent element has restyle damage (so the text flow also needs fixup).
node.get_raw_data().is_none() ||
parent_data.restyle.damage != RestyleDamage::empty()
parent_data.damage != RestyleDamage::empty()
}
fn shared_context(&self) -> &SharedStyleContext {

View file

@ -146,7 +146,7 @@ impl<T: ThreadSafeLayoutNode> ThreadSafeLayoutNodeHelpers for T {
// because that's what the code expects.
RestyleDamage::rebuild_and_reflow()
} else {
data.style_data.element_data.borrow().restyle.damage
data.style_data.element_data.borrow().damage
}
};

View file

@ -1168,7 +1168,7 @@ impl LayoutThread {
}
if had_used_viewport_units {
if let Some(mut data) = element.mutate_data() {
data.restyle.hint.insert(RestyleHint::recascade_subtree());
data.hint.insert(RestyleHint::recascade_subtree());
}
}
}
@ -1250,9 +1250,9 @@ impl LayoutThread {
let mut style_data = style_data.borrow_mut();
// Stash the data on the element for processing by the style system.
style_data.restyle.hint.insert(restyle.hint.into());
style_data.restyle.damage = restyle.damage;
debug!("Noting restyle for {:?}: {:?}", el, style_data.restyle);
style_data.hint.insert(restyle.hint.into());
style_data.damage = restyle.damage;
debug!("Noting restyle for {:?}: {:?}", el, style_data);
}
// Create a layout context for use throughout the following passes.

View file

@ -38,35 +38,6 @@ bitflags! {
}
}
/// 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)]
pub struct RestyleData {
/// The restyle damage, indicating what kind of layout changes are required
/// afte restyling.
pub damage: RestyleDamage,
/// The restyle hint, which indicates whether selectors need to be rematched
/// for this element, its children, and its descendants.
pub hint: RestyleHint,
}
impl Default for RestyleData {
fn default() -> Self {
Self::new()
}
}
impl RestyleData {
fn new() -> Self {
Self {
damage: RestyleDamage::empty(),
hint: RestyleHint::empty(),
}
}
}
/// A lazily-allocated list of styles for eagerly-cascaded pseudo-elements.
///
/// We use an Arc so that sharing these styles via the style sharing cache does
@ -220,8 +191,13 @@ pub struct ElementData {
/// The styles for the element and its pseudo-elements.
pub styles: ElementStyles,
/// Restyle state.
pub restyle: RestyleData,
/// The restyle damage, indicating what kind of layout changes are required
/// afte restyling.
pub damage: RestyleDamage,
/// The restyle hint, which indicates whether selectors need to be rematched
/// for this element, its children, and its descendants.
pub hint: RestyleHint,
/// Flags.
flags: ElementDataFlags,
@ -302,19 +278,18 @@ impl ElementData {
return RestyleKind::MatchAndCascade;
}
let hint = self.restyle.hint;
if hint.match_self() {
if self.hint.match_self() {
return RestyleKind::MatchAndCascade;
}
if hint.has_replacements() {
debug_assert!(!hint.has_animation_hint(),
if self.hint.has_replacements() {
debug_assert!(!self.hint.has_animation_hint(),
"Animation only restyle hint should have already processed");
return RestyleKind::CascadeWithReplacements(hint & RestyleHint::replacements());
return RestyleKind::CascadeWithReplacements(self.hint & RestyleHint::replacements());
}
debug_assert!(hint.has_recascade_self(),
"We definitely need to do something: {:?}!", hint);
debug_assert!(self.hint.has_recascade_self(),
"We definitely need to do something: {:?}!", self.hint);
return RestyleKind::CascadeOnly;
}
@ -331,9 +306,8 @@ impl ElementData {
// return either CascadeWithReplacements or CascadeOnly in case of
// animation-only restyle. I.e. animation-only restyle never does
// selector matching.
let hint = self.restyle.hint;
if hint.has_animation_hint() {
return RestyleKind::CascadeWithReplacements(hint & RestyleHint::for_animations());
if self.hint.has_animation_hint() {
return RestyleKind::CascadeWithReplacements(self.hint & RestyleHint::for_animations());
}
return RestyleKind::CascadeOnly;
@ -365,14 +339,14 @@ impl ElementData {
/// the hint is empty and call clear_flags_and_damage().
#[inline]
pub fn clear_restyle_state(&mut self) {
self.restyle.hint = RestyleHint::empty();
self.hint = RestyleHint::empty();
self.clear_restyle_flags_and_damage();
}
/// Drops restyle flags and damage from the element.
#[inline]
pub fn clear_restyle_flags_and_damage(&mut self) {
self.restyle.damage = RestyleDamage::empty();
self.damage = RestyleDamage::empty();
self.flags.remove(WAS_RESTYLED | ANCESTOR_WAS_RECONSTRUCTED)
}
@ -384,7 +358,7 @@ impl ElementData {
/// Returns whether this element is going to be reconstructed.
pub fn reconstructed_self(&self) -> bool {
self.restyle.damage.contains(RestyleDamage::reconstruct())
self.damage.contains(RestyleDamage::reconstruct())
}
/// Returns whether any ancestor of this element is going to be
@ -431,7 +405,7 @@ impl ElementData {
/// Returns whether this element has been part of a restyle.
#[inline]
pub fn contains_restyle_data(&self) -> bool {
self.is_restyle() || !self.restyle.hint.is_empty() || !self.restyle.damage.is_empty()
self.is_restyle() || !self.hint.is_empty() || !self.damage.is_empty()
}
/// If an ancestor is already getting reconstructed by Gecko's top-down

View file

@ -436,7 +436,7 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone +
// animation in a SequentialTask) is processed after the normal
// traversal in that we had elements that handled snapshot.
return data.has_styles() &&
!data.restyle.hint.has_animation_hint_or_recascade();
!data.hint.has_animation_hint_or_recascade();
}
if traversal_flags.contains(traversal_flags::UnstyledOnly) {
@ -448,7 +448,7 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone +
return false;
}
data.has_styles() && !data.restyle.hint.has_non_animation_invalidations()
data.has_styles() && !data.hint.has_non_animation_invalidations()
}
/// Returns whether the element's styles are up-to-date after traversal
@ -470,7 +470,7 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone +
//
// https://bugzilla.mozilla.org/show_bug.cgi?id=1389675 tracks fixing
// this.
!data.restyle.hint.has_non_animation_invalidations()
!data.hint.has_non_animation_invalidations()
}
/// Flag that this element has a descendant for style processing.
@ -620,7 +620,7 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone +
Some(d) => d,
None => return false,
};
return data.restyle.hint.has_animation_hint()
return data.hint.has_animation_hint()
}
/// Returns the anonymous content for the current element's XBL binding,

View file

@ -19,7 +19,7 @@ use app_units::Au;
use applicable_declarations::ApplicableDeclarationBlock;
use atomic_refcell::{AtomicRefCell, AtomicRefMut};
use context::{QuirksMode, SharedStyleContext, PostAnimationTasks, UpdateAnimationsTasks};
use data::{ElementData, RestyleData};
use data::ElementData;
use dom::{LayoutIterator, NodeInfo, TElement, TNode, UnsafeNode};
use dom::{OpaqueNode, PresentationalHintsSynthesizer};
use element_state::{ElementState, DocumentState, NS_DOCUMENT_STATE_WINDOW_INACTIVE};
@ -498,12 +498,12 @@ impl<'le> GeckoElement<'le> {
/// Returns true if a traversal starting from this element requires a post-traversal.
pub fn needs_post_traversal(&self) -> bool {
debug!("needs_post_traversal: dd={}, aodd={}, lfcd={}, lfc={}, restyle={:?}",
debug!("needs_post_traversal: dd={}, aodd={}, lfcd={}, lfc={}, data={:?}",
self.has_dirty_descendants(),
self.has_animation_only_dirty_descendants(),
self.descendants_need_frames(),
self.needs_frame(),
self.borrow_data().unwrap().restyle);
self.borrow_data().unwrap());
let has_flag =
self.flags() & (ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32 |
@ -688,10 +688,9 @@ impl<'le> GeckoElement<'le> {
/// Also this function schedules style flush.
unsafe fn maybe_restyle<'a>(&self,
data: &'a mut ElementData,
animation_only: bool) -> Option<&'a mut RestyleData> {
// Don't generate a useless RestyleData if the element hasn't been styled.
animation_only: bool) -> bool {
if !data.has_styles() {
return None;
return false;
}
// Propagate the bit up the chain.
@ -702,7 +701,7 @@ impl<'le> GeckoElement<'le> {
}
// Ensure and return the RestyleData.
Some(&mut data.restyle)
true
}
/// Set restyle and change hints to the element data.
@ -722,12 +721,12 @@ impl<'le> GeckoElement<'le> {
"Animation restyle hints should not appear with non-animation restyle hints");
let mut maybe_data = self.mutate_data();
let maybe_restyle_data = maybe_data.as_mut().and_then(|d| unsafe {
let should_restyle = maybe_data.as_mut().map_or(false, |d| unsafe {
self.maybe_restyle(d, restyle_hint.has_animation_hint())
});
if let Some(restyle_data) = maybe_restyle_data {
restyle_data.hint.insert(restyle_hint.into());
restyle_data.damage |= damage;
if should_restyle {
maybe_data.as_mut().unwrap().hint.insert(restyle_hint.into());
maybe_data.as_mut().unwrap().damage |= damage;
} else {
debug!("(Element not styled, discarding hints)");
}

View file

@ -209,7 +209,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 data = self.data.as_mut().unwrap();
data.restyle.hint.insert(RestyleHint::restyle_subtree());
data.hint.insert(RestyleHint::restyle_subtree());
}
let mut classes_removed = SmallVec::<[Atom; 8]>::new();
@ -287,7 +287,7 @@ impl<'a, 'b: 'a, E> TreeStyleInvalidator<'a, 'b, E>
if invalidated_self {
if let Some(ref mut data) = self.data {
data.restyle.hint.insert(RESTYLE_SELF);
data.hint.insert(RESTYLE_SELF);
}
}
@ -499,7 +499,7 @@ impl<'a, 'b: 'a, E> TreeStyleInvalidator<'a, 'b, E>
Some(ref data) => {
// FIXME(emilio): Only needs to check RESTYLE_DESCENDANTS,
// really.
if data.restyle.hint.contains_subtree() {
if data.hint.contains_subtree() {
return false;
}
}
@ -507,7 +507,7 @@ impl<'a, 'b: 'a, E> TreeStyleInvalidator<'a, 'b, E>
if let Some(checker) = self.stack_limit_checker {
if checker.limit_exceeded() {
self.data.as_mut().unwrap().restyle.hint.insert(RESTYLE_DESCENDANTS);
self.data.as_mut().unwrap().hint.insert(RESTYLE_DESCENDANTS);
return true;
}
}
@ -799,7 +799,7 @@ impl<'a, 'b: 'a, E> TreeStyleInvalidator<'a, 'b, E>
if invalidated_self {
if let Some(ref mut data) = self.data {
data.restyle.hint.insert(RESTYLE_SELF);
data.hint.insert(RESTYLE_SELF);
}
}

View file

@ -148,7 +148,7 @@ impl StylesheetInvalidationSet {
if self.fully_invalid {
debug!("process_invalidations: fully_invalid({:?})",
element);
data.restyle.hint.insert(RestyleHint::restyle_subtree());
data.hint.insert(RestyleHint::restyle_subtree());
return true;
}
}
@ -179,7 +179,7 @@ impl StylesheetInvalidationSet {
return false;
}
if data.restyle.hint.contains_subtree() {
if data.hint.contains_subtree() {
debug!("process_invalidations_in_subtree: {:?} was already invalid",
element);
return false;
@ -189,7 +189,7 @@ impl StylesheetInvalidationSet {
if scope.matches(element) {
debug!("process_invalidations_in_subtree: {:?} matched {:?}",
element, scope);
data.restyle.hint.insert(RestyleHint::restyle_subtree());
data.hint.insert(RestyleHint::restyle_subtree());
return true;
}
}

View file

@ -8,7 +8,7 @@
#![deny(missing_docs)]
use context::{ElementCascadeInputs, SelectorFlagsMap, SharedStyleContext, StyleContext};
use data::{ElementData, ElementStyles, RestyleData};
use data::{ElementData, ElementStyles};
use dom::TElement;
use invalidation::element::restyle_hints::{RESTYLE_CSS_ANIMATIONS, RESTYLE_CSS_TRANSITIONS};
use invalidation::element::restyle_hints::{RESTYLE_SMIL, RESTYLE_STYLE_ATTRIBUTE};
@ -353,7 +353,7 @@ trait PrivateMatchMethods: TElement {
&self,
shared_context: &SharedStyleContext,
skip_applying_damage: bool,
restyle: &mut RestyleData,
damage: &mut RestyleDamage,
old_values: &ComputedValues,
new_values: &ComputedValues,
pseudo: Option<&PseudoElement>,
@ -370,7 +370,7 @@ trait PrivateMatchMethods: TElement {
self.compute_style_difference(old_values, new_values, pseudo);
if !skip_applying_damage {
restyle.damage |= difference.damage;
*damage |= difference.damage;
}
debug!(" > style difference: {:?}", difference);
@ -543,7 +543,7 @@ pub trait MatchMethods : TElement {
context,
&mut data.styles.primary,
&mut new_styles.primary.as_mut().unwrap(),
data.restyle.hint,
data.hint,
important_rules_changed,
);
@ -607,7 +607,7 @@ pub trait MatchMethods : TElement {
self.accumulate_damage_for(
context.shared,
data.skip_applying_damage(),
&mut data.restyle,
&mut data.damage,
&old_primary_style,
new_primary_style,
None,
@ -629,7 +629,7 @@ pub trait MatchMethods : TElement {
self.accumulate_damage_for(
context.shared,
data.skip_applying_damage(),
&mut data.restyle,
&mut data.damage,
old,
new,
Some(&PseudoElement::from_eager_index(i)),
@ -649,7 +649,7 @@ pub trait MatchMethods : TElement {
old.as_ref().map_or(false,
|s| pseudo.should_exist(s));
if new_pseudo_should_exist != old_pseudo_should_exist {
data.restyle.damage |= RestyleDamage::reconstruct();
data.damage |= RestyleDamage::reconstruct();
return cascade_requirement;
}
}

View file

@ -214,7 +214,7 @@ pub trait DomTraversal<E: TElement> : Sync {
if traversal_flags.for_animation_only() {
return data.map_or(false, |d| d.has_styles()) &&
(el.has_animation_only_dirty_descendants() ||
data.as_ref().unwrap().restyle.hint.has_animation_hint_or_recascade());
data.as_ref().unwrap().hint.has_animation_hint_or_recascade());
}
// Non-incremental layout visits every node.
@ -283,14 +283,14 @@ pub trait DomTraversal<E: TElement> : Sync {
// 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() {
if !data.hint.is_empty() {
return true;
}
// Servo uses the post-order traversal for flow construction, so we need
// to traverse any element with damage so that we can perform fixup /
// reconstruction on our way back up the tree.
if cfg!(feature = "servo") && !data.restyle.damage.is_empty() {
if cfg!(feature = "servo") && !data.damage.is_empty() {
return true;
}
@ -510,10 +510,10 @@ where
RestyleHint::empty()
} else {
debug_assert!(flags.for_animation_only() ||
!data.restyle.hint.has_animation_hint(),
!data.hint.has_animation_hint(),
"animation restyle hint should be handled during \
animation-only restyles");
data.restyle.hint.propagate(&flags)
data.hint.propagate(&flags)
};
trace!("propagated_hint={:?}, cascade_requirement={:?}, \
@ -804,7 +804,7 @@ where
let mut child_data = child_data.as_mut().map(|d| &mut **d);
trace!(" > {:?} -> {:?} + {:?}, pseudo: {:?}",
child,
child_data.as_ref().map(|d| d.restyle.hint),
child_data.as_ref().map(|d| d.hint),
propagated_hint,
child.implemented_pseudo_element());
@ -830,7 +830,7 @@ where
}
}
child_data.restyle.hint.insert(child_hint);
child_data.hint.insert(child_hint);
// Handle element snapshots and invalidation of descendants and siblings
// as needed.

View file

@ -292,12 +292,12 @@ pub extern "C" fn Servo_TraverseSubtree(
traversal_flags,
unsafe { &*snapshots });
debug!("Servo_TraverseSubtree complete (dd={}, aodd={}, lfcd={}, lfc={}, restyle={:?})",
debug!("Servo_TraverseSubtree complete (dd={}, aodd={}, lfcd={}, lfc={}, data={:?})",
element.has_dirty_descendants(),
element.has_animation_only_dirty_descendants(),
element.descendants_need_frames(),
element.needs_frame(),
element.borrow_data().unwrap().restyle);
element.borrow_data().unwrap());
element.needs_post_traversal()
}
@ -2982,7 +2982,7 @@ pub extern "C" fn Servo_TakeChangeHint(element: RawGeckoElementBorrowed,
Some(mut data) => {
*was_restyled = data.is_restyle();
let damage = data.restyle.damage;
let damage = data.damage;
data.clear_restyle_state();
damage
}
@ -3859,7 +3859,7 @@ pub extern "C" fn Servo_HasPendingRestyleAncestor(element: RawGeckoElementBorrow
let mut element = Some(GeckoElement(element));
while let Some(e) = element {
if let Some(data) = e.borrow_data() {
if !data.restyle.hint.is_empty() {
if !data.hint.is_empty() {
return true;
}
}

View file

@ -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::{ElementData, ElementStyles, RestyleData};
use style::data::{ElementData, ElementStyles};
use style::gecko::selector_parser as real;
use style::properties::ComputedValues;
use style::rule_tree::{RuleNode, StrongRuleNode};
@ -38,7 +38,6 @@ size_of_test!(test_size_of_option_arc_cv, Option<Arc<ComputedValues>>, 8);
size_of_test!(test_size_of_option_rule_node, Option<StrongRuleNode>, 8);
size_of_test!(test_size_of_element_styles, ElementStyles, 16);
size_of_test!(test_size_of_restyle_data, RestyleData, 8);
size_of_test!(test_size_of_element_data, ElementData, 24);
size_of_test!(test_size_of_property_declaration, style::properties::PropertyDeclaration, 32);