mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
Do the sequential traversal breadth-first.
While we're at it, we also eliminate the 'unknown' dom depth for the bloom filter. Computing depth has negligible cost relative to the amount of work we do setting up the bloom filter at a given depth. Doing it once per traversal should be totally fine. I originally separated the elimination of unknown dom depth from the traversal changes, but I got bloom filter crashes on the intermediate patch, presumably because I didn't properly fix the sequential traversal for this case. Given that the final state is green, I just decided to squash and move on.
This commit is contained in:
parent
1b363ac909
commit
3f52052cf9
9 changed files with 63 additions and 75 deletions
|
@ -9,9 +9,12 @@
|
|||
use context::TraversalStatistics;
|
||||
use dom::{TElement, TNode};
|
||||
use std::borrow::BorrowMut;
|
||||
use std::collections::VecDeque;
|
||||
use time;
|
||||
use traversal::{DomTraversal, PerLevelTraversalData, PreTraverseToken};
|
||||
|
||||
struct WorkItem<N: TNode>(N, usize);
|
||||
|
||||
/// Do a sequential DOM traversal for layout or styling, generic over `D`.
|
||||
pub fn traverse_dom<E, D>(traversal: &D,
|
||||
root: E,
|
||||
|
@ -25,44 +28,37 @@ pub fn traverse_dom<E, D>(traversal: &D,
|
|||
debug_assert!(!traversal.is_parallel());
|
||||
debug_assert!(token.should_traverse());
|
||||
|
||||
fn doit<E, D>(traversal: &D, traversal_data: &mut PerLevelTraversalData,
|
||||
thread_local: &mut D::ThreadLocalContext, node: E::ConcreteNode)
|
||||
where E: TElement,
|
||||
D: DomTraversal<E>
|
||||
{
|
||||
traversal.process_preorder(traversal_data, thread_local, node);
|
||||
if let Some(el) = node.as_element() {
|
||||
if let Some(ref mut depth) = traversal_data.current_dom_depth {
|
||||
*depth += 1;
|
||||
}
|
||||
|
||||
traversal.traverse_children(thread_local, el, |tlc, kid| {
|
||||
doit(traversal, traversal_data, tlc, kid)
|
||||
});
|
||||
|
||||
if let Some(ref mut depth) = traversal_data.current_dom_depth {
|
||||
*depth -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if D::needs_postorder_traversal() {
|
||||
traversal.process_postorder(thread_local, node);
|
||||
}
|
||||
}
|
||||
|
||||
let mut traversal_data = PerLevelTraversalData {
|
||||
current_dom_depth: None,
|
||||
};
|
||||
|
||||
let mut discovered = VecDeque::<WorkItem<E::ConcreteNode>>::with_capacity(16);
|
||||
let mut tlc = traversal.create_thread_local_context();
|
||||
let root_depth = root.depth();
|
||||
|
||||
if token.traverse_unstyled_children_only() {
|
||||
for kid in root.as_node().children() {
|
||||
if kid.as_element().map_or(false, |el| el.get_data().is_none()) {
|
||||
doit(traversal, &mut traversal_data, &mut tlc, kid);
|
||||
discovered.push_back(WorkItem(kid, root_depth + 1));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
doit(traversal, &mut traversal_data, &mut tlc, root.as_node());
|
||||
discovered.push_back(WorkItem(root.as_node(), root_depth));
|
||||
}
|
||||
|
||||
// Process the nodes breadth-first, just like the parallel traversal does.
|
||||
// This helps keep similar traversal characteristics for the style sharing
|
||||
// cache.
|
||||
while let Some(WorkItem(node, depth)) = discovered.pop_front() {
|
||||
let mut children_to_process = 0isize;
|
||||
let traversal_data = PerLevelTraversalData { current_dom_depth: depth };
|
||||
traversal.process_preorder(&traversal_data, &mut tlc, node);
|
||||
|
||||
if let Some(el) = node.as_element() {
|
||||
traversal.traverse_children(&mut tlc, el, |_tlc, kid| {
|
||||
children_to_process += 1;
|
||||
discovered.push_back(WorkItem(kid, depth + 1))
|
||||
});
|
||||
}
|
||||
|
||||
traversal.handle_postorder_traversal(&mut tlc, root.as_node().opaque(),
|
||||
node, children_to_process);
|
||||
}
|
||||
|
||||
// Dump statistics to stdout if requested.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue