Make Restyle tracking more granular.

The primary idea of this patch is to ditch the rigid enum of Previous/Current
styles, and replace it with a series of indicators for the various types of
work that needs to be performed (expanding snapshots, rematching, recascading,
and damage processing). This loses us a little bit of sanity checking (since
the up-to-date-ness of our style is no longer baked into the type system), but
gives us a lot more flexibility that we'll need going forward (especially when
we separate matching from cascading). We also eliminate get_styling_mode in
favor of a method on the traversal.

This patch does a few other things as ridealongs:
* Temporarily eliminates the handling for transfering ownership of styles to the
  frame. We'll need this again at some point, but for now it's causing too much
  complexity for a half-implemented feature.
* Ditches TRestyleDamage, which is no longer necessary post-crate-merge, and is
  a constant source of compilation failures from either needing to be imported
  or being unnecessarily imported (which varies between gecko and servo).
* Expands Snapshots for the traversal root, which was missing before.
* Fixes up the skip_root stuff to avoid visiting the skipped root.
* Unifies parallel traversal and avoids spawning for a single work item.
* Adds an explicit pre_traverse step do any pre-processing and determine whether
  we need to traverse at all.

MozReview-Commit-ID: IKhLAkAigXE
This commit is contained in:
Bobby Holley 2016-11-30 19:36:08 -08:00
parent 4cb3404c09
commit 80460cc549
27 changed files with 502 additions and 474 deletions

View file

@ -15,7 +15,7 @@ use std::mem;
use style::atomic_refcell::AtomicRefCell;
use style::context::{LocalStyleContext, SharedStyleContext, StyleContext};
use style::data::ElementData;
use style::dom::{StylingMode, TElement, TNode};
use style::dom::{TElement, TNode};
use style::selector_parser::RestyleDamage;
use style::servo::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT};
use style::traversal::{DomTraversalContext, recalc_style_at, remove_from_bloom_filter};
@ -73,14 +73,15 @@ impl<'lc, N> DomTraversalContext<N> for RecalcStyleAndConstructFlows<'lc>
}
}
fn process_preorder(&self, node: N, data: &mut PerLevelTraversalData) {
fn process_preorder(&self, node: N, traversal_data: &mut PerLevelTraversalData) {
// FIXME(pcwalton): Stop allocating here. Ideally this should just be
// done by the HTML parser.
node.initialize_data();
if !node.is_text_node() {
let el = node.as_element().unwrap();
recalc_style_at::<_, _, Self>(&self.context, data, el);
let mut data = el.mutate_data().unwrap();
recalc_style_at::<_, _, Self>(&self.context, traversal_data, el, &mut data);
}
}
@ -88,19 +89,13 @@ impl<'lc, N> DomTraversalContext<N> for RecalcStyleAndConstructFlows<'lc>
construct_flows_at(&self.context, self.root, node);
}
fn should_traverse_child(child: N) -> bool {
match child.as_element() {
// Elements should be traversed if they need styling or flow construction.
Some(el) => el.styling_mode() != StylingMode::Stop ||
el.as_node().to_threadsafe().restyle_damage() != RestyleDamage::empty(),
// Text nodes never need styling. However, there are two cases they may need
// flow construction:
// (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).
None => child.get_raw_data().is_none() ||
child.parent_node().unwrap().to_threadsafe().restyle_damage() != RestyleDamage::empty(),
}
fn text_node_needs_traversal(node: N) -> bool {
// Text nodes never need styling. However, there are two cases they may need
// flow construction:
// (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() ||
node.parent_node().unwrap().to_threadsafe().restyle_damage() != RestyleDamage::empty()
}
unsafe fn ensure_element_data(element: &N::ConcreteElement) -> &AtomicRefCell<ElementData> {