Auto merge of #25230 - servo:sequential, r=nox

Fix `--layout-threads 1` in layout 2020
This commit is contained in:
bors-servo 2019-12-10 23:07:04 -05:00 committed by GitHub
commit b98a8fc576
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 72 additions and 43 deletions

View file

@ -11,6 +11,7 @@ use style::context::SharedStyleContext;
pub struct LayoutContext<'a> { pub struct LayoutContext<'a> {
pub id: PipelineId, pub id: PipelineId,
pub use_rayon: bool,
pub style_context: SharedStyleContext<'a>, pub style_context: SharedStyleContext<'a>,
pub font_cache_thread: Mutex<FontCacheThread>, pub font_cache_thread: Mutex<FontCacheThread>,
} }

View file

@ -168,12 +168,11 @@ impl BlockContainer {
builder.end_ongoing_inline_formatting_context(); builder.end_ongoing_inline_formatting_context();
} }
type Intermediate<Node> = IntermediateBlockLevelBox<Node>; struct Accumulator {
struct Target {
contains_floats: ContainsFloats, contains_floats: ContainsFloats,
outer_content_sizes_of_children: ContentSizes, outer_content_sizes_of_children: ContentSizes,
} }
impl Default for Target { impl Default for Accumulator {
fn default() -> Self { fn default() -> Self {
Self { Self {
contains_floats: ContainsFloats::No, contains_floats: ContainsFloats::No,
@ -181,37 +180,46 @@ impl BlockContainer {
} }
} }
} }
let mut target = Target { let mut acc = Accumulator {
contains_floats: builder.contains_floats, contains_floats: builder.contains_floats,
outer_content_sizes_of_children: ContentSizes::zero(), outer_content_sizes_of_children: ContentSizes::zero(),
}; };
let iter = builder.block_level_boxes.into_par_iter(); let mapfold =
let iter = iter.mapfold_reduce_into( |acc: &mut Accumulator,
&mut target, (intermediate, box_slot): (IntermediateBlockLevelBox<_>, BoxSlot<'_>)| {
|target, (intermediate, box_slot): (Intermediate<_>, BoxSlot<'_>)| {
let (block_level_box, box_contains_floats) = intermediate.finish( let (block_level_box, box_contains_floats) = intermediate.finish(
context, context,
content_sizes content_sizes.if_requests_inline(|| &mut acc.outer_content_sizes_of_children),
.if_requests_inline(|| &mut target.outer_content_sizes_of_children),
); );
target.contains_floats |= box_contains_floats; acc.contains_floats |= box_contains_floats;
box_slot.set(LayoutBox::BlockLevel(block_level_box.clone())); box_slot.set(LayoutBox::BlockLevel(block_level_box.clone()));
block_level_box block_level_box
}, };
|left, right| { let block_level_boxes = if context.use_rayon {
left.contains_floats |= right.contains_floats; builder
if content_sizes.requests_inline() { .block_level_boxes
left.outer_content_sizes_of_children .into_par_iter()
.max_assign(&right.outer_content_sizes_of_children) .mapfold_reduce_into(&mut acc, mapfold, |left, right| {
} left.contains_floats |= right.contains_floats;
}, if content_sizes.requests_inline() {
); left.outer_content_sizes_of_children
let container = BlockContainer::BlockLevelBoxes(iter.collect()); .max_assign(&right.outer_content_sizes_of_children)
}
})
.collect()
} else {
builder
.block_level_boxes
.into_iter()
.map(|x| mapfold(&mut acc, x))
.collect()
};
let container = BlockContainer::BlockLevelBoxes(block_level_boxes);
let Target { let Accumulator {
contains_floats, contains_floats,
outer_content_sizes_of_children, outer_content_sizes_of_children,
} = target; } = acc;
let content_sizes = content_sizes.compute(|| outer_content_sizes_of_children); let content_sizes = content_sizes.compute(|| outer_content_sizes_of_children);
(container, contains_floats, content_sizes) (container, contains_floats, content_sizes)
} }

View file

@ -135,7 +135,7 @@ fn layout_block_level_children<'a>(
containing_block: &ContainingBlock, containing_block: &ContainingBlock,
tree_rank: usize, tree_rank: usize,
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
float_context: Option<&mut FloatContext>, mut float_context: Option<&mut FloatContext>,
collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin, collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin,
) -> FlowLayout { ) -> FlowLayout {
fn place_block_level_fragment(fragment: &mut Fragment, placement_state: &mut PlacementState) { fn place_block_level_fragment(fragment: &mut Fragment, placement_state: &mut PlacementState) {
@ -203,7 +203,7 @@ fn layout_block_level_children<'a>(
current_block_direction_position: Length::zero(), current_block_direction_position: Length::zero(),
}; };
let mut fragments: Vec<_>; let mut fragments: Vec<_>;
if let Some(float_context) = float_context { if float_context.is_some() || !layout_context.use_rayon {
// Because floats are involved, we do layout for this block formatting context // Because floats are involved, we do layout for this block formatting context
// in tree order without parallelism. This enables mutable access // in tree order without parallelism. This enables mutable access
// to a `FloatContext` that tracks every float encountered so far (again in tree order). // to a `FloatContext` that tracks every float encountered so far (again in tree order).
@ -216,7 +216,7 @@ fn layout_block_level_children<'a>(
containing_block, containing_block,
tree_rank, tree_rank,
absolutely_positioned_fragments, absolutely_positioned_fragments,
Some(float_context), float_context.as_mut().map(|c| &mut **c),
); );
place_block_level_fragment(&mut fragment, &mut placement_state); place_block_level_fragment(&mut fragment, &mut placement_state);
fragment fragment

View file

@ -12,7 +12,7 @@ use crate::formatting_contexts::IndependentFormattingContext;
use crate::fragments::Fragment; use crate::fragments::Fragment;
use crate::geom; use crate::geom;
use crate::geom::flow_relative::Vec2; use crate::geom::flow_relative::Vec2;
use crate::positioned::AbsolutelyPositionedBox; use crate::positioned::{AbsolutelyPositionedBox, AbsolutelyPositionedFragment};
use crate::replaced::ReplacedContent; use crate::replaced::ReplacedContent;
use crate::sizing::ContentSizesRequest; use crate::sizing::ContentSizesRequest;
use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside}; use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside};
@ -118,11 +118,18 @@ impl BoxTreeRoot {
&mut absolutely_positioned_fragments, &mut absolutely_positioned_fragments,
); );
independent_layout.fragments.par_extend( let map =
absolutely_positioned_fragments |a: &AbsolutelyPositionedFragment| a.layout(layout_context, &initial_containing_block);
.par_iter() if layout_context.use_rayon {
.map(|a| a.layout(layout_context, &initial_containing_block)), independent_layout
); .fragments
.par_extend(absolutely_positioned_fragments.par_iter().map(map))
} else {
independent_layout
.fragments
.extend(absolutely_positioned_fragments.iter().map(map))
}
FragmentTreeRoot(independent_layout.fragments) FragmentTreeRoot(independent_layout.fragments)
} }
} }

View file

@ -139,11 +139,14 @@ impl<'a> AbsolutelyPositionedFragment<'a> {
size: padding_rect.size.clone(), size: padding_rect.size.clone(),
style, style,
}; };
let map = |a: &AbsolutelyPositionedFragment| a.layout(layout_context, &containing_block);
let children = if layout_context.use_rayon {
absolute.par_iter().map(map).collect()
} else {
absolute.iter().map(map).collect()
};
fragments.push(Fragment::Anonymous(AnonymousFragment { fragments.push(Fragment::Anonymous(AnonymousFragment {
children: absolute children,
.par_iter()
.map(|a| a.layout(layout_context, &containing_block))
.collect(),
rect: padding_rect, rect: padding_rect,
mode: style.writing_mode, mode: style.writing_mode,
})) }))

View file

@ -568,6 +568,7 @@ impl LayoutThread {
snapshot_map: snapshot_map, snapshot_map: snapshot_map,
}, },
font_cache_thread: Mutex::new(self.font_cache_thread.clone()), font_cache_thread: Mutex::new(self.font_cache_thread.clone()),
use_rayon: STYLE_THREAD_POOL.pool().is_some(),
} }
} }
@ -1076,14 +1077,18 @@ impl LayoutThread {
}; };
let rayon_pool = STYLE_THREAD_POOL.pool(); let rayon_pool = STYLE_THREAD_POOL.pool();
let rayon_pool = rayon_pool.as_ref().unwrap(); let rayon_pool = rayon_pool.as_ref();
let box_tree = if token.should_traverse() { let box_tree = if token.should_traverse() {
driver::traverse_dom(&traversal, token, Some(rayon_pool)); driver::traverse_dom(&traversal, token, rayon_pool);
let root_node = document.root_element().unwrap().as_node(); let root_node = document.root_element().unwrap().as_node();
let box_tree = let build_box_tree = || BoxTreeRoot::construct(traversal.context(), root_node);
rayon_pool.install(|| BoxTreeRoot::construct(traversal.context(), root_node)); let box_tree = if let Some(pool) = rayon_pool {
pool.install(build_box_tree)
} else {
build_box_tree()
};
Some(box_tree) Some(box_tree)
} else { } else {
None None
@ -1096,8 +1101,12 @@ impl LayoutThread {
self.viewport_size.width.to_f32_px(), self.viewport_size.width.to_f32_px(),
self.viewport_size.height.to_f32_px(), self.viewport_size.height.to_f32_px(),
); );
let fragment_tree = let run_layout = || box_tree.layout(&layout_context, viewport_size);
rayon_pool.install(|| box_tree.layout(&layout_context, viewport_size)); let fragment_tree = if let Some(pool) = rayon_pool {
pool.install(run_layout)
} else {
run_layout()
};
*self.box_tree_root.borrow_mut() = Some(box_tree); *self.box_tree_root.borrow_mut() = Some(box_tree);
*self.fragment_tree_root.borrow_mut() = Some(fragment_tree); *self.fragment_tree_root.borrow_mut() = Some(fragment_tree);
} }

View file

@ -454,10 +454,11 @@ impl ToCss for Display {
where where
W: fmt::Write, W: fmt::Write,
{ {
#[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
debug_assert_ne!( debug_assert_ne!(
self.inside(), self.inside(),
DisplayInside::Flow, DisplayInside::Flow,
"`flow` never appears in `display` computed value" "`flow` fears in `display` computed value"
); );
let outside = self.outside(); let outside = self.outside();
let inside = match self.inside() { let inside = match self.inside() {