Disable use of rayon with --layout-threads 1 instead of panicking

This commit is contained in:
Simon Sapin 2019-12-08 15:00:40 +01:00
parent aade603025
commit c895e3d236
6 changed files with 56 additions and 36 deletions

View file

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

View file

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

View file

@ -135,7 +135,7 @@ fn layout_block_level_children<'a>(
containing_block: &ContainingBlock,
tree_rank: usize,
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
float_context: Option<&mut FloatContext>,
mut float_context: Option<&mut FloatContext>,
collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin,
) -> FlowLayout {
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(),
};
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
// in tree order without parallelism. This enables mutable access
// 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,
tree_rank,
absolutely_positioned_fragments,
Some(float_context),
float_context.as_mut().map(|c| &mut **c),
);
place_block_level_fragment(&mut fragment, &mut placement_state);
fragment

View file

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

View file

@ -139,11 +139,14 @@ impl<'a> AbsolutelyPositionedFragment<'a> {
size: padding_rect.size.clone(),
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 {
children: absolute
.par_iter()
.map(|a| a.layout(layout_context, &containing_block))
.collect(),
children,
rect: padding_rect,
mode: style.writing_mode,
}))

View file

@ -568,6 +568,7 @@ impl LayoutThread {
snapshot_map: snapshot_map,
},
font_cache_thread: Mutex::new(self.font_cache_thread.clone()),
use_rayon: STYLE_THREAD_POOL.pool().is_some(),
}
}