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

style: Expose the traversal kind to the style system. #15160

Merged
merged 1 commit into from Jan 25, 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

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.
  • Loading branch information
emilio committed Jan 24, 2017
commit f00b628c3abf07b46d544e2f82fdd24602195f7a
@@ -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);
}
}

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.