Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rip out the generic abstractions around ThreadLocalStyleContext #17615

Merged
merged 1 commit into from Jul 6, 2017
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -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));

@@ -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,27 +55,21 @@ 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();

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);
@@ -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;
@@ -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()
}
@@ -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>,
{
@@ -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);
}
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.