From 92b9d70c3a28afd18f7cede0dcd135197e49c284 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Sun, 8 Jan 2017 11:42:39 -0800 Subject: [PATCH] Bug 1325734 - Pass the thread-local context into should_traverse_children. r=emilio --- components/layout/context.rs | 13 +++++++++++++ components/style/parallel.rs | 2 +- components/style/sequential.rs | 4 +++- components/style/traversal.rs | 23 +++++++++++++++-------- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/components/layout/context.rs b/components/layout/context.rs index 1cbee049f02..baac3f29c41 100644 --- a/components/layout/context.rs +++ b/components/layout/context.rs @@ -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; @@ -37,6 +38,18 @@ impl ScopedThreadLocalLayoutContext { } } +impl Borrow> for ScopedThreadLocalLayoutContext { + fn borrow(&self) -> &ThreadLocalStyleContext { + &self.style_context + } +} + +impl BorrowMut> for ScopedThreadLocalLayoutContext { + fn borrow_mut(&mut self) -> &mut ThreadLocalStyleContext { + &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 diff --git a/components/style/parallel.rs b/components/style/parallel.rs index e121f81c34b..70250073d24 100644 --- a/components/style/parallel.rs +++ b/components/style/parallel.rs @@ -112,7 +112,7 @@ fn top_down_dom<'a, 'scope, E, D>(nodes: &'a [SendNode], 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) }) }); diff --git a/components/style/sequential.rs b/components/style/sequential.rs index a6af5a52cdb..cc2a43bba27 100644 --- a/components/style/sequential.rs +++ b/components/style/sequential.rs @@ -29,7 +29,9 @@ pub fn traverse_dom(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; diff --git a/components/style/traversal.rs b/components/style/traversal.rs index 8f62d8c57bc..8dd541fbd5b 100644 --- a/components/style/traversal.rs +++ b/components/style/traversal.rs @@ -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; @@ -75,7 +76,7 @@ pub trait DomTraversal : 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>; /// Process `node` on the way down, before its children have been processed. fn process_preorder(&self, data: &mut PerLevelTraversalData, @@ -193,7 +194,11 @@ pub trait DomTraversal : 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, + 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()); @@ -237,10 +242,12 @@ pub trait DomTraversal : Sync { /// Helper for the traversal implementations to select the children that /// should be enqueued for processing. - fn traverse_children(parent: E, mut f: F) + fn traverse_children(&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; } @@ -252,7 +259,7 @@ pub trait DomTraversal : Sync { { unsafe { parent.set_dirty_descendants(); } } - f(kid); + f(thread_local, kid); } } } @@ -274,7 +281,7 @@ pub trait DomTraversal : 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; } @@ -397,7 +404,7 @@ pub fn recalc_style_at(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); }