Skip to content

Commit

Permalink
Bug 1325734 - Pass the thread-local context into should_traverse_chil…
Browse files Browse the repository at this point in the history
…dren. r=emilio
  • Loading branch information
bholley committed Jan 9, 2017
1 parent 3060865 commit 92b9d70
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 10 deletions.
13 changes: 13 additions & 0 deletions components/layout/context.rs
Expand Up @@ -16,6 +16,7 @@ use net_traits::image_cache_thread::{ImageOrMetadataAvailable, UsePlaceholder};
use parking_lot::RwLock;
use servo_config::opts;
use servo_url::ServoUrl;
use std::borrow::{Borrow, BorrowMut};
use std::cell::{RefCell, RefMut};
use std::collections::HashMap;
use std::hash::BuildHasherDefault;
Expand All @@ -37,6 +38,18 @@ impl<E: TElement> ScopedThreadLocalLayoutContext<E> {
}
}

impl<E: TElement> Borrow<ThreadLocalStyleContext<E>> for ScopedThreadLocalLayoutContext<E> {
fn borrow(&self) -> &ThreadLocalStyleContext<E> {
&self.style_context
}
}

impl<E: TElement> BorrowMut<ThreadLocalStyleContext<E>> for ScopedThreadLocalLayoutContext<E> {
fn borrow_mut(&mut self) -> &mut ThreadLocalStyleContext<E> {
&mut self.style_context
}
}

/// TLS data that persists across traversals.
pub struct PersistentThreadLocalLayoutContext {
// FontContext uses Rc all over the place and so isn't Send, which means we
Expand Down
2 changes: 1 addition & 1 deletion components/style/parallel.rs
Expand Up @@ -112,7 +112,7 @@ fn top_down_dom<'a, 'scope, E, D>(nodes: &'a [SendNode<E::ConcreteNode>],
let mut children_to_process = 0isize;
traversal.process_preorder(&mut traversal_data, &mut *tlc, node);
if let Some(el) = node.as_element() {
D::traverse_children(el, |kid| {
traversal.traverse_children(&mut *tlc, el, |_tlc, kid| {
children_to_process += 1;
discovered_child_nodes.push(unsafe { SendNode::new(kid) })
});
Expand Down
4 changes: 3 additions & 1 deletion components/style/sequential.rs
Expand Up @@ -29,7 +29,9 @@ pub fn traverse_dom<E, D>(traversal: &D,
*depth += 1;
}

D::traverse_children(el, |kid| doit(traversal, traversal_data, thread_local, kid));
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;
Expand Down
23 changes: 15 additions & 8 deletions components/style/traversal.rs
Expand Up @@ -7,13 +7,14 @@
#![deny(missing_docs)]

use atomic_refcell::{AtomicRefCell, AtomicRefMut};
use context::{SharedStyleContext, StyleContext};
use context::{SharedStyleContext, StyleContext, ThreadLocalStyleContext};
use data::{ElementData, ElementStyles, StoredRestyleHint};
use dom::{NodeInfo, TElement, TNode};
use matching::{MatchMethods, StyleSharingResult};
use restyle_hints::{RESTYLE_DESCENDANTS, RESTYLE_SELF};
use selector_parser::RestyleDamage;
use servo_config::opts;
use std::borrow::BorrowMut;
use std::mem;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use stylist::Stylist;
Expand Down Expand Up @@ -75,7 +76,7 @@ pub trait DomTraversal<E: TElement> : Sync {
/// The thread-local context, used to store non-thread-safe stuff that needs
/// to be used in the traversal, and of which we use one per worker, like
/// the bloom filter, for example.
type ThreadLocalContext: Send;
type ThreadLocalContext: Send + BorrowMut<ThreadLocalStyleContext<E>>;

/// Process `node` on the way down, before its children have been processed.
fn process_preorder(&self, data: &mut PerLevelTraversalData,
Expand Down Expand Up @@ -193,7 +194,11 @@ pub trait DomTraversal<E: TElement> : Sync {
///
/// This may be called multiple times when processing an element, so we pass
/// a parameter to keep the logs tidy.
fn should_traverse_children(parent: E, parent_data: &ElementData, log: LogBehavior) -> bool
fn should_traverse_children(&self,
_thread_local: &mut ThreadLocalStyleContext<E>,
parent: E,
parent_data: &ElementData,
log: LogBehavior) -> bool
{
// See the comment on `cascade_node` for why we allow this on Gecko.
debug_assert!(cfg!(feature = "gecko") || parent_data.has_current_styles());
Expand Down Expand Up @@ -237,10 +242,12 @@ pub trait DomTraversal<E: TElement> : Sync {

/// Helper for the traversal implementations to select the children that
/// should be enqueued for processing.
fn traverse_children<F: FnMut(E::ConcreteNode)>(parent: E, mut f: F)
fn traverse_children<F>(&self, thread_local: &mut Self::ThreadLocalContext, parent: E, mut f: F)
where F: FnMut(&mut Self::ThreadLocalContext, E::ConcreteNode)
{
// Check if we're allowed to traverse past this element.
if !Self::should_traverse_children(parent, &parent.borrow_data().unwrap(), MayLog) {
if !self.should_traverse_children(thread_local.borrow_mut(), parent,
&parent.borrow_data().unwrap(), MayLog) {
return;
}

Expand All @@ -252,7 +259,7 @@ pub trait DomTraversal<E: TElement> : Sync {
{
unsafe { parent.set_dirty_descendants(); }
}
f(kid);
f(thread_local, kid);
}
}
}
Expand All @@ -274,7 +281,7 @@ pub trait DomTraversal<E: TElement> : Sync {
/// Return the shared style context common to all worker threads.
fn shared_context(&self) -> &SharedStyleContext;

/// Create a thread-local context.
/// Creates a thread-local context.
fn create_thread_local_context(&self) -> Self::ThreadLocalContext;
}

Expand Down Expand Up @@ -397,7 +404,7 @@ pub fn recalc_style_at<E, D>(traversal: &D,
trace!("propagated_hint={:?}, inherited_style_changed={:?}", propagated_hint, inherited_style_changed);

// Preprocess children, propagating restyle hints and handling sibling relationships.
if D::should_traverse_children(element, &data, DontLog) &&
if traversal.should_traverse_children(&mut context.thread_local, element, &data, DontLog) &&
(element.has_dirty_descendants() || !propagated_hint.is_empty() || inherited_style_changed) {
preprocess_children(traversal, element, propagated_hint, inherited_style_changed);
}
Expand Down

0 comments on commit 92b9d70

Please sign in to comment.