diff options
author | Bobby Holley <bobbyholley@gmail.com> | 2017-07-05 14:19:37 -0700 |
---|---|---|
committer | Bobby Holley <bobbyholley@gmail.com> | 2017-07-05 16:37:17 -0700 |
commit | 3330653dc80cc8947af17f1989fb7fbf390c4d2f (patch) | |
tree | 85556e4b7c09512eb64519fa6fa7675e52eb532a /components | |
parent | 296a215e5404eb0fd0c0a34cc1283cd0b84aaea9 (diff) | |
download | servo-3330653dc80cc8947af17f1989fb7fbf390c4d2f.tar.gz servo-3330653dc80cc8947af17f1989fb7fbf390c4d2f.zip |
Rip out the generic abstractions around ThreadLocalStyleContext.
MozReview-Commit-ID: 5WTLuk323Ac
Diffstat (limited to 'components')
-rw-r--r-- | components/layout/context.rs | 29 | ||||
-rw-r--r-- | components/layout/traversal.rs | 24 | ||||
-rw-r--r-- | components/style/dom.rs | 2 | ||||
-rw-r--r-- | components/style/gecko/traversal.rs | 18 | ||||
-rw-r--r-- | components/style/parallel.rs | 24 | ||||
-rw-r--r-- | components/style/sequential.rs | 22 | ||||
-rw-r--r-- | components/style/traversal.rs | 35 |
7 files changed, 52 insertions, 102 deletions
diff --git a/components/layout/context.rs b/components/layout/context.rs index 22b407d1fb6..d261fe5d8a7 100644 --- a/components/layout/context.rs +++ b/components/layout/context.rs @@ -18,39 +18,12 @@ use script_layout_interface::{PendingImage, PendingImageState}; use script_traits::PaintWorkletExecutor; use script_traits::UntrustedNodeAddress; use servo_url::ServoUrl; -use std::borrow::{Borrow, BorrowMut}; use std::cell::{RefCell, RefMut}; use std::collections::HashMap; use std::hash::BuildHasherDefault; use std::sync::{Arc, Mutex}; use std::thread; -use style::context::{SharedStyleContext, ThreadLocalStyleContext}; -use style::dom::TElement; - -/// TLS data scoped to the traversal. -pub struct ScopedThreadLocalLayoutContext<E: TElement> { - pub style_context: ThreadLocalStyleContext<E>, -} - -impl<E: TElement> ScopedThreadLocalLayoutContext<E> { - pub fn new(context: &LayoutContext) -> Self { - ScopedThreadLocalLayoutContext { - style_context: ThreadLocalStyleContext::new(&context.style_context), - } - } -} - -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 - } -} +use style::context::SharedStyleContext; thread_local!(static FONT_CONTEXT_KEY: RefCell<Option<FontContext>> = RefCell::new(None)); diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs index ab4f2c2f1b6..f011925ebb8 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -6,7 +6,7 @@ use atomic_refcell::AtomicRefCell; use construct::FlowConstructor; -use context::{LayoutContext, ScopedThreadLocalLayoutContext}; +use context::LayoutContext; use display_list_builder::DisplayListBuildState; use flow::{self, PreorderFlowTraversal}; use flow::{CAN_BE_FRAGMENTED, Flow, ImmutableFlowUtils, PostorderFlowTraversal}; @@ -55,10 +55,8 @@ impl<'a, E> DomTraversal<E> for RecalcStyleAndConstructFlows<'a> E::ConcreteNode: LayoutNode, E::FontMetricsProvider: Send, { - type ThreadLocalContext = ScopedThreadLocalLayoutContext<E>; - fn process_preorder(&self, traversal_data: &PerLevelTraversalData, - thread_local: &mut Self::ThreadLocalContext, node: E::ConcreteNode) { + context: &mut StyleContext<E>, node: E::ConcreteNode) { // FIXME(pcwalton): Stop allocating here. Ideally this should just be // done by the HTML parser. node.initialize_data(); @@ -66,16 +64,12 @@ impl<'a, E> DomTraversal<E> for RecalcStyleAndConstructFlows<'a> if !node.is_text_node() { let el = node.as_element().unwrap(); let mut data = el.mutate_data().unwrap(); - let mut context = StyleContext { - shared: &self.context.shared_context(), - thread_local: &mut thread_local.style_context, - }; - recalc_style_at(self, traversal_data, &mut context, el, &mut data); + recalc_style_at(self, traversal_data, context, el, &mut data); } } - fn process_postorder(&self, thread_local: &mut Self::ThreadLocalContext, node: E::ConcreteNode) { - construct_flows_at(&self.context, thread_local, node); + fn process_postorder(&self, _style_context: &mut StyleContext<E>, node: E::ConcreteNode) { + construct_flows_at(&self.context, node); } fn text_node_needs_traversal(node: E::ConcreteNode) -> bool { @@ -100,10 +94,6 @@ impl<'a, E> DomTraversal<E> for RecalcStyleAndConstructFlows<'a> &self.context.style_context } - fn create_thread_local_context(&self) -> Self::ThreadLocalContext { - ScopedThreadLocalLayoutContext::new(&self.context) - } - fn is_parallel(&self) -> bool { self.driver.is_parallel() } @@ -118,9 +108,7 @@ pub trait PostorderNodeMutTraversal<ConcreteThreadSafeLayoutNode: ThreadSafeLayo /// The flow construction traversal, which builds flows for styled nodes. #[inline] #[allow(unsafe_code)] -fn construct_flows_at<N>(context: &LayoutContext, - _thread_local: &mut ScopedThreadLocalLayoutContext<N::ConcreteElement>, - node: N) +fn construct_flows_at<N>(context: &LayoutContext, node: N) where N: LayoutNode, { debug!("construct_flows_at: {:?}", node); diff --git a/components/style/dom.rs b/components/style/dom.rs index 7d8112a0554..ac5d051e865 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -296,7 +296,7 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone + /// /// XXXManishearth It would be better to make this a type parameter on /// ThreadLocalStyleContext and StyleContext - type FontMetricsProvider: FontMetricsProvider; + type FontMetricsProvider: FontMetricsProvider + Send; /// Get this element as a node. fn as_node(&self) -> Self::ConcreteNode; diff --git a/components/style/gecko/traversal.rs b/components/style/gecko/traversal.rs index eb7f52ad269..35683ba08e3 100644 --- a/components/style/gecko/traversal.rs +++ b/components/style/gecko/traversal.rs @@ -5,7 +5,7 @@ //! Gecko-specific bits for the styling DOM traversal. use atomic_refcell::AtomicRefCell; -use context::{SharedStyleContext, StyleContext, ThreadLocalStyleContext}; +use context::{SharedStyleContext, StyleContext}; use data::ElementData; use dom::{NodeInfo, TNode}; use gecko::wrapper::{GeckoElement, GeckoNode}; @@ -29,25 +29,19 @@ impl<'a> RecalcStyleOnly<'a> { } impl<'recalc, 'le> DomTraversal<GeckoElement<'le>> for RecalcStyleOnly<'recalc> { - type ThreadLocalContext = ThreadLocalStyleContext<GeckoElement<'le>>; - fn process_preorder(&self, traversal_data: &PerLevelTraversalData, - thread_local: &mut Self::ThreadLocalContext, + context: &mut StyleContext<GeckoElement<'le>>, node: GeckoNode<'le>) { if node.is_element() { let el = node.as_element().unwrap(); let mut data = unsafe { el.ensure_data() }.borrow_mut(); - let mut context = StyleContext { - shared: &self.shared, - thread_local: thread_local, - }; - recalc_style_at(self, traversal_data, &mut context, el, &mut data); + recalc_style_at(self, traversal_data, context, el, &mut data); } } - fn process_postorder(&self, _: &mut Self::ThreadLocalContext, _: GeckoNode<'le>) { + fn process_postorder(&self, _: &mut StyleContext<GeckoElement<'le>>, _: GeckoNode<'le>) { unreachable!(); } @@ -66,10 +60,6 @@ impl<'recalc, 'le> DomTraversal<GeckoElement<'le>> for RecalcStyleOnly<'recalc> &self.shared } - fn create_thread_local_context(&self) -> Self::ThreadLocalContext { - ThreadLocalStyleContext::new(&self.shared) - } - fn is_parallel(&self) -> bool { self.driver.is_parallel() } diff --git a/components/style/parallel.rs b/components/style/parallel.rs index 0526c07f94c..dd7072a201e 100644 --- a/components/style/parallel.rs +++ b/components/style/parallel.rs @@ -23,7 +23,7 @@ #![deny(missing_docs)] use arrayvec::ArrayVec; -use context::TraversalStatistics; +use context::{StyleContext, ThreadLocalStyleContext, TraversalStatistics}; use dom::{OpaqueNode, SendNode, TElement, TNode}; use rayon; use scoped_tls::ScopedTLS; @@ -84,7 +84,7 @@ pub fn traverse_dom<E, D>(traversal: &D, let traversal_data = PerLevelTraversalData { current_dom_depth: depth, }; - let tls = ScopedTLS::<D::ThreadLocalContext>::new(pool); + let tls = ScopedTLS::<ThreadLocalStyleContext<E>>::new(pool); let root = root.as_node().opaque(); pool.install(|| { @@ -124,11 +124,11 @@ pub fn traverse_dom<E, D>(traversal: &D, #[inline(never)] fn create_thread_local_context<'scope, E, D>( traversal: &'scope D, - slot: &mut Option<D::ThreadLocalContext>) + slot: &mut Option<ThreadLocalStyleContext<E>>) where E: TElement + 'scope, D: DomTraversal<E> { - *slot = Some(traversal.create_thread_local_context()) + *slot = Some(ThreadLocalStyleContext::new(traversal.shared_context())); } /// A parallel top-down DOM traversal. @@ -152,7 +152,7 @@ fn top_down_dom<'a, 'scope, E, D>(nodes: &'a [SendNode<E::ConcreteNode>], scope: &'a rayon::Scope<'scope>, pool: &'scope rayon::ThreadPool, traversal: &'scope D, - tls: &'scope ScopedTLS<'scope, D::ThreadLocalContext>) + tls: &'scope ScopedTLS<'scope, ThreadLocalStyleContext<E>>) where E: TElement + 'scope, D: DomTraversal<E>, { @@ -167,7 +167,11 @@ fn top_down_dom<'a, 'scope, E, D>(nodes: &'a [SendNode<E::ConcreteNode>], // Scope the borrow of the TLS so that the borrow is dropped before // a potential recursive call when we pass TailCall. let mut tlc = tls.ensure( - |slot: &mut Option<D::ThreadLocalContext>| create_thread_local_context(traversal, slot)); + |slot: &mut Option<ThreadLocalStyleContext<E>>| create_thread_local_context(traversal, slot)); + let mut context = StyleContext { + shared: traversal.shared_context(), + thread_local: &mut *tlc, + }; for n in nodes { // If the last node we processed produced children, spawn them off @@ -199,15 +203,15 @@ fn top_down_dom<'a, 'scope, E, D>(nodes: &'a [SendNode<E::ConcreteNode>], let node = **n; let mut children_to_process = 0isize; - traversal.process_preorder(&traversal_data, &mut *tlc, node); + traversal.process_preorder(&traversal_data, &mut context, node); if let Some(el) = node.as_element() { - traversal.traverse_children(&mut *tlc, el, |_tlc, kid| { + traversal.traverse_children(&mut context, el, |_context, kid| { children_to_process += 1; discovered_child_nodes.push(unsafe { SendNode::new(kid) }) }); } - traversal.handle_postorder_traversal(&mut *tlc, root, node, + traversal.handle_postorder_traversal(&mut context, root, node, children_to_process); } } @@ -256,7 +260,7 @@ fn traverse_nodes<'a, 'scope, E, D>(nodes: &[SendNode<E::ConcreteNode>], scope: &'a rayon::Scope<'scope>, pool: &'scope rayon::ThreadPool, traversal: &'scope D, - tls: &'scope ScopedTLS<'scope, D::ThreadLocalContext>) + tls: &'scope ScopedTLS<'scope, ThreadLocalStyleContext<E>>) where E: TElement + 'scope, D: DomTraversal<E>, { diff --git a/components/style/sequential.rs b/components/style/sequential.rs index f2fa63c95f3..49bb3bb0c4f 100644 --- a/components/style/sequential.rs +++ b/components/style/sequential.rs @@ -6,8 +6,8 @@ #![deny(missing_docs)] +use context::{StyleContext, ThreadLocalStyleContext}; use dom::{TElement, TNode}; -use std::borrow::BorrowMut; use std::collections::VecDeque; use time; use traversal::{DomTraversal, PerLevelTraversalData, PreTraverseToken}; @@ -28,7 +28,12 @@ pub fn traverse_dom<E, D>(traversal: &D, debug_assert!(token.should_traverse()); let mut discovered = VecDeque::<WorkItem<E::ConcreteNode>>::with_capacity(16); - let mut tlc = traversal.create_thread_local_context(); + let mut tlc = ThreadLocalStyleContext::new(traversal.shared_context()); + let mut context = StyleContext { + shared: traversal.shared_context(), + thread_local: &mut tlc, + }; + let root_depth = root.depth(); if token.traverse_unstyled_children_only() { @@ -47,25 +52,24 @@ pub fn traverse_dom<E, D>(traversal: &D, 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); + traversal.process_preorder(&traversal_data, &mut context, node); if let Some(el) = node.as_element() { - traversal.traverse_children(&mut tlc, el, |_tlc, kid| { + traversal.traverse_children(&mut context, el, |_context, kid| { children_to_process += 1; discovered.push_back(WorkItem(kid, depth + 1)) }); } - traversal.handle_postorder_traversal(&mut tlc, root.as_node().opaque(), + traversal.handle_postorder_traversal(&mut context, root.as_node().opaque(), node, children_to_process); } // Dump statistics to stdout if requested. if dump_stats { - let tlsc = tlc.borrow_mut(); - tlsc.statistics.finish(traversal, start_time.unwrap()); - if tlsc.statistics.is_large_traversal() { - println!("{}", tlsc.statistics); + context.thread_local.statistics.finish(traversal, start_time.unwrap()); + if context.thread_local.statistics.is_large_traversal() { + println!("{}", context.thread_local.statistics); } } } diff --git a/components/style/traversal.rs b/components/style/traversal.rs index ddb82e0950f..47203980fc5 100644 --- a/components/style/traversal.rs +++ b/components/style/traversal.rs @@ -5,7 +5,7 @@ //! Traversing the DOM tree; the bloom filter. use atomic_refcell::AtomicRefCell; -use context::{ElementCascadeInputs, StyleContext, SharedStyleContext, ThreadLocalStyleContext}; +use context::{ElementCascadeInputs, StyleContext, SharedStyleContext}; use data::{ElementData, ElementStyles}; use dom::{DirtyDescendants, NodeInfo, OpaqueNode, TElement, TNode}; use invalidation::element::restyle_hints::{RECASCADE_SELF, RECASCADE_DESCENDANTS, RestyleHint}; @@ -13,7 +13,6 @@ use matching::{ChildCascadeRequirement, MatchMethods}; use sharing::{StyleSharingBehavior, StyleSharingTarget}; #[cfg(feature = "servo")] use servo_config::opts; use smallvec::SmallVec; -use std::borrow::BorrowMut; /// A per-traversal-level chunk of data. This is sent down by the traversal, and /// currently only holds the dom depth for the bloom filter. @@ -138,22 +137,17 @@ fn is_servo_nonincremental_layout() -> bool { /// A DOM Traversal trait, that is used to generically implement styling for /// Gecko and Servo. 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 + BorrowMut<ThreadLocalStyleContext<E>>; - /// Process `node` on the way down, before its children have been processed. fn process_preorder(&self, data: &PerLevelTraversalData, - thread_local: &mut Self::ThreadLocalContext, + context: &mut StyleContext<E>, node: E::ConcreteNode); /// Process `node` on the way up, after its children have been processed. /// /// This is only executed if `needs_postorder_traversal` returns true. fn process_postorder(&self, - thread_local: &mut Self::ThreadLocalContext, + contect: &mut StyleContext<E>, node: E::ConcreteNode); /// Boolean that specifies whether a bottom up traversal should be @@ -177,7 +171,7 @@ pub trait DomTraversal<E: TElement> : Sync { /// call durign the parallel traversal. fn handle_postorder_traversal( &self, - thread_local: &mut Self::ThreadLocalContext, + context: &mut StyleContext<E>, root: OpaqueNode, mut node: E::ConcreteNode, children_to_process: isize @@ -190,7 +184,7 @@ pub trait DomTraversal<E: TElement> : Sync { if children_to_process == 0 { // We are a leaf. Walk up the chain. loop { - self.process_postorder(thread_local, node); + self.process_postorder(context, node); if node.opaque() == root { break; } @@ -404,7 +398,7 @@ pub trait DomTraversal<E: TElement> : Sync { /// a parameter to keep the logs tidy. fn should_traverse_children( &self, - thread_local: &mut ThreadLocalStyleContext<E>, + context: &mut StyleContext<E>, parent: E, parent_data: &ElementData, log: LogBehavior @@ -442,7 +436,7 @@ pub trait DomTraversal<E: TElement> : Sync { // happens, we may just end up doing wasted work, since Gecko // recursively drops Servo ElementData when the XBL insertion parent of // an Element is changed. - if cfg!(feature = "gecko") && thread_local.is_initial_style() && + if cfg!(feature = "gecko") && context.thread_local.is_initial_style() && parent_data.styles.primary().has_moz_binding() { if log.allow() { debug!("Parent {:?} has XBL binding, deferring traversal", @@ -458,23 +452,23 @@ pub trait DomTraversal<E: TElement> : Sync { /// should be enqueued for processing. fn traverse_children<F>( &self, - thread_local: &mut Self::ThreadLocalContext, + context: &mut StyleContext<E>, parent: E, mut f: F ) where - F: FnMut(&mut Self::ThreadLocalContext, E::ConcreteNode) + F: FnMut(&mut StyleContext<E>, E::ConcreteNode) { // Check if we're allowed to traverse past this element. let should_traverse = self.should_traverse_children( - thread_local.borrow_mut(), + context, parent, &parent.borrow_data().unwrap(), MayLog ); - thread_local.borrow_mut().end_element(parent); + context.thread_local.end_element(parent); if !should_traverse { return; } @@ -495,7 +489,7 @@ pub trait DomTraversal<E: TElement> : Sync { } } } - f(thread_local, kid); + f(context, kid); } } } @@ -517,9 +511,6 @@ pub trait DomTraversal<E: TElement> : Sync { /// Return the shared style context common to all worker threads. fn shared_context(&self) -> &SharedStyleContext; - /// Creates a thread-local context. - fn create_thread_local_context(&self) -> Self::ThreadLocalContext; - /// Whether we're performing a parallel traversal. /// /// NB: We do this check on runtime. We could guarantee correctness in this @@ -763,7 +754,7 @@ where // Preprocess children, propagating restyle hints and handling sibling // relationships. let should_traverse_children = traversal.should_traverse_children( - &mut context.thread_local, + context, element, &data, DontLog |