Skip to content

Commit

Permalink
Avoid recursion in clear_descendant_data.
Browse files Browse the repository at this point in the history
MozReview-Commit-ID: LeMhhcKoLr9
  • Loading branch information
bholley committed Aug 16, 2017
1 parent 99b4b7e commit 653107d
Showing 1 changed file with 21 additions and 17 deletions.
38 changes: 21 additions & 17 deletions components/style/traversal.rs
Expand Up @@ -509,7 +509,7 @@ where
if data.styles.is_display_none() {
debug!("{:?} style is display:none - clearing data from descendants.",
element);
clear_descendant_data(element)
unsafe { clear_descendant_data(element); }
}

// Inform any paint worklets of changed style, to speculatively
Expand Down Expand Up @@ -829,26 +829,30 @@ where
}
}

/// Clear style data for all the subtree under `el`.
pub fn clear_descendant_data<E>(el: E)
/// Clear style data for all the subtree under `root` (but not for root itself).
///
/// We use a list to avoid unbounded recursion, which we need to avoid in the
/// parallel traversal because the rayon stacks are small.
pub unsafe fn clear_descendant_data<E>(root: E)
where
E: TElement,
{
for kid in el.as_node().traversal_children() {
if let Some(kid) = kid.as_element() {
// We maintain an invariant that, if an element has data, all its
// ancestors have data as well.
//
// By consequence, any element without data has no descendants with
// data.
if kid.get_data().is_some() {
unsafe { kid.clear_data() };
clear_descendant_data(kid);
let mut parents = SmallVec::<[E; 32]>::new();
parents.push(root);
while let Some(p) = parents.pop() {
for kid in p.as_node().traversal_children() {
if let Some(kid) = kid.as_element() {
// We maintain an invariant that, if an element has data, all its
// ancestors have data as well.
//
// By consequence, any element without data has no descendants with
// data.
if kid.get_data().is_some() {
kid.clear_data();
parents.push(kid);
}
}
}
}

unsafe {
el.clear_descendants_bits();
p.clear_descendants_bits();
}
}

0 comments on commit 653107d

Please sign in to comment.