diff options
author | Emilio Cobos Álvarez <emilio@crisal.io> | 2017-01-23 19:55:06 +0100 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2017-01-24 08:41:29 +0100 |
commit | f00b628c3abf07b46d544e2f82fdd24602195f7a (patch) | |
tree | 0313e601161c22c58626b951d6a7092fb63097f3 | |
parent | 7e2329ea4eb81f9153a64f63264ebb29d771e82d (diff) | |
download | servo-f00b628c3abf07b46d544e2f82fdd24602195f7a.tar.gz servo-f00b628c3abf07b46d544e2f82fdd24602195f7a.zip |
style: Expose the traversal kind to the style system.
This way we'll be able to take different paths for the sequential and parallel
traversals in some concrete cases.
This is a preliminar patch to fix bug 1332525.
-rw-r--r-- | components/layout/traversal.rs | 10 | ||||
-rw-r--r-- | components/layout_thread/lib.rs | 13 | ||||
-rw-r--r-- | components/style/gecko/traversal.rs | 10 | ||||
-rw-r--r-- | components/style/parallel.rs | 1 | ||||
-rw-r--r-- | components/style/sequential.rs | 1 | ||||
-rw-r--r-- | components/style/traversal.rs | 25 | ||||
-rw-r--r-- | ports/geckolib/glue.rs | 17 |
7 files changed, 64 insertions, 13 deletions
diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs index 0b65d78df15..9ba0367e79e 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -17,13 +17,14 @@ use style::data::ElementData; use style::dom::{NodeInfo, TElement, TNode}; use style::selector_parser::RestyleDamage; use style::servo::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT}; -use style::traversal::{DomTraversal, recalc_style_at}; +use style::traversal::{DomTraversal, TraversalDriver, recalc_style_at}; use style::traversal::PerLevelTraversalData; use wrapper::{GetRawData, LayoutNodeHelpers, LayoutNodeLayoutData}; use wrapper::ThreadSafeLayoutNodeHelpers; pub struct RecalcStyleAndConstructFlows { shared: SharedLayoutContext, + driver: TraversalDriver, } impl RecalcStyleAndConstructFlows { @@ -34,9 +35,10 @@ impl RecalcStyleAndConstructFlows { impl RecalcStyleAndConstructFlows { /// Creates a traversal context, taking ownership of the shared layout context. - pub fn new(shared: SharedLayoutContext) -> Self { + pub fn new(shared: SharedLayoutContext, driver: TraversalDriver) -> Self { RecalcStyleAndConstructFlows { shared: shared, + driver: driver, } } @@ -101,6 +103,10 @@ impl<E> DomTraversal<E> for RecalcStyleAndConstructFlows fn create_thread_local_context(&self) -> Self::ThreadLocalContext { ScopedThreadLocalLayoutContext::new(&self.shared) } + + fn is_parallel(&self) -> bool { + self.driver.is_parallel() + } } /// A bottom-up, parallelizable traversal. diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 5d0524925a5..a2eea76bba0 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -124,7 +124,7 @@ use style::stylesheets::{Origin, Stylesheet, UserAgentStylesheets}; use style::stylist::Stylist; use style::thread_state; use style::timer::Timer; -use style::traversal::DomTraversal; +use style::traversal::{DomTraversal, TraversalDriver}; /// Information needed by the layout thread. pub struct LayoutThread { @@ -1173,7 +1173,13 @@ impl LayoutThread { data.reflow_info.goal); // NB: Type inference falls apart here for some reason, so we need to be very verbose. :-( - let traversal = RecalcStyleAndConstructFlows::new(shared_layout_context); + let traversal_driver = if self.parallel_flag && self.parallel_traversal.is_some() { + TraversalDriver::Parallel + } else { + TraversalDriver::Sequential + }; + + let traversal = RecalcStyleAndConstructFlows::new(shared_layout_context, traversal_driver); let dom_depth = Some(0); // This is always the root node. let token = { let stylist = &<RecalcStyleAndConstructFlows as @@ -1189,7 +1195,8 @@ impl LayoutThread { self.time_profiler_chan.clone(), || { // Perform CSS selector matching and flow construction. - if let (true, Some(pool)) = (self.parallel_flag, self.parallel_traversal.as_mut()) { + if traversal_driver.is_parallel() { + let pool = self.parallel_traversal.as_mut().unwrap(); // Parallel mode parallel::traverse_dom::<ServoLayoutElement, RecalcStyleAndConstructFlows>( &traversal, element, dom_depth, token, pool); diff --git a/components/style/gecko/traversal.rs b/components/style/gecko/traversal.rs index cdf3f141f16..3cb7f30cb1b 100644 --- a/components/style/gecko/traversal.rs +++ b/components/style/gecko/traversal.rs @@ -9,19 +9,21 @@ use context::{SharedStyleContext, StyleContext, ThreadLocalStyleContext}; use data::ElementData; use dom::{NodeInfo, TNode}; use gecko::wrapper::{GeckoElement, GeckoNode}; -use traversal::{DomTraversal, PerLevelTraversalData, recalc_style_at}; +use traversal::{DomTraversal, PerLevelTraversalData, TraversalDriver, recalc_style_at}; /// This is the simple struct that Gecko uses to encapsulate a DOM traversal for /// styling. pub struct RecalcStyleOnly { shared: SharedStyleContext, + driver: TraversalDriver, } impl RecalcStyleOnly { /// Create a `RecalcStyleOnly` traversal from a `SharedStyleContext`. - pub fn new(shared: SharedStyleContext) -> Self { + pub fn new(shared: SharedStyleContext, driver: TraversalDriver) -> Self { RecalcStyleOnly { shared: shared, + driver: driver, } } } @@ -66,4 +68,8 @@ impl<'le> DomTraversal<GeckoElement<'le>> for RecalcStyleOnly { 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 89e1331bfc6..3cc521e0533 100644 --- a/components/style/parallel.rs +++ b/components/style/parallel.rs @@ -45,6 +45,7 @@ pub fn traverse_dom<E, D>(traversal: &D, where E: TElement, D: DomTraversal<E>, { + debug_assert!(traversal.is_parallel()); // Handle Gecko's eager initial styling. We don't currently support it // in conjunction with bottom-up traversal. If we did, we'd need to put // it on the context to make it available to the bottom-up phase. diff --git a/components/style/sequential.rs b/components/style/sequential.rs index cbb5e253dee..a11bbd52d98 100644 --- a/components/style/sequential.rs +++ b/components/style/sequential.rs @@ -18,6 +18,7 @@ pub fn traverse_dom<E, D>(traversal: &D, where E: TElement, D: DomTraversal<E>, { + debug_assert!(!traversal.is_parallel()); debug_assert!(token.should_traverse()); fn doit<E, D>(traversal: &D, traversal_data: &mut PerLevelTraversalData, diff --git a/components/style/traversal.rs b/components/style/traversal.rs index 9e425043916..47d33dd7269 100644 --- a/components/style/traversal.rs +++ b/components/style/traversal.rs @@ -62,6 +62,23 @@ impl LogBehavior { fn allow(&self) -> bool { matches!(*self, MayLog) } } +/// The kind of traversals we could perform. +#[derive(Debug, Copy, Clone)] +pub enum TraversalDriver { + /// A potentially parallel traversal. + Parallel, + /// A sequential traversal. + Sequential, +} + +impl TraversalDriver { + /// Returns whether this represents a parallel traversal or not. + #[inline] + pub fn is_parallel(&self) -> bool { + matches!(*self, TraversalDriver::Parallel) + } +} + /// A DOM Traversal trait, that is used to generically implement styling for /// Gecko and Servo. pub trait DomTraversal<E: TElement> : Sync { @@ -284,6 +301,14 @@ pub trait DomTraversal<E: TElement> : Sync { /// 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 + /// regard via the type system via a `TraversalDriver` trait for this trait, + /// that could be one of two concrete types. It's not clear whether the + /// potential code size impact of that is worth it. + fn is_parallel(&self) -> bool; } /// Helper for the function below. diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 5e2550793e8..bcf393bb4a0 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -68,7 +68,7 @@ use style::stylesheets::StylesheetLoader as StyleStylesheetLoader; use style::supports::parse_condition_or_declaration; use style::thread_state; use style::timer::Timer; -use style::traversal::{resolve_style, DomTraversal}; +use style::traversal::{resolve_style, DomTraversal, TraversalDriver}; use style_traits::ToCss; use stylesheet_loader::StylesheetLoader; @@ -139,14 +139,19 @@ fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed, debug!("{:?}", ShowSubtreeData(element.as_node())); let shared_style_context = create_shared_context(&per_doc_data); - let traversal = RecalcStyleOnly::new(shared_style_context); - let known_depth = None; - - if per_doc_data.num_threads == 1 || per_doc_data.work_queue.is_none() { - sequential::traverse_dom(&traversal, element, token); + let traversal_driver = if per_doc_data.num_threads == 1 || per_doc_data.work_queue.is_none() { + TraversalDriver::Sequential } else { + TraversalDriver::Parallel + }; + + let traversal = RecalcStyleOnly::new(shared_style_context, traversal_driver); + let known_depth = None; + if traversal_driver.is_parallel() { parallel::traverse_dom(&traversal, element, known_depth, token, per_doc_data.work_queue.as_mut().unwrap()); + } else { + sequential::traverse_dom(&traversal, element, token); } } |