mirror of
https://github.com/servo/servo.git
synced 2025-08-09 07:25:35 +01:00
Switch to an iterator for traverse_nodes.
We can't use a slice anymore, because the input might be the VecDeque from the sequential traversal, which requires an iterator to handle the ring buffer. MozReview-Commit-ID: JwH6MtRgMfY
This commit is contained in:
parent
2908b52c7b
commit
f7c6b2f04e
1 changed files with 25 additions and 19 deletions
|
@ -25,6 +25,7 @@
|
||||||
use arrayvec::ArrayVec;
|
use arrayvec::ArrayVec;
|
||||||
use context::{StyleContext, ThreadLocalStyleContext, TraversalStatistics};
|
use context::{StyleContext, ThreadLocalStyleContext, TraversalStatistics};
|
||||||
use dom::{OpaqueNode, SendNode, TElement, TNode};
|
use dom::{OpaqueNode, SendNode, TElement, TNode};
|
||||||
|
use itertools::Itertools;
|
||||||
use rayon;
|
use rayon;
|
||||||
use scoped_tls::ScopedTLS;
|
use scoped_tls::ScopedTLS;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
@ -78,7 +79,7 @@ pub fn traverse_dom<E, D>(traversal: &D,
|
||||||
rayon::scope(|scope| {
|
rayon::scope(|scope| {
|
||||||
let root = send_root;
|
let root = send_root;
|
||||||
let root_opaque = root.opaque();
|
let root_opaque = root.opaque();
|
||||||
traverse_nodes(&[root],
|
traverse_nodes(Some(root).into_iter(),
|
||||||
DispatchMode::TailCall,
|
DispatchMode::TailCall,
|
||||||
true,
|
true,
|
||||||
root_opaque,
|
root_opaque,
|
||||||
|
@ -210,7 +211,7 @@ fn top_down_dom<'a, 'scope, E, D>(nodes: &'a [SendNode<E::ConcreteNode>],
|
||||||
if discovered_child_nodes.len() >= WORK_UNIT_MAX {
|
if discovered_child_nodes.len() >= WORK_UNIT_MAX {
|
||||||
let mut traversal_data_copy = traversal_data.clone();
|
let mut traversal_data_copy = traversal_data.clone();
|
||||||
traversal_data_copy.current_dom_depth += 1;
|
traversal_data_copy.current_dom_depth += 1;
|
||||||
traverse_nodes(&*discovered_child_nodes,
|
traverse_nodes(discovered_child_nodes.drain(),
|
||||||
DispatchMode::NotTailCall,
|
DispatchMode::NotTailCall,
|
||||||
recursion_ok,
|
recursion_ok,
|
||||||
root,
|
root,
|
||||||
|
@ -219,7 +220,6 @@ fn top_down_dom<'a, 'scope, E, D>(nodes: &'a [SendNode<E::ConcreteNode>],
|
||||||
pool,
|
pool,
|
||||||
traversal,
|
traversal,
|
||||||
tls);
|
tls);
|
||||||
discovered_child_nodes.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let node = **n;
|
let node = **n;
|
||||||
|
@ -240,7 +240,7 @@ fn top_down_dom<'a, 'scope, E, D>(nodes: &'a [SendNode<E::ConcreteNode>],
|
||||||
// worth of them) directly on this thread by passing TailCall.
|
// worth of them) directly on this thread by passing TailCall.
|
||||||
if !discovered_child_nodes.is_empty() {
|
if !discovered_child_nodes.is_empty() {
|
||||||
traversal_data.current_dom_depth += 1;
|
traversal_data.current_dom_depth += 1;
|
||||||
traverse_nodes(&discovered_child_nodes,
|
traverse_nodes(discovered_child_nodes.drain(),
|
||||||
DispatchMode::TailCall,
|
DispatchMode::TailCall,
|
||||||
recursion_ok,
|
recursion_ok,
|
||||||
root,
|
root,
|
||||||
|
@ -264,8 +264,11 @@ impl DispatchMode {
|
||||||
fn is_tail_call(&self) -> bool { matches!(*self, DispatchMode::TailCall) }
|
fn is_tail_call(&self) -> bool { matches!(*self, DispatchMode::TailCall) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enqueues |nodes| for processing, possibly on this thread if the tail call
|
||||||
|
/// conditions are met.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn traverse_nodes<'a, 'scope, E, D>(nodes: &[SendNode<E::ConcreteNode>],
|
fn traverse_nodes<'a, 'scope, E, D, I>(
|
||||||
|
nodes: I,
|
||||||
mode: DispatchMode,
|
mode: DispatchMode,
|
||||||
recursion_ok: bool,
|
recursion_ok: bool,
|
||||||
root: OpaqueNode,
|
root: OpaqueNode,
|
||||||
|
@ -273,11 +276,14 @@ fn traverse_nodes<'a, 'scope, E, D>(nodes: &[SendNode<E::ConcreteNode>],
|
||||||
scope: &'a rayon::Scope<'scope>,
|
scope: &'a rayon::Scope<'scope>,
|
||||||
pool: &'scope rayon::ThreadPool,
|
pool: &'scope rayon::ThreadPool,
|
||||||
traversal: &'scope D,
|
traversal: &'scope D,
|
||||||
tls: &'scope ScopedTLS<'scope, ThreadLocalStyleContext<E>>)
|
tls: &'scope ScopedTLS<'scope, ThreadLocalStyleContext<E>>
|
||||||
where E: TElement + 'scope,
|
)
|
||||||
|
where
|
||||||
|
E: TElement + 'scope,
|
||||||
D: DomTraversal<E>,
|
D: DomTraversal<E>,
|
||||||
|
I: ExactSizeIterator<Item = SendNode<E::ConcreteNode>>
|
||||||
{
|
{
|
||||||
debug_assert!(!nodes.is_empty());
|
debug_assert_ne!(nodes.len(), 0);
|
||||||
|
|
||||||
// This is a tail call from the perspective of the caller. However, we only
|
// This is a tail call from the perspective of the caller. However, we only
|
||||||
// want to actually dispatch the job as a tail call if there's nothing left
|
// want to actually dispatch the job as a tail call if there's nothing left
|
||||||
|
@ -293,7 +299,7 @@ fn traverse_nodes<'a, 'scope, E, D>(nodes: &[SendNode<E::ConcreteNode>],
|
||||||
// In the common case, our children fit within a single work unit, in which
|
// In the common case, our children fit within a single work unit, in which
|
||||||
// case we can pass the SmallVec directly and avoid extra allocation.
|
// case we can pass the SmallVec directly and avoid extra allocation.
|
||||||
if nodes.len() <= WORK_UNIT_MAX {
|
if nodes.len() <= WORK_UNIT_MAX {
|
||||||
let work = nodes.iter().cloned().collect::<WorkUnit<E::ConcreteNode>>();
|
let work: WorkUnit<E::ConcreteNode> = nodes.collect();
|
||||||
if may_dispatch_tail {
|
if may_dispatch_tail {
|
||||||
top_down_dom(&work, root,
|
top_down_dom(&work, root,
|
||||||
traversal_data, scope, pool, traversal, tls);
|
traversal_data, scope, pool, traversal, tls);
|
||||||
|
@ -305,8 +311,8 @@ fn traverse_nodes<'a, 'scope, E, D>(nodes: &[SendNode<E::ConcreteNode>],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for chunk in nodes.chunks(WORK_UNIT_MAX) {
|
for chunk in nodes.chunks(WORK_UNIT_MAX).into_iter() {
|
||||||
let nodes = chunk.iter().cloned().collect::<WorkUnit<E::ConcreteNode>>();
|
let nodes: WorkUnit<E::ConcreteNode> = chunk.collect();
|
||||||
let traversal_data_copy = traversal_data.clone();
|
let traversal_data_copy = traversal_data.clone();
|
||||||
scope.spawn(move |scope| {
|
scope.spawn(move |scope| {
|
||||||
let n = nodes;
|
let n = nodes;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue