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

Trim some fat from the traversal #17741

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

Always

Just for now

Prev

Pass a callback to recalc_style_at to avoid traversing children twice.

MozReview-Commit-ID: DIHXaVNzbFM
  • Loading branch information
bholley committed Jul 15, 2017
commit b7de96e7025c7336ff34ec779d3dfceb268d647d
@@ -12,6 +12,7 @@ use flow::{CAN_BE_FRAGMENTED, Flow, ImmutableFlowUtils, PostorderFlowTraversal};
use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
use servo_config::opts;
use style::context::{SharedStyleContext, StyleContext};
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};
@@ -53,30 +54,33 @@ impl<'a, E> DomTraversal<E> for RecalcStyleAndConstructFlows<'a>
E::ConcreteNode: LayoutNode,
E::FontMetricsProvider: Send,
{
fn process_preorder(&self, traversal_data: &PerLevelTraversalData,
context: &mut StyleContext<E>, node: E::ConcreteNode) {
fn process_preorder<F>(&self, traversal_data: &PerLevelTraversalData,
context: &mut StyleContext<E>, node: E::ConcreteNode,
note_child: F)
where F: FnMut(E::ConcreteNode)
{
// FIXME(pcwalton): Stop allocating here. Ideally this should just be
// done by the HTML parser.
unsafe { node.initialize_data() };

if !node.is_text_node() {
let el = node.as_element().unwrap();
let mut data = el.mutate_data().unwrap();
recalc_style_at(self, traversal_data, context, el, &mut data);
recalc_style_at(self, traversal_data, context, el, &mut data, note_child);
}
}

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 {
fn text_node_needs_traversal(node: E::ConcreteNode, parent_data: &ElementData) -> bool {
// Text nodes never need styling. However, there are two cases they may need
// flow construction:
// (1) They child doesn't yet have layout data (preorder traversal initializes it).
// (2) The parent element has restyle damage (so the text flow also needs fixup).
node.get_raw_data().is_none() ||
node.parent_node().unwrap().to_threadsafe().restyle_damage() != RestyleDamage::empty()
parent_data.restyle.damage != RestyleDamage::empty()
}

fn shared_context(&self) -> &SharedStyleContext {
@@ -70,11 +70,16 @@ impl RestyleData {
/// Returns whether this element or any ancestor is going to be
/// reconstructed.
pub fn reconstructed_self_or_ancestor(&self) -> bool {
self.reconstructed_ancestor() ||
self.reconstructed_ancestor() || self.reconstructed_self()
}

/// Returns whether this element is going to be reconstructed.
pub fn reconstructed_self(&self) -> bool {
self.damage.contains(RestyleDamage::reconstruct())
}

/// Returns whether any ancestor of this element was restyled.
/// Returns whether any ancestor of this element is going to be
/// reconstructed.
fn reconstructed_ancestor(&self) -> bool {
self.flags.contains(ANCESTOR_WAS_RECONSTRUCTED)
}
@@ -5,7 +5,7 @@
//! Gecko-specific bits for the styling DOM traversal.

use context::{SharedStyleContext, StyleContext};
use dom::{NodeInfo, TNode, TElement};
use dom::{TNode, TElement};
use gecko::wrapper::{GeckoElement, GeckoNode};
use traversal::{DomTraversal, PerLevelTraversalData, TraversalDriver, recalc_style_at};

@@ -27,15 +27,16 @@ impl<'a> RecalcStyleOnly<'a> {
}

impl<'recalc, 'le> DomTraversal<GeckoElement<'le>> for RecalcStyleOnly<'recalc> {
fn process_preorder(&self,
traversal_data: &PerLevelTraversalData,
context: &mut StyleContext<GeckoElement<'le>>,
node: GeckoNode<'le>)
fn process_preorder<F>(&self,
traversal_data: &PerLevelTraversalData,
context: &mut StyleContext<GeckoElement<'le>>,
node: GeckoNode<'le>,
note_child: F)
where F: FnMut(GeckoNode<'le>),
{
if node.is_element() {
let el = node.as_element().unwrap();
if let Some(el) = node.as_element() {
let mut data = unsafe { el.ensure_data() };
recalc_style_at(self, traversal_data, context, el, &mut data);
recalc_style_at(self, traversal_data, context, el, &mut data, note_child);
}
}

@@ -202,13 +202,11 @@ 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 context, node);
if let Some(el) = node.as_element() {
traversal.traverse_children(&mut context, el, |_context, kid| {
children_to_process += 1;
discovered_child_nodes.push(unsafe { SendNode::new(kid) })
});
}
traversal.process_preorder(&traversal_data, &mut context, node, |n| {
children_to_process += 1;
let send_n = unsafe { SendNode::new(n) };
discovered_child_nodes.push(send_n);
});

traversal.handle_postorder_traversal(&mut context, root, node,
children_to_process);
@@ -52,14 +52,10 @@ 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 context, node);

if let Some(el) = node.as_element() {
traversal.traverse_children(&mut context, el, |_context, kid| {
children_to_process += 1;
discovered.push_back(WorkItem(kid, depth + 1))
});
}
traversal.process_preorder(&traversal_data, &mut context, node, |n| {
children_to_process += 1;
discovered.push_back(WorkItem(n, depth + 1));
});

traversal.handle_postorder_traversal(&mut context, root.as_node().opaque(),
node, children_to_process);
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.