servo: Merge #3668 - Removes duplicate CSS selector matching logic (from cgaebel:sequential-reflow); r=pcwalton

Now that DOM/Flow traversals have been refactored out, the `recalc_style_for_subtree`
function in `css/matching.rs` can be removed, in lieu of just running the standard
`recalc_style_for_node` and `construct_flows` traversals sequentially. Now we
no longer have the maintenance headache of duplicating selector matching logic
in two places! \o/

This passes reftests with both default arguments, and with `-y 1`.

r? @pcwalton

Source-Repo: https://github.com/servo/servo
Source-Revision: 7eaeaeeb217e7cbd083fe318863e7de4b9f38e2b
This commit is contained in:
Clark Gaebel 2014-10-14 19:33:28 -06:00
Родитель ab3dd48482
Коммит f081b5599e
8 изменённых файлов: 201 добавлений и 312 удалений

Просмотреть файл

@ -431,18 +431,17 @@ struct AbsoluteAssignBSizesTraversal<'a>(&'a LayoutContext<'a>);
impl<'a> PreorderFlowTraversal for AbsoluteAssignBSizesTraversal<'a> {
#[inline]
fn process(&mut self, flow: &mut Flow) -> bool {
fn process(&self, flow: &mut Flow) {
let block_flow = flow.as_block();
// The root of the absolute flow tree is definitely not absolutely
// positioned. Nothing to process here.
if block_flow.is_root_of_absolute_flow_tree() {
return true;
return;
}
let AbsoluteAssignBSizesTraversal(ref ctx) = *self;
block_flow.calculate_abs_block_size_and_margins(*ctx);
true
}
}
@ -458,14 +457,13 @@ struct AbsoluteStoreOverflowTraversal<'a>{
impl<'a> PostorderFlowTraversal for AbsoluteStoreOverflowTraversal<'a> {
#[inline]
fn process(&mut self, flow: &mut Flow) -> bool {
fn process(&self, flow: &mut Flow) {
// This will be taken care of by the normal store-overflow traversal.
if flow.is_root_of_absolute_flow_tree() {
return true;
return;
}
flow.store_overflow(self.layout_context);
true
}
}
@ -711,16 +709,10 @@ impl BlockFlow {
///
/// Return true if the traversal is to continue or false to stop.
fn traverse_preorder_absolute_flows<T:PreorderFlowTraversal>(&mut self,
traversal: &mut T)
-> bool {
traversal: &mut T) {
let flow = self as &mut Flow;
if traversal.should_prune(flow) {
return true
}
if !traversal.process(flow) {
return false
}
traversal.process(flow);
let cb_block_start_edge_offset = flow.generated_containing_block_rect().start.b;
let mut descendant_offset_iter = mut_base(flow).abs_descendants.iter_with_offset();
@ -730,30 +722,20 @@ impl BlockFlow {
// The stored y_offset is wrt to the flow box.
// Translate it to the CB (which is the padding box).
block.static_b_offset = **y_offset - cb_block_start_edge_offset;
if !block.traverse_preorder_absolute_flows(traversal) {
return false
}
block.traverse_preorder_absolute_flows(traversal);
}
true
}
/// Traverse the Absolute flow tree in postorder.
///
/// Return true if the traversal is to continue or false to stop.
fn traverse_postorder_absolute_flows<T:PostorderFlowTraversal>(&mut self,
traversal: &mut T)
-> bool {
traversal: &mut T) {
let flow = self as &mut Flow;
if traversal.should_prune(flow) {
return true
}
for descendant_link in mut_base(flow).abs_descendants.iter() {
let block = descendant_link.as_block();
if !block.traverse_postorder_absolute_flows(traversal) {
return false
}
block.traverse_postorder_absolute_flows(traversal);
}
traversal.process(flow)

Просмотреть файл

@ -5,10 +5,8 @@
// High-level interface to CSS selector matching.
use css::node_style::StyledNode;
use construct::FlowConstructor;
use context::LayoutContext;
use util::{LayoutDataAccess, LayoutDataWrapper};
use wrapper::{LayoutElement, LayoutNode, PostorderNodeMutTraversal, ThreadSafeLayoutNode};
use wrapper::{LayoutElement, LayoutNode};
use wrapper::{TLayoutNode};
use script::dom::node::{TextNodeTypeId};
@ -295,15 +293,6 @@ pub trait MatchMethods {
/// called to reset the bloom filter after an `insert`.
fn remove_from_bloom_filter(&self, bf: &mut BloomFilter);
/// Performs aux initialization, selector matching, cascading, and flow construction
/// sequentially.
fn recalc_style_for_subtree(&self,
stylist: &Stylist,
layout_context: &LayoutContext,
parent_bf: &mut Option<Box<BloomFilter>>,
applicable_declarations: &mut ApplicableDeclarations,
parent: Option<LayoutNode>);
fn match_node(&self,
stylist: &Stylist,
parent_bf: &Option<Box<BloomFilter>>,
@ -524,67 +513,6 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
element.each_class(|class| bf.remove(class));
}
fn recalc_style_for_subtree(&self,
stylist: &Stylist,
layout_context: &LayoutContext,
parent_bf: &mut Option<Box<BloomFilter>>,
applicable_declarations: &mut ApplicableDeclarations,
parent: Option<LayoutNode>) {
self.initialize_layout_data(layout_context.shared.layout_chan.clone());
// First, check to see whether we can share a style with someone.
let sharing_result = unsafe {
self.share_style_if_possible(layout_context.style_sharing_candidate_cache(),
parent.clone())
};
// Otherwise, match and cascade selectors.
match sharing_result {
CannotShare(mut shareable) => {
if self.is_element() {
self.match_node(stylist, &*parent_bf, applicable_declarations, &mut shareable);
}
unsafe {
self.cascade_node(parent,
applicable_declarations,
layout_context.applicable_declarations_cache())
}
applicable_declarations.clear();
// Add ourselves to the LRU cache.
if shareable {
layout_context.style_sharing_candidate_cache().insert_if_possible(self)
}
}
StyleWasShared(index) => layout_context.style_sharing_candidate_cache().touch(index),
}
match *parent_bf {
None => {},
Some(ref mut pbf) => self.insert_into_bloom_filter(&mut **pbf),
}
for kid in self.children() {
kid.recalc_style_for_subtree(stylist,
layout_context,
parent_bf,
applicable_declarations,
Some(self.clone()));
}
match *parent_bf {
None => {},
Some(ref mut pbf) => self.remove_from_bloom_filter(&mut **pbf),
}
// Construct flows.
let layout_node = ThreadSafeLayoutNode::new(self);
let mut flow_constructor = FlowConstructor::new(layout_context);
flow_constructor.process(&layout_node);
}
unsafe fn cascade_node(&self,
parent: Option<LayoutNode>,
applicable_declarations: &ApplicableDeclarations,

Просмотреть файл

@ -411,10 +411,10 @@ pub trait MutableFlowUtils {
// Traversals
/// Traverses the tree in preorder.
fn traverse_preorder<T:PreorderFlowTraversal>(self, traversal: &mut T) -> bool;
fn traverse_preorder<T:PreorderFlowTraversal>(self, traversal: &T);
/// Traverses the tree in postorder.
fn traverse_postorder<T:PostorderFlowTraversal>(self, traversal: &mut T) -> bool;
fn traverse_postorder<T:PostorderFlowTraversal>(self, traversal: &T);
// Mutators
@ -464,41 +464,27 @@ pub enum FlowClass {
/// A top-down traversal.
pub trait PreorderFlowTraversal {
/// The operation to perform. Return true to continue or false to stop.
fn process(&mut self, flow: &mut Flow) -> bool;
fn process(&self, flow: &mut Flow);
/// Returns true if this node must be processed in-order. If this returns false,
/// we skip the operation for this node, but continue processing the descendants.
/// This is called *after* parent nodes are visited.
fn should_process(&mut self, _flow: &mut Flow) -> bool {
fn should_process(&self, _flow: &mut Flow) -> bool {
true
}
/// Returns true if this node should be pruned. If this returns true, we skip the operation
/// entirely and do not process any descendant nodes. This is called *before* child nodes are
/// visited. The default implementation never prunes any nodes.
fn should_prune(&mut self, _flow: &mut Flow) -> bool {
false
}
}
/// A bottom-up traversal, with a optional in-order pass.
pub trait PostorderFlowTraversal {
/// The operation to perform. Return true to continue or false to stop.
fn process(&mut self, flow: &mut Flow) -> bool;
fn process(&self, flow: &mut Flow);
/// Returns false if this node must be processed in-order. If this returns false, we skip the
/// operation for this node, but continue processing the ancestors. This is called *after*
/// child nodes are visited.
fn should_process(&mut self, _flow: &mut Flow) -> bool {
fn should_process(&self, _flow: &mut Flow) -> bool {
true
}
/// Returns true if this node should be pruned. If this returns true, we skip the operation
/// entirely and do not process any descendant nodes. This is called *before* child nodes are
/// visited. The default implementation never prunes any nodes.
fn should_prune(&mut self, _flow: &mut Flow) -> bool {
false
}
}
/// Flags used in flows, tightly packed to save space.
@ -1043,45 +1029,25 @@ impl<'a> ImmutableFlowUtils for &'a Flow + 'a {
impl<'a> MutableFlowUtils for &'a mut Flow + 'a {
/// Traverses the tree in preorder.
fn traverse_preorder<T:PreorderFlowTraversal>(self, traversal: &mut T) -> bool {
if traversal.should_prune(self) {
return true
}
if !traversal.should_process(self) {
return true
}
if !traversal.process(self) {
return false
fn traverse_preorder<T:PreorderFlowTraversal>(self, traversal: &T) {
if traversal.should_process(self) {
traversal.process(self);
}
for kid in child_iter(self) {
if !kid.traverse_preorder(traversal) {
return false
}
kid.traverse_preorder(traversal);
}
true
}
/// Traverses the tree in postorder.
fn traverse_postorder<T:PostorderFlowTraversal>(self, traversal: &mut T) -> bool {
if traversal.should_prune(self) {
return true
}
fn traverse_postorder<T:PostorderFlowTraversal>(self, traversal: &T) {
for kid in child_iter(self) {
if !kid.traverse_postorder(traversal) {
return false
}
kid.traverse_postorder(traversal);
}
if !traversal.should_process(self) {
return true
if traversal.should_process(self) {
traversal.process(self)
}
traversal.process(self)
}
/// Calculate and set overflow for current flow.

Просмотреть файл

@ -5,18 +5,16 @@
//! The layout task. Performs layout on the DOM, builds display lists and sends them to be
//! rendered.
use css::matching::{ApplicableDeclarations, MatchMethods};
use css::node_style::StyledNode;
use construct::FlowConstructionResult;
use context::{LayoutContext, SharedLayoutContext};
use flow::{Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
use flow::{PreorderFlowTraversal, PostorderFlowTraversal};
use flow;
use flow_ref::FlowRef;
use layout_debug;
use parallel::UnsafeFlow;
use parallel;
use traversal;
use sequential;
use util::{LayoutDataAccess, LayoutDataWrapper, OpaqueNodeMethods, ToGfxColor};
use wrapper::{LayoutNode, TLayoutNode, ThreadSafeLayoutNode};
@ -48,7 +46,6 @@ use servo_msg::constellation_msg::{ConstellationChan, PipelineId, Failure, Failu
use servo_net::image_cache_task::{ImageCacheTask, ImageResponseMsg};
use gfx::font_cache_task::{FontCacheTask};
use servo_net::local_image_cache::{ImageResponder, LocalImageCache};
use servo_util::bloom::BloomFilter;
use servo_net::resource_task::{ResourceTask, load_bytes_iter};
use servo_util::geometry::Au;
use servo_util::geometry;
@ -515,31 +512,10 @@ impl LayoutTask {
/// benchmarked against those two. It is marked `#[inline(never)]` to aid profiling.
#[inline(never)]
fn solve_constraints<'a>(&self,
layout_root: &mut Flow,
layout_context: &'a LayoutContext<'a>) {
layout_root: &mut FlowRef,
shared_layout_context: &SharedLayoutContext) {
let _scope = layout_debug_scope!("solve_constraints");
if layout_context.shared.opts.bubble_inline_sizes_separately {
let mut traversal = traversal::BubbleISizes {
layout_context: layout_context,
};
layout_root.traverse_postorder(&mut traversal);
}
// FIXME(pcwalton): Prune these two passes.
{
let mut traversal = traversal::AssignISizes {
layout_context: layout_context,
};
layout_root.traverse_preorder(&mut traversal);
}
{
let mut traversal = traversal::AssignBSizesAndStoreOverflow {
layout_context: layout_context,
};
layout_root.traverse_postorder(&mut traversal);
}
sequential::traverse_flow_tree_preorder(layout_root, shared_layout_context);
}
/// Performs layout constraint solving in parallel.
@ -552,12 +528,7 @@ impl LayoutTask {
rw_data: &mut LayoutTaskData,
layout_root: &mut FlowRef,
shared_layout_context: &SharedLayoutContext) {
if shared_layout_context.opts.bubble_inline_sizes_separately {
let mut traversal = traversal::BubbleISizes {
layout_context: &LayoutContext::new(shared_layout_context),
};
layout_root.get_mut().traverse_postorder(&mut traversal);
}
let _scope = layout_debug_scope!("solve_constraints_parallel");
match rw_data.parallel_traversal {
None => fail!("solve_contraints_parallel() called with no parallel traversal ready"),
@ -649,17 +620,10 @@ impl LayoutTask {
let rw_data = rw_data.deref_mut();
match rw_data.parallel_traversal {
None => {
let layout_ctx = LayoutContext::new(&shared_layout_ctx);
let mut applicable_declarations = ApplicableDeclarations::new();
let mut parent_bf = Some(box BloomFilter::new());
node.recalc_style_for_subtree(&*rw_data.stylist,
&layout_ctx,
&mut parent_bf,
&mut applicable_declarations,
None)
sequential::traverse_dom_preorder(*node, &shared_layout_ctx);
}
Some(ref mut traversal) => {
parallel::traverse_dom_preorder(*node, &mut shared_layout_ctx, traversal)
parallel::traverse_dom_preorder(*node, &shared_layout_ctx, traversal)
}
}
@ -702,8 +666,7 @@ impl LayoutTask {
match rw_data.parallel_traversal {
None => {
// Sequential mode.
let layout_ctx = LayoutContext::new(&shared_layout_ctx);
self.solve_constraints(layout_root.get_mut(), &layout_ctx)
self.solve_constraints(&mut layout_root, &shared_layout_ctx)
}
Some(_) => {
// Parallel mode.
@ -724,20 +687,19 @@ impl LayoutTask {
let rw_data = rw_data.deref_mut();
match rw_data.parallel_traversal {
None => {
let layout_ctx = LayoutContext::new(&shared_layout_ctx);
let mut traversal = traversal::BuildDisplayList {
layout_context: &layout_ctx,
};
traversal.process(layout_root.get_mut());
sequential::build_display_list_for_subtree(
&mut layout_root,
&shared_layout_ctx);
}
Some(ref mut traversal) => {
parallel::build_display_list_for_subtree(&mut layout_root,
&data.url,
data.iframe,
self.first_reflow.get(),
self.time_profiler_chan.clone(),
&mut shared_layout_ctx,
traversal);
parallel::build_display_list_for_subtree(
&mut layout_root,
&data.url,
data.iframe,
self.first_reflow.get(),
self.time_profiler_chan.clone(),
&shared_layout_ctx,
traversal);
}
}

Просмотреть файл

@ -55,6 +55,7 @@ pub mod layout_task;
pub mod inline;
pub mod model;
pub mod parallel;
pub mod sequential;
pub mod table_wrapper;
pub mod table;
pub mod table_caption;

Просмотреть файл

@ -11,7 +11,8 @@ use flow::{Flow, MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal
use flow;
use flow_ref::FlowRef;
use traversal::{RecalcStyleForNode, ConstructFlows};
use traversal::{AssignBSizesAndStoreOverflow, AssignISizes, BubbleISizes};
use traversal::{BubbleISizes, AssignISizes, AssignBSizesAndStoreOverflow};
use traversal::{ComputeAbsolutePositions, BuildDisplayList};
use url::Url;
use util::{LayoutDataAccess, LayoutDataWrapper};
use wrapper::{layout_node_to_unsafe_layout_node, layout_node_from_unsafe_layout_node, LayoutNode};
@ -79,12 +80,12 @@ impl DomParallelInfo {
/// A parallel top-down DOM traversal.
pub trait ParallelPreorderDomTraversal : PreorderDomTraversal {
fn run_parallel(&mut self,
fn run_parallel(&self,
node: UnsafeLayoutNode,
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeLayoutNode>);
#[inline(always)]
fn run_parallel_helper(&mut self,
fn run_parallel_helper(&self,
unsafe_node: UnsafeLayoutNode,
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeLayoutNode>,
top_down_func: extern "Rust" fn(UnsafeFlow,
@ -139,7 +140,7 @@ trait ParallelPostorderDomTraversal : PostorderDomTraversal {
///
/// The only communication between siblings is that they both
/// fetch-and-subtract the parent's children count.
fn run_parallel(&mut self,
fn run_parallel(&self,
mut unsafe_node: UnsafeLayoutNode,
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeLayoutNode>) {
loop {
@ -214,7 +215,7 @@ trait ParallelPostorderFlowTraversal : PostorderFlowTraversal {
///
/// The only communication between siblings is that they both
/// fetch-and-subtract the parent's children count.
fn run_parallel(&mut self,
fn run_parallel(&self,
mut unsafe_flow: UnsafeFlow,
_: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
loop {
@ -259,12 +260,12 @@ trait ParallelPostorderFlowTraversal : PostorderFlowTraversal {
/// A parallel top-down flow traversal.
trait ParallelPreorderFlowTraversal : PreorderFlowTraversal {
fn run_parallel(&mut self,
fn run_parallel(&self,
unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>);
#[inline(always)]
fn run_parallel_helper(&mut self,
fn run_parallel_helper(&self,
unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>,
top_down_func: extern "Rust" fn(UnsafeFlow,
@ -304,7 +305,7 @@ trait ParallelPreorderFlowTraversal : PreorderFlowTraversal {
impl<'a> ParallelPostorderFlowTraversal for BubbleISizes<'a> {}
impl<'a> ParallelPreorderFlowTraversal for AssignISizes<'a> {
fn run_parallel(&mut self,
fn run_parallel(&self,
unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
self.run_parallel_helper(unsafe_flow,
@ -316,10 +317,23 @@ impl<'a> ParallelPreorderFlowTraversal for AssignISizes<'a> {
impl<'a> ParallelPostorderFlowTraversal for AssignBSizesAndStoreOverflow<'a> {}
impl<'a> ParallelPreorderFlowTraversal for ComputeAbsolutePositions<'a> {
fn run_parallel(&self,
unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeFlow>) {
self.run_parallel_helper(unsafe_flow,
proxy,
compute_absolute_positions,
build_display_list)
}
}
impl<'a> ParallelPostorderFlowTraversal for BuildDisplayList<'a> {}
impl<'a> ParallelPostorderDomTraversal for ConstructFlows<'a> {}
impl <'a> ParallelPreorderDomTraversal for RecalcStyleForNode<'a> {
fn run_parallel(&mut self,
fn run_parallel(&self,
unsafe_node: UnsafeLayoutNode,
proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeLayoutNode>) {
self.run_parallel_helper(unsafe_node,
@ -333,7 +347,7 @@ fn recalc_style(unsafe_node: UnsafeLayoutNode,
proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeLayoutNode>) {
let shared_layout_context = unsafe { &**proxy.user_data() };
let layout_context = LayoutContext::new(shared_layout_context);
let mut recalc_style_for_node_traversal = RecalcStyleForNode {
let recalc_style_for_node_traversal = RecalcStyleForNode {
layout_context: &layout_context,
};
recalc_style_for_node_traversal.run_parallel(unsafe_node, proxy)
@ -343,7 +357,7 @@ fn construct_flows(unsafe_node: UnsafeLayoutNode,
proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeLayoutNode>) {
let shared_layout_context = unsafe { &**proxy.user_data() };
let layout_context = LayoutContext::new(shared_layout_context);
let mut construct_flows_traversal = ConstructFlows {
let construct_flows_traversal = ConstructFlows {
layout_context: &layout_context,
};
construct_flows_traversal.run_parallel(unsafe_node, proxy)
@ -353,91 +367,40 @@ fn assign_inline_sizes(unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
let shared_layout_context = unsafe { &**proxy.user_data() };
let layout_context = LayoutContext::new(shared_layout_context);
let mut assign_inline_sizes_traversal = AssignISizes {
let assign_inline_sizes_traversal = AssignISizes {
layout_context: &layout_context,
};
assign_inline_sizes_traversal.run_parallel(unsafe_flow, proxy)
}
fn assign_block_sizes_and_store_overflow(unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
let shared_layout_context = unsafe { &**proxy.user_data() };
let layout_context = LayoutContext::new(shared_layout_context);
let mut assign_block_sizes_traversal = AssignBSizesAndStoreOverflow {
let assign_block_sizes_traversal = AssignBSizesAndStoreOverflow {
layout_context: &layout_context,
};
assign_block_sizes_traversal.run_parallel(unsafe_flow, proxy)
}
fn compute_absolute_position(unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
let mut had_descendants = false;
unsafe {
// Get a real flow.
let flow: &mut FlowRef = mem::transmute(&unsafe_flow);
// Compute the absolute position for the flow.
flow.get_mut().compute_absolute_position();
// Enqueue all children.
for kid in flow::child_iter(flow.get_mut()) {
had_descendants = true;
proxy.push(WorkUnit {
fun: compute_absolute_position,
data: borrowed_flow_to_unsafe_flow(kid),
});
}
// If there were no more descendants, start building the display list.
if !had_descendants {
build_display_list(mut_owned_flow_to_unsafe_flow(flow), proxy)
}
}
}
fn build_display_list(mut unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
fn compute_absolute_positions(unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeFlow>) {
let shared_layout_context = unsafe { &**proxy.user_data() };
let layout_context = LayoutContext::new(shared_layout_context);
let compute_absolute_positions_traversal = ComputeAbsolutePositions {
layout_context: &layout_context,
};
compute_absolute_positions_traversal.run_parallel(unsafe_flow, proxy);
}
loop {
unsafe {
// Get a real flow.
let flow: &mut FlowRef = mem::transmute(&unsafe_flow);
// Build display lists.
flow.get_mut().build_display_list(&layout_context);
{
let base = flow::mut_base(flow.get_mut());
// Reset the count of children for the next layout traversal.
base.parallel.children_count.store(base.children.len() as int, Relaxed);
}
// Possibly enqueue the parent.
let unsafe_parent = flow::mut_base(flow.get_mut()).parallel.parent;
if unsafe_parent == null_unsafe_flow() {
// We're done!
break
}
// No, we're not at the root yet. Then are we the last child
// of our parent to finish processing? If so, we can continue
// on with our parent; otherwise, we've gotta wait.
let parent: &mut FlowRef = mem::transmute(&unsafe_parent);
let parent_base = flow::mut_base(parent.get_mut());
if parent_base.parallel
.children_count
.fetch_sub(1, SeqCst) == 1 {
// We were the last child of our parent. Build display lists for our parent.
unsafe_flow = unsafe_parent
} else {
// Stop.
break
}
}
}
fn build_display_list(unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeFlow>) {
let shared_layout_context = unsafe { &**proxy.user_data() };
let layout_context = LayoutContext::new(shared_layout_context);
let build_display_list_traversal = BuildDisplayList {
layout_context: &layout_context,
};
build_display_list_traversal.run_parallel(unsafe_flow, proxy);
}
pub fn traverse_dom_preorder(root: LayoutNode,
@ -462,6 +425,12 @@ pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
time_profiler_chan: TimeProfilerChan,
shared_layout_context: &SharedLayoutContext,
queue: &mut WorkQueue<*const SharedLayoutContext,UnsafeFlow>) {
if shared_layout_context.opts.bubble_inline_sizes_separately {
let layout_context = LayoutContext::new(shared_layout_context);
let bubble_inline_sizes = BubbleISizes { layout_context: &layout_context };
root.get_mut().traverse_postorder(&bubble_inline_sizes);
}
queue.data = shared_layout_context as *const _;
profile(time::LayoutParallelWarmupCategory, Some((url, iframe, first_reflow)), time_profiler_chan, || {
@ -487,7 +456,7 @@ pub fn build_display_list_for_subtree(root: &mut FlowRef,
profile(time::LayoutParallelWarmupCategory, Some((url, iframe, first_reflow)), time_profiler_chan, || {
queue.push(WorkUnit {
fun: compute_absolute_position,
fun: compute_absolute_positions,
data: mut_owned_flow_to_unsafe_flow(root),
})
});

Просмотреть файл

@ -0,0 +1,89 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Implements sequential traversals over the DOM and flow trees.
use context::{LayoutContext, SharedLayoutContext};
use flow::{Flow, MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal};
use flow;
use flow_ref::FlowRef;
use traversal::{BubbleISizes, RecalcStyleForNode, ConstructFlows};
use traversal::{AssignBSizesAndStoreOverflow, AssignISizes};
use traversal::{ComputeAbsolutePositions, BuildDisplayList};
use wrapper::LayoutNode;
use wrapper::{PostorderNodeMutTraversal};
use wrapper::{PreorderDomTraversal, PostorderDomTraversal};
pub fn traverse_dom_preorder(root: LayoutNode,
shared_layout_context: &SharedLayoutContext) {
fn doit(node: LayoutNode, recalc_style: RecalcStyleForNode, construct_flows: ConstructFlows) {
recalc_style.process(node);
for kid in node.children() {
doit(kid, recalc_style, construct_flows);
}
construct_flows.process(node);
}
let layout_context = LayoutContext::new(shared_layout_context);
let recalc_style = RecalcStyleForNode { layout_context: &layout_context };
let construct_flows = ConstructFlows { layout_context: &layout_context };
doit(root, recalc_style, construct_flows);
}
pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
shared_layout_context: &SharedLayoutContext) {
fn doit(flow: &mut Flow, assign_inline_sizes: AssignISizes, assign_block_sizes: AssignBSizesAndStoreOverflow) {
if assign_inline_sizes.should_process(flow) {
assign_inline_sizes.process(flow);
}
for kid in flow::child_iter(flow) {
doit(kid, assign_inline_sizes, assign_block_sizes);
}
if assign_block_sizes.should_process(flow) {
assign_block_sizes.process(flow);
}
}
let layout_context = LayoutContext::new(shared_layout_context);
let root = root.get_mut();
if layout_context.shared.opts.bubble_inline_sizes_separately {
let bubble_inline_sizes = BubbleISizes { layout_context: &layout_context };
root.traverse_postorder(&bubble_inline_sizes);
}
let assign_inline_sizes = AssignISizes { layout_context: &layout_context };
let assign_block_sizes = AssignBSizesAndStoreOverflow { layout_context: &layout_context };
doit(root, assign_inline_sizes, assign_block_sizes);
}
pub fn build_display_list_for_subtree(root: &mut FlowRef,
shared_layout_context: &SharedLayoutContext) {
fn doit(flow: &mut Flow, compute_absolute_positions: ComputeAbsolutePositions, build_display_list: BuildDisplayList) {
if compute_absolute_positions.should_process(flow) {
compute_absolute_positions.process(flow);
}
for kid in flow::mut_base(flow).child_iter() {
doit(kid, compute_absolute_positions, build_display_list);
}
if build_display_list.should_process(flow) {
build_display_list.process(flow);
}
}
let layout_context = LayoutContext::new(shared_layout_context);
let compute_absolute_positions = ComputeAbsolutePositions { layout_context: &layout_context };
let build_display_list = BuildDisplayList { layout_context: &layout_context };
doit(root.get_mut(), compute_absolute_positions, build_display_list);
}

Просмотреть файл

@ -261,14 +261,13 @@ struct FlowTreeVerification;
#[cfg(debug)]
impl PreorderFlow for FlowTreeVerification {
#[inline]
fn process(&mut self, flow: &mut Flow) -> bool {
fn process(&mut self, flow: &mut Flow) {
let base = flow::base(flow);
if !base.flags.is_leaf() && !base.flags.is_nonleaf() {
println("flow tree verification failed: flow wasn't a leaf or a nonleaf!");
flow.dump();
fail!("flow tree verification failed")
}
true
}
}
@ -280,18 +279,9 @@ pub struct BubbleISizes<'a> {
impl<'a> PostorderFlowTraversal for BubbleISizes<'a> {
#[inline]
fn process(&mut self, flow: &mut Flow) -> bool {
fn process(&self, flow: &mut Flow) {
flow.bubble_inline_sizes();
true
}
// FIXME: We can't prune until we start reusing flows
/*
#[inline]
fn should_prune(&mut self, flow: &mut Flow) -> bool {
flow::mut_base(flow).restyle_damage.lacks(BubbleISizes)
}
*/
}
/// The assign-inline-sizes traversal. In Gecko this corresponds to `Reflow`.
@ -301,9 +291,8 @@ pub struct AssignISizes<'a> {
impl<'a> PreorderFlowTraversal for AssignISizes<'a> {
#[inline]
fn process(&mut self, flow: &mut Flow) -> bool {
fn process(&self, flow: &mut Flow) {
flow.assign_inline_sizes(self.layout_context);
true
}
}
@ -317,36 +306,39 @@ pub struct AssignBSizesAndStoreOverflow<'a> {
impl<'a> PostorderFlowTraversal for AssignBSizesAndStoreOverflow<'a> {
#[inline]
fn process(&mut self, flow: &mut Flow) -> bool {
fn process(&self, flow: &mut Flow) {
flow.assign_block_size(self.layout_context);
// Skip store-overflow for absolutely positioned flows. That will be
// done in a separate traversal.
if !flow.is_store_overflow_delayed() {
flow.store_overflow(self.layout_context);
}
true
}
#[inline]
fn should_process(&mut self, flow: &mut Flow) -> bool {
fn should_process(&self, flow: &mut Flow) -> bool {
!flow::base(flow).flags.impacted_by_floats()
}
}
/// The display list construction traversal.
pub struct ComputeAbsolutePositions<'a> {
pub layout_context: &'a LayoutContext<'a>,
}
impl<'a> PreorderFlowTraversal for ComputeAbsolutePositions<'a> {
#[inline]
fn process(&self, flow: &mut Flow) {
flow.compute_absolute_position()
}
}
pub struct BuildDisplayList<'a> {
pub layout_context: &'a LayoutContext<'a>,
}
impl<'a> BuildDisplayList<'a> {
impl<'a> PostorderFlowTraversal for BuildDisplayList<'a> {
#[inline]
pub fn process(&mut self, flow: &mut Flow) {
flow.compute_absolute_position();
for kid in flow::mut_base(flow).child_iter() {
self.process(kid)
}
fn process(&self, flow: &mut Flow) {
flow.build_display_list(self.layout_context)
}
}