style: Avoid propagating the restyle flag all through the dom when a node gets dirty.

This puts us in pair with stylo.
This commit is contained in:
Emilio Cobos Álvarez 2016-07-22 19:33:53 -07:00
parent 96ea1a335c
commit d81fe27b11
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
4 changed files with 21 additions and 35 deletions

View file

@ -77,7 +77,9 @@ impl<'lc, N> DomTraversalContext<N> for RecalcStyleAndConstructFlows<'lc>
recalc_style_at(&self.context, self.root, node); recalc_style_at(&self.context, self.root, node);
} }
fn process_postorder(&self, node: N) { construct_flows_at(&self.context, self.root, node); } fn process_postorder(&self, node: N) {
construct_flows_at(&self.context, self.root, node);
}
} }
/// A bottom-up, parallelizable traversal. /// A bottom-up, parallelizable traversal.
@ -96,7 +98,7 @@ fn construct_flows_at<'a, N: LayoutNode>(context: &'a LayoutContext<'a>, root: O
// Always reconstruct if incremental layout is turned off. // Always reconstruct if incremental layout is turned off.
let nonincremental_layout = opts::get().nonincremental_layout; let nonincremental_layout = opts::get().nonincremental_layout;
if nonincremental_layout || node.has_dirty_descendants() { if nonincremental_layout || node.is_dirty() || node.has_dirty_descendants() {
let mut flow_constructor = FlowConstructor::new(context); let mut flow_constructor = FlowConstructor::new(context);
if nonincremental_layout || !flow_constructor.repair_if_possible(&tnode) { if nonincremental_layout || !flow_constructor.repair_if_possible(&tnode) {
flow_constructor.process(&tnode); flow_constructor.process(&tnode);

View file

@ -479,19 +479,7 @@ impl Node {
return return
} }
// 2. Dirty descendants. self.set_flag(IS_DIRTY, true);
fn dirty_subtree(node: &Node) {
// Stop if this subtree is already dirty.
if node.is_dirty() { return }
node.set_flag(IS_DIRTY | HAS_DIRTY_DESCENDANTS, true);
for kid in node.children() {
dirty_subtree(kid.r());
}
}
dirty_subtree(self);
// 4. Dirty ancestors. // 4. Dirty ancestors.
for ancestor in self.ancestors() { for ancestor in self.ancestors() {

View file

@ -153,10 +153,24 @@ pub trait DomTraversalContext<N: TNode> {
/// ///
/// Note that this is true unconditionally for servo, since it requires to /// Note that this is true unconditionally for servo, since it requires to
/// bubble the widths bottom-up for all the DOM. /// bubble the widths bottom-up for all the DOM.
fn should_process(&self, _node: N) -> bool { true } fn should_process(&self, node: N) -> bool {
node.is_dirty() || node.has_dirty_descendants()
}
/// Do an action over the child before pushing him to the work queue. /// Do an action over the child before pushing him to the work queue.
fn pre_process_child_hook(&self, _parent: N, _kid: N) {} ///
/// By default, propagate the IS_DIRTY flag down the tree.
#[allow(unsafe_code)]
fn pre_process_child_hook(&self, parent: N, kid: N) {
// NOTE: At this point is completely safe to modify either the parent or
// the child, since we have exclusive access to both of them.
if parent.is_dirty() {
unsafe {
kid.set_dirty(true);
parent.set_dirty_descendants(true);
}
}
}
} }
/// Calculates the style for a single node. /// Calculates the style for a single node.

View file

@ -6,7 +6,6 @@ use context::StandaloneStyleContext;
use std::mem; use std::mem;
use style::context::SharedStyleContext; use style::context::SharedStyleContext;
use style::dom::OpaqueNode; use style::dom::OpaqueNode;
use style::dom::TNode;
use style::traversal::{DomTraversalContext, recalc_style_at}; use style::traversal::{DomTraversalContext, recalc_style_at};
use wrapper::GeckoNode; use wrapper::GeckoNode;
@ -37,21 +36,4 @@ impl<'lc, 'ln> DomTraversalContext<GeckoNode<'ln>> for RecalcStyleOnly<'lc> {
} }
fn process_postorder(&self, _: GeckoNode<'ln>) {} fn process_postorder(&self, _: GeckoNode<'ln>) {}
/// In Gecko we use this traversal just for restyling, so we can stop once
/// we know there aren't more dirty nodes under ourselves.
fn should_process(&self, node: GeckoNode<'ln>) -> bool {
node.is_dirty() || node.has_dirty_descendants()
}
fn pre_process_child_hook(&self, parent: GeckoNode<'ln>, kid: GeckoNode<'ln>) {
// NOTE: At this point is completely safe to modify either the parent or
// the child, since we have exclusive access to them.
if parent.is_dirty() {
unsafe {
kid.set_dirty(true);
parent.set_dirty_descendants(true);
}
}
}
} }