aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <emilio@crisal.io>2017-01-23 19:55:06 +0100
committerEmilio Cobos Álvarez <emilio@crisal.io>2017-01-24 08:41:29 +0100
commitf00b628c3abf07b46d544e2f82fdd24602195f7a (patch)
tree0313e601161c22c58626b951d6a7092fb63097f3
parent7e2329ea4eb81f9153a64f63264ebb29d771e82d (diff)
downloadservo-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.rs10
-rw-r--r--components/layout_thread/lib.rs13
-rw-r--r--components/style/gecko/traversal.rs10
-rw-r--r--components/style/parallel.rs1
-rw-r--r--components/style/sequential.rs1
-rw-r--r--components/style/traversal.rs25
-rw-r--r--ports/geckolib/glue.rs17
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);
}
}