mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
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.
This commit is contained in:
parent
7e2329ea4e
commit
f00b628c3a
7 changed files with 64 additions and 13 deletions
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue