aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorBobby Holley <bobbyholley@gmail.com>2017-07-05 14:19:37 -0700
committerBobby Holley <bobbyholley@gmail.com>2017-07-05 16:37:17 -0700
commit3330653dc80cc8947af17f1989fb7fbf390c4d2f (patch)
tree85556e4b7c09512eb64519fa6fa7675e52eb532a /components
parent296a215e5404eb0fd0c0a34cc1283cd0b84aaea9 (diff)
downloadservo-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.rs29
-rw-r--r--components/layout/traversal.rs24
-rw-r--r--components/style/dom.rs2
-rw-r--r--components/style/gecko/traversal.rs18
-rw-r--r--components/style/parallel.rs24
-rw-r--r--components/style/sequential.rs22
-rw-r--r--components/style/traversal.rs35
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